Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Doc/changes.txt
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Doc/changes.txt	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Doc/changes.txt	(revision 516)
@@ -0,0 +1,101 @@
+XTIDE Universal BIOS v1.1.5 (28 November 2010)
+  * Errors are now being checked when calling previous INT 13h handler on AH=08h Read Disk Drive Parameters.
+    This fixes infinite drive checking loop on unofficial MS-DOS 7.10 installer.
+  * Better INT 40h handler detection to fix floppy drive detection with AMI 286/386 BIOS.
+  * AA55h signature no longer required when booting from floppy drives. This should make booter games work.
+
+
+XTIDE Universal BIOS v1.1.4 (24 August 2010)
+  * Correct number of drives is now returned from AH=08h when it is redirected to foreign BIOS.
+  * Interrupt controllers are now unmasked during drive reset.
+  * OS hooks are now enabled for all builds. IRQ waiting no longer uses HLT instruction to fix some EMM386 and VCPI issues.
+  * XT+ build is no more since it would now be the same as AT build
+
+
+XTIDE Universal BIOS v1.1.3 (1 August 2010)
+  * v1.1.1 broke booting from foreign drives, it is now fixed.
+  * Improved error handling a bit.
+  * Longer DRQ and IRQ timeouts to minimize write timouts with some (bad) CF cards.
+  * Default boot menu drive should now be properly selected.
+
+
+XTIDE Universal BIOS v1.1.2 (26 July 2010, no public release)
+  * Fixed a bug where Disk Parameter Table was accessed with wrong pointer register after writing last block.
+  * Cleaned AH=00h, Disk Controller Reset a bit.
+
+
+XTIDE Universal BIOS v1.1.1 (19 July 2010)
+*Booting is now possible from hard disks if floppy controller reset fails
+ since AH=00h, Disk Controller Reset now returns error code for the
+ requested drive only.
+*Now assembles with Yasm.
+
+
+XTIDE Universal BIOS v1.1.0 (first stable release, 2 May 2010)
+*Lite and full operating modes
+*Diagnostic cylinder no longer has to be reserved
+*Slave drives again work without master present
+*32-bit transfers for VLB and PCI IDE controllers
+*16- and 32-bit transfers are enabled on all builds
+*Boot menu hotkeys for all drives
+*Drive swapping is handled separately for floppy and hard disk drives so it
+ is now possible to install DOS to any hard disk from any floppy drive
+*INT 13h,AH=15h return value in DL now longer gets corrupted by drive swapping
+*Rewritten drive detection and lots of code cleaning
+*Longer timeout when detecting first drive
+*Minimum number of floppy drives can be specified if autodetection fails
+*Maybe other changes that i have forgotten
+
+XTIDE Universal BIOS v1.1.0 configuration and flashing program (idecfg.com)
+*Now works as a generic EEPROM flasher
+*Improvements to configuration menus
+*SDP can be completely disabled
+
+
+XTIDE Universal BIOS v1.0.0_RC2
+*No more boot menu slowdown when no XTIDE Universal BIOS
+ controlled drives present
+*Hard disks are now reset properly.
+ This fixes some Block Mode related bugs.
+*Major improvements for error handling
+*Small improvements for interrupt handling
+
+
+XTIDE Universal BIOS v1.0.0_RC1
+*Fixed 386+ stack exception bug
+*Stack is relocated for boot menu even if DPTs are not stored to 30:0h
+*Strings and boot menu are displayed properly on BIOSes that corrupts
+ AH when returning from INT 10h/AH=Eh
+*L-CHS addressing is now used for <=504MiB drives even if LBA is supported
+
+
+XTIDE Universal BIOS v1.0.0_b4
+*Boot menu with drive swapping
+*Block mode transfers
+*Cylinder limiting
+*Drive detection read errors are now properly detected
+*A little longer timeout value when detecting drives
+*Minor optimizations to save some bytes
+
+
+XTIDE Universal BIOS beta3
+*BIOS configuration and flashing program finally available
+*No more conflicts with other hard disk BIOSes
+*Slave drives should now be detected without master
+*Timeouts now use system timer
+*Variables can now be located to top of base memory
+*Completely rewritten interrupt handling
+*Minor optimizations to 8-bit transfers
+*CTRL can be held down to skip initialization
+*Late initialization to fix compatibility issues with old systems
+
+
+XTIDE Universal BIOS beta2
+*AT build and support for 16-bit IDE Controllers
+*XT+ build for 188/186/V20/V30/286 XTs
+*Auto detection for timeout values (AT+)
+*Minor optimizations
+
+
+XTIDE Universal BIOS beta1
+*Initial release
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Doc/readme.txt
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Doc/readme.txt	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Doc/readme.txt	(revision 516)
@@ -0,0 +1,5 @@
+See XTIDE Universal BIOS wiki pages for manual and other information:
+http://code.google.com/p/xtideuniversalbios/w/list
+
+XTIDE Universal BIOS discussion can be found at:
+http://www.vintage-computer.com/vcforum/showthread.php?17986-XTIDE-Universal-BIOS
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/ATA_ID.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/ATA_ID.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/ATA_ID.inc	(revision 516)
@@ -0,0 +1,485 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	ATA Identify Drive information.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef ATA_ID_INC
+%define ATA_ID_INC
+
+; Maximum valid P-CHS parameters
+MAX_VALID_PCHS_CYLINDERS			EQU		16383
+MAX_VALID_PCHS_HEADS				EQU		16
+MAX_VALID_PCHS_SECTORS_PER_TRACK	EQU		63
+
+
+; PIO Minimum Cycle Times (t0)
+; Timings for Advanced Modes (3 and above) can be read from ATA info WORDs 67 and 68
+; Those usually have the same Cycle Time as below
+PIO_0_MIN_CYCLE_TIME_NS		EQU		600
+PIO_1_MIN_CYCLE_TIME_NS		EQU		383
+PIO_2_MIN_CYCLE_TIME_NS		EQU		240
+PIO_3_MIN_CYCLE_TIME_NS		EQU		180
+PIO_4_MIN_CYCLE_TIME_NS		EQU		120
+PIO_5_MIN_CYCLE_TIME_NS		EQU		100		; CF specification
+PIO_6_MIN_CYCLE_TIME_NS		EQU		80		; CF specification
+
+; PIO Minimum Address Valid Times (t1)
+PIO_0_MIN_ADDRESS_VALID_NS	EQU		70
+PIO_1_MIN_ADDRESS_VALID_NS	EQU		50
+PIO_2_MIN_ADDRESS_VALID_NS	EQU		30
+PIO_3_MIN_ADDRESS_VALID_NS	EQU		30
+PIO_4_MIN_ADDRESS_VALID_NS	EQU		25
+PIO_5_MIN_ADDRESS_VALID_NS	EQU		15
+PIO_6_MIN_ADDRESS_VALID_NS	EQU		10
+
+; PIO Minimum Active Times (t2)
+PIO_0_MIN_ACTIVE_TIME_NS	EQU		165
+PIO_1_MIN_ACTIVE_TIME_NS	EQU		125
+PIO_2_MIN_ACTIVE_TIME_NS	EQU		100
+PIO_3_MIN_ACTIVE_TIME_NS	EQU		80
+PIO_4_MIN_ACTIVE_TIME_NS	EQU		70
+PIO_5_MIN_ACTIVE_TIME_NS	EQU		65
+PIO_6_MIN_ACTIVE_TIME_NS	EQU		55
+
+; PIO Minimum Recovery Times or Inactive Times (t2i) can be calculated
+; from Minimum Cycle Time (t0) - Minimum Active Time (t2) - Address Valid Time (t1).
+; I'm not sure about this calculation so correct me if I'm wrong!
+; Recovery time should be calculated at run time since Cycle Time t0 can be
+; read from ATA information (ATA2+) but most drives just report the
+; Min Cycle Times listed above.
+
+
+
+; ATA-1 Drive Information struct
+; F = Fixed value
+; V = Variable value
+; R = Reserved word
+; X = Vendor specific word
+struc ATA1
+	.wGenCfg	resw 1	; 0F, General configuration bit-significant information
+	.wCylCnt	resw 1	; 1F, Number of cylinders
+				resw 1	; 2R
+	.wHeadCnt	resw 1	; 3F, Number of heads
+	.wBpTrck	resw 1	; 4F, Number of unformatted bytes per track
+	.wBpSect	resw 1	; 5F, Number of unformatted bytes per sector
+	.wSPT		resw 1	; 6F, Number of sectors per track
+				resw 3	; 7...9X
+	.strSerial	resb 20	; 10...19F, Serial number (20 ASCII characters, 0000h=not specified)
+	.wBuffType	resw 1	; 20F, Buffer type
+	.wBuffSize	resw 1	; 21F, Buffer size in 512 byte increments (0000h=not specified)
+	.wEccCnt	resw 1	; 22F, # of ECC bytes avail on read/write long cmds (0000h=not spec'd)
+	.strFirmW	resb 8	; 23...26F, Firmware revision (8 ASCII characters, 0000h=not specified)
+	.strModel	resb 40	; 27...46F, Model number (40 ASCII characters, 0000h=not specified)
+	.bBlckSize	resb 1	; 47[0-7]F, Maximum number of sectors that can be transferred
+						;          per interrupt on read and write multiple commands
+						;		   (00h=Read/write multiple commands not implemented)
+				resb 1	; 47[8-15]X
+	.wDWIO		resw 1	; 48F, Can perform doubleword I/O (boolean)
+	.wCaps		resw 1	; 49FRX, Capabilities
+				resw 1	; 50R
+				resb 1	; 51[0-7]X
+	.bPioMode	resb 1	; 51[8-15]F, PIO data transfer cycle timing mode (0, 1 or 2)
+				resb 1	; 52[0-7]X
+	.bDMATiming	resb 1	; 52[8-15]F, DMA data transfer cycle timing mode
+	.wFields	resw 1	; 53FVR, Field (next words) validity bits
+
+	; Words 54-58 are valid only if bit0 is set in .wFields
+	.wCurCyls	resw 1	; 54V, Number of current cylinders
+	.wCurHeads	resw 1	; 55V, Number of current heads
+	.wCurSPT	resw 1	; 56V, Number of current sectors per track
+	.dwCurSCnt	resd 1	; 57...58V, Current capacity in sectors
+
+	; Words 59-63 are always valid
+	.bBlockSel	resb 1	; 59[0-7]V, Current setting for number of sectors that
+						;           can be transferred per interrupt on R/W multiple command
+	.bBlockFlgs	resb 1	; 59[8-15]VR, bit 0 set if Multiple sector setting is valid
+	.dwLBACnt	resd 1	; 60...61F, Total number of user addressable sectors (LBA mode only)
+	.bSDMASupp	resb 1	; 62[0-7]F, Single word DMA transfer modes supported
+	.bSDMAAct	resb 1	; 62[8-15]V, Single word DMA transfer mode active
+	.bMDMASupp	resb 1	; 63[0-7]F, Multiword DMA transfer modes supported
+	.bMDMAAct	resb 1	; 63[8-15]V, Multiword DMA transfer mode active
+endstruc
+
+A1_MODEL_NUMBER_LENGTH	EQU	40		; 40 ASCII characters
+
+; ATA-1 Word 0, General configuration
+A1_wGenCfg_NONMAG		EQU	(1<<15)	; Reserved for non-magnetic drives
+A1_wGenCfg_FGAPREQ		EQU	(1<<14)	; Format speed tolerance gap required
+A1_wGenCfg_TRCKOFF		EQU	(1<<13)	; Track offset option available
+A1_wGenCfg_DATAOFF		EQU	(1<<12)	; Data strobe offset option available
+A1_wGenCfg_ROTTOL		EQU	(1<<11)	; Rotational speed tolerance is > 0,5%
+A1_wGenCfg_XFERFAST		EQU (1<<10)	; Disk transfer rate > 10 Mbs
+A1_wGenCfg_XFERMED		EQU	(1<<9)	; Disk transfer rate > 5Mbs but <= 10Mbs
+A1_wGenCfg_XFERSLOW		EQU (1<<8)	; Disk transfer rate <= 5Mbs
+A1_wGenCfg_REMOVABLE	EQU	(1<<7)	; Removable cartridge drive
+A1_wGenCfg_FIXED		EQU	(1<<6)	; Fixed drive
+A1_wGenCfg_MOTCTRL		EQU	(1<<5)	; Spindle motor control option implemented
+A1_wGenCfg_HEADSLOW		EQU	(1<<4)	; Head switch time > 15 usec
+A1_wGenCfg_NOTMFM		EQU	(1<<3)	; Not MFM encoded
+A1_wGenCfg_SOFTSECT		EQU	(1<<2)	; Soft sectored
+A1_wGenCfg_HARDSECT		EQU	(1<<1)	; Hard sectored
+
+; ATA-1 Word 49, Capabilities
+A1_wCaps_LBA			EQU	(1<<9)	; LBA supported
+A1_wCaps_DMA			EQU	(1<<8)	; DMA supported
+
+; ATA-1 Word 53, Fields
+A1_wFields_54to58		EQU	(1<<0)	; The fields reported in words 54-58 are valid
+
+; ATA-1 Word 59 high byte, Block mode flags
+A1_bBlockFlgs_VALID		EQU	(1<<0)	; Multiple sector setting (bBlockSel) is valid
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; ATA-2 Drive Information struct
+; F = Fixed value
+; V = Variable value
+; R = Reserved word
+; X = Vendor specific word
+struc ATA2
+	.wGenCfg	resw 1	; 0F, General configuration bit-significant information
+	.wCylCnt	resw 1	; 1F, Number of logical cylinders
+				resw 1	; 2R
+	.wHeadCnt	resw 1	; 3F, Number of logical heads
+				resw 1	; 4X
+				resw 1	; 5X
+	.wSPT		resw 1	; 6F, Number of logical sectors per track
+				resw 3	; 7...9X
+	.strSerial	resb 20	; 10...19F, Serial number (20 ASCII characters, 0000h=not specified)
+				resw 1	; 20X
+				resw 1	; 21X
+	.wEccCnt	resw 1	; 22F, # of ECC bytes avail on read/write long cmds (0000h=not spec'd)
+	.strFirmW	resb 8	; 23...26F, Firmware revision (8 ASCII characters, 0000h=not specified)
+	.strModel	resb 40	; 27...46F, Model number (40 ASCII characters, 0000h=not specified)
+	.bBlckSize	resb 1	; 47[0-7]F, Maximum number of sectors that can be transferred
+						;          per interrupt on read and write multiple commands
+						;		   (00h=Read/write multiple commands not implemented)
+				resb 1	; 47[8-15]X
+				resw 1	; 48R
+	.wCaps		resw 1	; 49FRX, Capabilities
+				resw 1	; 50R
+				resb 1	; 51[0-7]X
+	.bPIOTiming	resb 1	; 51[8-15]F, PIO data transfer cycle timing mode
+				resb 1	; 52[0-7]X
+	.bDMATiming	resb 1	; 52[8-15]F, DMA data transfer cycle timing mode
+	.wFields	resw 1	; 53FVR, Field (next words) validity bits
+
+	; Words 54-58 are valid only if bit0 is set in .wFields
+	.wCurCyls	resw 1	; 54V, Number of current logical cylinders
+	.wCurHeads	resw 1	; 55V, Number of current logical heads
+	.wCurSPT	resw 1	; 56V, Number of current logical sectors per track
+	.dwCurSCnt	resd 1	; 57...58V, Current capacity in sectors
+
+	; Words 59-63 are always valid
+	.bBlockSel	resb 1	; 59[0-7]V, Current setting for number of sectors that
+						;           can be transferred per interrupt on R/W multiple command
+	.bBlockFlgs	resb 1	; 59[8-15]VR, bit 0 set if Multiple sector setting is valid
+	.dwLBACnt	resd 1	; 60...61F, Total number of user addressable sectors (LBA mode only)
+	.bSDMASupp	resb 1	; 62[0-7]F, Single word DMA transfer modes supported
+	.bSDMAAct	resb 1	; 62[8-15]V, Single word DMA transfer mode active
+	.bMDMASupp	resb 1	; 63[0-7]F, Multiword DMA transfer modes supported
+	.bMDMAAct	resb 1	; 63[8-15]V, Multiword DMA transfer mode active
+
+	; Words 64-70 are valid only if bit1 is set in .wFields (ATA2+)
+	.bPIOSupp	resb 1	; 64[0-7]F, Advanced PIO Transfer Modes Supported
+				resb 1	; 64[8-15]R
+	.wMDMAMinCy	resw 1	; 65F, Minimum Multiword DMA Transfer Cycle Time Per Word
+	.wMDMARecCy	resw 1	; 66F, Manufacturers Recommended Multiword DMA Transfer Cycle Time
+	.wPIOMinCy	resw 1	; 67F, Minimum PIO Transfer Cycle Time Without Flow Control
+	.wPIOMinCyF	resw 1	; 68F, Minimum PIO Transfer Cycle Time With IORDY Flow Control
+endstruc
+
+; ATA-2 Word 0, General configuration
+A2_wGenCfg_NONMAG		EQU	(1<<15)	; Reserved for non-magnetic drives
+A2_wGenCfg_REMOVABLE	EQU	(1<<7)	; Removable media device
+A2_wGenCfg_FIXED		EQU	(1<<6)	; Not removable controller and/or device
+
+; ATA-1 Word 49, Capabilities
+A2_wCaps_TIMER			EQU	(1<<13)	; Standby timer values as specified in this standard are supported
+A2_wCaps_IORDY			EQU	(1<<11)	; IORDY supported
+A2_wCaps_CANDISIORDY	EQU	(1<<10)	; IORDY can be disabled
+A2_wCaps_LBA			EQU	(1<<9)	; LBA supported
+A2_wCaps_DMA			EQU	(1<<8)	; DMA supported
+
+; ATA-2 Word 53, Fields
+A2_wFields_54to58		EQU	(1<<0)	; The fields reported in words 54-58 are valid
+A2_wFields_64to70		EQU	(1<<1)	; The fields reported in words 64-70 are valid
+
+; ATA-2 Word 59 high byte, Block mode flags
+A2_bBlockFlgs_VALID		EQU	(1<<0)	; Multiple sector setting (bBlockSel) is valid
+
+; ATA-2 Word 64, Advanced PIO transfer modes supported
+A2_bPIOSupp_PIO3		EQU	(1<<0)
+A2_bPIOSupp_PIO4		EQU	(1<<1)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; ATA-6 Drive Information struct
+; F = Fixed value
+; V = Variable value
+; R = Reserved word
+; X = Vendor specific word
+struc ATA6
+	.wGenCfg	resw 1	; 0F, General configuration bit-significant information
+				resw 1	; 1X, Obsolete (Number of logical cylinders)
+				resw 1	; 2V, Specific configuration
+				resw 1	; 3X, Obsolete (Number of logical heads)
+				resw 1	; 4X
+				resw 1	; 5X
+				resw 1	; 6X, Obsolete (Number of logical sectors per track)
+				resw 2	; 7...8V, Reserved for assignment by the CompactFlash Association
+				resw 1	; 9X
+	.strSerial	resb 20	; 10...19F, Serial number (20 ASCII characters, 0000h=not specified)
+				resw 1	; 20X
+				resw 1	; 21X
+				resw 1	; 22X, Obsolete (# of ECC bytes avail on read/write long cmds (0000h=not spec'd))
+	.strFirmW	resb 8	; 23...26F, Firmware revision (8 ASCII characters, 0000h=not specified)
+	.strModel	resb 40	; 27...46F, Model number (40 ASCII characters, 0000h=not specified)
+	.bBlckSize	resb 1	; 47[0-7]F, Maximum number of sectors that can be transferred
+						;           per interrupt on read and write multiple commands
+						;		    (00h=Read/write multiple commands not implemented)
+				resb 1	; 47[8-15]F, 80h
+				resw 1	; 48R
+	.wCaps		resw 1	; 49FX, Capabilities
+	.wCapsHigh	resw 1	; 50FX, Capabilities 2
+				resw 1	; 51X, Obsolete (PIO data transfer cycle timing mode)
+				resw 1	; 52X, Obsolete (DMA data transfer cycle timing mode)
+	.wFields	resw 1	; 53FX, Field (next words) validity bits
+
+	; Words 54-58 are valid only if bit0 is set in .wFields
+				resw 1	; 54X, Obsolete (Number of current logical cylinders)
+				resw 1	; 55X, Obsolete (Number of current logical heads)
+				resw 1	; 56X, Obsolete (Number of current logical sectors per track)
+				resd 1	; 57...58X, Obsolete (Current capacity in sectors)
+
+	; Words 59-63 are always valid
+	.bBlockSel	resb 1	; 59[0-7]V, Current setting for number of sectors that
+						;           can be transferred per interrupt on R/W multiple command
+	.bBlockFlgs	resb 1	; 59[8-15]VR, bit 0 set if Multiple sector setting is valid
+	.dwLBACnt	resd 1	; 60...61F, Total number of user addressable sectors (LBA-28)
+				resb 1	; 62[0-7]X, Obsolete (Single word DMA transfer modes supported)
+				resb 1	; 62[8-15]X, Obsolete (Single word DMA transfer mode active)
+	.wMDMA		resw 1	; 63FV, Multiword DMA transfer modes supported and active
+
+	; Words 64-70 are valid only if bit1 is set in .wFields (ATA2+)
+	.bPIOSupp	resb 1	; 64[0-7]F, Advanced PIO Transfer Modes Supported
+				resb 1	; 64[8-15]R
+	.wMDMAMinCy	resw 1	; 65F, Minimum Multiword DMA Transfer Cycle Time Per Word
+	.wMDMARecCy	resw 1	; 66F, Manufacturers Recommended Multiword DMA Transfer Cycle Time
+	.wPIOMinCy	resw 1	; 67F, Minimum PIO Transfer Cycle Time Without Flow Control
+	.wPIOMinCyF	resw 1	; 68F, Minimum PIO Transfer Cycle Time With IORDY Flow Control
+				resw 71-69	; 69...70R
+
+	; Words 71...74 are reserved for IDENTIFY PACKET DEVICE command
+				resw 75-71	; 71...74R
+
+	.wQueue		resw 1	; 75[0-4]F, Maximum queue depth - 1
+				resw 80-76	; 76...79R
+
+	.wMajorVer	resw 1	; 80F, Major Version Number
+	.wMinorVer	resw 1	; 81F, Minor Version Number
+	.wSetSup82	resw 1	; 82F, Command set supported
+	.wSetSup83	resw 1	; 83F, Command sets supported
+	.wSetSup84	resw 1	; 84F, Command set / Feature supported extension
+	.wEnFor82	resw 1	; 85FV, Command set / feature enabled (for word 82)
+	.wEnFor83	resw 1	; 86FV, Command set / feature enabled (for word 83)
+	.wEnFor84	resw 1	; 87FV, Command set / feature enabled (for word 84)
+
+	; Word 88 is valid only if bit2 is set in .wFields (word 53)
+	.wUDMA		resw 1	; 88FV, Ultra DMA Mode support
+
+	.wEraseTime	resw 1	; 89F, Time required for security erase unit completion
+	.wEnhErTime	resw 1	; 90F, Time required for Enhanced security erase completion
+	.wCurPower	resw 1	; 91V, Current advanced power management value
+	.wPWRev		resw 1	; 92V, Master Password Revision Code
+	.wReset		resw 1	; 93FV, Hardware reset result
+	.bCurAcous	resb 1	; 94[0-7]V, Current automatic acoustic management value
+	.bRecAcous	resb 1	; 94[8-15]V, Vendors recommended acoustic management value
+				resw 100-95		; 95...99R
+	.qwLBACnt	resb 8	; 100...103V, Total number of user addressable sectors (LBA48)
+				resw 127-104	; 104...126R
+	.wRMSN		resw 1	; 127F, Removable Media Status Notification feature set support
+	.wSecurity	resw 1	; 128FV, Security Status
+				resw 160-129	; 129...157X, Vendor Specific
+	.wCFAPower	resw 1	; 160FV, CFA Power Mode 1
+				resw 176-161	; 161...175R, Reserved for assignment by the CompactFlash Association
+	.strMediaSr	resw 206-176	; 176...205V, Current media serial number
+				resw 255-206	; 206...254R
+	.wIntegrityWord:
+	.bSignature	resb 1	; 255[0-7]X, Signature
+	.bChecksum	resb 1	; 255[8-15]X, Checksum
+endstruc
+
+; ATA-6 Word 0, General configuration
+A6_wGenCfg_REMOVABLE	EQU	(1<<7)	; Removable media device
+A6_wGenCfg_INCOMPLETE	EQU	(1<<2)	; Response incomplete
+
+; ATA-6 Word 49, Capabilities
+A6_wCaps_TIMER			EQU	(1<<13)	; Standby timer values as specified in this standard are supported
+A6_wCaps_IORDY			EQU	(1<<11)	; IORDY supported
+A6_wCaps_CANDISIORDY	EQU	(1<<10)	; IORDY can be disabled
+A6_wCaps_LBA			EQU	(1<<9)	; LBA supported
+A6_wCaps_DMA			EQU	(1<<8)	; DMA supported
+
+; ATA-6 Word 53, Fields
+A6_wFields_88			EQU	(1<<2)	; The fields reported in word 88 are valid
+A6_wFields_64to70		EQU	(1<<1)	; The fields reported in words 64-70 are valid
+
+; ATA-6 Word 59 high byte, Block mode flags
+A6_bBlockFlgs_VALID		EQU	(1<<0)	; Multiple sector setting (bBlockSel) is valid
+
+; ATA-6 Word 63, Multiword DMA Mode
+A6_wMDMA_MODE2_SELECTED	EQU	(1<<10)	; Multiword DMA mode 2 is selected
+A6_wMDMA_MODE1_SELECTED	EQU	(1<<9)	; Multiword DMA mode 1 is selected
+A6_wMDMA_MODE0_SELECTED	EQU	(1<<8)	; Multiword DMA mode 0 is selected
+A6_wMDMA_MODE2_SUPRTD	EQU	(1<<2)	; Multiword DMA mode 2 and below are supported
+A6_wMDMA_MODE1_SUPRTD	EQU	(1<<1)	; Multiword DMA mode 1 and below are supported
+A6_wMDMA_MODE0_SUPRTD	EQU	(1<<0)	; Multiword DMA mode 0 is supported
+
+; ATA-6 Word 80, Major version number
+A6_wMajorVer_ATA6		EQU	(1<<6)
+A6_wMajorVer_ATA5		EQU	(1<<5)
+A6_wMajorVer_ATA4		EQU	(1<<4)
+A6_wMajorVer_ATA3		EQU	(1<<3)
+
+; ATA-6 Word 82, Command set supported
+A6_wSetSup82_NOP		EQU	(1<<14)	; NOP command supported
+A6_wSetSup82_RDBUFF		EQU	(1<<13)	; READ BUFFER command supported
+A6_wSetSup82_WRBUFF		EQU	(1<<12)	; WRITE BUFFER command supported
+A6_wSetSup82_PROT_AREA	EQU	(1<<10)	; Host Protected Area feature set supported
+A6_wSetSup82_DEV_RESET	EQU	(1<<9)	; DEVICE RESET command supported
+A6_wSetSup82_SERVICE	EQU	(1<<8)	; SERVICE interrupt supported
+A6_wSetSup82_RELEASE	EQU	(1<<7)	; Release interrupt supported
+A6_wSetSup82_LOOKAHEAD	EQU	(1<<6)	; Look-ahead supported
+A6_wSetSup82_WRCACHE	EQU	(1<<5)	; Write cache supported
+A6_wSetSup82_POWERMAN	EQU	(1<<3)	; Power Management feature set supported
+A6_wSetSup82_REM_MEDIA	EQU	(1<<2)	; Removable Media feature set supported
+A6_wSetSup82_SECURITY	EQU	(1<<1)	; Security Mode feature set supported
+A6_wSetSup82_SMART		EQU	(1<<0)	; SMART feature set supported
+
+; ATA-6 Word 83, Command sets supported
+A6_wSetSup83_FLUSH_EXT	EQU	(1<<13)	; FLUSH CACHE EXT command supported
+A6_wSetSup83_FLUSH		EQU	(1<<12)	; FLUSH CACHE command supported
+A6_wSetSup83_CFG		EQU	(1<<11)	; Device Configuration Overlay feature set supported
+A6_wSetSup83_LBA48		EQU	(1<<10)	; 48-bit LBA feature set supported
+A6_wSetSup83_ACOUSTIC	EQU	(1<<9)	; Automatic Acoustic Management feature set supported
+A6_wSetSup83_SET_MAX	EQU	(1<<8)	; SET MAX security extension supported
+A6_wSetSup83_FEATURES	EQU	(1<<6)	; SET FEATURES subcommand required to spinup after power-up
+A6_wSetSup83_POWERUP	EQU	(1<<5)	; Power-Up In Standby feature set supported
+A6_wSetSup83_RMSN		EQU	(1<<4)	; Removable Media Status Notification feature set supported
+A6_wSetSup83_APM		EQU	(1<<3)	; Advanced Power Management feature set supported
+A6_wSetSup83_CFA		EQU	(1<<2)	; CFA feature set supported
+A6_wSetSup83_DMAQUEUED	EQU	(1<<1)	; READ/WRITE DMA QUEUED supported
+A6_wSetSup83_MICROCODE	EQU	(1<<0)	; DOWNLOAD MICROCODE command supported
+
+; ATA-6 Word 84, Command set/feature supported extension
+A6_wSetSup84_GENLOG		EQU	(1<<5)	; General Purpose Logging feature set supported
+A6_wSetSup84_MEDIAPASS	EQU	(1<<3)	; Media Card Pass Through Command feature set supported
+A6_wSetSup84_MEDIASER	EQU	(1<<2)	; Media serial number supported
+A6_wSetSup84_SMARTTEST	EQU	(1<<1)	; SMART self-test supported
+A6_wSetSup84_SMARTLOG	EQU	(1<<0)	; SMART error logging supported
+
+; ATA-6 Word 85, Command set/feature enabled (supported by word 82)
+A6_wEnFor82_NOP			EQU	(1<<14)	; NOP command enabled
+A6_wEnFor82_RDBUFF		EQU	(1<<13)	; READ BUFFER command enabled
+A6_wEnFor82_WRBUFF		EQU	(1<<12)	; WRITE BUFFER command enabled
+A6_wEnFor82_PROT_AREA	EQU	(1<<10)	; Host Protected Area feature set enabled
+A6_wEnFor82_DEV_RESET	EQU	(1<<9)	; DEVICE RESET command enabled
+A6_wEnFor82_SERVICE		EQU	(1<<8)	; SERVICE interrupt enabled
+A6_wEnFor82_RELEASE		EQU	(1<<7)	; Release interrupt enabled
+A6_wEnFor82_LOOKAHEAD	EQU	(1<<6)	; Look-ahead enabled
+A6_wEnFor82_WRCACHE		EQU	(1<<5)	; Write cache enabled
+A6_wEnFor82_POWERMAN	EQU	(1<<3)	; Power Management feature set enabled
+A6_wEnFor82_REM_MEDIA	EQU	(1<<2)	; Removable Media feature set enabled
+A6_wEnFor82_SECURITY	EQU	(1<<1)	; Security Mode feature set enabled
+A6_wEnFor82_SMART		EQU	(1<<0)	; SMART feature set enabled
+
+; ATA-6 Word 86, Command set/feature enabled (supported by word 83)
+A6_wEnFor83_FLUSH_EXT	EQU	(1<<13)	; FLUSH CACHE EXT command supported
+A6_wEnFor83_FLUSH		EQU	(1<<12)	; FLUSH CACHE command supported
+A6_wEnFor83_CFG			EQU	(1<<11)	; Device Configuration Overlay supported
+A6_wEnFor83_LBA48		EQU	(1<<10)	; 48-bit LBA feature set supported
+A6_wEnFor83_ACOUSTIC	EQU	(1<<9)	; Automatic Acoustic Management feature set enabled
+A6_wEnFor83_SET_MAX		EQU	(1<<8)	; SET MAX security extension enabled by SET MAX SET PASSWORD
+A6_wEnFor83_FEATURES	EQU	(1<<6)	; SET FEATURES subcommand required to spinup after power-up
+A6_wEnFor83_POWERUP		EQU	(1<<5)	; Power-Up In Standby feature set enabled
+A6_wEnFor83_RMSN		EQU	(1<<4)	; Removable Media Status Notification feature set enabled
+A6_wEnFor83_APM			EQU	(1<<3)	; Advanced Power Management feature set enabled
+A6_wEnFor83_CFA			EQU	(1<<2)	; CFA feature set enabled
+A6_wEnFor83_DMAQUEUED	EQU	(1<<1)	; READ/WRITE DMA QUEUED supported
+A6_wEnFor83_MICROCODE	EQU	(1<<0)	; DOWNLOAD MICROCODE command supported
+
+; ATA-6 Word 87, Command set/feature default
+A6_wEnFor84_GENLOG		EQU	(1<<5)	; General Purpose Logging feature set supported
+A6_wEnFor84_MEDIAPASS	EQU	(1<<3)	; Media Card Pass Through Command feature set enabled
+A6_wEnFor84_MEDIASER	EQU	(1<<2)	; Media serial number is valid
+A6_wEnFor84_SMARTTEST	EQU	(1<<1)	; SMART self-test supported
+A6_wEnFor84_SMARTLOG	EQU	(1<<0)	; SMART error logging supported
+
+; ATA-6 Word 88, Ultra DMA Mode
+A6_wUDMA_MODE5_SELECTED	EQU	(1<<13)	; Ultra DMA mode 5 is selected
+A6_wUDMA_MODE4_SELECTED	EQU	(1<<12)	; Ultra DMA mode 4 is selected
+A6_wUDMA_MODE3_SELECTED	EQU	(1<<11)	; Ultra DMA mode 3 is selected
+A6_wUDMA_MODE2_SELECTED	EQU	(1<<10)	; Ultra DMA mode 2 is selected
+A6_wUDMA_MODE1_SELECTED	EQU	(1<<9)	; Ultra DMA mode 1 is selected
+A6_wUDMA_MODE0_SELECTED	EQU	(1<<8)	; Ultra DMA mode 0 is selected
+A6_wUDMA_MODE5_SUPRTD	EQU	(1<<5)	; Ultra DMA mode 5 and below are supported
+A6_wUDMA_MODE4_SUPRTD	EQU	(1<<4)	; Ultra DMA mode 4 and below are supported
+A6_wUDMA_MODE3_SUPRTD	EQU	(1<<3)	; Ultra DMA mode 3 and below are supported
+A6_wUDMA_MODE2_SUPRTD	EQU	(1<<2)	; Ultra DMA mode 2 and below are supported
+A6_wUDMA_MODE1_SUPRTD	EQU	(1<<1)	; Ultra DMA mode 1 and below are supported
+A6_wUDMA_MODE0_SUPRTD	EQU	(1<<0)	; Ultra DMA mode 0 is supported
+
+; ATA-6 Word 93, Hardware reset result
+A6_wReset_CBLID_BELOW	EQU	(1<<13)	; Device detected CBLID- above ViH
+A6_wReset_DEV1_PDIAG	EQU	(1<<11)	; Device 1 asserted PDIAG-
+A6_wReset_DEV0_RESP_D1	EQU	(1<<6)	; Device 0 responds when Device 1 is selected
+A6_wReset_DEV0_DASP		EQU	(1<<5)	; Device 0 detected the assertion of DASP-
+A6_wReset_DEV0_PDIAG	EQU	(1<<4)	; Device 0 detected the assertion of PDIAG
+A6_wReset_DEV0_PASSED	EQU	(1<<3)	; Device 0 passed diagnostics
+A6_wReset_MASK_DEV1_DETERMINE	EQU ((1<<10)|(1<<9))	; These bits indicate how Device 1 determined the device number
+A6_wReset_MASK_DEV0_DETERMINE	EQU ((1<<2)|(1<<1))		; These bits indicate how Device 0 determined the device number:
+A6_wReset_RESERVED		EQU	00b
+A6_wReset_JUMPER		EQU	01b		; a jumper was used
+A6_wReset_CSEL			EQU	10b		; the CSEL signal was used
+A6_wReset_UNKNOWN		EQU	11b		; some other method was used or the method is unknown
+
+; ATA-6 Word 127, Removable Media Status Notification feature set support
+A6_wRMSN_SUPPORTED		EQU	(1<<0)	; Removable Media Status Notification feature supported
+
+; ATA-6 Word 128, Security status
+A6_wSecurity_MAX		EQU	(1<<8)	; Security level 0 = High, 1 = Maximum
+A6_wSecurity_ENH_ERASE	EQU	(1<<5)	; Enhanced security erase supported
+A6_wSecurity_EXPIRED	EQU	(1<<4)	; Security count expired
+A6_wSecurity_FROZEN		EQU	(1<<3)	; Security frozen
+A6_wSecurity_LOCKED		EQU	(1<<2)	; Security locked
+A6_wSecurity_ENABLED	EQU	(1<<1)	; Security enabled
+A6_wSecurity_SUPPORTED	EQU	(1<<0)	; Security supported
+
+; ATA-6 Word 160, CFA Power Mode 1
+A6_wCFAPower_WORDSUPP	EQU	(1<<15)	; Word 160 supported
+A6_wCFAPower_REQUIRED	EQU	(1<<13)	; CFA power mode 1 is required for one or more commands implemented by the device
+A6_wCFAPower_DISABLED	EQU	(1<<12)	; CFA power mode 1 disabled
+A6_wCFAPower_MASK_mA	EQU	0FFFh	; Maximum current in mA
+
+; ATA-6 WORD 255, Integrity Word (Signature and Checksum)
+A6_wIntegrity_SIGNATURE	EQU	0A5h
+
+
+%endif ; ATA_ID_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/BootMenu.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/BootMenu.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/BootMenu.inc	(revision 516)
@@ -0,0 +1,34 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates and structs used in Boot Menu.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef BOOTMENU_INC
+%define BOOTMENU_INC
+
+; Boot menu sizes
+BOOT_MENU_DEFAULT_TIMEOUT				EQU	(30 * TICKS_PER_SECOND)
+BOOT_MENU_TITLE_LINES					EQU	2	; Number of title lines
+BOOT_MENU_INFO_LINES					EQU	3	; Number of info lines
+BOOT_MENU_SEPARATOR_LINES_PLUS_SHADOW	EQU	5
+BOOT_MENU_TITLE_AND_INFO_LINES			EQU	(BOOT_MENU_TITLE_LINES | (BOOT_MENU_INFO_LINES<<8))
+BOOT_MENU_WIDTH							EQU	40	; Menu width in characters (including shadow)
+BOOT_MENU_HEIGHT_WITHOUT_ITEMS			EQU	(BOOT_MENU_TITLE_LINES + BOOT_MENU_INFO_LINES + BOOT_MENU_SEPARATOR_LINES_PLUS_SHADOW)
+MENU_SCREEN_BOTTOM_LINES				EQU	1
+
+
+%endif ; BOOTMENU_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/BootVars.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/BootVars.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/BootVars.inc	(revision 516)
@@ -0,0 +1,186 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Defines for BOOTVARS struct used by boot menu
+;					and drive initialization.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef BOOTVARS_INC
+%define BOOTVARS_INC
+
+; Default drives
+DEFAULT_FLOPPY_DRIVE_LETTER				EQU	'A'
+DEFAULT_HARD_DRIVE_LETTER				EQU	'C'
+
+; Number of times to retry booting before accepting error
+BOOT_READ_RETRY_TIMES		EQU		3
+
+
+
+; Pre-boot variables. These do not exist after successful boot to OS.
+; Segment is always 0000h, same as BDA segment
+struc BOOTVARS
+						resb	7C00h
+	.rgbAtaInfo:						; 7C00h, ATA Information for drive detection
+	.rgbBootSect		resb 	512		; 7C00h, Boot sector
+						resb	256		; Boot Menu stack
+	.rgbMnuStack:
+	.dwPostStack		resb	4		; POST stack pointer when entering INT 19h
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	.wNextXTCFportToScan	resb	2	; Needed for XT-CF port autodetection
+%endif
+
+	.clearToZeroFromThisPoint:
+%ifdef MODULE_HOTKEYS
+	.hotkeyVars				resb	HOTKEYVARS_size
+%endif
+
+	.rgDrvDetectInfo:					; Array containing DRVDETECTINFO structs
+endstruc
+
+%ifdef MODULE_HOTKEYS
+
+struc HOTKEYVARS
+	.wTimeToClose		resb	2		; Earliest system time when Hotkey Bar can be closed
+	.wFddAndHddLetters:
+	.bFddLetter			resb	1		; Floppy Drive letter hotkey (upper case)
+	.bHddLetter			resb	1		; Hard Drive letter hotkey (upper case)
+	.bFlags				resb	1		; Must be just after .bHddLetter!  (dependency in Hotkeybar.asm)
+	.bScancode			resb	1		; Function hotkey scancode, must be just after .bFlags!
+endstruc
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if HOTKEYVARS.bFddLetter+1 != HOTKEYVARS.bHddLetter || HOTKEYVARS.bHddLetter+1 != HOTKEYVARS.bFlags || HOTKEYVARS.bFlags+1 != HOTKEYVARS.bScancode 
+%error "HOTKEYVARS: bytes need to come in the order .bFddLetter, then .bHddLetter, then .bFlags, then .bScancode"
+%endif
+%endif
+
+; Bit defines for KEYBOARDVARS.bFlags
+FLG_HOTKEY_HD_FIRST		EQU		(1<<0)	; First try to boot from HDD, then FDD
+
+%endif ; MODULE_HOTKEYS
+
+struc DRVDETECTINFO
+	.StartOfDrvDetectInfo:
+	.szDrvName				resb	MAX_HARD_DISK_NAME_LENGTH
+							resb	2	; Zero word (ensures string terminates)
+	.wInitErrorFlags		resb	2	; Errors during initialization
+
+	; DRVDETECTINFO's size must be an even multiple of DPT's size
+	.EndOfDriveDetectInfo:	resb	LARGEST_DPT_SIZE - (.EndOfDriveDetectInfo % LARGEST_DPT_SIZE)
+endstruc
+
+; Boot Menu Information Table. These are generated for all XTIDE Universal
+; BIOS drives. Available only until boot is successful.
+MAX_HARD_DISK_NAME_LENGTH			EQU		30		; Bytes reserved for drive name
+DPT_DRVDETECTINFO_SIZE_MULTIPLIER	EQU		DRVDETECTINFO_size / LARGEST_DPT_SIZE
+
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+
+%if MAX_HARD_DISK_NAME_LENGTH % 2 <> 0
+	%error "MAX_HARD_DISK_NAME_LENGTH needs to be a multiple of 2, memory is moved with word operations."
+%endif
+
+%if DRVDETECTINFO_size % LARGEST_DPT_SIZE <> 0
+	%error "DRVDETECTINFO's size must be an even multiple of DPT's size.  Add or remove padding at the bottom of DRVDETECTINFO to bring the two sizes into alignment.  As DRVDETECTINFO is only used at boot time, with plenty of memory to consume, it is OK to waste some space here."
+%endif
+
+%if DRVDETECTINFO.szDrvName <> 0
+	%error "DRVDETECTINFO.szDrvName is assumed to be the first member of struc DRVDETECTINFO, in BootMenuPrint_RefreshItem"
+%endif
+
+%endif
+
+
+;--------------------------------------------------------------------
+; Stores POST stack pointer to BOOTVARS.
+;
+; STORE_POST_STACK_POINTER
+;	Parameters:
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro STORE_POST_STACK_POINTER 0
+	mov		[es:BOOTVARS.dwPostStack], sp
+	mov		[es:BOOTVARS.dwPostStack+2], ss
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Initializes stack for boot menu usage.
+; POST stack is not large enough when DPTs are stored to 30:0h.
+;
+; Note regarding LOAD_BDA_SEGMENT_TO: If you force the use of SP
+; then you also have to unconditionally enable the CLI/STI pair.
+; The reason for this is that only some buggy 808x CPU:s need the
+; CLI/STI instruction pair when changing stacks. Other CPU:s disable
+; interrupts automatically when SS is modified for the duration of
+; the immediately following instruction to give time to change SP.
+;
+; SWITCH_TO_BOOT_MENU_STACK
+;	Parameters:
+;		Nothing
+;	Returns:
+;		SS:SP:	Pointer to top of Boot Menu stack
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro SWITCH_TO_BOOT_MENU_STACK 0
+%ifndef USE_186
+	cli									; Disable interrupts
+%endif
+	LOAD_BDA_SEGMENT_TO	ss, sp
+	mov		sp, BOOTVARS.rgbMnuStack	; Load offset to stack
+%ifndef USE_186
+	sti									; Enable interrupts
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Restores SS and SP to initial boot loader values.
+;
+; Note! Must return with AX=0 and CF preserved.
+; See Int19hMenu_JumpToBootSector_or_RomBoot.
+;
+; SWITCH_BACK_TO_POST_STACK
+;	Parameters:
+;		AX:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		SS:SP:	Ptr to POST stack
+;	Corrupts registers:
+;		Nothing (not even FLAGS)
+;--------------------------------------------------------------------
+%macro SWITCH_BACK_TO_POST_STACK 0
+%ifndef USE_386
+	cli
+	mov		ss, ax
+	mov		sp, [ss:BOOTVARS.dwPostStack]
+	mov		ss, [ss:BOOTVARS.dwPostStack+2]
+	sti
+%else
+	mov		ss, ax
+	lss		sp, [ss:BOOTVARS.dwPostStack]
+%endif
+%endmacro
+
+
+%endif ; BOOTVARS_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/JRIDE_ISA.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/JRIDE_ISA.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/JRIDE_ISA.inc	(revision 516)
@@ -0,0 +1,29 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	JR-IDE/ISA specifications.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef JRIDEISA_INC
+%define JRIDEISA_INC
+
+JRIDE_DEFAULT_SEGMENT_ADDRESS				EQU	0D800h
+JRIDE_SECTOR_ACCESS_WINDOW_OFFSET			EQU	3C00h	; 512 byte IDE Sector Access Window
+JRIDE_COMMAND_BLOCK_REGISTER_WINDOW_OFFSET	EQU	3E00h	; 8 byte CS0 IDE Register Window
+JRIDE_CONTROL_BLOCK_REGISTER_WINDOW_OFFSET	EQU	3E08h	; 8 byte CS1 IDE Register Window
+
+
+%endif ; JRIDEISA_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/Vision.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/Vision.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/Vision.inc	(revision 516)
@@ -0,0 +1,97 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	QDI Vision QD6500 and QD6580 VLB IDE controller
+;					specifications.
+;
+;					Specifications can be found at http://www.ryston.cz/petr/vlb/vlbidechips.html
+;					QD6580 DOS Driver Analysis: http://www.ryston.cz/petr/qd/dos37.html
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef VISION_INC
+%define VISION_INC
+
+; Possible base addresses for QD6500 and QD6580
+QD65XX_BASE_PORT					EQU		30h
+QD65XX_ALTERNATIVE_BASE_PORT		EQU		0B0h
+
+
+; Vision Register offsets from QD chip base port
+QD6500_IDE_TIMING_REGISTER				EQU	0
+QD6580_PRIMARY_IDE_TIMING_REGISTER		EQU	0		; QD6500 has only one channel
+QD65XX_CONFIG_REGISTER_in				EQU	1
+QD6580_SECONDARY_IDE_TIMING_REGISTER	EQU	2		; Same definitions as Primary IDE Timing Register
+QD6580_CONTROL_REGISTER					EQU	3
+
+
+; Bit definitions for QD65xx IDE Timing Register(s)
+MASK_QD6500IDE_ACTIVE_TIME				EQU	7h		; Active time in VLB clocks (bits 0...2)
+													; 000b = 8 clocks (<= 33 MHz), 9 clocks (>33 MHz)
+													; 111b = 1 clock (<= 33 MHz), 2 clocks (>33 MHz)
+MASK_QD6580IDE_ACTIVE_TIME				EQU	0Fh		; Active time in VLB clocks (bits 0...3)
+													; 0000b = 17 clocks, 1111b = 2 clocks
+
+MASK_QD6500IDE_RECOVERY_TIME			EQU	0F0h	; Recovery time in VLB clocks (bits 4...7)
+													; 0000b = 18 clocks (<= 33 MHz), 15 clocks (>33 MHz)
+													; 1111b = 3 clocks (<= 33 MHz), 0 clocks (>33 MHz)
+MASK_QD6580IDE_RECOVERY_TIME			EQU	MASK_QD6500IDE_RECOVERY_TIME
+													; 0000b = 15 clocks, 1101b = 2 clocks
+POSITON_QD65XXIDE_RECOVERY_TIME			EQU	4
+
+
+; Bit definitions for QD65xx Config Register (read only)
+FLG_QDCONFIG_PRIMARY_IDE				EQU	(1<<0)	; IDE Controller Base Address
+													; 0 = 170h, 1 = 1F0h
+FLG_QDCONFIG_ALTERNATIVE_BASE			EQU	(1<<1)	; QD Vision Controller Base Address
+													; 0 = 30h, 1 = B0h
+FLG_QDCONFIG_ID3						EQU	(1<<2)	; VLB bus speed
+													; 0 = > 33 MHz, 1 = <= 33 MHz
+FLG_QDCONFIG_QD6500STATUS				EQU	(1<<3)	; QD6500 Enabled/Disabled status
+													; 0 = Enabled, 1 = Disabled
+MASK_QDCONFIG_CONTROLLER_ID				EQU	0F0h	; QDI Vision Controller Identification nibble
+
+; QDI Vision Controller Identification nibbles
+ID_QD6500								EQU	1100b
+ID_QD6580								EQU	1010b
+ID_QD6580_ALTERNATE						EQU	0101b
+
+
+; Bit definitions for QD6580 Control Register
+FLG_QDCONTROL_SECONDARY_DISABLED_in		EQU	(1<<0)	; 0 = Primary and Secondary IDE enabled (Primary at 1F0h and Secondary at 170h)
+													; 1 = Only Primary IDE enabled (always at 1F0h)
+FLG_QDCONTROL_HDONLY_in					EQU	(1<<1)	; 0 = Hard drive or ATAPI device
+													; 1 = Hard drives only
+FLG_QDCONTROL_NONATAPI					EQU	(1<<7)	; Set to 1 for non-ATAPI devices (hard drives,
+													; probably Read ahead and/or post-write control?)
+MASK_QDCONTROL_FLAGS_TO_SET			EQU	01011111b	; Bits that must be set when writing the Control Register
+
+
+
+; Minimum and Maximum Active and Recovery Time Values
+QD6500_MAX_ACTIVE_TIME_CLOCKS			EQU	8		; VLB clocks
+QD6500_MIN_ACTIVE_TIME_CLOCKS			EQU	1		; VLB clocks
+QD6580_MAX_ACTIVE_TIME_CLOCKS			EQU	17		; VLB clocks
+QD6580_MIN_ACTIVE_TIME_CLOCKS			EQU	2		; VLB clocks
+QD65xx_MAX_RECOVERY_TIME_CLOCKS			EQU	15		; VLB clocks
+QD65xx_MIN_RECOVERY_TIME_CLOCKS			EQU	2		; VLB clocks
+
+
+; Cycle times for different VLB bus clocks
+VLB_33MHZ_CYCLE_TIME					EQU	30		; ns
+VLB_40MHZ_CYCLE_TIME					EQU	25		; ns
+
+
+%endif ; VISION_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/XTCF.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/XTCF.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Controllers/XTCF.inc	(revision 516)
@@ -0,0 +1,91 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Lo-tech XT-CFv2 board specifications.
+;
+;					More information at http://www.lo-tech.co.uk/wiki/Lo-tech_XT-CFv2_Board
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef XTCF_INC
+%define XTCF_INC
+
+DEFAULT_XTCF_SECTOR_WINDOW_SEGMENT	EQU		0D800h
+
+; XT-CF requires that block must be less than 128 sectors (64 kiB).
+; Instead of limiting block size to 64, we limit it to 32 (16 kiB).
+; Transferring more than 16 kiB with 8237 DMA controller block or demand
+; mode might interfere with DRAM refresh on XT systems.
+XTCF_DMA_MODE_MAX_BLOCK_SIZE		EQU		32		; Sectors
+
+; Possible base addresses. Note that all XT-CF IDE registers are SHL 1 compared
+; to standard IDE registers.
+XTCF_BASE_PORT_DETECTION_SEED		EQU		140h	; Not a valid base address but needed for autodetection
+XTCF_BASE_PORT_1					EQU		200h
+XTCF_BASE_PORT_2					EQU		240h
+XTCF_BASE_PORT_3					EQU		300h	; Default setting
+XTCF_BASE_PORT_4					EQU		340h
+
+
+; XT-CF Control Register (do not SHL 1 these!)
+XTCF_CONTROL_REGISTER				EQU		1Fh
+XTCF_CONTROL_REGISTER_INVERTED_in	EQU		1Eh
+
+; Control Register contents:
+;
+; Control Register holds high byte from Sector Window segment if >= A0h
+; (First possible segment for Sector Window is A000h)
+;
+; 8-bit PIO transfers (port I/O) are used if Control Register is zero.
+; Any other value means DMA transfers (using DMA channel 3).
+XTCF_8BIT_PIO_MODE						EQU		0
+XTCF_DMA_MODE							EQU		10h
+XTCF_MEMORY_MAPPED_MODE					EQU		0A0h
+RAISE_DRQ_AND_CLEAR_XTCF_XFER_COUNTER	EQU		40h
+
+
+
+; Subcommands for AH=1Eh, Lo-tech XT-CF features.
+; Return values common for all subcommands:
+;		AH:		RET_HD_SUCCESS if drive is XT-CF
+;				RET_HD_INVALID if drive is not XT-CF
+;		CF:		0 if successful, 1 if error
+
+;--------------------------------------------------------------------
+; IS_THIS_DRIVE_XTCF
+;	Parameters:
+;		DL:		Drive Number
+;--------------------------------------------------------------------
+IS_THIS_DRIVE_XTCF					EQU		0
+
+;--------------------------------------------------------------------
+; READ_XTCF_CONTROL_REGISTER_TO_DH
+;	Parameters:
+;		DL:		Drive Number
+;	Returns:
+;		DH:		XT-CF Control Register contents
+;--------------------------------------------------------------------
+READ_XTCF_CONTROL_REGISTER_TO_DH	EQU		1
+
+;--------------------------------------------------------------------
+; WRITE_DH_TO_XTCF_CONTROL_REGISTER
+;	Parameters:
+;		DH:		Byte to write to XT-CF Control Register
+;		DL:		Drive Number
+;--------------------------------------------------------------------
+WRITE_DH_TO_XTCF_CONTROL_REGISTER	EQU		2
+
+
+%endif ; XTCF_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/CustomDPT.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/CustomDPT.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/CustomDPT.inc	(revision 516)
@@ -0,0 +1,156 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Defines for DPT structs containing custom
+;					Disk Parameter Table used by this BIOS.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef CUSTOMDPT_INC
+%define CUSTOMDPT_INC
+
+; Base DPT for all device types
+struc DPT
+	; General Disk Parameter Table related
+	.wFlags:
+	.bFlagsLow				resb	1
+	.bFlagsHigh				resb	1
+	.bIdevarsOffset			resb	1	; Offset to IDEVARS for this drive
+	.bInitError				resb	1	; Flags for AH=09h initialization errors
+	.wBasePort				resb	2	; Segment for JR-IDE/ISA
+
+	; CHS variables
+	.wLchsCylinders			resb	2	; (1...1027, yes 1027)
+	.wLchsHeadsAndSectors:
+	.bLchsHeads				resb	1	; (1...255)
+	.bLchsSectorsPerTrack	resb	1	; (1...63)
+	.bPchsHeads				resb	1	; (1...16)
+
+	; LBA and remaining P-CHS variables
+%ifdef MODULE_EBIOS
+	.bPchsSectorsPerTrack	resb	1
+	.wPchsCylinders			resb	2
+	.twLbaSectors			resb	6	; 48-bit sector count for LBA addressing
+%endif
+							alignb	2	; WORD alignment for DPT_SERIAL or DPT_ATA
+endstruc
+
+	; Bit definitions for DPT.bFlagsLow
+	MASKL_DPT_CHS_SHIFT_COUNT			EQU	(3<<0)				; Bits 0...1, P-CHS to L-CHS bit shift count (0...3)
+	MASKL_DPT_TRANSLATEMODE				EQU	MASK_DRVPARAMS_TRANSLATEMODE	; Bits 2...3, NORMAL, LARGE or Assisted LBA addressing mode
+	FLGL_DPT_ASSISTED_LBA				EQU	(1<<(TRANSLATEMODE_FIELD_POSITION+1))
+	FLGL_DPT_SLAVE						EQU	FLG_DRVNHEAD_DRV	; Bit 4, Drive is a Slave Drive
+%ifdef MODULE_IRQ
+	FLGL_DPT_ENABLE_IRQ					EQU	(1<<5)				; Bit 5, Enable IRQ
+%endif
+%ifdef MODULE_EBIOS
+	FLGL_DPT_LBA_AND_EBIOS_SUPPORTED	EQU	FLG_DRVNHEAD_LBA	; Bit 6, Drive supports LBA and so EBIOS functions can be supported
+	FLGL_DPT_LBA48						EQU	(1<<7)				; Bit 7, Drive supports 48-bit LBA (Must be bit 7!)
+%endif
+
+
+	; Bit definitions for DPT.bFlagsHigh
+	FLGH_DPT_BLOCK_MODE_SUPPORTED		EQU	(1<<1)	; Bit 1, Use block transfer commands (must be bit 1!)
+%ifdef MODULE_SERIAL
+	FLGH_DPT_SERIAL_DEVICE				EQU	(1<<2)	; Bit 2, Serial Port Device
+%endif
+%ifdef MODULE_IRQ
+	FLGH_DPT_INTERRUPT_IN_SERVICE		EQU	(1<<3)	; Bit 3, Set when waiting for IRQ
+%endif
+%ifdef MODULE_FEATURE_SETS
+	FLGH_DPT_POWER_MANAGEMENT_SUPPORTED	EQU (1<<5)	; Bit 5, Drive supports power management
+%endif
+%ifdef MODULE_ADVANCED_ATA
+	FLGH_DPT_IORDY						EQU	(1<<7)	; Bit 7, Controller and Drive supports IORDY
+%endif
+
+	; Serial device only
+%ifdef MODULE_SERIAL_FLOPPY
+	FLGH_DPT_SERIAL_FLOPPY						EQU	(1<<4)
+	FLGH_DPT_SERIAL_FLOPPY_TYPE_MASK			EQU	0e0h
+	FLGH_DPT_SERIAL_FLOPPY_TYPE_FIELD_POSITION	EQU	5
+%endif
+
+
+	; Flags for DPT_ADVANCED_ATA.bInitError
+	FLG_INITERROR_FAILED_TO_SELECT_DRIVE				EQU (1<<0)
+	FLG_INITERROR_FAILED_TO_INITIALIZE_CHS_PARAMETERS	EQU (1<<1)
+	FLG_INITERROR_FAILED_TO_SET_WRITE_CACHE				EQU (1<<2)
+	FLG_INITERROR_FAILED_TO_RECALIBRATE_DRIVE			EQU (1<<3)
+	FLG_INITERROR_FAILED_TO_SET_BLOCK_MODE				EQU (1<<4)
+	FLG_INITERROR_FAILED_TO_SET_PIO_MODE				EQU (1<<5)
+	FLG_INITERROR_FAILED_TO_INITIALIZE_STANDBY_TIMER	EQU	(1<<6)
+	FLG_INITERROR_FAILED_TO_SET_XTCF_MODE				EQU	(1<<7)
+	FLG_INITERROR_FAILED_TO_SET_8BIT_MODE				EQU	FLG_INITERROR_FAILED_TO_SET_XTCF_MODE
+
+
+
+; DPT for ATA devices
+struc DPT_ATA
+	.dpt					resb	DPT_size
+	.bDevice				resb	1	; Device Type from IDEVARS (overrided when 32-bit controller detected)
+	.bBlockSize				resb	1	; Current block size in sectors (do not set to zero!)
+endstruc
+
+
+
+; Additional variables needed to initialize and reset Advanced IDE Controllers.
+; EBDA must be reserved for DPTs when using these!
+%ifdef MODULE_ADVANCED_ATA
+struc DPT_ADVANCED_ATA
+	.dpt_ata				resb	DPT_ATA_size
+	.wControllerID			resb	2	; Controller specific ID WORD (from Advanced Controller detection)
+	.wControllerBasePort	resb	2	; Advanced Controller port (not IDE port)
+	.wMinPioCycleTime		resb	2	; Minimum PIO Cycle Time in ns
+	.bPioMode				resb	1	; Best supported PIO mode
+							alignb	2
+endstruc
+%endif
+
+
+; DPT for Serial devices
+%ifdef MODULE_SERIAL
+struc DPT_SERIAL
+	.dpt					resb	DPT_size
+	.wSerialPortAndBaud:
+	.bSerialPort			resb	1	; Serial connection I/O port address, divided by 4
+	.bSerialBaud			resb 	1	; Serial connection baud rate divisor
+endstruc
+
+; On performance critical situations we compare DPT_ATA.bDevice without checking FLGH_DPT_SERIAL_DEVICE
+; first! DPT_ATA.bDevice uses small values so there will be no problems.
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if DPT_SERIAL.bSerialPort <> DPT_ATA.bDevice
+		%error "DPT_ATA.bDevice and DPT_SERIAL.bSerialPort must be in same offsets!"
+	%endif
+%endif
+%endif ; MODULE_SERIAL
+
+
+; This is the common size for all DPTs. All DPTs must be equal size.
+%ifdef MODULE_ADVANCED_ATA
+	LARGEST_DPT_SIZE			EQU		DPT_ADVANCED_ATA_size
+%else
+	LARGEST_DPT_SIZE			EQU		DPT_ATA_size
+%endif
+
+
+	; Number of Sectors per Track is fixed to 63 for LBA assist calculation.
+	; 1024 cylinders, 256 heads, 63 sectors = 8.4 GB limit (but DOS does not support more than 255 heads)
+	MAX_LCHS_CYLINDERS			EQU		1024
+	LBA_ASSIST_SPT				EQU		63
+
+
+%endif ; CUSTOMDPT_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/DeviceIDE.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/DeviceIDE.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/DeviceIDE.inc	(revision 516)
@@ -0,0 +1,41 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Device specific equates for IDE drives.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef DEVICEIDE_INC
+%define DEVICEIDE_INC
+
+; Reset delays
+HSR0_RESET_WAIT_US		EQU		6		; Delay must be at least 5 us
+HSR1_RESET_WAIT_US		EQU		2100	; Delay must be at least 2 ms
+
+; Polling timeout delays (system timer ticks, 1 tick = 54.9 ms)
+TIMEOUT_DRQ				EQU		255			;   14 s (some CF cards occasionally have long write delays)
+TIMEOUT_SELECT_DRIVE_DURING_DRIVE_DETECTION	EQU	(500/55)	;  500 ms
+TIMEOUT_MOTOR_STARTUP	EQU		(10000/55)	;   10 s
+TIMEOUT_MAXIMUM			EQU		255			; We would actually want 31 seconds here but I don't think there are so slow drives
+
+%ifdef MODULE_FEATURE_SETS
+	TIMEOUT_BSY			EQU		TIMEOUT_MOTOR_STARTUP
+	TIMEOUT_DRDY		EQU		TIMEOUT_MOTOR_STARTUP
+%else
+	TIMEOUT_BSY			EQU		(2600/55)	; 2600 ms
+	TIMEOUT_DRDY		EQU		(2600/55)	; 2600 ms
+%endif
+
+%endif ; DEVICEIDE_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/DmaController.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/DmaController.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/DmaController.inc	(revision 516)
@@ -0,0 +1,202 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates for 8237 DMA Controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef DMA_CONTROLLER_INC
+%define DMA_CONTROLLER_INC
+
+; 8237 Master (8-bit) and Slave (16-bit) DMA Controller Ports
+
+; Page Registers
+PAGE_DMA8_CH_1		EQU		83h
+PAGE_DMA8_CH_2		EQU		81h
+PAGE_DMA8_CH_3		EQU		82h
+PAGE_DMA16_CH_5		EQU		8Bh		; AT+
+PAGE_DMA16_CH_6		EQU		89h		; AT+
+PAGE_DMA16_CH_7		EQU		8Ah		; AT+
+
+; Base and Current Address Registers
+BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH1_out	EQU		02h
+BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH2_out	EQU		04h
+BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out	EQU		06h
+BASE_AND_CURRENT_ADDRESS_REGISTER_DMA16_CH5_out	EQU		0C4h	; AT+
+BASE_AND_CURRENT_ADDRESS_REGISTER_DMA16_CH6_out	EQU		0C8h	; AT+
+BASE_AND_CURRENT_ADDRESS_REGISTER_DMA16_CH7_out	EQU		0CCh	; AT+
+CURRENT_ADDRESS_REGISTER_DMA8_CH1_in			EQU		02h
+CURRENT_ADDRESS_REGISTER_DMA8_CH2_in			EQU		04h
+CURRENT_ADDRESS_REGISTER_DMA8_CH3_in			EQU		06h
+CURRENT_ADDRESS_REGISTER_DMA16_CH5_in			EQU		0C4h	; AT+
+CURRENT_ADDRESS_REGISTER_DMA16_CH6_in			EQU		0C8h	; AT+
+CURRENT_ADDRESS_REGISTER_DMA16_CH7_in			EQU		0CCh	; AT+
+
+; Base and Current Count Registers
+BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH1_out	EQU		03h
+BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH2_out	EQU		05h
+BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out	EQU		07h
+BASE_AND_CURRENT_COUNT_REGISTER_DMA16_CH5_out	EQU		0C6h	; AT+
+BASE_AND_CURRENT_COUNT_REGISTER_DMA16_CH6_out	EQU		0CAh	; AT+
+BASE_AND_CURRENT_COUNT_REGISTER_DMA16_CH7_out	EQU		0CEh	; AT+
+CURRENT_COUNT_REGISTER_DMA8_CH1_in				EQU		03h
+CURRENT_COUNT_REGISTER_DMA8_CH2_in				EQU		05h
+CURRENT_COUNT_REGISTER_DMA8_CH3_in				EQU		07h
+CURRENT_COUNT_REGISTER_DMA16_CH5_in				EQU		0C6h	; AT+
+CURRENT_COUNT_REGISTER_DMA16_CH6_in				EQU		0CAh	; AT+
+CURRENT_COUNT_REGISTER_DMA16_CH7_in				EQU		0CEh	; AT+
+
+; Command Registers (Command Value used by PCs is 0)
+COMMAND_REGISTER_DMA8_out		EQU		08h
+COMMAND_REGISTER_DMA16_out		EQU		0D0h	; AT+
+	MEM_TO_MEM_XFERS_DISABLE	EQU		0
+	MEM_TO_MEM_XFERS_ENABLE		EQU		(1<<0)
+
+	CH0_ADDRESS_HOLD_DISABLE	EQU		0
+	CH0_ADDRESS_HOLD_ENABLE		EQU		(1<<1)	; When MEM_TO_MEM_XFERS_ENABLE
+
+	CONTROLLER_ENABLE			EQU		0
+	CONTROLLER_DISABLE			EQU		(1<<2)	; Instead of Controller Enable
+
+	NORMAL_TIMING				EQU		0
+	COMPRESSED_TIMING			EQU		(1<<3)	; Instead of Normal Timing when MEM_TO_MEM_XFERS_DISABLE
+
+	FIXED_PRIORITY				EQU		0
+	ROTATING_PRIORITY			EQU		(1<<4)	; Instead of Fixed Priority
+
+	LATE_WRITE_SELECTION		EQU		0
+	EXTENDED_WRITE_SELECTION	EQU		(1<<5)	; Instead of Late Write Selection
+
+	DREQ_SENSE_ACTIVE_HIGH		EQU		0
+	DREQ_SENSE_ACTIVE_LOW		EQU		(1<<6)	; Instead of DREQ Sense Active High
+
+	DACK_SENSE_ACTIVE_LOW		EQU		0
+	DACK_SENSE_ACTIVE_HIGH		EQU		(1<<7)	; Instead of DACK Sense Active Low
+
+
+; Status Registers (reading will clear Terminal Count flags)
+STATUS_REGISTER_DMA8_in			EQU		COMMAND_REGISTER_DMA8_out
+	FLG_CH1_HAS_REACHED_TERMINAL_COUNT		EQU		(1<<1)
+	FLG_CH2_HAS_REACHED_TERMINAL_COUNT		EQU		(1<<2)
+	FLG_CH3_HAS_REACHED_TERMINAL_COUNT		EQU		(1<<3)
+	FLG_CH1_REQUEST							EQU		(1<<5)
+	FLG_CH2_REQUEST							EQU		(1<<6)
+	FLG_CH3_REQUEST							EQU		(1<<7)
+STATUS_REGISTER_DMA16_in		EQU		COMMAND_REGISTER_DMA16_out	; AT+
+	FLG_CH5_HAS_REACHED_TERMINAL_COUNT		EQU		(1<<1)
+	FLG_CH6_HAS_REACHED_TERMINAL_COUNT		EQU		(1<<2)
+	FLG_CH7_HAS_REACHED_TERMINAL_COUNT		EQU		(1<<3)
+	FLG_CH5_REQUEST							EQU		(1<<5)
+	FLG_CH6_REQUEST							EQU		(1<<6)
+	FLG_CH7_REQUEST							EQU		(1<<7)
+
+
+; Request Registers (Software DMA Request)
+REQUEST_REGISTER_DMA8_out		EQU		09h
+	FLG_SET_REQUEST		EQU		(1<<2)
+	CLEAR_CH1_REQUEST	EQU		CHANNEL_1
+	CLEAR_CH2_REQUEST	EQU		CHANNEL_2
+	CLEAR_CH3_REQUEST	EQU		CHANNEL_3
+	SET_CH1_REQUEST		EQU		(CHANNEL_1 | FLG_SET_REQUEST)
+	SET_CH2_REQUEST		EQU		(CHANNEL_2 | FLG_SET_REQUEST)
+	SET_CH3_REQUEST		EQU		(CHANNEL_3 | FLG_SET_REQUEST)
+REQUEST_REGISTER_DMA16_out		EQU		0D2h	; AT+
+	CLEAR_CH5_REQUEST	EQU		CLEAR_CH1_REQUEST
+	CLEAR_CH6_REQUEST	EQU		CLEAR_CH2_REQUEST
+	CLEAR_CH7_REQUEST	EQU		CLEAR_CH3_REQUEST
+	SET_CH5_REQUEST		EQU		SET_CH1_REQUEST
+	SET_CH6_REQUEST		EQU		SET_CH2_REQUEST
+	SET_CH7_REQUEST		EQU		SET_CH3_REQUEST
+
+
+; Mask Registers (setting a mask bit disables DMA channel)
+MASK_REGISTER_DMA8_out			EQU		0Ah
+	FLG_SET_MASK		EQU		FLG_SET_REQUEST
+	CLEAR_CH1_MASK_BIT	EQU		CLEAR_CH1_REQUEST
+	CLEAR_CH2_MASK_BIT	EQU		CLEAR_CH2_REQUEST
+	CLEAR_CH3_MASK_BIT	EQU		CLEAR_CH3_REQUEST
+	SET_CH1_MASK_BIT	EQU		SET_CH1_REQUEST
+	SET_CH2_MASK_BIT	EQU		SET_CH2_REQUEST
+	SET_CH3_MASK_BIT	EQU		SET_CH3_REQUEST
+MASK_REGISTER_DMA16_out			EQU		0D4h	; AT+
+	CLEAR_CH5_MASK_BIT	EQU		CLEAR_CH5_REQUEST
+	CLEAR_CH6_MASK_BIT	EQU		CLEAR_CH6_REQUEST
+	CLEAR_CH7_MASK_BIT	EQU		CLEAR_CH7_REQUEST
+	SET_CH5_MASK_BIT	EQU		SET_CH5_REQUEST
+	SET_CH6_MASK_BIT	EQU		SET_CH6_REQUEST
+	SET_CH7_MASK_BIT	EQU		SET_CH7_REQUEST
+
+
+; Mode Registers
+MODE_REGISTER_DMA8_out			EQU		0Bh
+	; Select channel number (bits 0...1)
+	CHANNEL_1			EQU		1
+	CHANNEL_2			EQU		2
+	CHANNEL_3			EQU		3
+MODE_REGISTER_DMA16_out			EQU		0D6h	; AT+
+	CHANNEL_5			EQU		CHANNEL_1
+	CHANNEL_6			EQU		CHANNEL_2
+	CHANNEL_7			EQU		CHANNEL_3
+	; Transfer type (bits 2...3)
+	VERIFY				EQU		(0<<2)
+	WRITE				EQU		(1<<2)	; To memory
+	READ				EQU		(2<<2)	; From memory
+	; Autoinitialization enable/disable (bit 4)
+	AUTOINIT_DISABLE	EQU		0
+	AUTOINIT_ENABLE		EQU		(1<<4)	; Instead of autoinitialization disable
+	; Address increment/decrement select (bit 5)
+	ADDRESS_INCREMENT	EQU		0
+	ADDRESS_DECREMENT	EQU		(1<<5)	; Instead of address increment
+	; Mode type selection (bits 6...7)
+	DEMAND_MODE			EQU		(0<<6)
+	SINGLE_MODE			EQU		(1<<6)
+	BLOCK_MODE			EQU		(2<<6)
+	CASCADE_MODE		EQU		(3<<6)
+
+
+; Clear Byte Flip-Flops (any byte resets low/high byte flip-flop to low)
+CLEAR_FLIPFLOP_DMA8_out			EQU		0Ch
+CLEAR_FLIPFLOP_DMA16_out		EQU		0D8h	; AT+
+
+
+; Temporary Registers
+TEMP_REGISTER_DMA8_in			EQU		0Dh
+TEMP_REGISTER_DMA16_in			EQU		0DAh	; AT+
+
+
+; Master Clear (any byte does the same as hardware reset)
+MASTER_CLEAR_DMA8_out			EQU		TEMP_REGISTER_DMA8_in
+MASTER_CLEAR_DMA16_out			EQU		TEMP_REGISTER_DMA16_in	; AT+
+
+
+; Clear all mask bits (any byte enables all DMA channels)
+CLEAR_ALL_MASK_BITS_DMA8_out	EQU		0Eh
+CLEAR_ALL_MASK_BITS_DMA16_out	EQU		0DCh	; AT+
+
+
+; Write All Mask Bits
+WRITE_ALL_MASK_BITS_DMA8_out	EQU		0Fh
+	ALL_MASK_BITS_SET_CH0		EQU		(1<<0)
+	ALL_MASK_BITS_SET_CH1		EQU		(1<<CHANNEL_1)
+	ALL_MASK_BITS_SET_CH2		EQU		(1<<CHANNEL_2)
+	ALL_MASK_BITS_SET_CH3		EQU		(1<<CHANNEL_3)
+WRITE_ALL_MASK_BITS_DMA16_out	EQU		0DEh	; AT+
+	ALL_MASK_BITS_SET_CH4		EQU		ALL_MASK_BITS_SET_CH0
+	ALL_MASK_BITS_SET_CH5		EQU		(1<<CHANNEL_5)
+	ALL_MASK_BITS_SET_CH6		EQU		(1<<CHANNEL_6)
+	ALL_MASK_BITS_SET_CH7		EQU		(1<<CHANNEL_7)
+
+
+%endif ; DMA_CONTROLLER_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/EBIOS.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/EBIOS.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/EBIOS.inc	(revision 516)
@@ -0,0 +1,70 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates used in Enhanced INT 13h functions (EBIOS).
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef EBIOS_INC
+%define EBIOS_INC
+
+; EBIOS specification returned by INT 13h, AH=41h
+EBIOS_VERSION						EQU	21h		; 21h = EDD version 1.1
+
+; Support bits returned by INT 13h, AH=41h
+ENHANCED_DRIVE_ACCESS_SUPPORT		EQU	(1<<0)	; 41h, 42h, 43h 44h, 47h and 48h are available
+DRIVE_LOCKING_AND_EJECTING_SUPPORT	EQU	(1<<1)	; 41h, 45h, 46h, 48h, 49h are available and INT 15h, AH=52h
+ENHANCED_DISK_DRIVE_SUPPORT			EQU	(1<<2)	; 41h, 48h, 4Eh are available (EDD)
+
+
+; Extended Drive Information returned by AH=48h
+struc EDRIVE_INFO
+	.wSize					resb	2	; 0, Size of this buffer, at least 26
+	.wFlags					resb	2	; 2, Information flags
+	.dwCylinders			resb	4	; 4, Total number of addressable cylinders
+	.dwHeads				resb	4	; 8, Total number of addressable heads
+	.dwSectorsPerTrack		resb	4	; 12, Number of sectors per track
+	.qwTotalSectors			resb	8	; 16, Total number of addressable sectors
+	.wSectorSize			resb	2	; 24, Number of bytes per sector
+	.fpEDDparams			resb	8	; 26, Optional pointer to Enhanced Disk Drive (EDD) configuration parameters
+endstruc
+
+MINIMUM_EDRIVEINFO_SIZE		EQU		26	; 26 bytes does not include EDD pointer
+
+; Flags for EDRIVE_INFO.wFlags
+FLG_DMA_BOUNDARY_ERRORS_HANDLED_BY_BIOS				EQU	(1<<0)
+FLG_CHS_INFORMATION_IS_VALID						EQU	(1<<1)
+FLG_REMOVABLE_DRIVE									EQU	(1<<2)
+FLG_WRITE_WITH_VERIFY_SUPPORTED						EQU	(1<<3)
+FLG_CHANGE_LINE_SUPPORT								EQU	(1<<4)	; Removable media only
+FLG_LOCKABLE										EQU	(1<<5)	; Removable media only
+FLG_NO_MEDIA_PRESENT_AND_CHS_SET_TO_MAX				EQU	(1<<6)	; Removable media only
+
+
+; Disk Address Packet for read, write and verify functions
+struc DAP
+	.bSize					resb	1	; 0, Size of this packet in bytes
+	.bReservedAt1			resb	1	; 1, Currently unused, must be zero
+	.wSectorCount			resb	2	; 2, Number of sectors to process (0...127)
+	.dwMemoryAddress:
+	.wOffset				resb	2	; 4, Memory offset for transfer
+	.wSegment				resb	2	; 6, Memory segment for transfer
+	.qwLBA					resb	8	; 8, Starting sector for transfer
+endstruc
+
+MINIMUM_DAP_SIZE			EQU		16
+
+
+%endif ; EBIOS_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/HotkeyBar.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/HotkeyBar.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/HotkeyBar.inc	(revision 516)
@@ -0,0 +1,35 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates and structs used in Hotkey Bar.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef HOTKEYBAR_INC
+%define HOTKEYBAR_INC
+
+MIN_TIME_TO_DISPLAY_HOTKEY_BAR			EQU	(2000/55)	; 2000 ms
+
+ROM_BOOT_HOTKEY_SCANCODE				EQU	42h	; F8
+
+%ifdef MODULE_BOOT_MENU
+BOOT_MENU_HOTKEY_SCANCODE				EQU	3Ch	; F2
+%endif
+
+%ifdef MODULE_SERIAL
+COM_DETECT_HOTKEY_SCANCODE				EQU	40h	; F6
+%endif
+
+%endif ; HOTKEYBAR_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc	(revision 516)
@@ -0,0 +1,159 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Macros for accessing data port(s) on 8-bit
+;					IDE controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef IDE_8BIT_INC
+%define IDE_8BIT_INC
+
+;--------------------------------------------------------------------
+; UNROLL_SECTORS_IN_CX_TO_DWORDS
+; UNROLL_SECTORS_IN_CX_TO_QWORDS
+; UNROLL_SECTORS_IN_CX_TO_OWORDS
+;	Parameters:
+;		CX:		Number of sectors in block
+;	Returns:
+;		CX:		Number of DWORDs, QWORDs or OWORDs in block
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro UNROLL_SECTORS_IN_CX_TO_DWORDS 0
+%ifdef USE_186
+	shl		cx, 7
+%else
+	xchg	cl, ch		; Sectors to WORDs (SHL CX, 8)
+	shr		cx, 1
+%endif
+%endmacro
+
+%macro UNROLL_SECTORS_IN_CX_TO_QWORDS 0
+%ifdef USE_186
+	shl		cx, 6
+%else
+	UNROLL_SECTORS_IN_CX_TO_DWORDS
+	shr		cx, 1
+%endif
+%endmacro
+
+%macro UNROLL_SECTORS_IN_CX_TO_OWORDS 0
+%ifdef USE_186
+	shl		cx, 5
+%else
+;	UNROLL_SECTORS_IN_CX_TO_QWORDS
+;	shr		cx, 1
+	mov		ch, cl		; 2 bytes shorter but possibly slower
+	mov		cl, 3
+	shr		cx, cl
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates INSW for XTIDE.
+;
+; XTIDE_INSW
+;	Parameters:
+;		BL:		Bit mask for toggling XTIDE data low/high reg
+;		DX:		XTIDE Data Low Register address
+;		ES:DI:	Ptr to destination buffer
+;	Returns:
+;		ES:DI:	Incremented/decremented for next word
+;	Corrupts registers:
+;		AL, FLAGS
+;--------------------------------------------------------------------
+%macro XTIDE_INSW 0
+%ifdef USE_186	; INS instruction available
+	insb						; Load low byte from port DX to [ES:DI]
+	xor		dl, bl				; IDE Data Reg to XTIDE Data High Reg
+	insb						; Load high byte from port DX to [ES:DI]
+	xor		dl, bl				; Restore to IDE Data Register
+%else	; If 8088/8086
+	in		al, dx				; Load low byte from port
+	xor		dl, bl				; IDE Data Reg to XTIDE Data High Reg
+	stosb						; Store byte to [ES:DI]
+	in		al, dx				; Load high byte from port
+	xor		dl, bl				; Restore to IDE Data Register
+	stosb						; Store byte to [ES:DI]
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates OUTSW for XTIDE.
+;
+; XTIDE_OUTSW
+;	Parameters:
+;		BL:		Bit mask for toggling XTIDE data low/high reg
+;		DX:		XTIDE Data Low Register address
+;		DS:SI:	Ptr to source buffer
+;	Returns:
+;		SI:		Incremented/decremented for next word
+;	Corrupts registers:
+;		AX, FLAGS
+;--------------------------------------------------------------------
+%macro XTIDE_OUTSW 0
+%ifdef USE_186	; OUTS instruction available
+	lodsb						; Load low byte from [DS:SI] to AL
+	xor		dl, bl				; IDE Data Reg to XTIDE Data High Reg
+	outsb						; Output high byte from [DS:SI]
+	xor		dl, bl				; XTIDE Data High Reg to Data Low Reg
+	out		dx, al				; Output low byte from AL
+%else	; If 8088/8086
+	lodsw						; Load word from [DS:SI]
+	xor		dl, bl				; IDE Data Reg to XTIDE Data High Reg
+	xchg	al, ah				; => AL=high byte, AH=low byte
+	out		dx, al				; Output high byte
+	xor		dl, bl				; XTIDE Data High Reg to Data Low Reg
+	mov		al, ah				; Copy low byte to AL
+	out		dx, al				; Output low byte
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates OUTSW for modified XTIDE.
+;
+; XTIDE_MOD_OUTSW
+;	Parameters:
+;		DX:		XTIDE Data Low Register address
+;		DS:SI:	Ptr to source buffer
+;	Returns:
+;		SI:		Incremented/decremented for next word
+;	Corrupts registers:
+;		AX, FLAGS
+;--------------------------------------------------------------------
+%macro XTIDE_MOD_OUTSW 0
+%ifdef USE_186	; OUTS instruction available
+	lodsb						; Load low byte from [DS:SI] to AL
+	inc		dx					; IDE Data Reg to XTIDE MOD Data High Reg
+	outsb						; Output high byte from [DS:SI]
+	dec		dx					; XTIDE Data High Reg to Data Low Reg
+	out		dx, al				; Output low byte from AL
+%else	; If 8088/8086
+	lodsw						; Load word from [DS:SI]
+	inc		dx					; IDE Data Reg to XTIDE MOD Data High Reg
+	xchg	al, ah				; => AL=high byte, AH=low byte
+	out		dx, al				; Output high byte
+	dec		dx					; XTIDE Data High Reg to Data Low Reg
+	mov		al, ah				; Copy low byte to AL
+	out		dx, al				; Output low byte
+%endif
+%endmacro
+
+
+%endif ; IDE_8BIT_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IdeIO.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IdeIO.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IdeIO.inc	(revision 516)
@@ -0,0 +1,107 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Macros for normal I/O mapped ATA controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef IDE_IO_INC
+%define IDE_IO_INC
+
+;--------------------------------------------------------------------
+; OUTPUT_AL_TO_IDE_REGISTER
+; OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER
+;	Parameters:
+;		AL:		Byte to output
+;		%1:		IDE Register				(OUTPUT_AL_TO_IDE_REGISTER)
+;				IDE Control Block Register	(OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+%macro OUTPUT_AL_TO_IDE_REGISTER 1
+%ifndef MODULE_8BIT_IDE	; Standard IDE controllers only
+
+	%ifnidni %1, dx
+		mov		dx, %1
+	%endif
+	add		dx, [di+DPT.wBasePort]
+	out		dx, al
+
+%else	; Register translations required
+
+	%ifnidni %1, dl
+		mov		dl, %1
+	%endif
+	call	IdeIO_OutputALtoIdeRegisterInDL
+
+%endif
+%endmacro
+
+
+%macro OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER 1
+%ifndef MODULE_8BIT_IDE	; Standard IDE controllers only
+
+	%ifnidni %1, dx
+		mov		dx, %1
+	%endif
+	eMOVZX	bx, BYTE [di+DPT.bIdevarsOffset]
+	add		dx, [cs:bx+IDEVARS.wControlBlockPort]
+	out		dx, al
+
+%else	; Register translations required
+
+	%ifnidni %1, dl
+		mov		dl, %1
+	%endif
+	call	IdeIO_OutputALtoIdeControlBlockRegisterInDL
+
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; INPUT_TO_AL_FROM_IDE_REGISTER
+;	Parameters:
+;		%1:		IDE Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AL:		Inputted byte
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+%macro INPUT_TO_AL_FROM_IDE_REGISTER 1
+%ifndef MODULE_8BIT_IDE	; Standard IDE controllers only
+
+	%ifnidni %1, dx
+		mov		dx, %1
+	%endif
+	add		dx, [di+DPT.wBasePort]
+	in		al, dx
+
+%else	; Register translations required
+
+	%ifnidni %1, dl
+		mov		dl, %1
+	%endif
+		call	IdeIO_InputToALfromIdeRegisterInDL
+
+%endif
+%endmacro
+
+
+%endif ; IDE_IO_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc	(revision 516)
@@ -0,0 +1,113 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates for IDE registers, flags and commands.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef IDEREGISTERS_INC
+%define IDEREGISTERS_INC
+
+; IDE Register offsets from Command Block base port
+DATA_REGISTER					EQU		0
+ERROR_REGISTER_in				EQU		1		; Read only
+FEATURES_REGISTER_out			EQU		1		; Write only, ATA1+
+;WRITE_PRECOMPENSATION_out		EQU		1		; Write only, Obsolete on ATA1+
+SECTOR_COUNT_REGISTER			EQU		2
+SECTOR_NUMBER_REGISTER			EQU		3		; LBA Low Register
+LOW_CYLINDER_REGISTER			EQU		4		; LBA Middle Register
+HIGH_CYLINDER_REGISTER			EQU		5		; LBA High Register
+LBA_LOW_REGISTER				EQU		3		; LBA 7...0, LBA48 31...24
+LBA_MIDDLE_REGISTER				EQU		4		; LBA 15...8, LBA48 39...32
+LBA_HIGH_REGISTER				EQU		5		; LBA 23...16, LBA48 47...40
+DRIVE_AND_HEAD_SELECT_REGISTER	EQU		6		; LBA28 27...24
+STATUS_REGISTER_in				EQU		7		; Read only
+COMMAND_REGISTER_out			EQU		7		; Write only
+;XTIDE_DATA_HIGH_REGISTER		EQU		8		; Non-standard (actually first Control Block reg)
+
+; IDE Register offsets from Control Block base port
+; (usually Command Block base port + 200h)
+ALTERNATE_STATUS_REGISTER_in	EQU		6		; Read only
+DEVICE_CONTROL_REGISTER_out		EQU		6		; Write only
+;DRIVE_ADDRESS_REGISTER			EQU		7		; Obsolete on ATA2+
+
+; Bit mask for XTIDE mod with reversed A0 and A3 address lines
+MASK_A3_AND_A0_ADDRESS_LINES	EQU		((1<<3) | (1<<0))
+
+; Bit definitions for IDE Error Register
+FLG_ERROR_BBK			EQU		(1<<7)	; Bad Block Detected (reserved on ATA2+, command dependent on ATA4+)
+FLG_ERROR_UNC			EQU		(1<<6)	; Uncorrectable Data Error (command dependent on ATA4+)
+FLG_ERROR_MC			EQU		(1<<5)	; Media Changed (command dependent on ATA4+)
+FLG_ERROR_IDNF			EQU		(1<<4)	; ID Not Found (command dependent on ATA4+)
+FLG_ERROR_MCR			EQU		(1<<3)	; Media Change Request (command dependent on ATA4+)
+FLG_ERROR_ABRT			EQU		(1<<2)	; Command Aborted
+FLG_ERROR_TK0NF			EQU		(1<<1)	; Track 0 Not Found (command dependent on ATA4+)
+FLG_ERROR_AMNF			EQU		(1<<0)	; Address Mark Not Found (command dependent on ATA4+)
+
+; Bit definitions for IDE Drive and Head Select Register
+FLG_DRVNHEAD_LBA		EQU		(1<<6)	; LBA Addressing enabled (instead of CHS)
+FLG_DRVNHEAD_DRV		EQU		(1<<4)	; Drive Select (0=Master, 1=Slave)
+MASK_DRVNHEAD_HEAD		EQU		0Fh		; Head select bits (bits 0...3)
+MASK_DRVNHEAD_SET		EQU		0A0h	; Bits that must be set to 1 on ATA1 (reserved on ATA2+)
+
+; Bit definitions for IDE Status Register
+FLG_STATUS_BSY			EQU		(1<<7)	; Busy (other flags undefined when set)
+FLG_STATUS_DRDY			EQU		(1<<6)	; Device Ready
+FLG_STATUS_DF			EQU		(1<<5)	; Device Fault (command dependent on ATA4+)
+FLG_STATUS_DSC			EQU		(1<<4)	; Device Seek Complete (command dependent on ATA4+)
+FLG_STATUS_DRQ			EQU		(1<<3)	; Data Request
+FLG_STATUS_CORR			EQU		(1<<2)	; Corrected Data (obsolete on ATA4+)
+FLG_STATUS_IDX			EQU		(1<<1)	; Index (vendor specific on ATA2+, obsolete on ATA4+)
+FLG_STATUS_ERR			EQU		(1<<0)	; Error
+
+; Bit definitions for IDE Device Control Register
+; Bit 0 must be zero, unlisted bits are reserved.
+;FLG_DEVCONTROL_HOB		EQU		(1<<7)	; High Order Byte (ATA6+)
+;FLG_DEVCONTROL_O8H		EQU		(1<<3)	; Drive has more than 8 heads (pre-ATA only, 1 on ATA1, reserved on ATA2+)
+FLG_DEVCONTROL_SRST		EQU		(1<<2)	; Software Reset
+FLG_DEVCONTROL_nIEN		EQU		(1<<1)	; Negated Interrupt Enable (IRQ disabled when set)
+
+; Commands for IDE Controller
+COMMAND_RECALIBRATE						EQU		10h
+COMMAND_READ_SECTORS					EQU		20h
+COMMAND_READ_SECTORS_EXT				EQU		24h		; LBA48
+COMMAND_WRITE_SECTORS					EQU		30h
+COMMAND_WRITE_SECTORS_EXT				EQU		34h		; LBA48
+COMMAND_VERIFY_SECTORS					EQU		40h
+COMMAND_VERIFY_SECTORS_EXT				EQU		42h		; LBA48
+COMMAND_SEEK							EQU		70h
+COMMAND_INITIALIZE_DEVICE_PARAMETERS	EQU		91h
+COMMAND_SET_MULTIPLE_MODE				EQU		0C6h	; Block mode
+COMMAND_READ_MULTIPLE					EQU		0C4h	; Block mode
+COMMAND_READ_MULTIPLE_EXT				EQU		29h		; LBA48, Block mode
+COMMAND_WRITE_MULTIPLE					EQU		0C5h	; Block mode
+COMMAND_WRITE_MULTIPLE_EXT				EQU		39h		; LBA48, Block mode
+COMMAND_IDENTIFY_DEVICE					EQU		0ECh
+COMMAND_SET_FEATURES					EQU		0EFh
+COMMAND_IDLE							EQU		0E3h
+
+
+; Subcommands for COMMAND_SET_FEATURES
+FEATURE_ENABLE_8BIT_PIO_TRANSFER_MODE	EQU		01h		; CFA feature set only
+FEATURE_ENABLE_WRITE_CACHE				EQU		02h
+FEATURE_DISABLE_8BIT_PIO_TRANSFER_MODE	EQU		81h		; CFA feature set only
+FEATURE_DISABLE_WRITE_CACHE				EQU		82h		; Can also be used to flush cache
+FEATURE_SET_TRANSFER_MODE				EQU		03h		; Transfer mode goes to the Sector Count Register
+	PIO_DEFAULT_MODE					EQU		0h
+	PIO_DEFAULT_MODE_DISABLE_IORDY		EQU		1h
+	PIO_FLOW_CONTROL_MODE_xxx			EQU		(1<<3)	; Bits 2...0 hold the PIO mode
+
+
+%endif ; IDEREGISTERS_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Int13h.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Int13h.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Int13h.inc	(revision 516)
@@ -0,0 +1,67 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates used in INT 13h functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef INT13H_INC
+%define INT13H_INC
+
+; Hard Disk function (INT 13h) return status codes in AH
+RET_HD_SUCCESS			EQU		0h		; Operation successful, no error occurred
+RET_HD_INVALID			EQU		1h		; Invalid value passed or unsupported func
+RET_HD_ADDRMARK			EQU		2h		; Missing address mark
+RET_HD_WRITEPROT		EQU		3h		; Removable media is write protected
+RET_HD_NOT_FOUND		EQU		4h		; Requested sector not found
+RET_HD_RESETFAIL		EQU		5h		; Reset failed
+RET_HD_CHANGED			EQU		6h		; Media changed
+RET_HD_PARAMACT			EQU		7h		; Drive parameter activity failed
+RET_HD_OVERRUN			EQU		8h		; DMA overrun
+RET_HD_BOUNDARY			EQU		9h		; Data boundary error
+RET_HD_BADSECTOR		EQU		0Ah		; Bad sector detected
+RET_HD_BADTRACK			EQU		0Bh		; Bad track detected
+RET_HD_UNCORRECC		EQU		10h		; Uncorrectable ECC error
+RET_HD_ECC				EQU		11h		; Corrected ECC error
+RET_HD_CONTROLLER		EQU		20h		; Hard disk controller or drive problem
+RET_HD_NOMEDIA			EQU		31h		; No media in removable media drive
+RET_HD_SEEK_FAIL		EQU		40h		; Seek operation failed
+RET_HD_TIMEOUT			EQU		80h		; Drive failed to respond
+RET_HD_NOTREADY			EQU		0AAh	; Drive is not ready or is not selected
+RET_HD_NOTLOCKED		EQU		0B0h	; Volume not locked in drive
+RET_HD_LOCKED			EQU		0B1h	; Volume locked in drive
+RET_HD_NOTREMOVABLE		EQU		0B2h	; Volume not removable
+RET_HD_INUSE			EQU		0B3h	; Volume in use
+RET_HD_LOCKEXCEEDED		EQU		0B4h	; Lock count exceeded
+RET_HD_EJECTFAIL		EQU		0B5h	; Valid eject request failed
+RET_HD_UNDEFINED		EQU		0BBh	; Undefined error occurred
+RET_HD_WRFAULT			EQU		0CCh	; Write fault on selected drive
+RET_HD_STATUSERR		EQU		0E0h	; Status error without error
+RET_HD_SENSEFAIL		EQU		0FFh	; Sense operation failed
+
+
+; Floppy Drive types returned by INT 13h, AH=08h
+FLOPPY_TYPE_525_OR_35_DD	EQU	0
+FLOPPY_TYPE_525_DD			EQU	1
+FLOPPY_TYPE_525_HD			EQU	2
+FLOPPY_TYPE_35_DD			EQU	3
+FLOPPY_TYPE_35_HD			EQU	4
+FLOPPY_TYPE_35_ED			EQU	6
+
+
+%define TIMEOUT_AND_STATUS_TO_WAIT(timeout, status)		(((timeout)<<8) | (status))
+
+
+%endif ; INT13H_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IntController.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IntController.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/IntController.inc	(revision 516)
@@ -0,0 +1,69 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates for 8259 Interrupt Controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef INT_CONTROLLER_INC
+%define INT_CONTROLLER_INC
+
+; 8259 Master and Slave Interrupt Controller Ports
+MASTER_8259_IRR_AND_ISR_in	EQU		20h		; Interrupt Request Register / Interrupt In-Service Register
+MASTER_8259_COMMAND_out		EQU		20h		; Command output
+MASTER_8259_IMR				EQU		21h		; Interrupt Mask Register
+MASTER_8259_INIT_out		EQU		21h		; Initialization Command Parameters
+SLAVE_8259_IRR_AND_ISR_in	EQU		0A0h	; Interrupt Request Register / Interrupt In-Service Register
+SLAVE_8259_COMMAND_out		EQU		0A0h	; Command output
+SLAVE_8259_IMR				EQU		0A1h	; Interrupt Mask Register
+SLAVE_8259_INIT_out			EQU		0A1h	; Initialization Command Parameters
+
+; 8259 Interrupt Controller Commands
+COMMAND_CLEAR_ROTATE_IN_AUTOMATIC_EOI_MODE	EQU		00h
+COMMAND_READ_INTERRUPT_REQUEST_REGISTER		EQU		0Ah
+COMMAND_READ_INTERRUPT_INSERVICE_REGISTER	EQU		0Bh
+COMMAND_END_OF_INTERRUPT					EQU		20h
+COMMAND_NO_OPERATION						EQU		40h
+COMMAND_CLEAR_SPECIAL_MASK_MODE				EQU		48h
+COMMAND_SPECIFIC_EOI_FOR_IR0				EQU		60h
+COMMAND_SPECIFIC_EOI_FOR_IR1				EQU		61h
+COMMAND_SPECIFIC_EOI_FOR_IR2				EQU		62h
+COMMAND_SPECIFIC_EOI_FOR_IR3				EQU		63h
+COMMAND_SPECIFIC_EOI_FOR_IR4				EQU		64h
+COMMAND_SPECIFIC_EOI_FOR_IR5				EQU		65h
+COMMAND_SPECIFIC_EOI_FOR_IR6				EQU		66h
+COMMAND_SPECIFIC_EOI_FOR_IR7				EQU		67h
+COMMAND_SET_SPECIAL_MASK_MODE				EQU		68h
+COMMAND_SET_ROTATE_IN_AUTOMATIC_EOI_MODE	EQU		80h
+COMMAND_ROTATE_ON_NONSPECIFIC_EOI			EQU		0A0h
+COMMAND_IR0_LOWEST_PRIORITY					EQU		0C0h
+COMMAND_IR1_LOWEST_PRIORITY					EQU		0C1h
+COMMAND_IR2_LOWEST_PRIORITY					EQU		0C2h
+COMMAND_IR3_LOWEST_PRIORITY					EQU		0C3h
+COMMAND_IR4_LOWEST_PRIORITY					EQU		0C4h
+COMMAND_IR5_LOWEST_PRIORITY					EQU		0C5h
+COMMAND_IR6_LOWEST_PRIORITY					EQU		0C6h
+COMMAND_IR7_LOWEST_PRIORITY					EQU		0C7h
+COMMAND_EOI_AND_IR0_LOWEST_PRIORITY			EQU		0E0h
+COMMAND_EOI_AND_IR1_LOWEST_PRIORITY			EQU		0E1h
+COMMAND_EOI_AND_IR2_LOWEST_PRIORITY			EQU		0E2h
+COMMAND_EOI_AND_IR3_LOWEST_PRIORITY			EQU		0E3h
+COMMAND_EOI_AND_IR4_LOWEST_PRIORITY			EQU		0E4h
+COMMAND_EOI_AND_IR5_LOWEST_PRIORITY			EQU		0E5h
+COMMAND_EOI_AND_IR6_LOWEST_PRIORITY			EQU		0E6h
+COMMAND_EOI_AND_IR7_LOWEST_PRIORITY			EQU		0E7h
+
+
+%endif ; INT_CONTROLLER_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/ModuleDependency.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/ModuleDependency.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/ModuleDependency.inc	(revision 516)
@@ -0,0 +1,131 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Dependencies for optional modules.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifdef MODULE_SERIAL_FLOPPY
+	%ifndef MODULE_SERIAL
+		%define MODULE_SERIAL
+	%endif
+%endif
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	%define MODULE_8BIT_IDE
+	%include "DmaController.inc"
+	%include "XTCF.inc"				; For Lo-tech XT-CF
+	%include "JRIDE_ISA.inc"		; For JR-IDE/ISA
+%endif
+
+; Include module specific .INC files
+%ifdef MODULE_8BIT_IDE
+	%include "IDE_8bit.inc"			; For IDE 8-bit data port macros
+%endif
+
+%ifdef MODULE_ADVANCED_ATA
+	%include "Vision.inc"			; For QDI Vision QD65xx VLB IDE Controllers
+%endif
+
+%ifdef MODULE_EBIOS
+	%include "EBIOS.inc"			; Equates for EBIOS functions
+%endif
+
+%ifdef MODULE_HOTKEYS
+	%include "HotkeyBar.inc"		; For Hotkeys
+%endif
+
+%ifdef MODULE_BOOT_MENU
+	%include "BootMenu.inc"			; For Boot Menu
+%endif
+
+%ifdef MODULE_BOOT_MENU OR MODULE_HOTKEYS
+	%define MODULE_DRIVEXLATE
+%endif
+
+%ifdef MODULE_IRQ
+	%include "IntController.inc"
+%endif
+
+
+; Included modules for ROMVARS.wFlags
+%ifdef MODULE_8BIT_IDE
+	MAIN_FLG_MODULE_8BIT_IDE	EQU	FLG_ROMVARS_MODULE_8BIT_IDE
+%else
+	MAIN_FLG_MODULE_8BIT_IDE	EQU	0
+%endif
+
+%ifdef MODULE_ADVANCED_ATA
+	MAIN_FLG_MODULE_ADVANCED_ATA	EQU	FLG_ROMVARS_MODULE_ADVANCED_ATA
+%else
+	MAIN_FLG_MODULE_ADVANCED_ATA	EQU	0
+%endif
+
+%ifdef MODULE_BOOT_MENU
+	MAIN_FLG_MODULE_BOOT_MENU	EQU	FLG_ROMVARS_MODULE_BOOT_MENU
+%else
+	MAIN_FLG_MODULE_BOOT_MENU	EQU	0
+%endif
+
+%ifdef MODULE_EBIOS
+	MAIN_FLG_MODULE_EBIOS	EQU	FLG_ROMVARS_MODULE_EBIOS
+%else
+	MAIN_FLG_MODULE_EBIOS	EQU	0
+%endif
+
+%ifdef MODULE_HOTKEYS
+	MAIN_FLG_MODULE_HOTKEYS	EQU	FLG_ROMVARS_MODULE_HOTKEYS
+%else
+	MAIN_FLG_MODULE_HOTKEYS	EQU	0
+%endif
+
+%ifdef MODULE_IRQ
+	MAIN_FLG_MODULE_IRQ		EQU	FLG_ROMVARS_MODULE_IRQ
+%else
+	MAIN_FLG_MODULE_IRQ		EQU	0
+%endif
+
+%ifdef MODULE_SERIAL
+	MAIN_FLG_MODULE_SERIAL	EQU	FLG_ROMVARS_MODULE_SERIAL
+%else
+	MAIN_FLG_MODULE_SERIAL	EQU	0
+%endif
+
+%ifdef MODULE_SERIAL_FLOPPY
+	MAIN_FLG_MODULE_SERIAL_FLOPPY	EQU	FLG_ROMVARS_MODULE_SERIAL_FLOPPY
+%else
+	MAIN_FLG_MODULE_SERIAL_FLOPPY	EQU	0
+%endif
+
+%ifdef MODULE_STRINGS_COMPRESSED
+	MAIN_FLG_MODULE_STRINGS_COMPRESSED	EQU	FLG_ROMVARS_MODULE_STRINGS_COMPRESSED
+%else
+	MAIN_FLG_MODULE_STRINGS_COMPRESSED	EQU	0
+%endif
+
+%ifdef MODULE_FEATURE_SETS
+	MAIN_FLG_MODULE_FEATURE_SETS	EQU	FLG_ROMVARS_MODULE_FEATURE_SETS
+%else
+	MAIN_FLG_MODULE_FEATURE_SETS	EQU	0
+%endif
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	MAIN_FLG_MODULE_8BIT_IDE_ADVANCED	EQU	FLG_ROMVARS_MODULE_8BIT_IDE_ADVANCED
+%else
+	MAIN_FLG_MODULE_8BIT_IDE_ADVANCED	EQU	0
+%endif
+
+MASK_ROMVARS_INCLUDED_MODULES	EQU	MAIN_FLG_MODULE_8BIT_IDE | MAIN_FLG_MODULE_ADVANCED_ATA | MAIN_FLG_MODULE_BOOT_MENU | MAIN_FLG_MODULE_EBIOS | MAIN_FLG_MODULE_HOTKEYS | MAIN_FLG_MODULE_IRQ | MAIN_FLG_MODULE_SERIAL | MAIN_FLG_MODULE_SERIAL_FLOPPY | MAIN_FLG_MODULE_STRINGS_COMPRESSED | MAIN_FLG_MODULE_FEATURE_SETS | MAIN_FLG_MODULE_8BIT_IDE_ADVANCED
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/RamVars.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/RamVars.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/RamVars.inc	(revision 516)
@@ -0,0 +1,139 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	RAMVARS struct containing BIOS variables stored in RAM.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef RAMVARS_INC
+%define RAMVARS_INC
+
+; Segment when RAMVARS is stored to top of interrupt vectors.
+%ifndef USE_AT
+	LITE_MODE_RAMVARS_SEGMENT	EQU		30h
+%endif
+
+
+%ifdef MODULE_SERIAL_FLOPPY OR MODULE_DRIVEXLATE
+	%define NEED_XLATEVARS
+%endif
+
+
+; RAM Variables.
+; Variables should be kept to minimum since they might be located
+; at the top of interrupt vectors.
+struc RAMVARS
+%ifdef RELOCATE_INT13H_STACK
+	.fpInt13hEntryStack	resb	4
+	.dwStackChangeDSDI:
+	.wStackChangeDI		resb	2
+	.wStackChangeDS		resb	2
+	.wNewStackOffset	resb	2
+%endif
+	.wDrvDetectSignature:			; Signature when BIOS is in drive detection mode
+	.fpOldI13h			resb	4	; Far pointer to old INT 13h handler
+	.wSignature			resb	2	; Sign for finding stolen 1...64 kiB
+	.bTimeoutTicksLeft	resb	1
+	.bLastTimeoutUpdate	resb	1
+
+	.wFirstDrvAndCount:
+	.bFirstDrv			resb	1	; Number of first drive for this BIOS
+	.wDrvCntAndFlopCnt:				; Both the hard disk and floppy counts in one word
+									; (yes, misaligned, but it is only used this way during initialization)
+	.bDrvCnt			resb	1	; Number of drives handled by this BIOS
+
+	; Variables for drive number translation
+%ifdef NEED_XLATEVARS
+	.xlateVars			resb	XLATEVARS_size
+%endif
+endstruc
+
+; Note!!! .wDrvDetectSignature and .wSignature are intentionally in different locations.
+RAMVARS_RAM_SIGNATURE			EQU	"Xu"	; RAMVARS signature for .wSignature
+RAMVARS_DRV_DETECT_SIGNATURE	EQU	5A5Ah	; Signature when BIOS is in drive detection mode
+
+
+%ifdef NEED_XLATEVARS
+; Variables for translating drive numbers.
+	struc XLATEVARS
+	%ifdef MODULE_SERIAL_FLOPPY
+		.bFlopCreateCnt:
+		.bFlopCntAndFirst	resb	1	; Normally, packed starting floppy drive number (high order 7 bits)
+										; and number of drives (low order bit, max 2 drives supported).
+										; During initialization, until the end of DetectDrives_FromAllIDEControllers,
+										; this byte contains the raw number of floppy drives seen
+										; (using .bFlopCreateCnt)
+	%else
+							resb	1	; alignment
+	%endif
+
+	%ifdef MODULE_DRIVEXLATE
+		.bXlatedDrv			resb	1	; Drive number after translation
+		.wFDandHDswap:
+		.bFDSwap			resb	1	; Floppy Drive to swap to 00h and vice versa
+		.bHDSwap			resb	1	; Hard Drive to swap to 80h and vice versa
+	%else
+							resb	1	; alignment
+	%endif
+	endstruc
+%endif
+
+%ifdef MODULE_SERIAL_FLOPPY
+  %ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if RAMVARS.xlateVars != RAMVARS.bDrvCnt+1 || XLATEVARS.bFlopCreateCnt != 0
+		%error "bFlopCreateCnt needs to be the first thing in XLATEVARS, and .xlateVars needs to come immediately after .bDrvCnt.  In at least one place, we read .wDrvCntAndFlopCnt to get both counts in one fetch"
+	%endif
+  %endif
+%endif
+
+
+
+;
+; IDEPACK NOTE: The first six bytes of this structure are directly put on the
+; wire for MODULE_SERIAL, please do not change the order or insert other members.
+;
+struc IDEPACK	; PIOVARS and MEMPIOVARS overwrite the first 7 bytes
+	.bFeatures				resb	1
+	.bDrvAndHead			resb	1	; LBA28 27...24
+
+	.wSectorCountAndLbaLow:
+	.bSectorCount			resb	1
+	.bSectorNumber:
+	.bLbaLow				resb	1	; LBA 7...0
+
+	.wCylinder:
+	.wLbaMiddleAndHigh:
+	.bLbaMiddle				resb	1	; LBA 15...8
+	.bLbaHigh				resb	1	; LBA 23...16
+
+	.bCommand				resb	1
+	.bDeviceControl			resb	1	; Offset 7 shared with PIOVARS and MEMPIOVARS
+							resb	1	; Used by PIOVARS and MEMPIOVARS
+
+%ifdef MODULE_EBIOS
+	; Parameters for 48-bit LBA
+	.bLbaLowExt				resb	1	; LBA48 31...24
+	.wLbaMiddleAndHighExt:
+	.bLbaMiddleExt			resb	1	; LBA48 39...32
+	.bLbaHighExt			resb	1	; LBA48 47...40
+%endif
+
+	.intpack				resb	INTPACK_size
+endstruc
+
+SIZE_OF_IDEPACK_WITHOUT_INTPACK		EQU	(IDEPACK_size - INTPACK_size)
+
+
+%endif ; RAMVARS_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/RomVars.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 516)
@@ -0,0 +1,199 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Defines for ROMVARS struct containing variables stored
+;					in BIOS ROM.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef ROMVARS_INC
+%define ROMVARS_INC
+
+; ROM Variables. Written to the ROM image before flashing.
+struc ROMVARS
+	.wRomSign			resb	2	; ROM Signature (AA55h)
+	.bRomSize			resb	1	; ROM size in 512 byte blocks
+	.rgbJump			resb	3	; First instruction to ROM init (jmp)
+
+	.rgbSign			resb	8	; Signature for XTIDE Configurator Program
+	.szTitle			resb	31	; BIOS title string
+	.szVersion			resb	25	; BIOS version string
+
+	.wFlags				resb	2	; Word for ROM flags
+	.wDisplayMode		resb	2	; Display mode for boot menu
+	.wBootTimeout		resb	2	; Boot Menu selection timeout in system timer ticks
+	.bIdeCnt			resb	1	; Number of available IDE controllers
+	.bBootDrv			resb	1	; Default drive to boot from
+	.bMinFddCnt			resb	1	; Minimum number of Floppy Drives
+	.bStealSize			resb	1	; Number of 1kB blocks stolen from 640kB base RAM
+	.bIdleTimeout		resb	1	; Standby timer value
+
+	.ideVarsBegin:
+	.ideVars0			resb	IDEVARS_size
+	.ideVars1			resb	IDEVARS_size
+	.ideVars2			resb	IDEVARS_size
+	.ideVars3			resb	IDEVARS_size
+
+%ifdef MODULE_SERIAL
+	.ideVarsSerialAuto	resb	IDEVARS_size
+%endif
+
+	.ideVarsEnd:
+endstruc
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if ROMVARS.ideVarsEnd & 0xff00 <> 0
+		%error ".ideVars structures must fit within the first 256 bytes of the ROM image"
+	%endif
+	%if (ROMVARS.ideVarsEnd - ROMVARS.ideVarsBegin) = 0
+		%error "there must be at least one .ideVars structure, it would be bizarre if this were not true, but it is assumed in the ah0h reset code."
+	%endif
+%endif
+
+NUMBER_OF_IDEVARS					EQU	((ROMVARS.ideVarsEnd - ROMVARS.ideVarsBegin) / IDEVARS_size)
+
+; Bit defines for ROMVARS.wFlags
+FLG_ROMVARS_FULLMODE				EQU	(1<<0)	; Full operating mode (steals base RAM, supports EBIOS etc.)
+FLG_ROMVARS_SERIAL_SCANDETECT 		EQU	(1<<3)	; Scan COM ports at the end of drive detection.  Can also be invoked
+												; by holding down the ALT key at the end of drive detection.
+												; (Conveniently, this is 8, a fact we exploit when testing the bit)
+
+; Here in case the configuration needs to know functionality is present
+FLG_ROMVARS_MODULE_FEATURE_SETS			EQU	(1<<5)
+FLG_ROMVARS_MODULE_8BIT_IDE				EQU	(1<<6)
+FLG_ROMVARS_MODULE_8BIT_IDE_ADVANCED	EQU (1<<7)
+FLG_ROMVARS_MODULE_ADVANCED_ATA			EQU	(1<<8)
+FLG_ROMVARS_MODULE_BOOT_MENU			EQU	(1<<9)
+FLG_ROMVARS_MODULE_EBIOS				EQU	(1<<10)
+FLG_ROMVARS_MODULE_HOTKEYS				EQU	(1<<11)
+FLG_ROMVARS_MODULE_IRQ					EQU	(1<<12)
+FLG_ROMVARS_MODULE_SERIAL				EQU (1<<13)
+FLG_ROMVARS_MODULE_SERIAL_FLOPPY		EQU (1<<14)
+FLG_ROMVARS_MODULE_STRINGS_COMPRESSED	EQU (1<<15)
+
+
+; Boot Menu Display Modes (see Assembly Library Display.inc for standard modes)
+DEFAULT_TEXT_MODE		EQU	4
+
+
+; Controller specific variables
+struc IDEVARS
+;;; Word 0
+	.wSerialPortAndBaud:					; Serial connection port (low, divided by 4) and baud rate divisor (high)
+	.wBasePort:								; IDE Base Port for Command Block (usual) Registers
+	.bSerialPort				resb	1
+	.bSerialBaud				resb	1
+
+;;; Word 1
+	.wControlBlockPort:
+	.bXTCFcontrolRegister:					; XT-CF autodetects ports
+	.bSerialUnused				resb	1	; IDE Base Port for Control Block Registers
+
+	.wSerialCOMPortCharAndDevice:			; In DetectPrint, we grab the COM Port char and Device at the same time
+	.bSerialCOMPortChar			resb	1	; Serial connection COM port number/letter
+
+;;; Word 2
+	.bDevice					resb	1	; Device type
+	.bIRQ						resb	1	; Interrupt Request Number
+
+;;; And more...
+	.drvParamsMaster			resb	DRVPARAMS_size
+	.drvParamsSlave				resb	DRVPARAMS_size
+endstruc
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if IDEVARS.bSerialCOMPortChar+1 != IDEVARS.bDevice
+		%error "IDEVARS.bSerialCOMPortChar needs to come immediately before IDEVARS.bDevice so that both bytes can be fetched at the same time inside DetectPrint.asm"
+	%endif
+%endif
+
+STANDARD_CONTROL_BLOCK_OFFSET			EQU		200h
+XTIDE_CONTROL_BLOCK_OFFSET				EQU		8h
+XTCF_CONTROL_BLOCK_OFFSET				EQU		(XTIDE_CONTROL_BLOCK_OFFSET << 1)
+
+; Default values for Port and PortCtrl, shared with the configurator
+;
+DEVICE_XTIDE_DEFAULT_PORT				EQU		300h
+DEVICE_XTIDE_DEFAULT_PORTCTRL			EQU		(DEVICE_XTIDE_DEFAULT_PORT + XTIDE_CONTROL_BLOCK_OFFSET)
+
+DEVICE_ATA_PRIMARY_PORT					EQU		1F0h
+DEVICE_ATA_PRIMARY_PORTCTRL				EQU		(DEVICE_ATA_PRIMARY_PORT + STANDARD_CONTROL_BLOCK_OFFSET)
+
+DEVICE_ATA_SECONDARY_PORT				EQU		170h
+DEVICE_ATA_SECONDARY_PORTCTRL			EQU		(DEVICE_ATA_SECONDARY_PORT + STANDARD_CONTROL_BLOCK_OFFSET)
+
+DEVICE_ATA_TERTIARY_PORT				EQU		1E8h
+DEVICE_ATA_TERTIARY_PORTCTRL			EQU		(DEVICE_ATA_TERTIARY_PORT + STANDARD_CONTROL_BLOCK_OFFSET)
+
+DEVICE_ATA_QUATERNARY_PORT				EQU		168h
+DEVICE_ATA_QUATERNARY_PORTCTRL			EQU		(DEVICE_ATA_QUATERNARY_PORT + STANDARD_CONTROL_BLOCK_OFFSET)
+
+
+; Device types for IDEVARS.bDevice
+; IDE Devices are grouped so device numbers cannot be changed without modifying code elsewhere!
+;
+COUNT_OF_STANDARD_IDE_DEVICES			EQU	2	; 16- and 32-bit controllers
+COUNT_OF_8BIT_IDE_DEVICES				EQU	7
+COUNT_OF_ALL_IDE_DEVICES				EQU	(COUNT_OF_8BIT_IDE_DEVICES + COUNT_OF_STANDARD_IDE_DEVICES)
+; Standard port mapped I/O
+DEVICE_16BIT_ATA						EQU	(0<<1)
+DEVICE_32BIT_ATA						EQU	(1<<1)
+DEVICE_8BIT_ATA							EQU	((COUNT_OF_STANDARD_IDE_DEVICES+0)<<1)	; 16- or 32-bit controller in 8-bit mode
+DEVICE_8BIT_XTIDE_REV1					EQU	((COUNT_OF_STANDARD_IDE_DEVICES+1)<<1)
+; Address lines A0 and A3 are swapped
+DEVICE_8BIT_XTIDE_REV2					EQU	((COUNT_OF_STANDARD_IDE_DEVICES+2)<<1)	; Or rev 1 with swapped A0 and A3
+; IDE Register offsets are SHL 1
+DEVICE_8BIT_XTCF_PIO8					EQU	((COUNT_OF_STANDARD_IDE_DEVICES+3)<<1)	; XT-CF using 8-bit PIO mode
+DEVICE_8BIT_XTCF_DMA					EQU	((COUNT_OF_STANDARD_IDE_DEVICES+4)<<1)	; XT-CF using DMA
+DEVICE_8BIT_XTCF_MEMMAP					EQU	((COUNT_OF_STANDARD_IDE_DEVICES+5)<<1)	; XT-CF using Memory Mapped transfers (not I/O)
+; Memory Mapped I/O
+DEVICE_8BIT_JRIDE_ISA					EQU	((COUNT_OF_STANDARD_IDE_DEVICES+6)<<1)	; JR-IDE/ISA (Memory Mapped I/O)
+; Virtual devices
+DEVICE_SERIAL_PORT						EQU	(COUNT_OF_ALL_IDE_DEVICES<<1)
+
+
+
+; Master/Slave drive specific parameters
+struc DRVPARAMS
+	.wFlags			resb	2	; Drive flags
+	.dwMaximumLBA:				; User specified maximum number of sectors
+	.wCylinders		resb	2	; User specified cylinders (1...16383)
+	.wHeadsAndSectors:
+	.bHeads			resb	1	; User specified Heads (1...16)
+	.bSect			resb	1	; User specified Sectors per track (1...63)
+endstruc
+
+; Bit defines for DRVPARAMS.wFlags
+MASK_DRVPARAMS_WRITECACHE		EQU	(3<<0)	; Bits 0...1, Drive internal write cache settings (must start at bit 0)
+	DEFAULT_WRITE_CACHE				EQU	0	; Must be 0
+	DISABLE_WRITE_CACHE				EQU	1
+	ENABLE_WRITE_CACHE				EQU	2
+MASK_DRVPARAMS_TRANSLATEMODE	EQU	(3<<TRANSLATEMODE_FIELD_POSITION)	; Bits 2...3, Position shared with DPT
+	TRANSLATEMODE_FIELD_POSITION	EQU	2
+	TRANSLATEMODE_NORMAL			EQU	0
+	TRANSLATEMODE_LARGE				EQU	1
+	TRANSLATEMODE_ASSISTED_LBA		EQU	2	; 28-bit or 48-bit LBA
+	TRANSLATEMODE_AUTO				EQU	3	; Only available in ROMVARS, not in DPTs
+FLG_DRVPARAMS_BLOCKMODE			EQU	(1<<4)	; Enable Block mode transfers
+FLG_DRVPARAMS_USERCHS			EQU	(1<<5)	; User specified P-CHS values
+	MAX_USER_CYLINDERS				EQU	16383
+	MAX_USER_HEADS					EQU	16
+	MAX_USER_SECTORS_PER_TRACK		EQU	63
+FLG_DRVPARAMS_USERLBA			EQU	(1<<6)	; User specified LBA value
+	MIN_USER_LBA_COUNT				EQU	((MAX_USER_CYLINDERS*MAX_USER_HEADS*MAX_USER_SECTORS_PER_TRACK)+1)
+	MAX_USER_LBA_COUNT				EQU	((2^28)-1)
+
+
+%endif ; ROMVARS_INC
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Version.inc
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Version.inc	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Inc/Version.inc	(revision 516)
@@ -0,0 +1,64 @@
+; /*
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Version information.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+;--------------------------------------------------------------------------------
+;
+; Assembler Version
+;
+
+%ifndef VERSION_INC
+%define VERSION_INC
+
+
+%define TITLE_STRING_START	"-=XTIDE Universal BIOS "
+%ifdef USE_AT
+	%ifdef USE_386
+		%define	TITLE_STRING_END	"(386)=-",NULL
+	%else
+		%define	TITLE_STRING_END	"(AT)=-",NULL
+	%endif
+%elifdef USE_186
+	%define	TITLE_STRING_END	"(XT+)=-",NULL
+%else
+	%define	TITLE_STRING_END	"(XT)=-",NULL
+%endif
+
+%define	TITLE_STRING			TITLE_STRING_START, TITLE_STRING_END
+%define	ROM_VERSION_STRING		"v2.0.0",BETA,"3 (",__DATE__,")",NULL
+%define	FLASH_SIGNATURE			"XTIDE203"	; Do not terminate with NULL
+
+
+%endif ; VERSION_INC
+
+%if 0			; equivalent of a NASM comment block
+;*/
+
+//--------------------------------------------------------------------------------
+//
+// C/C++ Version
+//
+
+#define BETA " Beta "
+
+#define ROM_VERSION_STRING		"v2.0.0" BETA "3 (" __DATE__ ")"
+
+/*
+%endif
+;*/
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Device.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Device.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Device.asm	(revision 516)
@@ -0,0 +1,162 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Command and port direction functions for different device types.
+		
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;
+		
+; Section containing code
+SECTION .text
+
+
+%macro TEST_USING_DPT_AND_JUMP_IF_SERIAL_DEVICE 1
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_SERIAL_DEVICE
+	jnz		SHORT %1
+%endmacro
+
+%macro CMP_USING_IDEVARS_IN_CSBP_AND_JUMP_IF 2
+	cmp		BYTE [cs:bp+IDEVARS.bDevice], %1
+	je		SHORT %2
+%endmacro
+
+
+
+;--------------------------------------------------------------------
+; Device_FinalizeDPT
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+%ifdef MODULE_SERIAL	; IDE + Serial
+Device_FinalizeDPT:
+	; needs to check IDEVARS vs. checking the DPT as the serial bit in the DPT is set in the Finalize routine
+	CMP_USING_IDEVARS_IN_CSBP_AND_JUMP_IF	DEVICE_SERIAL_PORT, .FinalizeDptForSerialPortDevice
+	jmp		IdeDPT_Finalize
+.FinalizeDptForSerialPortDevice:
+	jmp		SerialDPT_Finalize
+
+%else					; IDE
+	Device_FinalizeDPT		EQU		IdeDPT_Finalize
+%endif
+
+
+;--------------------------------------------------------------------
+; Device_ResetMasterAndSlaveController
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+%ifdef MODULE_SERIAL	; IDE + Serial
+Device_ResetMasterAndSlaveController:
+	TEST_USING_DPT_AND_JUMP_IF_SERIAL_DEVICE	ReturnSuccessForSerialPort
+	jmp		IdeCommand_ResetMasterAndSlaveController
+
+%else					; IDE
+	Device_ResetMasterAndSlaveController	EQU		IdeCommand_ResetMasterAndSlaveController
+%endif
+
+
+;--------------------------------------------------------------------
+; Device_IdentifyToBufferInESSIwithDriveSelectByteInBH
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Select Register
+;		DX:		Autodetected port (for devices that support autodetection)
+;		DS:		Segment to RAMVARS
+;		ES:SI:	Ptr to buffer to receive 512-byte IDE Information
+;		CS:BP:	Ptr to IDEVARS
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+%ifdef MODULE_SERIAL	; IDE + Serial
+Device_IdentifyToBufferInESSIwithDriveSelectByteInBH:
+	CMP_USING_IDEVARS_IN_CSBP_AND_JUMP_IF	DEVICE_SERIAL_PORT, .IdentifyDriveFromSerialPort
+	jmp		IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
+.IdentifyDriveFromSerialPort:
+	jmp		SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
+
+%else					; IDE
+	Device_IdentifyToBufferInESSIwithDriveSelectByteInBH	EQU		IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
+%endif
+
+
+;--------------------------------------------------------------------
+; Device_OutputCommandWithParameters
+;	Parameters:
+;		BH:		Default system timer ticks for timeout (can be ignored)
+;		BL:		IDE Status Register bit to poll after command
+;		ES:SI:	Ptr to buffer (for data transfer commands)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors (for transfer commands)
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, (CX), DX, (ES:SI for data transfer commands)
+;--------------------------------------------------------------------
+%ifdef MODULE_SERIAL	; IDE + Serial
+ALIGN JUMP_ALIGN
+Device_OutputCommandWithParameters:
+	TEST_USING_DPT_AND_JUMP_IF_SERIAL_DEVICE .OutputCommandToSerialPort
+	jmp		IdeCommand_OutputWithParameters
+
+ALIGN JUMP_ALIGN
+.OutputCommandToSerialPort:
+	jmp		SerialCommand_OutputWithParameters
+
+%else					; IDE
+	Device_OutputCommandWithParameters		EQU		IdeCommand_OutputWithParameters
+%endif
+
+
+;--------------------------------------------------------------------
+; Device_SelectDrive
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+%ifdef MODULE_SERIAL	; IDE + Serial
+Device_SelectDrive:
+	TEST_USING_DPT_AND_JUMP_IF_SERIAL_DEVICE	ReturnSuccessForSerialPort
+	jmp		IdeCommand_SelectDrive
+
+%else					; IDE
+	Device_SelectDrive		EQU		IdeCommand_SelectDrive
+%endif
+
+
+%ifdef MODULE_SERIAL
+ALIGN JUMP_ALIGN
+ReturnSuccessForSerialPort:
+	xor		ax, ax
+	ret
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeCommand.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeCommand.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeCommand.asm	(revision 516)
@@ -0,0 +1,255 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device Command functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeCommand_ResetMasterAndSlaveController
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+IdeCommand_ResetMasterAndSlaveController:
+	; HSR0: Set_SRST
+	call	AccessDPT_GetDeviceControlByteToAL
+	or		al, FLG_DEVCONTROL_SRST | FLG_DEVCONTROL_nIEN	; Set Reset bit
+	OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER		DEVICE_CONTROL_REGISTER_out
+	mov		ax, HSR0_RESET_WAIT_US
+	call	Timer_DelayMicrosecondsFromAX
+
+	; HSR1: Clear_wait
+	call	AccessDPT_GetDeviceControlByteToAL
+	or		al, FLG_DEVCONTROL_nIEN
+	and		al, ~FLG_DEVCONTROL_SRST						; Clear reset bit
+	OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER		DEVICE_CONTROL_REGISTER_out
+	mov		ax, HSR1_RESET_WAIT_US
+	call	Timer_DelayMicrosecondsFromAX
+
+	; HSR2: Check_status
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_MAXIMUM, FLG_STATUS_BSY)
+	jmp		IdeWait_PollStatusFlagInBLwithTimeoutInBH
+
+
+;--------------------------------------------------------------------
+; IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Select Register
+;		DX:		Autodetected port for XT-CF
+;		DS:		Segment to RAMVARS
+;		ES:SI:	Ptr to buffer to receive 512-byte IDE Information
+;		CS:BP:	Ptr to IDEVARS
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH:
+	; Create fake DPT to be able to use Device.asm functions
+	call	FindDPT_ForNewDriveToDSDI
+	eMOVZX	ax, bh
+	mov		[di+DPT.wFlags], ax
+	call	CreateDPT_StoreIdevarsOffsetAndBasePortFromCSBPtoDPTinDSDI
+	call	IdeDPT_StoreDeviceTypeToDPTinDSDIfromIdevarsInCSBP
+	mov		BYTE [di+DPT_ATA.bBlockSize], 1	; Block = 1 sector
+
+	; Wait until drive motors have reached full speed
+	cmp		bp, BYTE ROMVARS.ideVars0	; First controller?
+	jne		SHORT .SkipLongWaitSinceDriveIsNotPrimaryMaster
+	test	bh, FLG_DRVNHEAD_DRV		; Wait already done for Master
+	jnz		SHORT .SkipLongWaitSinceDriveIsNotPrimaryMaster
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_MOTOR_STARTUP, FLG_STATUS_DRDY)
+	call	IdeWait_PollStatusFlagInBLwithTimeoutInBH
+.SkipLongWaitSinceDriveIsNotPrimaryMaster:
+
+	; Create IDEPACK without INTPACK
+	push	bp
+	call	Idepack_FakeToSSBP
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	; Enable 8-bit PIO mode for 8-bit ATA and XT-CF
+	push	si
+	call	AH9h_Enable8bitModeForDevice8bitAta
+	xor		al, al						; XTCF_8BIT_PIO_MODE
+	call	AH9h_SetModeFromALtoXTCF
+	pop		si
+%endif ; MODULE_8BIT_IDE_ADVANCED
+
+	; Prepare to output Identify Device command
+	mov		dl, 1						; Sector count (required by IdeTransfer.asm)
+	mov		al, COMMAND_IDENTIFY_DEVICE
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+	call	Idepack_StoreNonExtParametersAndIssueCommandFromAL
+
+	; Clean stack and return
+.FailedToSet8bitMode:
+	lea		sp, [bp+SIZE_OF_IDEPACK_WITHOUT_INTPACK]	; This assumes BP hasn't changed between Idepack_FakeToSSBP and here
+	pop		bp
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeCommand_OutputWithParameters
+;	Parameters:
+;		BH:		System timer ticks for timeout
+;		BL:		IDE Status Register bit to poll after command
+;		ES:SI:	Ptr to buffer (for data transfer commands)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors (for transfer commands)
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, (CX), DX, (ES:SI for data transfer commands)
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeCommand_OutputWithParameters:
+	push	bx						; Store status register bits to poll
+
+	; Select Master or Slave drive and output head number or LBA28 top bits
+	call	IdeCommand_SelectDrive
+	jc		SHORT .DriveNotReady
+
+	; Output Device Control Byte to enable or disable interrupts
+	mov		al, [bp+IDEPACK.bDeviceControl]
+%ifdef MODULE_IRQ
+	test	al, FLG_DEVCONTROL_nIEN	; Interrupts disabled?
+	jnz		SHORT .DoNotSetInterruptInServiceFlag
+
+	; Clear Task Flag and set Interrupt In-Service Flag
+	or		BYTE [di+DPT.bFlagsHigh], FLGH_DPT_INTERRUPT_IN_SERVICE
+	push	ds
+	LOAD_BDA_SEGMENT_TO	ds, dx, !	; Also zero DX
+	mov		[BDA.bHDTaskFlg], dl
+	pop		ds
+.DoNotSetInterruptInServiceFlag:
+%endif
+	OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER		DEVICE_CONTROL_REGISTER_out
+
+	; Output Feature Number
+	mov		al, [bp+IDEPACK.bFeatures]
+	OUTPUT_AL_TO_IDE_REGISTER	FEATURES_REGISTER_out
+
+	; Output Sector Address High (only used by LBA48)
+%ifdef MODULE_EBIOS
+	eMOVZX	ax, [bp+IDEPACK.bLbaLowExt]		; Zero sector count
+	mov		cx, [bp+IDEPACK.wLbaMiddleAndHighExt]
+	call	OutputSectorCountAndAddress
+%endif
+
+	; Output Sector Address Low
+	mov		ax, [bp+IDEPACK.wSectorCountAndLbaLow]
+	mov		cx, [bp+IDEPACK.wLbaMiddleAndHigh]
+	call	OutputSectorCountAndAddress
+
+	; Output command
+	mov		al, [bp+IDEPACK.bCommand]
+	OUTPUT_AL_TO_IDE_REGISTER	COMMAND_REGISTER_out
+
+	; Wait until command completed
+	pop		bx								; Pop status and timeout for polling
+	cmp		bl, FLG_STATUS_DRQ				; Data transfer started?
+	jne		SHORT .WaitUntilNonTransferCommandCompletes
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	cmp		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_XTCF_MEMMAP
+	jae		SHORT JrIdeTransfer_StartWithCommandInAL	; DEVICE_8BIT_XTCF_MEMMAP or DEVICE_8BIT_JRIDE_ISA
+%endif
+	jmp		IdeTransfer_StartWithCommandInAL
+
+.WaitUntilNonTransferCommandCompletes:
+%ifdef MODULE_IRQ
+	test	BYTE [bp+IDEPACK.bDeviceControl], FLG_DEVCONTROL_nIEN
+	jz		SHORT .PollStatusFlagInsteadOfWaitIrq
+	jmp		IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
+.PollStatusFlagInsteadOfWaitIrq:
+%endif
+	jmp		IdeWait_PollStatusFlagInBLwithTimeoutInBH
+
+.DriveNotReady:
+	pop		bx							; Clean stack
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeCommand_SelectDrive
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeCommand_SelectDrive:
+	; We use different timeout value when detecting drives.
+	; This prevents unnecessary long delays when drive is not present.
+	mov		cx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRDY, FLG_STATUS_DRDY)
+	cmp		WORD [RAMVARS.wDrvDetectSignature], RAMVARS_DRV_DETECT_SIGNATURE
+	eCMOVE	ch, TIMEOUT_SELECT_DRIVE_DURING_DRIVE_DETECTION
+
+	; Select Master or Slave Drive
+	mov		al, [bp+IDEPACK.bDrvAndHead]
+	OUTPUT_AL_TO_IDE_REGISTER	DRIVE_AND_HEAD_SELECT_REGISTER
+	mov		bx, cx
+	call	IdeWait_PollStatusFlagInBLwithTimeoutInBH
+
+	; Ignore errors from IDE Error Register (set by previous command)
+	cmp		ah, RET_HD_TIMEOUT
+	je		SHORT .FailedToSelectDrive
+	xor		ax, ax					; Always success unless timeout
+	ret
+.FailedToSelectDrive:
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; OutputSectorCountAndAddress
+;	Parameters:
+;		AH:		LBA low bits (Sector Number)
+;		AL:		Sector Count
+;		CL:		LBA middle bits (Cylinder Number low)
+;		CH:		LBA high bits (Cylinder Number high)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AL, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+OutputSectorCountAndAddress:
+	OUTPUT_AL_TO_IDE_REGISTER	SECTOR_COUNT_REGISTER
+
+	mov		al, ah
+	OUTPUT_AL_TO_IDE_REGISTER	LBA_LOW_REGISTER
+
+	mov		al, cl
+	OUTPUT_AL_TO_IDE_REGISTER	LBA_MIDDLE_REGISTER
+
+	mov		al, ch
+	OUTPUT_AL_TO_IDE_REGISTER	LBA_HIGH_REGISTER
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDPT.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDPT.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDPT.asm	(revision 516)
@@ -0,0 +1,152 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Sets IDE Device specific parameters to DPT.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeDPT_Finalize
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		CF:		Clear, IDE interface only supports hard disks
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+IdeDPT_Finalize:
+
+%ifdef MODULE_FEATURE_SETS
+;--------------------------------------------------------------------
+; .DetectPowerManagementSupport
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+.DetectPowerManagementSupport:
+	test	BYTE [es:si+ATA6.wSetSup82], A6_wSetSup82_POWERMAN
+	jz		SHORT .NoPowerManagementSupport
+	or		BYTE [di+DPT.bFlagsHigh], FLGH_DPT_POWER_MANAGEMENT_SUPPORTED
+.NoPowerManagementSupport:
+%endif ; MODULE_FEATURE_SETS
+
+
+;--------------------------------------------------------------------
+; .StoreDeviceType
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AL
+;--------------------------------------------------------------------
+.StoreDeviceType:
+	call	IdeDPT_StoreDeviceTypeToDPTinDSDIfromIdevarsInCSBP
+
+
+;--------------------------------------------------------------------
+; .StoreBlockMode
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+.StoreBlockMode:
+	mov		BYTE [di+DPT_ATA.bBlockSize], 1
+
+
+%ifdef MODULE_ADVANCED_ATA
+;--------------------------------------------------------------------
+; .StorePioModeAndTimings
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+.StorePioMode:
+	call	AtaID_GetMaxPioModeToAXandMinCycleTimeToCX
+	mov		[di+DPT_ADVANCED_ATA.wMinPioCycleTime], cx
+	mov		[di+DPT_ADVANCED_ATA.bPioMode], al
+	or		[di+DPT.bFlagsHigh], ah
+
+
+;--------------------------------------------------------------------
+; .DetectAdvancedIdeController
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+.DetectAdvancedIdeController:
+	mov		bx, [di+DPT.wBasePort]
+	call	AdvAtaInit_DetectControllerForIdeBaseInBX
+	mov		[di+DPT_ADVANCED_ATA.wControllerID], ax	; Store zero if none detected
+	mov		[di+DPT_ADVANCED_ATA.wControllerBasePort], dx
+	jnc		SHORT .NoAdvancedControllerDetected
+
+	; Use highest common PIO mode from controller and drive.
+	; Many VLB controllers support PIO modes up to 2.
+	call	AdvAtaInit_GetControllerMaxPioModeToAL
+	jnc		SHORT .ChangeTo32bitDevice
+	and		BYTE [di+DPT.bFlagsHigh], ~FLGH_DPT_IORDY	; No IORDY supported if need to limit
+	MIN_U	[di+DPT_ADVANCED_ATA.bPioMode], al
+
+	; We have detected 32-bit controller so change Device Type since
+	; it might have been set to 16-bit on IDEVARS
+.ChangeTo32bitDevice:
+	mov		BYTE [di+DPT_ATA.bDevice], DEVICE_32BIT_ATA
+.NoAdvancedControllerDetected:
+%endif	; MODULE_ADVANCED_ATA
+
+
+; End DPT
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeDPT_StoreDeviceTypeToDPTinDSDIfromIdevarsInCSBP
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AL
+;--------------------------------------------------------------------
+IdeDPT_StoreDeviceTypeToDPTinDSDIfromIdevarsInCSBP:
+	mov		al, [cs:bp+IDEVARS.bDevice]
+	mov		[di+DPT_ATA.bDevice], al
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaBlock.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaBlock.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaBlock.asm	(revision 516)
@@ -0,0 +1,198 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Read/Write functions for transferring
+;					block using DMA.
+;					These functions should only be called from IdeTransfer.asm.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeDmaBlock_WriteToXTCF
+;	Parameters:
+;		CX:		Block size in 512 byte sectors
+;		DX:		XTCF Base Port Address
+;		ES:SI:	Physical address to buffer to receive data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeDmaBlock_WriteToXTCF:
+	xchg	si, di
+	mov		bl, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
+	call	TransferBlockToOrFromXTCF
+	xchg	di, si
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeDmaBlock_ReadFromXTCF
+;	Parameters:
+;		CX:		Block size in 512 byte sectors
+;		DX:		XTCF Base Port Address
+;		ES:DI:	Physical address to buffer to receive data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeDmaBlock_ReadFromXTCF:
+	mov		bl, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
+	; Fall to TransferBlockToOrFromXTCF
+
+
+;--------------------------------------------------------------------
+; TransferBlockToOrFromXTCF
+;	Parameters:
+;		BL:		Mode byte for DMA Mode Register
+;		CX:		Block size in 512 byte sectors
+;		DX:		XTCF Base Port Address
+;		ES:DI:	Physical address to buffer to receive data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+TransferBlockToOrFromXTCF:
+	; 8-bit DMA transfers must be done within 64k physical page.
+	; XT-CF support maximum of 64 sector (32768 bytes) blocks in DMA mode
+	; so we never need to separate transfer to more than 2 separate DMA operations.
+
+	; Load XT-CF Control Register port to DX
+	add		dl, XTCF_CONTROL_REGISTER
+
+	; Calculate bytes for first page
+	mov		ax, di
+	neg		ax										; AX = Max BYTEs for first page
+%ifdef USE_186
+	shl		cx, 9									; CX = Block size in BYTEs
+%else
+	xchg	cl, ch
+	shl		cx, 1
+%endif
+	cmp		cx, ax
+	jbe		SHORT .TransferLastDmaPageWithSizeInCX
+
+	; Push size for second DMA page
+	xchg	cx, ax									; CX = BYTEs for first page
+	sub		ax, cx									; AX = BYTEs for second page
+	push	ax
+
+	; Transfer first DMA page
+	call	StartDMAtransferForXTCFwithDmaModeInBL
+	pop		cx										; Pop size for second DMA page
+
+.TransferLastDmaPageWithSizeInCX:
+	; Fall to StartDMAtransferForXTCFwithDmaModeInBL
+
+
+;--------------------------------------------------------------------
+; StartDMAtransferForXTCFwithDmaModeInBL
+;	Parameters:
+;		BL:		Byte for DMA Mode Register
+;		CX:		Number of BYTEs to transfer (1...32768 since max block size is limited to 64)
+;		DX:		XTCF Control Register
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+StartDMAtransferForXTCFwithDmaModeInBL:
+	; Program 8-bit DMA Controller
+	; Disable Interrupts and DMA Channel 3 during DMA setup
+	mov		al, SET_CH3_MASK_BIT
+	cli										; Disable interrupts
+	out		MASK_REGISTER_DMA8_out, al		; Disable DMA Channel 3
+
+	; Set DMA Mode (read or write using channel 3)
+	mov		al, bl
+	out		MODE_REGISTER_DMA8_out, al
+
+	; Set address to DMA controller
+	out		CLEAR_FLIPFLOP_DMA8_out, al		; Reset flip-flop to low byte
+	mov		ax, es
+	out		PAGE_DMA8_CH_3, al
+	mov		ax, di
+	out		BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al	; Low byte
+	mov		al, ah
+	out		BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al	; High byte
+
+	; Set number of bytes to transfer (DMA controller must be programmed number of bytes - 1)
+	mov		ax, cx
+	dec		ax								; DMA controller is programmed for one byte less
+	out		BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al	; Low byte
+	mov		al, ah
+	out		BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al	; High byte
+
+	; Enable DMA Channel 3
+	mov		al, CLEAR_CH3_MASK_BIT
+	out		MASK_REGISTER_DMA8_out, al		; Enable DMA Channel 3
+	sti										; Enable interrupts
+
+
+%if 0 ; Slow DMA code
+	; XT-CF transfers 16 bytes at a time. We need to manually
+	; start transfer for every block.
+ALIGN JUMP_ALIGN
+.TransferNextBlock:
+	mov		al, RAISE_DRQ_AND_CLEAR_XTCF_XFER_COUNTER
+	cli									; We want no ISR to read DMA Status Register before we do
+	out		dx, al						; Transfer up to 16 bytes to/from XT-CF card
+	; * Here XT-CF sets CPU to wait states during transfer *
+	in		al, STATUS_REGISTER_DMA8_in
+	sti
+	test	al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT
+	jz		SHORT .TransferNextBlock	; All bytes transferred?
+%endif ; Slow DMA code
+
+
+%if 1 ; Fast DMA code
+	push	cx
+	add		cx, BYTE 15					; Include any partial DMA block (since we had to divide transfer to 64k physical pages)
+	eSHR_IM	cx, 4						; Drive Block size to 16 Byte DMA Block Size
+
+.JustOneMoreDmaBlock:
+	mov		al, RAISE_DRQ_AND_CLEAR_XTCF_XFER_COUNTER
+ALIGN JUMP_ALIGN
+.TransferNextDmaBlock:
+	out		dx, al						; Transfer 16 bytes to/from XT-CF card
+	loop	.TransferNextDmaBlock
+
+	inc		cx							; set up CX, in case we need to do an extra iteration
+	in		al, STATUS_REGISTER_DMA8_in
+	test	al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT
+	jz		SHORT .JustOneMoreDmaBlock			; it wasn't set so get more bytes
+	pop		cx
+%endif ; Fast DMA code
+
+
+	; Restore XT-CF to normal operation
+	mov		al, XTCF_DMA_MODE
+	out		dx, al
+
+	; Increment physical address in ES:DI
+	mov		ax, es
+	add		di, cx
+	adc		al, ah
+	mov		es, ax
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeError.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeError.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeError.asm	(revision 516)
@@ -0,0 +1,101 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device error functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL
+;	Parameters:
+;		AL:		IDE Status Register contents
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		BIOS error code
+;		CF:		Set if error
+;				Cleared if no error
+;	Corrupts registers:
+;		AL, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL:
+	mov		ah, al			; IDE Status Register to AH
+	INPUT_TO_AL_FROM_IDE_REGISTER	ERROR_REGISTER_in
+	xchg	al, ah			; Status Register now in AL, Error Register now in AH
+	; Fall to GetBiosErrorCodeToAHfromStatusAndErrorRegistersInAX
+
+
+;--------------------------------------------------------------------
+; GetBiosErrorCodeToAHfromStatusAndErrorRegistersInAX
+;	Parameters:
+;		AL:		IDE Status Register contents
+;		AH:		IDE Error Register contents
+;	Returns:
+;		AH:		BIOS INT 13h error code
+;		CF:		Set if error
+;				Cleared if no error
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetBiosErrorCodeToAHfromStatusAndErrorRegistersInAX:
+	test	al, FLG_STATUS_BSY
+	jz		SHORT .CheckErrorBitsFromStatusRegisterInAL
+	mov		ah, RET_HD_TIMEOUT
+	jmp		SHORT .ReturnBiosErrorCodeInAH
+
+ALIGN JUMP_ALIGN
+.CheckErrorBitsFromStatusRegisterInAL:
+	test	al, FLG_STATUS_DF | FLG_STATUS_CORR | FLG_STATUS_ERR
+	jnz		SHORT .ProcessErrorFromStatusRegisterInAL
+	xor		ah, ah					; No errors, zero AH and CF
+	ret
+
+.ProcessErrorFromStatusRegisterInAL:
+	test	al, FLG_STATUS_ERR		; Error specified in Error register?
+	jnz		SHORT .ConvertBiosErrorToAHfromErrorRegisterInAH
+	mov		ah, RET_HD_ECC			; Assume ECC corrected error
+	test	al, FLG_STATUS_CORR		; ECC corrected error?
+	jnz		SHORT .ReturnBiosErrorCodeInAH
+	mov		ah, RET_HD_CONTROLLER	; Must be Device Fault
+	jmp		SHORT .ReturnBiosErrorCodeInAH
+
+.ConvertBiosErrorToAHfromErrorRegisterInAH:
+	xor		bx, bx					; Clear CF
+.ErrorBitLoop:
+	rcr		ah, 1					; Set CF if error bit set
+	jc		SHORT .LookupErrorCode
+	inc		bx
+	test	ah, ah					; Clear CF
+	jnz		SHORT .ErrorBitLoop
+.LookupErrorCode:
+	mov		ah, [cs:bx+.rgbRetCodeLookup]
+.ReturnBiosErrorCodeInAH:
+	stc								; Set CF since error
+	ret
+
+.rgbRetCodeLookup:
+	db	RET_HD_ADDRMARK		; Bit0=AMNF, Address Mark Not Found
+	db	RET_HD_SEEK_FAIL	; Bit1=TK0NF, Track 0 Not Found
+	db	RET_HD_INVALID		; Bit2=ABRT, Aborted Command
+	db	RET_HD_NOTLOCKED	; Bit3=MCR, Media Change Requested
+	db	RET_HD_NOT_FOUND	; Bit4=IDNF, ID Not Found
+	db	RET_HD_LOCKED		; Bit5=MC, Media Changed
+	db	RET_HD_UNCORRECC	; Bit6=UNC, Uncorrectable Data Error
+	db	RET_HD_BADSECTOR	; Bit7=BBK, Bad Block Detected
+	db	RET_HD_STATUSERR	; When Error Register is zero
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIO.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIO.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIO.asm	(revision 516)
@@ -0,0 +1,205 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Register I/O functions when supporting 8-bit
+;					devices that need address translations.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeIO_InputStatusRegisterToAL
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AL:		IDE Status Register contents
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIO_InputStatusRegisterToAL:
+%ifndef MODULE_8BIT_IDE
+	INPUT_TO_AL_FROM_IDE_REGISTER STATUS_REGISTER_in
+	ret
+
+%else
+	mov		dl, STATUS_REGISTER_in
+	; Fall to IdeIO_InputToALfromIdeRegisterInDL
+
+;--------------------------------------------------------------------
+; IdeIO_InputToALfromIdeRegisterInDL
+;	Parameters:
+;		DL:		IDE Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AL:		Inputted byte
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+IdeIO_InputToALfromIdeRegisterInDL:
+	xor		dh, dh	; IDE Register index now in DX
+	mov		bx, dx	; and BX
+	mov		al, [di+DPT_ATA.bDevice]
+	cmp		al, DEVICE_8BIT_XTIDE_REV2
+	jb		SHORT .InputToALfromRegisterInDX	; Standard IDE controllers and XTIDE rev 1
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	je		SHORT .ReverseA0andA3fromRegisterIndexInDX
+
+	cmp		al, DEVICE_8BIT_JRIDE_ISA
+	jne		SHORT .ShlRegisterIndexInDX			; All XT-CF modes
+	; Fall to .InputToALfromMemoryMappedRegisterInDX
+
+.InputToALfromMemoryMappedRegisterInDX:
+	push	ds
+	mov		ds, [di+DPT.wBasePort]	; Segment for JR-IDE/ISA
+	mov		al, [bx+JRIDE_COMMAND_BLOCK_REGISTER_WINDOW_OFFSET]
+	pop		ds
+	ret
+%endif
+
+.ReverseA0andA3fromRegisterIndexInDX:
+	mov		dl, [cs:bx+g_rgbSwapA0andA3fromIdeRegisterIndex]
+	SKIP2B	bx	; Skip shl dx, 1
+
+.ShlRegisterIndexInDX:
+	eSHL_IM	dx, 1
+	; Fall to .InputToALfromRegisterInDX
+
+.InputToALfromRegisterInDX:
+	add		dx, [di+DPT.wBasePort]
+	in		al, dx
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeIO_OutputALtoIdeControlBlockRegisterInDL
+;	Parameters:
+;		AL:		Byte to output
+;		DL:		IDE Control Block Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+IdeIO_OutputALtoIdeControlBlockRegisterInDL:
+	xor		dh, dh	; IDE Register index now in DX
+
+	mov		bl, [di+DPT_ATA.bDevice]
+	cmp		bl, DEVICE_8BIT_XTIDE_REV2
+	jb		SHORT .OutputALtoControlBlockRegisterInDX	; Standard IDE controllers and XTIDE rev 1
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	je		SHORT .ReverseA0andA3fromRegisterIndexInDX
+
+	cmp		bl, DEVICE_8BIT_JRIDE_ISA
+	jne		SHORT .ShlRegisterIndexInDX		; All XT-CF modes
+	; Fall to .OutputALtoMemoryMappedRegisterInDX
+
+.OutputALtoMemoryMappedRegisterInDX:
+	mov		bx, JRIDE_CONTROL_BLOCK_REGISTER_WINDOW_OFFSET
+	jmp 	SHORT IdeIO_OutputALtoIdeRegisterInDL.OutputALtoMemoryMappedRegisterInDXwithWindowOffsetInBX
+%endif
+
+.ReverseA0andA3fromRegisterIndexInDX:
+	; We cannot use lookup table since A3 will be always set because
+	; Control Block Registers start from Command Block + 8h. We can do
+	; a small trick since we only access Device Control Register at
+	; offset 6h: Always clear A3 and set A0.
+	add		dx, [cs:bx+IDEVARS.wControlBlockPort]
+	xor		dl, 1001b						; Clear A3, Set A0
+	jmp		SHORT OutputALtoPortInDX
+
+.ShlRegisterIndexInDX:
+	eSHL_IM	dx, 1
+	add		dx, BYTE XTCF_CONTROL_BLOCK_OFFSET
+	jmp		SHORT OutputALtoRegisterInDX
+
+.OutputALtoControlBlockRegisterInDX:
+	call	AccessDPT_GetIdevarsToCSBX
+	add		dx, [cs:bx+IDEVARS.wControlBlockPort]
+	jmp		SHORT OutputALtoPortInDX
+
+
+;--------------------------------------------------------------------
+; IdeIO_OutputALtoIdeRegisterInDL
+;	Parameters:
+;		AL:		Byte to output
+;		DL:		IDE Command Block Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIO_OutputALtoIdeRegisterInDL:
+	xor		dh, dh	; IDE Register index now in DX
+
+	mov		bl, [di+DPT_ATA.bDevice]
+	cmp		bl, DEVICE_8BIT_XTIDE_REV2
+	jb		SHORT OutputALtoRegisterInDX	; Standard IDE controllers and XTIDE rev 1
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	je		SHORT .ReverseA0andA3fromRegisterIndexInDX
+
+	cmp		bl, DEVICE_8BIT_JRIDE_ISA
+	jne		SHORT .ShlRegisterIndexInDX		; All XT-CF modes
+	; Fall to .OutputALtoMemoryMappedRegisterInDX
+
+.OutputALtoMemoryMappedRegisterInDX:
+	mov		bx, JRIDE_COMMAND_BLOCK_REGISTER_WINDOW_OFFSET
+.OutputALtoMemoryMappedRegisterInDXwithWindowOffsetInBX:
+	add		bx, dx
+	push	ds
+	mov		ds, [di+DPT.wBasePort]	; Segment for JR-IDE/ISA
+	mov		[bx], al
+	pop		ds
+	ret
+%endif
+
+.ReverseA0andA3fromRegisterIndexInDX:
+	mov		bx, dx
+	mov		dl, [cs:bx+g_rgbSwapA0andA3fromIdeRegisterIndex]
+	SKIP2B	bx	; Skip shl dx, 1
+
+.ShlRegisterIndexInDX:
+	eSHL_IM	dx, 1
+	; Fall to OutputALtoRegisterInDX
+
+ALIGN JUMP_ALIGN
+OutputALtoRegisterInDX:
+	add		dx, [di+DPT.wBasePort]
+OutputALtoPortInDX:
+	out		dx, al
+	ret
+
+
+
+; A0 <-> A3 lookup table
+g_rgbSwapA0andA3fromIdeRegisterIndex:
+	db	0000b	; <-> 0000b, 0
+	db	1000b	; <-> 0001b, 1
+	db	0010b	; <-> 0010b, 2
+	db	1010b	; <-> 0011b, 3
+	db	0100b	; <-> 0100b, 4
+	db	1100b	; <-> 0101b, 5
+	db	0110b	; <-> 0110b, 6
+	db	1110b	; <-> 0111b, 7
+
+%endif ; MODULE_8BIT_IDE
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIrq.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIrq.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIrq.asm	(revision 516)
@@ -0,0 +1,142 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Interrupt handling related functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeIrq_WaitForIRQ
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		CF:		Set if wait done by operating system
+;				Cleared if BIOS must perform task flag polling
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIrq_WaitForIRQ:
+
+;--------------------------------------------------------------------
+; .NotifyOperatingSystemAboutWaitingForIRQ
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CF:		Set if wait done by operating system
+;				Cleared if BIOS must perform task flag polling
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.NotifyOperatingSystemAboutWaitingForIRQ:
+	push	ds
+
+	LOAD_BDA_SEGMENT_TO	ds, ax, !		; Zero AX
+	mov		ah, OS_HOOK_DEVICE_BUSY		; Hard disk busy (AX=9000h)
+	cli									; Disable interrupts
+	cmp		al, [BDA.bHDTaskFlg]		; Task flag already set?
+	jc		SHORT .ReturnFromWaitNotify	;  If so, skip OS notification
+	int		BIOS_SYSTEM_INTERRUPT_15h	; OS hook, device busy
+	jnc		SHORT .ReturnFromWaitNotify	; CF cleared, BIOS handles waiting
+
+	; Make sure that OS hooks are supported, otherwise the CF means unsupported function
+	test	ah, ah						; OS hook supported? (clears CF)
+	jnz		SHORT .ReturnFromWaitNotify	; AH has error, BIOS must do the wait
+	stc									; Set CF since wait done by OS
+.ReturnFromWaitNotify:
+	sti									; Enable interrupts
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; IDE Interrupt Service Routines.
+;
+; IdeIrq_InterruptServiceRoutineForIrqs2to7
+; IdeIrq_InterruptServiceRoutineForIrqs8to15
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIrq_InterruptServiceRoutineForIrqs2to7:
+	push	di
+	push	ax
+	call	AcknowledgeIdeInterruptAndSetTaskFlag
+
+	mov		al, COMMAND_END_OF_INTERRUPT
+	jmp		SHORT AcknowledgeMasterInterruptController
+
+
+ALIGN JUMP_ALIGN
+IdeIrq_InterruptServiceRoutineForIrqs8to15:
+	push	di
+	push	ax
+	call	AcknowledgeIdeInterruptAndSetTaskFlag
+
+	mov		al, COMMAND_END_OF_INTERRUPT
+	out		SLAVE_8259_COMMAND_out, al	; Acknowledge Slave 8259
+AcknowledgeMasterInterruptController:
+	out		MASTER_8259_COMMAND_out, al	; Acknowledge Master 8259
+
+	; Issue Int 15h, function AX=9100h (Interrupt ready)
+	mov		ax, OS_HOOK_DEVICE_POST<<8	; Interrupt ready, device 0 (HD)
+	int		BIOS_SYSTEM_INTERRUPT_15h
+
+	pop		ax
+	pop		di
+	iret
+
+
+;--------------------------------------------------------------------
+; AcknowledgeIdeInterruptAndSetTaskFlag
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AcknowledgeIdeInterruptAndSetTaskFlag:
+	push	ds
+	push	si
+	push	dx
+	push	bx
+
+	; Reading Status Register acknowledges IDE interrupt
+	call	RamVars_GetSegmentToDS
+	mov		bl, FLGH_DPT_INTERRUPT_IN_SERVICE
+	call	FindDPT_ToDSDIforFlagsHighInBL
+	INPUT_TO_AL_FROM_IDE_REGISTER STATUS_REGISTER_in
+
+	; Clear Interrupt In-Service Flag from DPT
+	and		BYTE [di+DPT.bFlagsHigh], ~FLGH_DPT_INTERRUPT_IN_SERVICE
+
+	; Set Task Flag
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	mov		BYTE [BDA.bHDTaskFlg], 0FFh		; Set task flag
+
+	pop		bx
+	pop		dx
+	pop		si
+	pop		ds
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdePioBlock.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdePioBlock.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdePioBlock.asm	(revision 516)
@@ -0,0 +1,271 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Read/Write functions for transferring
+;					block using PIO modes.
+;					These functions should only be called from IdeTransfer.asm.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+%ifdef MODULE_8BIT_IDE
+
+;--------------------------------------------------------------------
+; IdePioBlock_ReadFromXtideRev1
+;	Parameters:
+;		CX:		Block size in 512 byte sectors
+;		DX:		IDE Data port address
+;		ES:DI:	Normalized ptr to buffer to receive data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_ReadFromXtideRev1:
+	UNROLL_SECTORS_IN_CX_TO_OWORDS
+	mov		bl, 8		; Bit mask for toggling data low/high reg
+ALIGN JUMP_ALIGN
+.InswLoop:
+	%rep 8 ; WORDs
+		XTIDE_INSW
+	%endrep
+	loop	.InswLoop
+	ret
+
+
+;--------------------------------------------------------------------
+; IdePioBlock_ReadFromXtideRev2		or rev 1 with swapped A0 and A3 (chuck-mod)
+;	Parameters:
+;		CX:		Block size in 512 byte sectors
+;		DX:		IDE Data port address
+;		ES:DI:	Normalized ptr to buffer to receive data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+%ifndef USE_186			; 8086/8088 compatible WORD read
+
+ALIGN JUMP_ALIGN
+IdePioBlock_ReadFromXtideRev2:
+	UNROLL_SECTORS_IN_CX_TO_OWORDS
+ALIGN JUMP_ALIGN
+.ReadNextOword:
+	%rep 8	; WORDs
+		in		ax, dx		; Read WORD
+		stosw				; Store WORD to [ES:DI]
+	%endrep
+		loop	.ReadNextOword
+		ret
+
+%endif
+
+
+;--------------------------------------------------------------------
+; IdePioBlock_ReadFrom8bitDataPort		CF-XT when using 8-bit PIO
+;	Parameters:
+;		CX:		Block size in 512 byte sectors
+;		DX:		IDE Data port address
+;		ES:DI:	Normalized ptr to buffer to receive data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_ReadFrom8bitDataPort:
+%ifdef USE_186
+	shl		cx, 9		; Sectors to BYTEs
+	rep insb
+	ret
+
+%else ; If 8088/8086
+	UNROLL_SECTORS_IN_CX_TO_OWORDS
+ALIGN JUMP_ALIGN
+.ReadNextOword:
+	%rep 16	; BYTEs
+		in		al, dx		; Read BYTE
+		stosb				; Store BYTE to [ES:DI]
+	%endrep
+	loop	.ReadNextOword
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; IdePioBlock_WriteToXtideRev1
+;	Parameters:
+;		CX:		Block size in 512-byte sectors
+;		DX:		IDE Data port address
+;		ES:SI:	Normalized ptr to buffer containing data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_WriteToXtideRev1:
+	push	ds
+	UNROLL_SECTORS_IN_CX_TO_QWORDS
+	mov		bl, 8		; Bit mask for toggling data low/high reg
+	push	es			; Copy ES...
+	pop		ds			; ...to DS
+ALIGN JUMP_ALIGN
+.OutswLoop:
+	%rep 4	; WORDs
+		XTIDE_OUTSW
+	%endrep
+	loop	.OutswLoop
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; IdePioBlock_WriteToXtideRev2	or rev 1 with swapped A0 and A3 (chuck-mod)
+;	Parameters:
+;		CX:		Block size in 512-byte sectors
+;		DX:		IDE Data port address
+;		ES:SI:	Normalized ptr to buffer containing data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_WriteToXtideRev2:
+	UNROLL_SECTORS_IN_CX_TO_QWORDS
+	push	ds
+	push	es			; Copy ES...
+	pop		ds			; ...to DS
+ALIGN JUMP_ALIGN
+.WriteNextQword:
+	%rep 4	; WORDs
+		XTIDE_MOD_OUTSW
+	%endrep
+	loop	.WriteNextQword
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; IdePioBlock_WriteTo8bitDataPort		XT-CF when using 8-bit PIO
+;	Parameters:
+;		CX:		Block size in 512-byte sectors
+;		DX:		IDE Data port address
+;		ES:SI:	Normalized ptr to buffer containing data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_WriteTo8bitDataPort:
+
+%ifdef USE_186
+	shl		cx, 9		; Sectors to BYTEs
+	es					; Source is ES segment
+	rep outsb
+	ret
+
+%else ; If 8088/8086
+	UNROLL_SECTORS_IN_CX_TO_DWORDS
+	push	ds
+	push	es
+	pop		ds
+ALIGN JUMP_ALIGN
+.WriteNextDword:
+	%rep 4	; BYTEs
+		lodsb				; Load BYTE from [DS:SI]
+		out		dx, al		; Write BYTE
+	%endrep
+	loop	.WriteNextDword
+	pop		ds
+	ret
+%endif
+
+%endif ; MODULE_8BIT_IDE
+
+
+;--------------------------------------------------------------------
+; IdePioBlock_ReadFromXtideRev2			(when 80186/80188 instructions are available)
+; IdePioBlock_ReadFrom16bitDataPort		Normal 16-bit IDE
+; IdePioBlock_ReadFrom32bitDataPort		VLB/PCI 32-bit IDE
+;	Parameters:
+;		CX:		Block size in 512 byte sectors
+;		DX:		IDE Data port address
+;		ES:DI:	Normalized ptr to buffer to receive data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+%ifdef USE_186
+%ifdef MODULE_8BIT_IDE
+IdePioBlock_ReadFromXtideRev2:
+%endif
+%endif
+IdePioBlock_ReadFrom16bitDataPort:
+	xchg	cl, ch		; Sectors to WORDs
+	rep
+	db		6Dh			; INSW
+	ret
+
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_ReadFrom32bitDataPort:
+	db		0C1h		; SHL
+	db		0E1h		; CX
+	db		7			; 7	(Sectors to DWORDs)
+	rep
+	db		66h			; Override operand size to 32-bit
+	db		6Dh			; INSW/INSD
+	ret
+
+
+;--------------------------------------------------------------------
+; IdePioBlock_WriteTo16bitDataPort		Normal 16-bit IDE
+; IdePioBlock_WriteTo32bitDataPort		VLB/PCI 32-bit IDE
+;	Parameters:
+;		CX:		Block size in 512-byte sectors
+;		DX:		IDE Data port address
+;		ES:SI:	Normalized ptr to buffer containing data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_WriteTo16bitDataPort:
+	xchg	cl, ch		; Sectors to WORDs
+	es					; Source is ES segment
+	rep
+	db		6Fh			; OUTSW
+	ret
+
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdePioBlock_WriteTo32bitDataPort:
+	db		0C1h		; SHL
+	db		0E1h		; CX
+	db		7			; 7	(Sectors to DWORDs)
+	es					; Source is ES segment
+	rep
+	db		66h			; Override operand size to 32-bit
+	db		6Fh			; OUTSW/OUTSD
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm	(revision 516)
@@ -0,0 +1,328 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device transfer functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Structure containing variables for PIO transfer functions.
+; This struct must not be larger than IDEPACK without INTPACK.
+struc PIOVARS	; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
+	.wDataPort				resb	2	; 0-1, IDE Data Port
+	.fnXfer					resb	2	; 2-3, Offset to transfer function
+	.wSectorsInBlock		resb	2	; 4-5, Block size in sectors
+	.bSectorsLeft			resb	1	; 6, Sectors left to transfer
+							resb	1	; 7, IDEPACK.bDeviceControl
+	.bSectorsDone			resb	1	; 8, Number of sectors xferred
+endstruc
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeTransfer_StartWithCommandInAL
+;	Parameters:
+;		AL:		IDE command that was used to start the transfer
+;				(all PIO read and write commands including Identify Device)
+;		ES:SI:	Ptr to data buffer
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, DX, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeTransfer_StartWithCommandInAL:
+	; Are we reading or writing?
+	test	al, 16	; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
+	mov		ah, [bp+IDEPACK.bSectorCount]
+	jnz		SHORT WriteToDrive
+	cmp		al, COMMAND_WRITE_MULTIPLE
+	je		SHORT WriteToDrive
+	; Fall to ReadFromDrive
+
+;--------------------------------------------------------------------
+; ReadFromDrive
+;	Parameters:
+;		AH:		Number of sectors to transfer (1...128)
+;		ES:SI:	Ptr to buffer to receive data
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to PIOVARS
+;	Returns:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		AH:		BIOS Error code
+;		CX:		Number of successfully transferred sectors
+;		CF:		0 if transfer successful
+;				1 if any error
+;	Corrupts registers:
+;		AL, BX, DX, SI, ES
+;--------------------------------------------------------------------
+ReadFromDrive:
+	; Prepare to read data to ESSI
+	mov		bx, g_rgfnPioRead
+	call	InitializePiovarsInSSBPwithSectorCountInAH
+
+	; Wait until drive is ready to transfer
+	call	IdeWait_IRQorDRQ					; Wait until ready to transfer
+	jc		SHORT ReturnWithTransferErrorInAH
+	xchg	si, di								; ES:DI now points buffer
+
+	mov		cx, [bp+PIOVARS.wSectorsInBlock]	; Max 128
+
+ALIGN JUMP_ALIGN
+.ReadNextBlockFromDrive:
+	mov		dx, [bp+PIOVARS.wDataPort]
+	cmp		[bp+PIOVARS.bSectorsLeft], cl
+	jbe		SHORT .ReadLastBlockFromDrive
+	call	[bp+PIOVARS.fnXfer]
+
+	; Wait until ready for next block and check for errors
+	xchg	di, si								; DS:DI now points DPT
+	call	IdeWait_IRQorDRQ					; Wait until ready to transfer
+	jc		SHORT ReturnWithTransferErrorInAH
+	xchg	si, di								; ES:DI now points buffer
+
+	; Increment number of successfully read sectors
+	mov		cx, [bp+PIOVARS.wSectorsInBlock]
+	sub		[bp+PIOVARS.bSectorsLeft], cl
+	add		[bp+PIOVARS.bSectorsDone], cl
+	jmp		SHORT .ReadNextBlockFromDrive
+
+ALIGN JUMP_ALIGN
+.ReadLastBlockFromDrive:
+	mov		cl, [bp+PIOVARS.bSectorsLeft]		; CH is already zero
+	push	cx
+	call	[bp+PIOVARS.fnXfer]					; Transfer possibly partial block
+
+	; Check for errors in last block
+	mov		di, si								; DS:DI now points DPT
+CheckErrorsAfterTransferringLastBlock:
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
+	call	IdeWait_PollStatusFlagInBLwithTimeoutInBH
+	pop		cx	; [bp+PIOVARS.bSectorsLeft]
+	jc		SHORT ReturnWithTransferErrorInAH
+
+	; All sectors successfully transferred
+	add		cx, [bp+PIOVARS.bSectorsDone]		; Never sets CF
+	ret
+
+	; Return number of successfully read sectors
+ReturnWithTransferErrorInAH:
+%ifdef USE_386
+	movzx	cx, [bp+PIOVARS.bSectorsDone]
+%else
+	mov		cl, [bp+PIOVARS.bSectorsDone]
+	mov		ch, 0								; Preserve CF
+%endif
+	ret
+
+
+;--------------------------------------------------------------------
+; WriteToDrive
+;	Parameters:
+;		AH:		Number of sectors to transfer (1...128)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		ES:SI:	Ptr to buffer containing data
+;		SS:BP:	Ptr to PIOVARS
+;	Returns:
+;		AH:		BIOS Error code
+;		CX:		Number of successfully transferred sectors
+;		CF:		0 if transfer successful
+;				1 if any error
+;	Corrupts registers:
+;		AL, BX, DX, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+WriteToDrive:
+	; Prepare to write data from ESSI
+	mov		bx, g_rgfnPioWrite
+	call	InitializePiovarsInSSBPwithSectorCountInAH
+
+	; Always poll when writing first block (IRQs are generated for following blocks)
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+	call	IdeWait_PollStatusFlagInBLwithTimeoutInBH
+	jc		SHORT ReturnWithTransferErrorInAH
+
+	mov		cx, [bp+PIOVARS.wSectorsInBlock]	; Max 128
+
+ALIGN JUMP_ALIGN
+.WriteNextBlockToDrive:
+	mov		dx, [bp+PIOVARS.wDataPort]
+	cmp		[bp+PIOVARS.bSectorsLeft], cl
+	jbe		SHORT .WriteLastBlockToDrive
+	call	[bp+PIOVARS.fnXfer]
+
+	; Wait until ready for next block and check for errors
+	call	IdeWait_IRQorDRQ					; Wait until ready to transfer
+	jc		SHORT ReturnWithTransferErrorInAH
+
+	; Increment number of successfully written sectors
+	mov		cx, [bp+PIOVARS.wSectorsInBlock]
+	sub		[bp+PIOVARS.bSectorsLeft], cl
+	add		[bp+PIOVARS.bSectorsDone], cl
+	jmp		SHORT .WriteNextBlockToDrive
+
+ALIGN JUMP_ALIGN
+.WriteLastBlockToDrive:
+	mov		cl, [bp+PIOVARS.bSectorsLeft]		; CH is already zero
+	push	cx
+%ifdef USE_186
+	push	CheckErrorsAfterTransferringLastBlock
+	jmp		[bp+PIOVARS.fnXfer]					; Transfer possibly partial block
+%else
+	call	[bp+PIOVARS.fnXfer]					; Transfer possibly partial block
+	jmp		SHORT CheckErrorsAfterTransferringLastBlock
+%endif
+
+
+;--------------------------------------------------------------------
+; InitializePiovarsInSSBPwithSectorCountInAH
+;	Parameters:
+;		AH:		Number of sectors to transfer (1...128)
+;		BX:		Offset to transfer function lookup table
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		ES:SI:	Ptr to data buffer
+;		SS:BP:	Ptr to PIOVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+InitializePiovarsInSSBPwithSectorCountInAH:
+	; Store sizes and Data Port
+	mov		[bp+PIOVARS.bSectorsLeft], ah
+	mov		ax, [di+DPT.wBasePort]
+	mov		[bp+PIOVARS.wDataPort], ax
+	eMOVZX	ax, [di+DPT_ATA.bBlockSize]
+	mov		[bp+PIOVARS.wSectorsInBlock], ax
+	mov		[bp+PIOVARS.bSectorsDone], ah		; Zero
+
+	; Get transfer function based on bus type
+	xchg	ax, bx								; Lookup table offset to AX
+	mov		bl, [di+DPT_ATA.bDevice]
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	mov		dl, bl
+%endif
+	add		bx, ax
+	mov		ax, [cs:bx]							; Load offset to transfer function
+	mov		[bp+PIOVARS.fnXfer], ax
+
+	; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	cmp		dl, DEVICE_8BIT_XTCF_DMA
+	jb		SHORT IdeTransfer_NormalizePointerInESSI
+
+	; Convert ES:SI to physical address
+%ifdef USE_186			; Bytes	EU Cycles(286)
+	mov		ax, es		; 2		2
+	rol		ax, 4		; 3		9
+	mov		dx, ax		; 2		2
+	and		ax, BYTE 0Fh; 3		3
+	xor		dx, ax		; 2		2
+	add		si, dx		; 2		2
+	adc		al, ah		; 2		2
+	mov		es, ax		; 2		2
+	;------------------------------------
+						; 18	24
+%else ; 808x
+
+%if 0
+						; Bytes	EU Cycles(808x)
+	mov		al, 4		; 2		4
+	mov		dx, es		; 2		2
+	xchg	cx, ax		; 1		3
+	rol		dx, cl		; 2		24
+	mov		cx, dx		; 2		2
+	xchg	cx, ax		; 1		3
+	and		ax, BYTE 0Fh; 3		4
+	xor		dx, ax		; 2		3
+	add		si, dx		; 2		3
+	adc		al, ah		; 2		3
+	mov		es, ax		; 2		2
+	;------------------------------------
+						; 21	53
+;
+; Judging by the Execution Unit cycle count the above block of code is
+; apparently slower. However, the shifts and rotates in the block below
+; execute faster than the Bus Interface Unit on an 8088 can fetch them,
+; thus causing the EU to starve. The difference in true execution speed
+; (if any) might not be worth the extra 5 bytes.
+; In other words, we could use a real world test here.
+;
+%endif ; 0
+						; Bytes	EU Cycles(808x/286)
+	xor		dx, dx		; 2		3/2
+	mov		ax, es		; 2		2/2
+%rep 4
+	shl		ax, 1		; 8		8/8
+	rcl		dx, 1		; 8		8/8
+%endrep
+	add		si, ax		; 2		3/2
+	adc		dl, dh		; 2		3/2
+	mov		es, dx		; 2		2/2
+	;------------------------------------
+%endif					; 26	29/26
+	ret
+%endif ; MODULE_8BIT_IDE_ADVANCED
+	; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE
+
+
+;--------------------------------------------------------------------
+; IdeTransfer_NormalizePointerInESSI
+;	Parameters:
+;		ES:SI:	Ptr to be normalized
+;	Returns:
+;		ES:SI:	Normalized pointer (SI = 0...15)
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+IdeTransfer_NormalizePointerInESSI:
+	NORMALIZE_FAR_POINTER	es, si, ax, dx
+	ret
+
+
+; Lookup tables to get transfer function based on bus type
+ALIGN WORD_ALIGN
+g_rgfnPioRead:
+		dw		IdePioBlock_ReadFrom16bitDataPort	; 0, DEVICE_16BIT_ATA
+		dw		IdePioBlock_ReadFrom32bitDataPort	; 1, DEVICE_32BIT_ATA
+%ifdef MODULE_8BIT_IDE
+		dw		IdePioBlock_ReadFrom8bitDataPort	; 2, DEVICE_8BIT_ATA
+		dw		IdePioBlock_ReadFromXtideRev1		; 3, DEVICE_8BIT_XTIDE_REV1
+		dw		IdePioBlock_ReadFromXtideRev2		; 4, DEVICE_8BIT_XTIDE_REV2
+%ifdef MODULE_8BIT_IDE_ADVANCED
+		dw		IdePioBlock_ReadFrom8bitDataPort	; 5, DEVICE_8BIT_XTCF_PIO8
+		dw		IdeDmaBlock_ReadFromXTCF			; 6, DEVICE_8BIT_XTCF_DMA
+%endif
+%endif
+
+
+g_rgfnPioWrite:
+		dw		IdePioBlock_WriteTo16bitDataPort	; 0, DEVICE_16BIT_ATA
+		dw		IdePioBlock_WriteTo32bitDataPort	; 1, DEVICE_32BIT_ATA
+%ifdef MODULE_8BIT_IDE
+		dw		IdePioBlock_WriteTo8bitDataPort		; 2, DEVICE_8BIT_ATA
+		dw		IdePioBlock_WriteToXtideRev1		; 3, DEVICE_8BIT_XTIDE_REV1
+		dw		IdePioBlock_WriteToXtideRev2		; 4, DEVICE_8BIT_XTIDE_REV2
+%ifdef MODULE_8BIT_IDE_ADVANCED		
+		dw		IdePioBlock_WriteTo8bitDataPort		; 5, DEVICE_8BIT_XTCF_PIO8
+		dw		IdeDmaBlock_WriteToXTCF				; 6, DEVICE_8BIT_XTCF_DMA
+%endif
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeWait.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeWait.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/IdeWait.asm	(revision 516)
@@ -0,0 +1,135 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device wait functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeWait_IRQorDRQ
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK, PIOVARS or MEMPIOVARS
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+IdeWait_IRQorDRQ:
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+
+%ifdef MODULE_IRQ
+	test	BYTE [bp+IDEPACK.bDeviceControl], FLG_DEVCONTROL_nIEN
+	jnz		SHORT IdeWait_PollStatusFlagInBLwithTimeoutInBH	; Interrupt disabled
+%endif
+	; Fall to IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
+
+
+;--------------------------------------------------------------------
+; IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
+;	Parameters:
+;		BH:		Timeout ticks
+;		BL:		IDE Status Register bit to wait
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+IdeWait_IRQorStatusFlagInBLwithTimeoutInBH:
+%ifdef MODULE_IRQ
+	call	IdeIrq_WaitForIRQ
+%endif
+	; Always fall to IdeWait_PollStatusFlagInBLwithTimeoutInBH for error processing
+
+
+;--------------------------------------------------------------------
+; IdeWait_PollStatusFlagInBLwithTimeoutInBH
+;	Parameters:
+;		BH:		Timeout ticks
+;		BL:		IDE Status Register bit to poll
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+IdeWait_PollStatusFlagInBLwithTimeoutInBH:
+	mov		ah, bl
+	mov		cl, bh
+	call	Timer_InitializeTimeoutWithTicksInCL
+	and		ah, ~FLG_STATUS_BSY
+	jz		SHORT PollBsyOnly
+	; Fall to PollBsyAndFlgInAH
+
+;--------------------------------------------------------------------
+; PollBsyAndFlgInAH
+;	Parameters:
+;		AH:		Status Register Flag to poll (until set) when device not busy
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		BIOS Error code
+;		CF:		Clear if wait completed successfully (no errors)
+;				Set if any error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+PollBsyAndFlgInAH:
+	call	IdeIO_InputStatusRegisterToAL		; Discard contents of first read
+
+.PollLoop:
+	call	IdeIO_InputStatusRegisterToAL
+	test	al, FLG_STATUS_BSY					; Controller busy?
+	jnz		SHORT .UpdateTimeout				;  If so, jump to timeout update
+	test	al, ah								; Test secondary flag
+	jnz		SHORT IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL
+.UpdateTimeout:
+	call	Timer_SetCFifTimeout
+	jnc		SHORT .PollLoop						; Loop if time left
+	call	IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL
+	jc		SHORT .ReturnErrorCodeInAH
+	mov		ah, RET_HD_TIMEOUT					; Expected bit never got set
+	stc
+.ReturnErrorCodeInAH:
+	ret
+
+
+;--------------------------------------------------------------------
+; PollBsyOnly
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		BIOS Error code
+;		CF:		Clear if wait completed successfully (no errors)
+;				Set if any error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+PollBsyOnly:
+	call	IdeIO_InputStatusRegisterToAL		; Discard contents of first read
+
+.PollLoop:
+	call	IdeIO_InputStatusRegisterToAL
+	test	al, FLG_STATUS_BSY					; Controller busy?
+	jz		SHORT IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL
+	call	Timer_SetCFifTimeout				; Update timeout counter
+	jnc		SHORT .PollLoop						; Loop if time left (sets CF on timeout)
+	jmp		SHORT IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/JrIdeTransfer.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/JrIdeTransfer.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/IDE/JrIdeTransfer.asm	(revision 516)
@@ -0,0 +1,296 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Memory mapped IDE Device transfer functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Structure containing variables for PIO transfer functions.
+; This struct must not be larger than IDEPACK without INTPACK.
+struc MEMPIOVARS	; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
+	.wSectorsInBlock		resb	2	; 0-1, Block size in sectors
+	.fpDPT					resb	4	; 2-5, Far pointer to DPT
+	.bSectorsLeft			resb	1	; 6, Sectors left to transfer
+							resb	1	; 7, IDEPACK.bDeviceControl
+	.bSectorsDone			resb	1	; 8, Number of sectors xferred
+endstruc
+
+SECTOR_ACCESS_WINDOW_SIZE	EQU		512	; 512 bytes
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; JrIdeTransfer_StartWithCommandInAL
+;	Parameters:
+;		AL:		IDE command that was used to start the transfer
+;				(all PIO read and write commands including Identify Device)
+;		ES:SI:	Ptr to data buffer
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, DX, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+JrIdeTransfer_StartWithCommandInAL:
+	; Initialize MEMPIOVARS
+	xchg	cx, ax			; IDE command to CL
+	xor		ax, ax
+	mov		[bp+MEMPIOVARS.bSectorsDone], al
+	mov		al, [bp+IDEPACK.bSectorCount]
+	mov		[bp+MEMPIOVARS.bSectorsLeft], al
+	mov		al, [di+DPT_ATA.bBlockSize]
+	mov		[bp+MEMPIOVARS.wSectorsInBlock], ax
+	mov		[bp+MEMPIOVARS.fpDPT], di
+	mov		[bp+MEMPIOVARS.fpDPT+2], ds
+
+	; Normalize pointer
+	call	IdeTransfer_NormalizePointerInESSI
+
+	; Get far pointer to Sector Access Window
+	mov		dx, [di+DPT.wBasePort]
+	cmp		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
+	jne		SHORT .GetSectorAccessWindowForXTCF
+
+	; Get Sector Access Window for JR-IDE/ISA
+	mov		di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
+	mov		ds, dx		; Segment for JR-IDE/ISA
+	jmp		SHORT .SectorAccessWindowLoadedToDSDI
+
+.GetSectorAccessWindowForXTCF:
+	xor		di, di
+	add		dl, XTCF_CONTROL_REGISTER
+	in		al, dx					; Read high byte for Sector Access Window segment
+	xchg	ah, al
+	mov		ds, ax
+
+	; Are we reading or writing?
+.SectorAccessWindowLoadedToDSDI:
+	test	cl, 16	; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
+	jnz		SHORT WriteToSectorAccessWindow
+	cmp		cl, COMMAND_WRITE_MULTIPLE
+	je		SHORT WriteToSectorAccessWindow
+	; Fall to ReadFromSectorAccessWindow
+
+;--------------------------------------------------------------------
+; ReadFromSectorAccessWindow
+;	Parameters:
+;		DS:DI:	Ptr to Sector Access Window
+;		ES:SI:	Normalized ptr to buffer to receive data
+;		SS:BP:	Ptr to MEMPIOVARS
+;	Returns:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		AH:		BIOS Error code
+;		CX:		Number of successfully transferred sectors
+;		CF:		0 if transfer successful
+;				1 if any error
+;	Corrupts registers:
+;		AL, BX, DX, SI
+;--------------------------------------------------------------------
+ReadFromSectorAccessWindow:
+	xchg	si, di	; DS:SI = source, ES:DI = Destination
+	call	WaitUntilReadyToTransferNextBlock
+	jc		SHORT ReturnWithMemoryIOtransferErrorInAH
+
+	mov		cx, [bp+MEMPIOVARS.wSectorsInBlock]	; Clears CH
+	cmp		[bp+MEMPIOVARS.bSectorsLeft], cl
+	jbe		SHORT .ReadLastBlockFromDrive
+
+ALIGN JUMP_ALIGN
+.ReadNextBlockFromDrive:
+	call	ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
+	call	WaitUntilReadyToTransferNextBlock
+	jc		SHORT ReturnWithMemoryIOtransferErrorInAH
+
+	; Update number of successfully read sectors and sectors left to transfer.
+	; We cannot use SUB instruction as a comparison since it will not
+	; work in this situation:
+	; Before SUB we have 2 full blocks left to transfer. SUB command
+	; then compares 2 full blocks against one full block and updates
+	; sectors left to one full block and jumps to .ReadNextBlockFromDrive,
+	; since we have one full block left to transfer. After it has been
+	; transferred, there will be a wait for next block but DRQ is never
+	; set since all is transferred! Then we get timeout error.
+	mov		cx, [bp+MEMPIOVARS.wSectorsInBlock]
+	sub		[bp+MEMPIOVARS.bSectorsLeft], cl
+	add		[bp+MEMPIOVARS.bSectorsDone], cl
+	cmp		[bp+MEMPIOVARS.bSectorsLeft], cl
+	ja		SHORT .ReadNextBlockFromDrive
+
+ALIGN JUMP_ALIGN
+.ReadLastBlockFromDrive:
+	mov		cl, [bp+MEMPIOVARS.bSectorsLeft]
+	push	cx
+	call	ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
+
+	; Check for errors in last block
+CheckErrorsAfterTransferringLastMemoryMappedBlock:
+	lds		di, [bp+MEMPIOVARS.fpDPT]			; DPT now in DS:DI
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
+	call	IdeWait_PollStatusFlagInBLwithTimeoutInBH
+	pop		cx	; [bp+MEMPIOVARS.bSectorsLeft]
+	jc		SHORT ReturnWithMemoryIOtransferErrorInAH
+
+	; All sectors successfully transferred
+	add		cl, [bp+MEMPIOVARS.bSectorsDone]	; Never sets CF
+	ret
+
+	; Return number of successfully transferred sectors
+ReturnWithMemoryIOtransferErrorInAH:
+	lds		di, [bp+MEMPIOVARS.fpDPT]			; DPT now in DS:DI
+%ifdef USE_386
+	movzx	cx, BYTE [bp+MEMPIOVARS.bSectorsDone]
+%else
+	mov		ch, 0								; Preserve CF
+	mov		cl, [bp+MEMPIOVARS.bSectorsDone]
+%endif
+	ret
+
+
+;--------------------------------------------------------------------
+; WriteToSectorAccessWindow
+;	Parameters:
+;		DS:DI:	Ptr to Sector Access Window
+;		ES:SI:	Normalized ptr to buffer containing data
+;		SS:BP:	Ptr to MEMPIOVARS
+;	Returns:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		AH:		BIOS Error code
+;		CX:		Number of successfully transferred sectors
+;		CF:		0 if transfer successful
+;				1 if any error
+;	Corrupts registers:
+;		AL, BX, DX, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+WriteToSectorAccessWindow:
+	push	es
+	push	ds
+	pop		es		; ES:DI = Sector Access Window (destination)
+	pop		ds		; DS:SI = Ptr to source buffer
+
+	; Always poll when writing first block (IRQs are generated for following blocks)
+	call	WaitUntilReadyToTransferNextBlock
+	jc		SHORT ReturnWithMemoryIOtransferErrorInAH
+
+	mov		cx, [bp+MEMPIOVARS.wSectorsInBlock]
+	cmp		[bp+MEMPIOVARS.bSectorsLeft], cl
+	jbe		SHORT .WriteLastBlockToDrive
+
+ALIGN JUMP_ALIGN
+.WriteNextBlockToDrive:
+	call	WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
+	call	WaitUntilReadyToTransferNextBlock
+	jc		SHORT ReturnWithMemoryIOtransferErrorInAH
+
+	; Increment number of successfully written WORDs
+	mov		cx, [bp+MEMPIOVARS.wSectorsInBlock]
+	sub		[bp+MEMPIOVARS.bSectorsLeft], cl
+	add		[bp+MEMPIOVARS.bSectorsDone], cl
+	cmp		[bp+MEMPIOVARS.bSectorsLeft], cl
+	ja		SHORT .WriteNextBlockToDrive
+
+ALIGN JUMP_ALIGN
+.WriteLastBlockToDrive:
+	mov		cl, [bp+MEMPIOVARS.bSectorsLeft]
+	push	cx
+	ePUSH_T	bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
+	; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
+
+;--------------------------------------------------------------------
+; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
+;	Parameters:
+;		CX:		Number of sectors in block
+;		DS:SI:	Normalized ptr to source buffer
+;		ES:DI:	Ptr to Sector Access Window
+;	Returns:
+;		CX, DX:	Zero
+;		SI:		Updated
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
+	mov		bx, di
+	mov		dx, cx
+	xor		cl, cl
+ALIGN JUMP_ALIGN
+.WriteNextSector:
+	mov		ch, SECTOR_ACCESS_WINDOW_SIZE >> 9
+	rep movsw
+	mov		di, bx	; Reset for next sector
+	dec		dx
+	jnz		SHORT .WriteNextSector
+	ret
+
+
+;--------------------------------------------------------------------
+; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
+;	Parameters:
+;		CX		Number of sectors in full block or sectors in last partial block
+;		ES:DI:	Normalized ptr to buffer to receive data (destination)
+;		DS:SI:	Ptr to Sector Access Window (source)
+;	Returns:
+;		CX, DX:	Zero
+;		DI:		Updated
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
+	mov		bx, si
+	mov		dx, cx
+	xor		cl, cl
+ALIGN JUMP_ALIGN
+.ReadNextSector:
+	mov		ch, SECTOR_ACCESS_WINDOW_SIZE >> 9
+	rep movsw
+	mov		si, bx	; Reset for next sector
+	dec		dx
+	jnz		SHORT .ReadNextSector
+	ret
+
+
+;--------------------------------------------------------------------
+; WaitUntilReadyToTransferNextBlock
+;	Parameters:
+;		SS:BP:	Ptr to MEMPIOVARS
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+WaitUntilReadyToTransferNextBlock:
+	push	ds
+	push	di
+	lds		di, [bp+MEMPIOVARS.fpDPT]	; DPT now in DS:DI
+	call	IdeWait_IRQorDRQ			; Always polls
+	pop		di
+	pop		ds
+	ret
+
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS		
+%if SECTOR_ACCESS_WINDOW_SIZE <> 512
+	%error "SECTOR_ACCESS_WINDOW_SIZE is no longer equal to 512. JrIdeTransfer.asm needs changes."
+%endif
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Idepack.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Idepack.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Idepack.asm	(revision 516)
@@ -0,0 +1,159 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for managing IDEPACK struct.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Idepack_FakeToSSBP
+;	Parameters:
+;		Nothing
+;	Returns:
+;		SS:BP:	Ptr to IDEPACK
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+Idepack_FakeToSSBP:
+	pop		ax
+	sub		sp, BYTE SIZE_OF_IDEPACK_WITHOUT_INTPACK
+	mov		bp, sp
+	jmp		ax
+
+
+;--------------------------------------------------------------------
+; Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+;	Parameters:
+;		AH:		IDE command to issue
+;		BH:		Timeout ticks
+;		BL:		IDE Status Register flag to wait after command
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		ES:SI:	Ptr to DAP (EBIOS Disk Address Packet)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors (for transfer commands)
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, (CX), DX, SI, ES
+;--------------------------------------------------------------------
+%ifdef MODULE_EBIOS
+ALIGN JUMP_ALIGN
+Idepack_ConvertDapToIdepackAndIssueCommandFromAH:
+	mov		al, [es:si+DAP.wSectorCount]
+	mov		[bp+IDEPACK.bSectorCount], al
+	mov		[bp+IDEPACK.bCommand], ah
+
+	mov		al, [es:si+DAP.qwLBA]		; LBA byte 0
+	mov		[bp+IDEPACK.bLbaLow], al
+	mov		ax, [es:si+DAP.qwLBA+1]		; LBA bytes 1 and 2
+	mov		[bp+IDEPACK.wLbaMiddleAndHigh], ax
+	mov		ah, [es:si+DAP.qwLBA+3]		; LBA byte 3, LBA28 bits 24...27
+	mov		[bp+IDEPACK.bLbaLowExt], ah
+	mov		cx, [es:si+DAP.qwLBA+4]		; LBA bytes 4 and 5
+	mov		[bp+IDEPACK.wLbaMiddleAndHighExt], cx
+
+	and		ah, 0Fh						; Limit bits for LBA28
+	call	AccessDPT_GetDriveSelectByteForEbiosToAL
+	or		al, ah
+	mov		[bp+IDEPACK.bDrvAndHead], al
+
+	; Load data buffer pointer to ES:SI
+	les		si, [es:si+DAP.dwMemoryAddress]
+	jmp		SHORT GetDeviceControlByteToIdepackAndStartTransfer
+%endif ; MODULE_EBIOS
+
+
+;--------------------------------------------------------------------
+; Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+;	Parameters:
+;		AH:		IDE command to issue
+;		AL:		Number of sectors to transfer (for xfer commands)
+;		BH:		Timeout ticks
+;		BL:		IDE Status Register flag to wait after command
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Starting sector number (1...63)
+;		DH:		Starting head number (0...255)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		ES:SI:	Ptr to normalized data buffer (for xfer commands)
+;		SS:BP:	Ptr to IDEPACK (containing INTPACK)
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors (for transfer commands)
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, (CX), DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH:
+	mov		[bp+IDEPACK.bSectorCount], al
+	mov		[bp+IDEPACK.bCommand], ah
+
+	push	bx
+	call	Address_OldInt13hAddressToIdeAddress
+	call	AccessDPT_GetDriveSelectByteForOldInt13hToAL
+	or		al, bh			; AL now has Drive and Head Select Byte
+	mov		[bp+IDEPACK.bDrvAndHead], al
+	mov		[bp+IDEPACK.bLbaLow], bl
+	mov		[bp+IDEPACK.wLbaMiddleAndHigh], cx
+	pop		bx
+
+GetDeviceControlByteToIdepackAndStartTransfer:
+	call	AccessDPT_GetDeviceControlByteToAL
+	mov		[bp+IDEPACK.bDeviceControl], al
+	jmp		Device_OutputCommandWithParameters
+
+
+;--------------------------------------------------------------------
+; Idepack_StoreNonExtParametersAndIssueCommandFromAL
+;	Parameters:
+;		BH:		Timeout ticks
+;		BL:		IDE Status Register flag to wait after command
+;		AL:		IDE command to issue
+;		AH:		Parameter to Drive and Head Select Register (Head bits only)
+;		DL:		Parameter to Sector Count Register
+;		DH:		Parameter to LBA Low / Sector Number Register
+;		CL:		Parameter to LBA Middle / Cylinder Low Register
+;		CH:		Parameter to LBA High / Cylinder High Register
+;		SI:		Parameter to Features Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Idepack_StoreNonExtParametersAndIssueCommandFromAL:
+	mov		[bp+IDEPACK.bFeatures], si
+	mov		[bp+IDEPACK.bCommand], al
+	mov		[bp+IDEPACK.wSectorCountAndLbaLow], dx
+	mov		[bp+IDEPACK.wLbaMiddleAndHigh], cx
+
+	; Drive and Head select byte
+	and		ah, MASK_DRVNHEAD_HEAD		; Keep head bits only
+	call	AccessDPT_GetDriveSelectByteForOldInt13hToAL
+	or		al, ah
+	mov		[bp+IDEPACK.bDrvAndHead], al
+
+	; Device Control byte with interrupts disabled
+	mov		BYTE [bp+IDEPACK.bDeviceControl], FLG_DEVCONTROL_nIEN
+
+	jmp		Device_OutputCommandWithParameters
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm	(revision 516)
@@ -0,0 +1,198 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Serial Device Command functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+%define SERIALSERVER_AH_ALREADY_HAS_COMMAND_BYTE
+%define SERIALSERVER_NO_ZERO_SECTOR_COUNTS		
+
+;--------------------------------------------------------------------
+; SerialCommand_OutputWithParameters
+;	Parameters:
+;		BH:		Non-zero if 48-bit addressing used
+;               (ignored at present as 48-bit addressing is not supported)
+;		BL:		IDE Status Register bit to poll after command
+;               (ignored at present, since there is no IDE status register to poll)
+;		ES:SI:	Ptr to buffer (for data transfer commands)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors (for transfer commands)
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, (ES:SI for data transfer commands)
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SerialCommand_OutputWithParameters:
+
+		mov		ah,SerialServer_Command_Read
+
+		mov		al,[bp+IDEPACK.bCommand]
+
+		cmp		al,20h			; Read Sectors IDE command
+		jz		.readOrWrite
+		inc		ah				; now SerialServer_Protocol_Write
+		cmp		al,30h			; Write Sectors IDE command
+		jz		.readOrWrite
+
+;  all other commands return success
+;  including function 0ech which should return drive information, this is handled with the identify functions
+;
+		xor		ah,ah			;  also clears carry
+		ret
+
+.readOrWrite:
+		mov		[bp+IDEPACK.bFeatures],ah		; store protocol command		
+		call	IdeTransfer_NormalizePointerInESSI
+				
+		mov		dx, [di+DPT_SERIAL.wSerialPortAndBaud]
+
+; fall through to SerialCommand_FallThroughToSerialServer_SendReceive
+		
+ALIGN JUMP_ALIGN
+SerialCommand_FallThroughToSerialServer_SendReceive:		
+
+; fall through to SerialServer_SendReceive
+		
+%include "SerialServer.asm"
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS		
+	%if SerialCommand_FallThroughToSerialServer_SendReceive <> SerialServer_SendReceive
+		%error "SerialServer_SendReceive must be the first routine at the top of SerialServer.asm in the Assembly_Library"
+	%endif
+%endif
+
+ALIGN JUMP_ALIGN		
+SerialCommand_ReturnError:		
+		stc
+		ret		
+
+;--------------------------------------------------------------------
+; SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Select Register
+;		DS:		Segment to RAMVARS
+;		ES:SI:	Ptr to buffer to receive 512-byte IDE Information
+;		CS:BP:	Ptr to IDEVARS
+;	Returns:
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BL, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH:
+;
+; To improve boot time, we do our best to avoid looking for slave serial drives when we already know the results
+; from the looking for a master.  This is particularly true when doing a COM port scan, as we will end up running
+; through all the COM ports and baud rates a second time.
+;
+; But drive detection isn't the only case - we also need to get the right drive when called on int13h/25h.
+;
+; The decision tree:
+;
+;    Master:
+;		   wSerialPortAndBaud Non-Zero:           -> Continue with wSerialPortAndBaud (1)
+;		   wSerialPortAndBaud Zero:
+;		       previous serial drive not found:   -> Scan (2)
+;		       previous serial drive found:       -> Continue with previous serial drive info (3)
+;
+;    Slave:
+;		   wSerialPortAndBaud Non-Zero:
+;		   	   previous serial drive not found:   -> Error - Not Found (4)
+;			   previous serial drive found:       -> Continue with wSerialPackedAndBaud (5)
+;          wSerialPortAndBaud Zero:
+;		   	   previous serial drive not found:	  -> Error - Not Found (4)
+;			   previous serial drive found:       -> Continue with previous serial drive info (6)
+;
+; (1) This was a port/baud that was explicitly set with the configurator.  In the drive detection case, as this
+;     is the Master, we are checking out a new controller, and so don't care if we already have a serial drive.
+;     And as with the int13h/25h case, we just go off and get the needed information using the user's setting.
+; (2) We are using the special .ideVarsSerialAuto structure.  During drive detection, we would only be here
+;     if we hadn't already seen a serial drive (since we only scan if no explicit drives are set),
+;     so we go off to scan.
+; (3) We are using the special .ideVarsSerialAuto structure.  We won't get here during drive detection, but
+;     we might get here on an int13h/25h call.  If we have scanned COM drives, they are the ONLY serial drives
+;     in use, and so we use the values from the previously seen serial drive DPT.
+; (4) No master has been found yet, therefore no slave should be found.  Avoiding the slave reduces boot time,
+;     especially in the full COM port scan case.  Note that this is different from the hardware IDE, where we
+;     will scan for a slave even if a master is not present.  Note that if ANY master had been previously found,
+;     we will do the slave scan, which isn't harmful, it just wastes time.  But the most common case (by a wide
+;     margin) will be just one serial controller.
+; (5) A COM port scan for a master had been previously completed, and a drive was found.  In a multiple serial
+;     controller scenario being called with int13h/25h, we need to use the value in bSerialPackedPortAndBaud
+;     to make sure we get the proper drive.
+; (6) A COM port scan for a master had been previously completed, and a drive was found.  We would only get here
+;     if no serial drive was explicitly set by the user in the configurator or that drive had not been found.
+;     Instead of performing the full COM port scan for the slave, use the port/baud value stored during the
+;     master scan.
+;
+		mov		dx,[cs:bp+IDEVARS.wSerialPortAndBaud]
+		xor		ax,ax
+		
+		push	si
+		call	FindDPT_ToDSDIforSerialDevice
+		pop		si
+%ifdef MODULE_SERIAL_FLOPPY
+		jnc		.founddpt
+;
+; If not found above with FindDPT_ToDSDIforSerialDevice, DI will point to the DPT after the last hard disk DPT
+; So, if there was a previously found floppy disk, DI will point to that DPT and we use that value for the slave.
+;
+		cmp		byte [RAMVARS.xlateVars+XLATEVARS.bFlopCntAndFirst], 0
+		jz		.notfounddpt
+.founddpt:
+%else
+		jc		.notfounddpt
+%endif
+		mov		ax, [di+DPT_SERIAL.wSerialPortAndBaud]
+.notfounddpt:
+
+		test	bh, FLG_DRVNHEAD_DRV
+		jz		.master
+
+		test	ax,ax			; Take care of the case that is different between master and slave.
+		jz		SerialCommand_ReturnError
+
+; fall-through
+.master:
+		test	dx,dx
+		jnz		.identifyDeviceInDX
+
+		xchg	dx, ax			;  move ax to dx (move previously found serial drive to dx, could be zero)
+
+.identifyDeviceInDX:
+
+; fall through to SerialCommand_FallThroughToSerialServerScan_ScanForServer
+		
+ALIGN JUMP_ALIGN
+SerialCommand_FallThroughToSerialServerScan_ScanForServer:
+
+; fall through to SerialServerScan_ScanForServer
+		
+%include "SerialServerScan.asm"
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS				
+	%if SerialCommand_FallThroughToSerialServerScan_ScanForServer <> SerialServerScan_ScanForServer
+		%error "SerialServerScan_ScanForServer must be the first routine at the top of SerialServerScan.asm in the Assembly_Library"
+	%endif
+%endif
+
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Serial/SerialDPT.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Serial/SerialDPT.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Serial/SerialDPT.asm	(revision 516)
@@ -0,0 +1,53 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Sets Serial Device specific parameters to DPT.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; SerialDPT_Finalize
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		CF:		Set, indicates that this is a floppy disk
+;               Clear, indicates that this is a hard disk
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+SerialDPT_Finalize:
+		mov		ax, [es:si+SerialServer_ATA_wPortAndBaud]
+		mov		[di+DPT_SERIAL.wSerialPortAndBaud], ax
+
+;
+; Note that this section is not under %ifdef MODULE_SERIAL_FLOPPY.  It is important to
+; distinguish floppy disks presented by the server and not treat them as hard disks, even
+; if the floppy support is disabled.
+;
+		mov		al, [es:si+SerialServer_ATA_wDriveFlags]
+		eSHL_IM	al, 1
+		mov		byte [di+DPT.bFlagsHigh], al
+
+		ret
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if FLGH_DPT_SERIAL_DEVICE != 0x4 || FLGH_DPT_SERIAL_FLOPPY != 0x10 || FLGH_DPT_SERIAL_FLOPPY_TYPE_MASK != 0xe0 || FLGH_DPT_SERIAL_FLOPPY_TYPE_FIELD_POSITION != 5
+		%error "The serial server passes FLGH values into SerialDPT_Finalize directly.  If the flag positions are changed, corresponding changes will need to be made in the serial server, and likely a version check put in to deal with servers talking to incompatible clients"
+	%endif
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Timer.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Timer.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Device/Timer.asm	(revision 516)
@@ -0,0 +1,134 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Timeout and delay functions for INT 13h services.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Timer_InitializeTimeoutWithTicksInCL
+;	Parameters:
+;		CL:		Timeout value in system timer ticks
+;		DS:		Segment to RAMVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Timer_InitializeTimeoutWithTicksInCL:
+	mov		[RAMVARS.bTimeoutTicksLeft], cl		; Ticks until timeout
+	call	ReadTimeFromBdaToCX
+	mov		[RAMVARS.bLastTimeoutUpdate], cl	; Start time
+	ret
+
+
+;--------------------------------------------------------------------
+; Timer_SetCFifTimeout
+;	Parameters:
+;		DS:		Segment to RAMVARS
+;	Returns:
+;		CF:		Set if timeout
+;				Cleared if time left
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Timer_SetCFifTimeout:
+	call	ReadTimeFromBdaToCX
+	cmp		cl, [RAMVARS.bLastTimeoutUpdate]
+	je		SHORT .StillPollingTheSameTick
+	mov		[RAMVARS.bLastTimeoutUpdate], cl
+	sub		BYTE [RAMVARS.bTimeoutTicksLeft], 1	; DEC does not update CF
+.StillPollingTheSameTick:
+	ret
+
+
+;--------------------------------------------------------------------
+; Delay is always at least one millisecond since
+; RTC resolution is 977 microsecs.
+;
+; Timer_DelayMicrosecondsFromAX
+;	Parameters:
+;		AX:		Number of microsecs to wait
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+Timer_DelayMicrosecondsFromAX:
+%ifndef USE_AT
+	mov		ax, 2
+	; Fall to Timer_DelayTimerTicksFromAX
+%else
+	push	dx
+	push	cx
+
+	xor		cx, cx
+	xchg	dx, ax						; Microsecs now in CX:DX
+	mov		ah, EVENT_WAIT
+	int		BIOS_SYSTEM_INTERRUPT_15h
+	sti									; XT BIOSes return with interrupts disabled. TODO: Maybe we can remove this since it's in an AT-only block?
+
+	pop		cx
+	pop		dx
+	mov		ax, 1								; Prepare to wait 1 timer tick
+	jc		SHORT Timer_DelayTimerTicksFromAX	; Event Wait was unsupported or busy
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; First tick might take 0...54.9 ms and remaining ticks
+; will occur at 54.9 ms intervals.
+;
+; Timer_DelayTimerTicksFromAX
+;	Parameters:
+;		AX:		Number of timer ticks to wait
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+Timer_DelayTimerTicksFromAX:
+	sti								; Make sure that interrupts are enabled
+	call	ReadTimeFromBdaToCX
+	add		ax, cx					; AX = end time
+.WaitLoop:
+	call	ReadTimeFromBdaToCX
+	cmp		cx, ax
+	jne		SHORT .WaitLoop			; Loop until end time is reached
+	ret
+
+
+;--------------------------------------------------------------------
+; ReadTimeFromBdaToCX
+;	Parameters
+;		Nothing
+;	Returns:
+;		CX:		System time in 54.9 ms ticks
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ReadTimeFromBdaToCX:
+	push	ds
+	LOAD_BDA_SEGMENT_TO	ds, cx
+	mov		cx, [BDA.dwTimerTicks]	; Read low WORD only
+	pop		ds
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h.asm	(revision 516)
@@ -0,0 +1,430 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h BIOS functions (Floppy and Hard disk).
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h software interrupt handler.
+; This handler changes stack to top of stolen conventional memory
+; and then calls the actual INT 13h handler (Int13h_DiskFunctionsHandler).
+;
+; Int13h_DiskFunctionsHandlerWithStackChange
+;	Parameters:
+;		AH:		Bios function
+;		DL:		Drive number
+;		Other:	Depends on function
+;	Returns:
+;		Depends on function
+;--------------------------------------------------------------------
+%ifdef RELOCATE_INT13H_STACK
+ALIGN JUMP_ALIGN
+Int13h_DiskFunctionsHandlerWithStackChange:
+	push	ds
+	push	di
+	call	RamVars_GetSegmentToDS
+
+	; Store entry registers to RAMVARS
+	mov		[RAMVARS.fpInt13hEntryStack], sp
+	mov		[RAMVARS.fpInt13hEntryStack+2], ss
+	pop		WORD [RAMVARS.wStackChangeDI]
+	pop		WORD [RAMVARS.wStackChangeDS]
+
+	; Load new stack and restore DS and DI
+	mov		di, ds		; We do not want to overwrite DS and DI in stack
+	mov		ss, di
+	mov		sp, [RAMVARS.wNewStackOffset]
+	lds		di, [RAMVARS.dwStackChangeDSDI]
+
+	; Call INT 13h
+	pushf
+	push	cs
+	call	Int13h_DiskFunctionsHandler
+
+	; Restore stack (we must not corrupt FLAGS!)
+	cli
+%ifdef USE_386
+	lss		sp, [ss:RAMVARS.fpInt13hEntryStack]
+%else
+	mov		sp, [ss:RAMVARS.fpInt13hEntryStack]
+	mov		ss, [ss:RAMVARS.fpInt13hEntryStack+2]
+%endif
+	pop		di			; DI before stack change
+	pop		ds			; DS before stack change
+	retf	2			; Skip FLAGS from stack
+%endif ; RELOCATE_INT13H_STACK
+
+
+;--------------------------------------------------------------------
+; Int 13h software interrupt handler.
+; Jumps to specific function defined in AH.
+;
+; Note to developers: Do not make recursive INT 13h calls!
+;
+; Int13h_DiskFunctionsHandler
+;	Parameters:
+;		AH:		Bios function
+;		DL:		Drive number
+;		Other:	Depends on function
+;	Returns:
+;		Depends on function
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Int13h_DiskFunctionsHandler:
+	sti									; Enable interrupts
+	cld									; String instructions to increment pointers
+	CREATE_FRAME_INTPACK_TO_SSBP	SIZE_OF_IDEPACK_WITHOUT_INTPACK
+	call	RamVars_GetSegmentToDS
+
+%ifdef MODULE_DRIVEXLATE
+	call	DriveXlate_ToOrBack
+	mov		[RAMVARS.xlateVars+XLATEVARS.bXlatedDrv], dl
+%endif
+	call	FindDPT_ForDriveNumberInDL	; DS:DI points to our DPT, or NULL if not our drive
+	jc		SHORT .NotOurDrive			; DPT not found so this is not one of our drives
+
+.OurFunction:
+	; Jump to correct BIOS function
+	eMOVZX	bx, ah
+	eSHL_IM	bx, 1
+	cmp		ah, 25h						; Possible EBIOS function?
+%ifndef MODULE_EBIOS
+	ja		SHORT UnsupportedFunction
+	jmp		[cs:bx+g_rgw13hFuncJump]	; Jump to BIOS function
+
+%else ; If using MODULE_EBIOS
+	ja		SHORT .JumpToEbiosFunction
+	jmp		[cs:bx+g_rgw13hFuncJump]	; Jump to BIOS function
+
+ALIGN JUMP_ALIGN
+.JumpToEbiosFunction:
+	test	BYTE [di+DPT.bFlagsLow], FLGL_DPT_LBA_AND_EBIOS_SUPPORTED
+	jz		SHORT UnsupportedFunction	; No eINT 13h for CHS drives
+	sub		bl, 41h<<1					; BX = Offset to eINT 13h jump table
+	jb		SHORT UnsupportedFunction
+	cmp		ah, 48h
+	ja		SHORT UnsupportedFunction
+	jmp		[cs:bx+g_rgwEbiosFunctionJumpTable]
+%endif	; MODULE_EBIOS
+
+
+ALIGN JUMP_ALIGN
+.NotOurDrive:
+	test	ah, ah
+	jz		SHORT .OurFunction			; We handle all function 0h requests (resets)
+
+%ifndef MODULE_SERIAL_FLOPPY
+; Without floppy support, we handle only hard disk traffic for function 08h.
+	test	dl, dl
+	jns		SHORT Int13h_DirectCallToAnotherBios
+%endif
+; With floppy support, we handle all traffic for function 08h, as we need to wrap both hard disk and floppy drive counts.
+	cmp		ah, 8
+	je		SHORT .OurFunction
+	; Fall to Int13h_DirectCallToAnotherBios
+
+
+;--------------------------------------------------------------------
+; UnsupportedFunction
+; Int13h_DirectCallToAnotherBios
+;	Parameters:
+;		DL:		Translated drive number
+;		DS:		RAMVARS segment
+;		SS:BP:	Ptr to IDEPACK
+;		BX, DI:	Corrupted on Int13h_DiskFunctionsHandler
+;		Other:	Function specific INT 13h parameters
+;	Returns:
+;		Depends on function
+;	Corrupts registers:
+;		Flags
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+UnsupportedFunction:
+Int13h_DirectCallToAnotherBios:
+	call	ExchangeCurrentInt13hHandlerWithOldInt13hHandler
+	mov		bx, [bp+IDEPACK.intpack+INTPACK.bx]
+	mov		di, [bp+IDEPACK.intpack+INTPACK.di]
+	mov		ds, [bp+IDEPACK.intpack+INTPACK.ds]
+	push	WORD [bp+IDEPACK.intpack+INTPACK.flags]
+	popf
+	push	bp
+	mov		bp, [bp+IDEPACK.intpack+INTPACK.bp]
+	int		BIOS_DISK_INTERRUPT_13h	; Can safely do as much recursion as it wants
+
+	; Store returned values to INTPACK
+	pop		bp	; Standard INT 13h functions never uses BP as return register
+%ifdef USE_386
+;	mov		[bp+IDEPACK.intpack+INTPACK.gs], gs
+;	mov		[bp+IDEPACK.intpack+INTPACK.fs], fs
+%endif
+	mov		[bp+IDEPACK.intpack+INTPACK.es], es
+	mov		[bp+IDEPACK.intpack+INTPACK.ds], ds
+	mov		[bp+IDEPACK.intpack+INTPACK.di], di
+	mov		[bp+IDEPACK.intpack+INTPACK.si], si
+	mov		[bp+IDEPACK.intpack+INTPACK.bx], bx
+%ifdef MODULE_DRIVEXLATE
+	mov		[bp+IDEPACK.intpack+INTPACK.dh], dh
+%else
+	mov		[bp+IDEPACK.intpack+INTPACK.dx], dx
+%endif
+	mov		[bp+IDEPACK.intpack+INTPACK.cx], cx
+	mov		[bp+IDEPACK.intpack+INTPACK.ax], ax
+	pushf
+	pop		WORD [bp+IDEPACK.intpack+INTPACK.flags]
+	call	RamVars_GetSegmentToDS
+
+%ifdef MODULE_DRIVEXLATE
+	cmp		dl, [RAMVARS.xlateVars+XLATEVARS.bXlatedDrv]	; DL is still drive number?
+	je		SHORT .ExchangeInt13hHandlers
+	mov		[bp+IDEPACK.intpack+INTPACK.dl], dl	; Something is returned in DL
+ALIGN JUMP_ALIGN
+.ExchangeInt13hHandlers:
+%endif
+
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		SHORT ExchangeCurrentInt13hHandlerWithOldInt13hHandler
+%else
+	call	ExchangeCurrentInt13hHandlerWithOldInt13hHandler
+	jmp		SHORT Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
+
+
+%ifdef MODULE_SERIAL_FLOPPY
+;--------------------------------------------------------------------
+; Int13h_ReturnSuccessForFloppy
+;
+; Some operations, such as format of a floppy disk track, should just
+; return success, while for hard disks it should be treated as unsupported.
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Int13h_ReturnSuccessForFloppy:
+	test	dl, dl
+	js		SHORT UnsupportedFunction
+	xor		ah, ah
+	jmp		SHORT Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
+
+
+;--------------------------------------------------------------------
+; Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL
+;	Parameters:
+;		AH:		BIOS Error code
+;		CL:		Number of sectors actually transferred
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		All registers are loaded from INTPACK
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL:
+	mov		[bp+IDEPACK.intpack+INTPACK.al], cl
+	; Fall to Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+
+
+;--------------------------------------------------------------------
+; Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+; Int13h_ReturnFromHandlerWithoutStoringErrorCode
+;	Parameters:
+;		AH:		BIOS Error code
+;		DS:		RAMVARS segment
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		All registers are loaded from INTPACK
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH:
+%ifdef MODULE_SERIAL_FLOPPY
+	mov		al, [bp+IDEPACK.intpack+INTPACK.dl]
+Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH_ALHasDriveNumber:
+	call	Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH_ALHasDriveNumber
+
+%else
+	call	Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH
+%endif
+
+Int13h_ReturnFromHandlerWithoutStoringErrorCode:
+	; Always return with interrupts enabled since there are programs that rely
+	; on INT 13h to enable interrupts.
+	or		BYTE [bp+IDEPACK.intpack+INTPACK.flags+1], (FLG_FLAGS_IF>>8)
+	mov		sp, bp	; This makes possible to exit anytime, no matter what is on stack
+	RESTORE_FRAME_INTPACK_FROM_SSBP		SIZE_OF_IDEPACK_WITHOUT_INTPACK
+
+
+;--------------------------------------------------------------------
+; Int13h_CallPreviousInt13hHandler
+;	Parameters:
+;		AH:		INT 13h function to call
+;		DL:		Drive number
+;		DS:		RAMVARS segment
+;	Returns:
+;		Depends on function
+;       NOTE: ES:DI needs to be returned from the previous interrupt
+;		      handler, for floppy DPT in function 08h
+;	Corrupts registers:
+;		None
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Int13h_CallPreviousInt13hHandler:
+	call	ExchangeCurrentInt13hHandlerWithOldInt13hHandler
+	int		BIOS_DISK_INTERRUPT_13h
+;;;  fall-through to ExchangeCurrentInt13hHandlerWithOldInt13hHandler
+
+;--------------------------------------------------------------------
+; ExchangeCurrentInt13hHandlerWithOldInt13hHandler
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;       Nothing
+;       Note: Flags are preserved
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ExchangeCurrentInt13hHandlerWithOldInt13hHandler:
+	push	es
+	push	si
+	LOAD_BDA_SEGMENT_PRESERVE_FLAGS_TO	es, si
+	mov		si, [RAMVARS.fpOldI13h]
+	cli
+	xchg	si, [es:BIOS_DISK_INTERRUPT_13h*4]
+	mov		[RAMVARS.fpOldI13h], si
+	mov		si, [RAMVARS.fpOldI13h+2]
+	xchg	si, [es:BIOS_DISK_INTERRUPT_13h*4+2]
+	sti
+	mov		[RAMVARS.fpOldI13h+2], si
+	pop		si
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH
+; Int13h_SetErrorCodeToIntpackInSSBPfromAH
+;	Parameters:
+;		AH:		BIOS error code (00h = no error)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		SS:BP:	Ptr to IDEPACK with error condition set
+;	Corrupts registers:
+;		DS, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+%ifdef MODULE_SERIAL_FLOPPY
+Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH_ALHasDriveNumber:
+	; Store error code to BDA
+	mov		bx, BDA.bHDLastSt
+	test	al, al
+	js		SHORT .HardDisk
+	mov		bl, BDA.bFDRetST & 0xff
+.HardDisk:
+	LOAD_BDA_SEGMENT_TO	ds, di
+	mov		[bx], ah
+	; Fall to Int13h_SetErrorCodeToIntpackInSSBPfromAH
+
+%else
+Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH:
+	; Store error code to BDA
+	LOAD_BDA_SEGMENT_TO	ds, di
+	mov		[BDA.bHDLastSt], ah
+	; Fall to Int13h_SetErrorCodeToIntpackInSSBPfromAH
+%endif
+
+	; Store error code to INTPACK
+Int13h_SetErrorCodeToIntpackInSSBPfromAH:
+	mov		[bp+IDEPACK.intpack+INTPACK.ah], ah
+	test	ah, ah
+	jnz		SHORT .SetCFtoIntpack
+	and		BYTE [bp+IDEPACK.intpack+INTPACK.flags], ~FLG_FLAGS_CF
+	ret
+.SetCFtoIntpack:
+	or		BYTE [bp+IDEPACK.intpack+INTPACK.flags], FLG_FLAGS_CF
+	ret
+
+
+; Jump table for correct BIOS function
+ALIGN WORD_ALIGN
+g_rgw13hFuncJump:
+	dw	AH0h_HandlerForDiskControllerReset			; 00h, Disk Controller Reset (All)
+	dw	AH1h_HandlerForReadDiskStatus				; 01h, Read Disk Status (All)
+	dw	AH2h_HandlerForReadDiskSectors				; 02h, Read Disk Sectors (All)
+	dw	AH3h_HandlerForWriteDiskSectors				; 03h, Write Disk Sectors (All)
+	dw	AH4h_HandlerForVerifyDiskSectors			; 04h, Verify Disk Sectors (All)
+%ifdef MODULE_SERIAL_FLOPPY
+	dw	Int13h_ReturnSuccessForFloppy				; 05h, Format Disk Track (XT, AT, EISA)
+%else
+	dw	UnsupportedFunction							; 05h, Format Disk Track (XT, AT, EISA)
+%endif
+	dw	UnsupportedFunction							; 06h, Format Disk Track with Bad Sectors (XT)
+	dw	UnsupportedFunction							; 07h, Format Multiple Cylinders (XT)
+	dw	AH8h_HandlerForReadDiskDriveParameters		; 08h, Read Disk Drive Parameters (All)
+	dw	AH9h_HandlerForInitializeDriveParameters	; 09h, Initialize Drive Parameters (All)
+	dw	UnsupportedFunction							; 0Ah, Read Disk Sectors with ECC (XT, AT, EISA)
+	dw	UnsupportedFunction							; 0Bh, Write Disk Sectors with ECC (XT, AT, EISA)
+	dw	AHCh_HandlerForSeek							; 0Ch, Seek (All)
+	dw	AH9h_HandlerForInitializeDriveParameters	; 0Dh, Alternate Disk Reset (All)
+	dw	UnsupportedFunction							; 0Eh, Read Sector Buffer (XT, PS/1), ESDI Undocumented Diagnostic (PS/2)
+	dw	UnsupportedFunction							; 0Fh, Write Sector Buffer (XT, PS/1), ESDI Undocumented Diagnostic (PS/2)
+	dw	AH10h_HandlerForCheckDriveReady				; 10h, Check Drive Ready (All)
+	dw	AH11h_HandlerForRecalibrate					; 11h, Recalibrate (All)
+	dw	UnsupportedFunction							; 12h, Controller RAM Diagnostic (XT)
+	dw	UnsupportedFunction							; 13h, Drive Diagnostic (XT)
+	dw	UnsupportedFunction							; 14h, Controller Internal Diagnostic (All)
+	dw	AH15h_HandlerForReadDiskDriveSize			; 15h, Read Disk Drive Size (AT+)
+	dw	UnsupportedFunction							; 16h,
+	dw	UnsupportedFunction							; 17h,
+	dw	UnsupportedFunction							; 18h,
+	dw	UnsupportedFunction							; 19h, Park Heads (PS/2)
+	dw	UnsupportedFunction							; 1Ah, Format ESDI Drive (PS/2)
+	dw	UnsupportedFunction							; 1Bh, Get ESDI Manufacturing Header (PS/2)
+	dw	UnsupportedFunction							; 1Ch, ESDI Special Functions (PS/2)
+	dw	UnsupportedFunction							; 1Dh,
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	dw	AH1Eh_HandlerForXTCFfeatures				; 1Eh, Lo-tech XT-CF features (XTIDE Universal BIOS)
+%else
+	dw	UnsupportedFunction							; 1Eh, 
+%endif
+	dw	UnsupportedFunction							; 1Fh,
+	dw	UnsupportedFunction							; 20h,
+	dw	UnsupportedFunction							; 21h, Read Disk Sectors, Multiple Blocks (PS/1)
+	dw	UnsupportedFunction							; 22h, Write Disk Sectors, Multiple Blocks (PS/1)
+	dw	AH23h_HandlerForSetControllerFeatures		; 23h, Set Controller Features Register (PS/1)
+	dw	AH24h_HandlerForSetMultipleBlocks			; 24h, Set Multiple Blocks (PS/1)
+	dw	AH25h_HandlerForGetDriveInformation			; 25h, Get Drive Information (PS/1)
+
+%ifdef MODULE_EBIOS
+g_rgwEbiosFunctionJumpTable:
+	dw	AH41h_HandlerForCheckIfExtensionsPresent	; 41h, Check if Extensions Present (EBIOS)*
+	dw	AH42h_HandlerForExtendedReadSectors			; 42h, Extended Read Sectors (EBIOS)*
+	dw	AH43h_HandlerForExtendedWriteSectors		; 43h, Extended Write Sectors (EBIOS)*
+	dw	AH44h_HandlerForExtendedVerifySectors		; 44h, Extended Verify Sectors (EBIOS)*
+	dw	UnsupportedFunction							; 45h, Lock and Unlock Drive (EBIOS)***
+	dw	UnsupportedFunction							; 46h, Eject Media Request (EBIOS)***
+	dw	AH47h_HandlerForExtendedSeek				; 47h, Extended Seek (EBIOS)*
+	dw	AH48h_HandlerForGetExtendedDriveParameters	; 48h, Get Extended Drive Parameters (EBIOS)*
+;	dw	UnsupportedFunction							; 49h, Get Extended Disk Change Status (EBIOS)***
+;	dw	UnsupportedFunction							; 4Ah, Initiate Disk Emulation (Bootable CD-ROM)
+;	dw	UnsupportedFunction							; 4Bh, Terminate Disk Emulation (Bootable CD-ROM)
+;	dw	UnsupportedFunction							; 4Ch, Initiate Disk Emulation and Boot (Bootable CD-ROM)
+;	dw	UnsupportedFunction							; 4Dh, Return Boot Catalog (Bootable CD-ROM)
+;	dw	UnsupportedFunction							; 4Eh, Set Hardware Configuration (EBIOS)**
+;
+;   * = Enhanced Drive Access Support (minimum required EBIOS functions)
+;  ** = Enhanced Disk Drive (EDD) Support
+; *** = Drive Locking and Ejecting Support
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH0h_HReset.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH0h_HReset.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH0h_HReset.asm	(revision 516)
@@ -0,0 +1,181 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=0h, Disk Controller Reset.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=0h, Disk Controller Reset.
+;
+; Note: We handle all AH=0h calls, even for drives handled by other
+; BIOSes!
+;
+; AH0h_HandlerForDiskControllerReset
+;	Parameters:
+;		DL:		Translated Drive number (ignored so all drives are reset)
+;				If bit 7 is set all hard disks and floppy disks reset.
+;		DS:DI:	Ptr to DPT (or Null if foreign drive)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
+;		AH:		Int 13h return status (from drive requested in DL)
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH0h_HandlerForDiskControllerReset:
+	; Reset foreign Floppy and Hard Drives (those handled by other BIOSes)
+	eMOVZX	bx, dl										; Copy requested drive to BL and zero BH to assume no errors
+
+	xor		ah, ah										; Disk Controller Reset
+	call	Int13h_CallPreviousInt13hHandler			; Reset floppy drives only or floppy drives and foreign hard disks
+	call	BackupErrorCodeFromTheRequestedDriveToBH
+
+%ifdef MODULE_SERIAL_FLOPPY
+;
+; "Reset" emulated serial floppy drives, if any.  There is nothing to actually do for this reset,
+; but record the proper error return code if one of these floppy drives is the drive requested.
+;
+	call	RamVars_UnpackFlopCntAndFirstToAL
+	cbw													; Clears AH (there are flop drives) or ffh (there are not)
+														; Either AH has success code (flop drives are present)
+														; or it doesn't matter because we won't match drive ffh
+
+	cwd													; clears DX (there are flop drives) or ffffh (there are not)
+
+	adc		dl, al										; second drive (CF set) if present
+														; If no drive is present, this will result in ffh which
+														; won't match a drive
+	call	BackupErrorCodeFromTheRequestedDriveToBH
+	mov		dl, al										; We may end up doing the first drive twice (if there is
+	call	BackupErrorCodeFromTheRequestedDriveToBH	; only one drive), but doing it again is not harmful.
+%endif
+	test	bl, bl										; If we were called with a floppy disk, then we are done,
+	jns		SHORT .SkipHardDiskReset					; don't do hard disks.
+
+	; Resetting our hard disks will modify dl and bl to be idevars offset based instead of drive number based,
+	; such that this call must be the last in the list of reset routines called.
+	;
+	; This needs to happen after ResetForeignDrives, as that call may have set the error code for 80h,
+	; and we need to override that value if we are xlate'd into 80h with one of our drives.
+	;
+	call	ResetHardDisksHandledByOurBIOS
+
+.SkipHardDiskReset:
+	mov		ah, bh
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+
+
+;--------------------------------------------------------------------
+; BackupErrorCodeFromTheRequestedDriveToBH
+;	Parameters:
+;		AH:		Error code from the last resetted drive
+;		DL:		Drive last resetted
+;		BL:		Requested drive (DL when entering AH=00h)
+;	Returns:
+;		BH:		Backuped error code
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+BackupErrorCodeFromTheRequestedDriveToBH:
+	cmp		dl, bl				; Requested drive?
+	eCMOVE	bh, ah
+	ret
+
+
+
+; This defines what is called when resetting our drives at the end of drive detection.
+AH0h_ResetAllOurHardDisksAtTheEndOfDriveInitialization equ ResetHardDisksHandledByOurBIOS.ErrorCodeNotUsed
+
+;--------------------------------------------------------------------
+; ResetHardDisksHandledByOurBIOS
+;	Parameters:
+;		BL:		Requested drive (DL when entering AH=00h)
+;		DS:DI:	Ptr to DPT for requested drive
+;				If DPT pointer is not available, or error result in BH won't be used anyway,
+;				enter through .ErrorCodeNotUsed.
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		BH:		Error code from requested drive (if available)
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ResetHardDisksHandledByOurBIOS:
+	xor		bl, bl										; Assume Null IdevarsOffset for now, assuming foreign drive
+	test	di, di
+	jz		SHORT .ErrorCodeNotUsed
+	mov		bl, [di+DPT.bIdevarsOffset]					; replace drive number with Idevars pointer for cmp with dl
+.ErrorCodeNotUsed:
+
+	mov		si, ControllerResetForDPTinDSDI
+	call	.CallSIforEveryDrive						; Reset all drives to power on settings
+	mov		si, AH9h_InitializeDriveForUse
+	; Fall to .CallSIforEveryDrive						; Initialize all drives
+
+.CallSIforEveryDrive:									; BH will be garbage on exit if this entry point is used,
+														; but reset of all drives will still happen
+
+	mov		dl, ROMVARS.ideVars0						; starting Idevars offset
+
+    ; Get count of ALL Idevars structures, not just the ones that are configured.  This may seem odd,
+    ; but it catches the .ideVarsSerialAuto structure, which would not be scanned if the count from
+	; RamVars_GetIdeControllerCountToCX was used.  Unused controllers won't make a difference, since no DPT
+	; will point to them.  Performance isn't an issue, as this is a reset operation.
+    ;
+	mov		cx, NUMBER_OF_IDEVARS
+
+.loop:
+	push	si
+	call	FindDPT_ForIdevarsOffsetInDL				; look for the first drive on this controller, if any
+	pop		si
+	jc		SHORT .notFound
+
+	push	bx
+	push	cx
+	push	dx
+	call	si											; Reset Master AND Slave or initialize Master OR Slave drive
+	pop		dx
+	pop		cx
+	pop		bx
+	call	BackupErrorCodeFromTheRequestedDriveToBH	; save error code if same controller as drive from entry
+
+.notFound:
+	add		dl, IDEVARS_size							; move Idevars pointer forward
+	loop	.loop
+	ret
+
+
+;--------------------------------------------------------------------
+; ControllerResetForDPTinDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT for drive to reset (resets both Master and Slave drive)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+ControllerResetForDPTinDSDI:
+%ifdef MODULE_IRQ
+	call	Interrupts_UnmaskInterruptControllerForDriveInDSDI
+%endif
+%ifdef MODULE_ADVANCED_ATA
+	call	Device_ResetMasterAndSlaveController
+	jmp		AdvAtaInit_InitializeControllerForDPTinDSDI
+%else
+	jmp		Device_ResetMasterAndSlaveController
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH10h_HReady.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH10h_HReady.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH10h_HReady.asm	(revision 516)
@@ -0,0 +1,43 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=10h, Check Drive Ready.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=10h, Check Drive Ready.
+;
+; AH10h_HandlerForCheckDriveReady
+;	Parameters:
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH10h_HandlerForCheckDriveReady:
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		Device_SelectDrive
+%else
+	call	Device_SelectDrive
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH11h_HRecal.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH11h_HRecal.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH11h_HRecal.asm	(revision 516)
@@ -0,0 +1,61 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=11h, Recalibrate.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=11h, Recalibrate.
+;
+; AH11h_HandlerForRecalibrate
+;	Parameters:
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns with INTPACK:
+;		AH:		BIOS Error code
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH11h_HandlerForRecalibrate:
+%ifndef USE_186
+	call	AH11h_RecalibrateDrive
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%else
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	; Fall to AH11h_RecalibrateDrive
+%endif
+
+
+;--------------------------------------------------------------------
+; AH11h_HRecalibrate
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns:
+;		AH:		BIOS Error code
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+AH11h_RecalibrateDrive:
+	; Recalibrate command is optional, vendor specific and not even
+	; supported on later ATA-standards. Let's do seek instead.
+	mov		cx, 1						; Seek to Cylinder 0, Sector 1
+	xor		dh, dh						; Head 0
+	jmp		AHCh_SeekToCylinder
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm	(revision 516)
@@ -0,0 +1,102 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=15h, Read Disk Drive Size.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=15h, Read Disk Drive Size.
+;
+; AH15h_HandlerForReadDiskDriveSize
+;	Parameters:
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
+;		If successful:
+;			AH:		Hard Disk: 3 (Hard disk accessible)
+;                   Floppy:    1 (Floppy disk, without change detection)
+;			CX:DX:	Total number of sectors
+;			CF:		0
+;		If failed:
+;			AH:		0 (Drive not present)
+;			CX:DX:	0
+;			CF:		1
+;--------------------------------------------------------------------
+AH15h_HandlerForReadDiskDriveSize:
+%ifdef MODULE_SERIAL_FLOPPY
+	mov		cl, 1										; 1 = floppy disk, no change detection
+
+	test	dl,dl										; DO NOT store the sector count if this is a
+	jns		.FloppyDrive								; floppy disk, some OS's depend on this not
+														; happening for floppies in order to boot.
+%endif
+
+	call	AH15h_GetSectorCountToBXDXAX
+	mov		[bp+IDEPACK.intpack+INTPACK.cx], dx			; HIWORD to CX
+	xchg	[bp+IDEPACK.intpack+INTPACK.dx], ax			; LOWORD to DX, AL gets drive number
+
+	xor		ah, ah
+%ifdef MODULE_SERIAL_FLOPPY
+	mov		cl, 3										; 3 = Hard Disk Accessible
+.FloppyDrive:
+
+	call	Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH_ALHasDriveNumber	; Store success to BDA and CF
+	mov		[bp+IDEPACK.intpack+INTPACK.ah], cl
+%else
+	call	Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH	; Store success to BDA and CF
+	mov		BYTE [bp+IDEPACK.intpack+INTPACK.ah], 3
+%endif
+
+	jmp		Int13h_ReturnFromHandlerWithoutStoringErrorCode
+
+
+;--------------------------------------------------------------------
+; AH15h_GetSectorCountFromForeignDriveToDXAX:
+; AH15h_GetSectorCountToBXDXAX:
+;	Parameters:
+;		DL:		Drive number (AH15h_GetSectorCountFromForeignDriveToDXAX only)
+;		DS:		RAMVARS segment
+;		DS:DI:	Ptr to DPT (AH15h_GetSectorCountToDXAX only)
+;	Returns:
+;		DX:AX:	Total sector count
+;		BX:		Zero
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+%ifdef MODULE_BOOT_MENU
+AH15h_GetSectorCountFromForeignDriveToDXAX:
+	mov		ah, GET_DRIVE_PARAMETERS
+	call	Int13h_CallPreviousInt13hHandler
+	jmp		SHORT ConvertAH08hReturnValuesToSectorCount
+%endif
+
+AH15h_GetSectorCountToBXDXAX:
+	call	AH8h_GetDriveParameters
+	; Fall to ConvertAH08hReturnValuesToSectorCount
+
+ConvertAH08hReturnValuesToSectorCount:
+	call	Address_ExtractLCHSparametersFromOldInt13hAddress
+	mov		al, bh		; AL = Max head number
+	inc		cx			; Max cylinder number to cylinder count
+	inc		ax			; Max head number to head count (AH=8h returns max 254 so no overflow to AH)
+	mul		bl			; AX = Head count * Sectors per track
+	mul		cx			; DX:AX = Total sector count for AH=0xh transfer functions
+	xor		bx, bx
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1Eh_XTCF.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1Eh_XTCF.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1Eh_XTCF.asm	(revision 516)
@@ -0,0 +1,165 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=1Eh, Lo-tech XT-CF features.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=1Eh, Lo-tech XT-CF features.
+; This function is supported only by XTIDE Universal BIOS.
+;
+; AH1Eh_HandlerForXTCFfeatures
+;	Parameters:
+;		AL, CX:	Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		AL:		XT-CF subcommand (see XTCF.inc for more info)
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH1Eh_HandlerForXTCFfeatures:
+%ifndef USE_186
+	call	ProcessXTCFsubcommandFromAL
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%else
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	; Fall to ProcessXTCFsubcommandFromAL
+%endif
+
+
+;--------------------------------------------------------------------
+; ProcessXTCFsubcommandFromAL
+;	Parameters:
+;		AL:		XT-CF subcommand (see XTCF.inc for more info)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI
+;--------------------------------------------------------------------
+ProcessXTCFsubcommandFromAL:
+	; IS_THIS_DRIVE_XTCF. We check this for all commands.
+	call	AccessDPT_IsThisDeviceXTCF
+	jne		SHORT XTCFnotFound
+	and		ax, BYTE 7Fh				; Subcommand now in AX (clears AH and CF)
+	jz		SHORT .ReturnWithSuccess	; IS_THIS_DRIVE_XTCF
+
+	; READ_XTCF_CONTROL_REGISTER_TO_DH
+	dec		ax							; Subcommand
+	jnz		SHORT .SkipReadXtcfControlRegisterToDH
+	mov		dx, [di+DPT.wBasePort]
+	add		dl, XTCF_CONTROL_REGISTER	; Will never overflow (keeps CF cleared)
+	in		al, dx
+	mov		[bp+IDEPACK.intpack+INTPACK.dh], al
+.ReturnWithSuccess:
+	ret		; With AH and CF cleared
+
+.SkipReadXtcfControlRegisterToDH:
+	; WRITE_DH_TO_XTCF_CONTROL_REGISTER
+	dec		ax							; Subcommand
+	jnz		SHORT XTCFnotFound			; Invalid subcommand
+	mov		al, [bp+IDEPACK.intpack+INTPACK.dh]
+	; Fall to AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL
+
+
+;--------------------------------------------------------------------
+; AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL
+;	Parameters:
+;		AL:		XT-CF Control Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI
+;--------------------------------------------------------------------
+AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL:
+	; Output Control Register
+	mov		dx, [di+DPT.wBasePort]
+	add		dl, XTCF_CONTROL_REGISTER
+	out		dx, al
+
+	; We always need to enable 8-bit mode since 16-bit mode is restored
+	; when controller is reset (AH=00h or 0Dh)
+	ePUSH_T	bx, AH23h_Enable8bitPioMode
+
+	; Convert Control Register Contents to device code
+	test	al, al
+	jz		SHORT .Set8bitPioMode
+	cmp		al, XTCF_MEMORY_MAPPED_MODE
+	jae		SHORT .SetMemoryMappedMode
+
+; We need to limit block size here. Consider this scenario;
+; 1. While in PIO mode or memory mapped mode, the drive is set to do
+;    block transfers larger than XTCF_DMA_MODE_MAX_BLOCK_SIZE.
+; 2. A call is subsequently made to change device mode to DEVICE_8BIT_XTCF_DMA.
+; 3. The call to AH24h_SetBlockSize fails but the change in device mode has been made.
+
+	; Set DMA Mode
+	mov		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_XTCF_DMA
+	mov		al, [di+DPT_ATA.bBlockSize]
+	MIN_U	al, XTCF_DMA_MODE_MAX_BLOCK_SIZE
+	jmp		SHORT AH24h_SetBlockSize	; Returns via AH23h_Enable8bitPioMode
+
+.SetMemoryMappedMode:
+	mov		al, DEVICE_8BIT_XTCF_MEMMAP
+	SKIP2B	bx
+
+.Set8bitPioMode:
+	mov		al, DEVICE_8BIT_XTCF_PIO8
+	mov		[di+DPT_ATA.bDevice], al
+	ret		; Via AH23h_Enable8bitPioMode
+
+
+;--------------------------------------------------------------------
+; AH1Eh_DetectXTCFwithBasePortInDX
+;	Parameters:
+;		DX:		Base I/O port address to check
+;	Returns:
+;		AH:		RET_HD_SUCCESS if XT-CF is found from port
+;				RET_HD_INVALID if XT-CF is not found
+;		CF:		Cleared if XT-CF found
+;				Set if XT-CF not found
+;	Corrupts registers:
+;		AL
+;--------------------------------------------------------------------
+AH1Eh_DetectXTCFwithBasePortInDX:
+	push	dx
+	add		dl, XTCF_CONTROL_REGISTER_INVERTED_in	; set DX to XT-CF config register (inverted)
+	in		al, dx		; get value
+	mov		ah, al		; save in ah
+	inc		dx			; set DX to XT-CF config register (non-inverted)
+	in		al, dx		; get value
+	not		al			; invert value
+	pop		dx
+	sub		ah, al		; do they match? (clear AH if they do)
+	jz		SHORT XTCFfound
+
+XTCFnotFound:
+AH1Eh_LoadInvalidCommandToAHandSetCF:
+	stc					; set carry flag since XT-CF not found
+	mov		ah, RET_HD_INVALID
+XTCFfound:
+	ret					; and return
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1h_HStatus.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1h_HStatus.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1h_HStatus.asm	(revision 516)
@@ -0,0 +1,56 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=1h, Read Disk Status.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=1h, Read Disk Status.
+;
+; AH1h_HandlerForReadDiskStatus
+;	Parameters:
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns with INTPACK:
+;		AH:		Int 13h floppy return status
+;		CF:		0 if AH = RET_HD_SUCCESS, 1 otherwise (error)
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH1h_HandlerForReadDiskStatus:
+	LOAD_BDA_SEGMENT_TO	ds, ax, !
+
+%ifdef MODULE_SERIAL_FLOPPY
+	test	dl, dl
+	js		.HardDisk
+	mov		ah, [BDA.bFDRetST]	; Unlike for hard disks below, floppy version does not clear the status
+	jmp		.done
+.HardDisk:
+%endif
+
+	xchg	ah, [BDA.bHDLastSt]	; Load and clear last error (AH is cleared with the LOAD_BDA_SEGMENT_TO above)
+
+.done:
+%ifndef USE_186
+	call	Int13h_SetErrorCodeToIntpackInSSBPfromAH
+	jmp		Int13h_ReturnFromHandlerWithoutStoringErrorCode
+%else
+	push	Int13h_ReturnFromHandlerWithoutStoringErrorCode
+	jmp		Int13h_SetErrorCodeToIntpackInSSBPfromAH
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH23h_HFeatures.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH23h_HFeatures.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH23h_HFeatures.asm	(revision 516)
@@ -0,0 +1,93 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=23h,
+;					Set Controller Features Register.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=23h, Set Controller Features Register.
+;
+; AH23h_HandlerForSetControllerFeatures
+;	Parameters:
+;		AL, CX:	Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		AL:		Feature Number (parameter to Features Register = subcommand)
+;	(Parameter registers are undocumented, these are specific for this BIOS):
+;		BL:		Parameter to Sector Count Register (subcommand specific)
+;		BH:		Parameter to LBA Low / Sector Number Register (subcommand specific)
+;		CL:		Parameter to LBA Middle / Cylinder Low Register (subcommand specific)
+;		CH:		Parameter to LBA High / Cylinder High Register (subcommand specific)
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH23h_HandlerForSetControllerFeatures:
+	xchg	si, ax		; SI = Feature Number
+	mov		dx, [bp+IDEPACK.intpack+INTPACK.bx]
+%ifndef USE_186
+	call	AH23h_SetControllerFeatures
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%else
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	; Fall to AH23h_SetControllerFeatures
+%endif
+
+
+;--------------------------------------------------------------------
+; AH23h_SetControllerFeatures
+;	Parameters:
+;		DL:		Parameter to Sector Count Register (subcommand specific)
+;		DH:		Parameter to LBA Low / Sector Number Register (subcommand specific)
+;		CL:		Parameter to LBA Middle / Cylinder Low Register (subcommand specific)
+;		CH:		Parameter to LBA High / Cylinder High Register (subcommand specific)
+;		SI:		Feature Number (parameter to Features Register = subcommand)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+AH23h_SetControllerFeatures:
+	mov		al, COMMAND_SET_FEATURES
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_BSY, FLG_STATUS_BSY)
+	jmp		Idepack_StoreNonExtParametersAndIssueCommandFromAL
+
+
+;--------------------------------------------------------------------
+; AH23h_Enable8bitPioMode
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI
+;--------------------------------------------------------------------
+%ifdef MODULE_8BIT_IDE
+AH23h_Enable8bitPioMode:
+	mov		si, FEATURE_ENABLE_8BIT_PIO_TRANSFER_MODE
+	jmp		SHORT AH23h_SetControllerFeatures
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm	(revision 516)
@@ -0,0 +1,84 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=24h, Set Multiple Blocks.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=24h, Set Multiple Blocks.
+;
+; AH24h_HandlerForSetMultipleBlocks
+;	Parameters:
+;		AL:		Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		AL:		Number of Sectors per Block (1, 2, 4, 8, 16, 32, 64 or 128)
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH24h_HandlerForSetMultipleBlocks:
+%ifndef USE_186
+	call	AH24h_SetBlockSize
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%else
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	; Fall to AH24h_SetBlockSize
+%endif
+
+
+;--------------------------------------------------------------------
+; AH24h_SetBlockSize
+;	Parameters:
+;		AL:		Number of Sectors per Block (1, 2, 4, 8, 16, 32, 64 or 128)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, CX, DX
+;--------------------------------------------------------------------
+AH24h_SetBlockSize:
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	; XT-CF does not support largest block size in DMA mode.
+	cmp		al, XTCF_DMA_MODE_MAX_BLOCK_SIZE
+	jbe		SHORT .NoNeedToLimitBlockSize
+	cmp		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_XTCF_DMA
+	je		SHORT AH1Eh_LoadInvalidCommandToAHandSetCF
+.NoNeedToLimitBlockSize:
+%endif ; MODULE_8BIT_IDE_ADVANCED
+
+	push	bx
+
+	push	ax
+	xchg	dx, ax		; DL = Block size (Sector Count Register)
+	mov		al, COMMAND_SET_MULTIPLE_MODE
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRDY, FLG_STATUS_DRDY)
+	call	Idepack_StoreNonExtParametersAndIssueCommandFromAL
+	pop		bx
+	jnc		SHORT .StoreBlockSize
+	mov		bl, 1		; Block size 1 will always work
+.StoreBlockSize:		; Store new block size to DPT and return
+	mov		[di+DPT_ATA.bBlockSize], bl
+
+	pop		bx
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH25h_HDrvID.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH25h_HDrvID.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH25h_HDrvID.asm	(revision 516)
@@ -0,0 +1,48 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=25h, Get Drive Information.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=25h, Get Drive Information.
+;
+; AH25h_HandlerForGetDriveInformation
+;	Parameters:
+;		ES:		Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		ES:BX:	Ptr to buffer to receive 512-byte drive information
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH25h_HandlerForGetDriveInformation:
+	mov		ax, (COMMAND_IDENTIFY_DEVICE << 8 | 1)		; Read 1 sector
+	call	Prepare_BufferToESSIforOldInt13hTransfer	; Preserves AX
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+%else
+	call	Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH2h_HRead.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH2h_HRead.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH2h_HRead.asm	(revision 516)
@@ -0,0 +1,58 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=2h, Read Disk Sectors.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=2h, Read Disk Sectors.
+;
+; AH2h_HandlerForReadDiskSectors
+;	Parameters:
+;		AL, CX, DH, ES:	Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		AL:		Number of sectors to read (1...128)
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Starting sector number (1...63)
+;		DH:		Starting head number (0...255)
+;		ES:BX:	Pointer to buffer receiving data
+;	Returns with INTPACK:
+;		AH:		Int 13h/40h floppy return status
+;		AL:		Burst error length if AH returns 11h (we never return error code 11h)
+;				Number of sectors actually read (only valid if CF set for someBIOSes)
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH2h_HandlerForReadDiskSectors:
+	call	Prepare_BufferToESSIforOldInt13hTransfer
+	call	Prepare_GetOldInt13hCommandIndexToBX
+	mov		ah, [cs:bx+g_rgbReadCommandLookup]
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+%else
+	call	Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL
+%endif
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH3h_HWrite.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH3h_HWrite.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH3h_HWrite.asm	(revision 516)
@@ -0,0 +1,56 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=3h, Write Disk Sectors.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=3h, Write Disk Sectors.
+;
+; AH3h_HandlerForWriteDiskSectors
+;	Parameters:
+;		AL, CX, DH, ES:	Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Parameters on INTPACK:
+;		AL:		Number of sectors to write (1...128)
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Starting sector number (1...63)
+;		DH:		Starting head number (0...255)
+;		ES:BX:	Pointer to source data
+;	Returns with INTPACK:
+;		AH:		Int 13h/40h floppy return status
+;		AL:		Number of sectors actually written (only valid if CF set for someBIOSes)
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH3h_HandlerForWriteDiskSectors:
+	call	Prepare_BufferToESSIforOldInt13hTransfer
+	call	Prepare_GetOldInt13hCommandIndexToBX
+	mov		ah, [cs:bx+g_rgbWriteCommandLookup]
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+%else
+	call	Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH4h_HVerify.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH4h_HVerify.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH4h_HVerify.asm	(revision 516)
@@ -0,0 +1,54 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=4h, Verify Disk Sectors.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=4h, Verify Disk Sectors.
+;
+; AH4h_HandlerForVerifyDiskSectors
+;	Parameters:
+;		AL, CX, DH:	Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to INTPACK
+;	Parameters on INTPACK in SS:BP:
+;		AL:		Number of sectors to verify (1...128)
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Starting sector number (1...63)
+;		DH:		Starting head number (0...255)
+;	Returns with INTPACK in SS:BP:
+;		AH:		Int 13h/40h floppy return status
+;		AL:		Number of sectors actually verified (only valid if CF set for someBIOSes)
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH4h_HandlerForVerifyDiskSectors:
+	mov		ah, COMMAND_VERIFY_SECTORS
+	call	Prepare_ByValidatingSectorsInALforOldInt13h	; Preserves AX
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+%else
+	call	Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAHandTransferredSectorsFromCL
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm	(revision 516)
@@ -0,0 +1,194 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=8h, Read Disk Drive Parameters.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=8h, Read Disk Drive Parameters.
+;
+; AH8h_HandlerForReadDiskDriveParameters
+;	Parameters:
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
+;       BL:     Drive Type (for floppies only)
+;		CH:		Maximum cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9...8
+;				Bits 5...0:	Maximum sector number (1...63)
+;		DH:		Maximum head number (0...254)
+;		DL:		Number of drives!!!
+;       ES:DI:  Floppy DPT (for floppies only)
+;		AH:		Int 13h/40h floppy return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH8h_HandlerForReadDiskDriveParameters:
+	test	di, di
+	jz		SHORT .NotOurDrive
+
+	call	AH8h_GetDriveParameters
+
+%ifdef MODULE_SERIAL_FLOPPY
+	push	cs							; setup registers if we are a floppy drive, in all cases
+	pop		es							; if it is not a floppy drive, these values will not be put in INTPACK
+	mov		di, AH8h_FloppyDPT
+%endif
+	;; fall-through
+
+.MidGame:
+	call	RamVars_GetCountOfKnownDrivesToAX		; assume hard disk for now, will discard if for floppies
+
+	test	byte [bp+IDEPACK.intpack+INTPACK.dl], 080h
+	jnz		.Done
+
+	mov		[bp+IDEPACK.intpack+INTPACK.bl], bl
+
+	mov		[bp+IDEPACK.intpack+INTPACK.es], es
+	mov		[bp+IDEPACK.intpack+INTPACK.di], di
+
+	call	FloppyDrive_GetCountToAX
+
+.Done:
+	mov		ah, dh
+
+	mov		[bp+IDEPACK.intpack+INTPACK.cx], cx
+	xchg	[bp+IDEPACK.intpack+INTPACK.dx], ax		; recover DL for BDA last status byte determination
+
+	xor		ah, ah
+%ifdef MODULE_SERIAL_FLOPPY
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH_ALHasDriveNumber
+%else
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
+
+.NotOurDrive:
+	call	Int13h_CallPreviousInt13hHandler
+	jnc		SHORT .MidGame
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+
+
+;--------------------------------------------------------------------
+; Returns L-CHS parameters for drive and total hard disk count.
+;
+; AH8h_GetDriveParameters
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		CH:		Maximum cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9...8
+;				Bits 5...0:	Maximum sector number (1...63)
+;		DH:		Maximum head number (0...254)
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+AH8h_GetDriveParameters:
+	call	AccessDPT_GetLCHStoAXBLBH
+%ifdef RESERVE_DIAGNOSTIC_CYLINDER
+	dec		ax
+%endif
+	MIN_U	ax, MAX_LCHS_CYLINDERS
+	; Fall to .PackReturnValues
+
+;--------------------------------------------------------------------
+; Packs L-CHS values to INT 13h, AH=08h return values.
+;
+; .PackReturnValues
+;	Parameters:
+;		AX:		Number of L-CHS cylinders available (1...1024)
+;		BL:		Number of L-CHS heads (1...255)
+;		BH:		Number of L-CHS sectors per track (1...63)
+;		DS:		RAMVARS segment
+;	Returns:
+;		CH:		Maximum cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9...8
+;				Bits 5...0:	Maximum sector number (1...63)
+;		DH:		Maximum head number (0...254)
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+.PackReturnValues:
+	dec		ax						; AX = Number of last cylinder
+	dec		bx						; BL = Number of last head
+	xchg	cx, ax
+	xchg	cl, ch					; CH = Last cylinder bits 0...7
+	eROR_IM	cl, 2					; CL bits 6...7 = Last cylinder bits 8...9
+	or		cl, bh					; CL bits 0...5 = Sectors per track
+	mov		dh, bl					; DH = Maximum head number
+
+%ifdef MODULE_SERIAL_FLOPPY
+	mov		bl, [di+DPT.bFlagsHigh]
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS             ; not sure why this is needed for preprocessor-only
+	eSHR_IM	bl, FLGH_DPT_SERIAL_FLOPPY_TYPE_FIELD_POSITION
+%endif
+%endif
+	ret
+
+%ifdef MODULE_SERIAL_FLOPPY
+;
+; Floppy Disk Parameter Table.  There is no way to specify more than one of these
+; for any given system, so no way to make this drive or media specific.
+; So we return fixed values out of the ROM for callers who might be expecting this information.
+;
+; On AT systems, we return the information for a 1.44 MB disk,
+; and on XT systems, we return the information for a 360 KB disk.
+;
+AH8h_FloppyDPT:
+%ifdef USE_AT
+	db		0ah << 4 | 0fh			; Offset 0: Drive timings, 1.44MB values
+%else
+	db		0dh << 4 | 0fh			; Offset 0: Drive timings, 360KB values
+%endif
+
+	db		1h << 1 | 0				; Offset 1: Typical values of 1 for head load time
+									;           DMA used (although it actually is not, but is more restrictive)
+	db		25h						; Offset 2: Inactivity motor turn-off delay,
+									; 			Typical value of 25h for 2 second delay
+	db		02h						; Offset 3: Sector size, always 512
+
+%ifdef USE_AT
+	db		12h						; Offset 4: Sectors per track, 1.44MB value
+	db		1bh						; Offset 5: Sector gap, 1.44MB value
+%else
+	db		09h						; Offset 4: Sectors per track, 360KB value
+	db		2ah						; Offset 5: Sector gap, 360KB value
+%endif
+
+	db		0ffh					; Offset 6: Data length
+
+%ifdef USE_AT
+	db		6ch						; Offset 7: Format gap length, 1.44MB value
+%else
+	db		50h						; Offset 7: Format gap length, 360KB value
+%endif
+
+	db		0f6h					; Offset 8: Fill byte for format
+	db		0fh						; Offset 9: Head setting time
+	db		08h						; Offset A: Wait for motor startup time
+
+%ifdef USE_AT
+	db		79						; Offset B: Maximum track number, 1.44MB value
+	db		0						; Offset C: Data transfer rate, 1.44MB value
+	db		4						; Offset D: Diskette CMOS drive type, 1.44MB value
+%else
+	db		39						; Offset B: Maximum track number, 360KB value
+	db		80h						; Offset C: Data transfer rate, 360KB value
+	db		1						; Offset D: Diskette CMOS drive type, 360KB value
+%endif
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm	(revision 516)
@@ -0,0 +1,310 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=9h, Initialize Drive Parameters.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; STORE_ERROR_FLAG_TO_DPT
+;	Parameters:
+;		%1:		Error flag to set
+;		AH:		BIOS Error Code
+;		DS:DI:	Ptr to DPT
+;		CF:		Set if error code in AH
+;	Returns:
+;		CF:		Clear if no error
+;				Set if error flag was set
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro STORE_ERROR_FLAG_TO_DPT 1
+	mov		al, %1
+	call	SetErrorFlagFromALwithErrorCodeInAH
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Int 13h function AH=9h, Initialize Drive Parameters.
+;
+; AH9h_HandlerForInitializeDriveParameters
+;	Parameters:
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH9h_HandlerForInitializeDriveParameters:
+%ifndef USE_186
+	call	AH9h_InitializeDriveForUse
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%else
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	; Fall to AH9h_InitializeDriveForUse
+%endif
+
+
+;--------------------------------------------------------------------
+; Initialize drive to be ready for use.
+;
+; AH9h_InitializeDriveForUse
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+AH9h_InitializeDriveForUse:
+	xor		ax, ax				; Clear AH to assume no errors
+
+%ifdef MODULE_ADVANCED_ATA
+	; Clear Initialization Error flags from DPT
+	mov		[di+DPT.bInitError], al
+%endif
+
+%ifdef MODULE_SERIAL
+	; No need to do this for serial devices
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_SERIAL_DEVICE	; Clears CF
+	jz		SHORT .ContinueInitialization
+	ret		; With AH and CF cleared
+.ContinueInitialization:
+%endif
+
+	push	es
+	push	si
+
+
+;;;	SelectDrive
+	; Try to select drive and wait until ready
+	call	AccessDPT_GetDriveSelectByteForOldInt13hToAL
+	mov		[bp+IDEPACK.bDrvAndHead], al
+	call	Device_SelectDrive
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_SELECT_DRIVE
+%ifdef USE_386
+	jc		.ReturnWithErrorCodeInAH
+%else
+	jnc		SHORT .ContinueInitializationSinceDriveSelectedSuccesfully
+	jmp		.ReturnWithErrorCodeInAH
+.ContinueInitializationSinceDriveSelectedSuccesfully:
+%endif
+
+
+;;; Set XT-CF mode
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	call	AccessDPT_GetIdevarsToCSBX
+	mov		al, [cs:bx+IDEVARS.bXTCFcontrolRegister]
+	call	AH9h_SetModeFromALtoXTCF
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_SET_XTCF_MODE
+.DoNotSetXTCFmode:
+%endif	; MODULE_8BIT_IDE_ADVANCED
+
+%ifdef MODULE_8BIT_IDE
+;;; Set 8-bit PIO mode
+	call	AH9h_Enable8bitModeForDevice8bitAta
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_SET_8BIT_MODE
+.DoNotSet8bitMode:
+%endif ; MODULE_8BIT_IDE
+
+
+;;;	InitializeDeviceParameters
+	; Initialize CHS parameters if LBA is not used and
+	; user has specified P-CHS parameters
+	test	BYTE [di+DPT.bFlagsLow], FLGL_DPT_ASSISTED_LBA
+	jnz		SHORT .SkipInitializeDeviceParameters		; No need to initialize CHS parameters if LBA mode enabled
+	call	AccessDPT_GetPointerToDRVPARAMStoCSBX
+	test	BYTE [cs:bx+DRVPARAMS.wFlags], FLG_DRVPARAMS_USERCHS    ; User specified P-CHS?
+	jz		SHORT .SkipInitializeDeviceParameters
+
+	; Initialize Logical Sectors per Track and Max Head number
+	mov		ax, [cs:bx+DRVPARAMS.wHeadsAndSectors]
+	dec		ax							; Max Head number
+	xchg	al, ah						; Heads now in AH
+	mov		dx, ax						; Sectors per Track now in DL
+	mov		al, COMMAND_INITIALIZE_DEVICE_PARAMETERS
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_BSY, FLG_STATUS_BSY)
+	call	Idepack_StoreNonExtParametersAndIssueCommandFromAL
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_INITIALIZE_CHS_PARAMETERS
+.SkipInitializeDeviceParameters:
+
+
+;;;	SetWriteCache
+	; Enable or Disable Write Cache
+	call	AccessDPT_GetPointerToDRVPARAMStoCSBX
+	mov		bl, [cs:bx+DRVPARAMS.wFlags]
+	push	bx	; Save .wFlags for later use in InitializeBlockMode
+	and		bx, BYTE MASK_DRVPARAMS_WRITECACHE
+	jz		SHORT .SkipSetWriteCache		; DEFAULT_WRITE_CACHE
+	mov		si, [cs:bx+.rgbWriteCacheCommands]
+	call	AH23h_SetControllerFeatures
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_SET_WRITE_CACHE
+.SkipSetWriteCache:
+
+
+;;;	RecalibrateDrive
+	; Recalibrate drive by seeking to cylinder 0
+	call	AH11h_RecalibrateDrive
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_RECALIBRATE_DRIVE
+
+
+;;;	InitializeBlockMode
+	; Initialize block mode transfers
+	pop		ax	; Restore .wFlags saved in SetWriteCache
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_BLOCK_MODE_SUPPORTED
+	jz		SHORT .BlockModeNotSupportedOrDisabled
+	test	al, FLG_DRVPARAMS_BLOCKMODE
+	jz		SHORT .BlockModeNotSupportedOrDisabled
+
+	; Try block sizes until we find largest possible supported by drive
+	mov		bl, 128
+.TryNextBlockSize:
+	mov		al, bl
+	call	AH24h_SetBlockSize	; Stores block size to DPT
+	jnc		SHORT .SupportedBlockSizeFound
+	shr		bl, 1
+	jnc		SHORT .TryNextBlockSize
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_SET_BLOCK_MODE
+.BlockModeNotSupportedOrDisabled:
+.SupportedBlockSizeFound:
+
+
+%ifdef MODULE_ADVANCED_ATA
+;;;	InitializePioMode
+	; Initialize fastest supported PIO mode
+	mov		dl, PIO_DEFAULT_MODE_DISABLE_IORDY
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_IORDY
+	jz		SHORT .IordyNotSupported
+
+	; Advanced PIO mode 3 and above
+	mov		dl, [di+DPT_ADVANCED_ATA.bPioMode]
+	or		dl, PIO_FLOW_CONTROL_MODE_xxx
+
+.IordyNotSupported:
+	mov		si, FEATURE_SET_TRANSFER_MODE
+	call	AH23h_SetControllerFeatures
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_SET_PIO_MODE
+%endif ; MODULE_ADVANCED_ATA
+
+
+%ifdef MODULE_FEATURE_SETS
+;;;	InitStandbyTimer
+	; Initialize the standby timer (if supported)
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_POWER_MANAGEMENT_SUPPORTED
+	jz		SHORT .NoPowerManagementSupport
+
+	mov		al, COMMAND_IDLE
+	mov		dl, [cs:ROMVARS.bIdleTimeout]
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_BSY, FLG_STATUS_BSY)
+	call	Idepack_StoreNonExtParametersAndIssueCommandFromAL
+	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_INITIALIZE_STANDBY_TIMER
+.NoPowerManagementSupport:
+%endif ; MODULE_FEATURE_SETS
+
+
+	; There might have been several errors so just return one error code for them all
+.ReturnWithErrorCodeInAH:
+%ifdef MODULE_ADVANCED_ATA
+	mov		ah, [di+DPT.bInitError]
+	test	ah, ah	; Clears CF
+	jz		SHORT .ReturnWithSuccess
+	mov		ah, RET_HD_RESETFAIL
+	stc
+.ReturnWithSuccess:
+%endif
+
+	pop		si
+	pop		es
+	ret
+
+
+.rgbWriteCacheCommands:
+	db		0								; DEFAULT_WRITE_CACHE
+	db		FEATURE_DISABLE_WRITE_CACHE		; DISABLE_WRITE_CACHE
+	db		FEATURE_ENABLE_WRITE_CACHE		; ENABLE_WRITE_CACHE
+
+
+
+;--------------------------------------------------------------------
+; SetErrorFlagFromALwithErrorCodeInAH
+;	Parameters:
+;		AH:		BIOS Error Code
+;		AL:		Error flag to set
+;		DS:DI:	Ptr to DPT
+;		CF:		Set if error code in AH
+;				Clear if AH = 0
+;	Returns:
+;		CF:		Clear if no error
+;				Set if error flag was set
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+IgnoreInvalidCommandError:
+	xor		ah, ah	; Clears CF
+SetErrorFlagFromALwithErrorCodeInAH:
+	jnc		SHORT .NoErrorFlagToSet
+	cmp		ah, RET_HD_INVALID
+	jbe		SHORT IgnoreInvalidCommandError
+
+	or		[di+DPT.bInitError], al
+	stc
+.NoErrorFlagToSet:
+	ret
+
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+;--------------------------------------------------------------------
+; AH9h_SetModeFromALtoXTCF
+;	Parameters:
+;		AL:		XT-CF Mode to set
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		Clear if successful or device is not XT-CF
+;				Set if failed to set mode for XT-CF
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI
+;--------------------------------------------------------------------
+AH9h_SetModeFromALtoXTCF:
+	call	AccessDPT_IsThisDeviceXTCF
+	jne		SHORT IgnoreInvalidCommandError
+	jmp		AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL
+%endif ; MODULE_8BIT_IDE_ADVANCED
+
+%ifdef MODULE_8BIT_IDE
+;--------------------------------------------------------------------
+; AH9h_Enable8bitModeForDevice8bitAta
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		Clear if successful or device is not DEVICE_8BIT_ATA
+;				Set if failed to set 8-bit mode for DEVICE_8BIT_ATA
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI
+;--------------------------------------------------------------------
+AH9h_Enable8bitModeForDevice8bitAta:
+	cmp		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_ATA
+	jne		SHORT IgnoreInvalidCommandError
+	jmp		AH23h_Enable8bitPioMode
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHCh_HSeek.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHCh_HSeek.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHCh_HSeek.asm	(revision 516)
@@ -0,0 +1,69 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=Ch, Seek.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=Ch, Seek.
+;
+; AHCh_HandlerForSeek
+;	Parameters:
+;		CX, DH:	Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Parameters on INTPACK:
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Starting sector number (1...63)
+;		DH:		Starting head number (0...255)
+;	Returns with INTPACK:
+;		AH:		BIOS Error code
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AHCh_HandlerForSeek:
+%ifndef USE_186
+	call	AHCh_SeekToCylinder
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%else
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	; Fall to AHCh_SeekToCylinder
+%endif
+
+;--------------------------------------------------------------------
+; AHCh_SeekToCylinder
+;	Parameters:
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Starting sector number (1...63)
+;		DH:		Starting head number (0...255)
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns:
+;		AH:		BIOS Error code
+;		CF:		0 if successful, 1 if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+AHCh_SeekToCylinder:
+	mov		ah, COMMAND_SEEK
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH41h_CheckIfExtensionsPresent.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH41h_CheckIfExtensionsPresent.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH41h_CheckIfExtensionsPresent.asm	(revision 516)
@@ -0,0 +1,49 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=41h, Check if Extensions Present.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=41h, Check if Extensions Present.
+;
+; AH41h_HandlerForCheckIfExtensionsPresent
+;	Parameters:
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		BX:		55AAh
+;	Returns with INTPACK:
+;		AH:		Major version of EBIOS extensions
+;		BX:		AA55h
+;		CX:		Support bits
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH41h_HandlerForCheckIfExtensionsPresent:
+	cmp		WORD [bp+IDEPACK.intpack+INTPACK.bx], 55AAh
+	jne		SHORT .EbiosNotSupported
+
+	mov		BYTE [bp+IDEPACK.intpack+INTPACK.ah], EBIOS_VERSION
+	mov		WORD [bp+IDEPACK.intpack+INTPACK.bx], 0AA55h
+	mov		WORD [bp+IDEPACK.intpack+INTPACK.cx], ENHANCED_DRIVE_ACCESS_SUPPORT
+	and		BYTE [bp+IDEPACK.intpack+INTPACK.flags], ~FLG_FLAGS_CF	; Return with CF cleared
+	jmp		Int13h_ReturnFromHandlerWithoutStoringErrorCode
+.EbiosNotSupported:
+	jmp		Int13h_DirectCallToAnotherBios
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH42h_ExtendedReadSectors.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH42h_ExtendedReadSectors.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH42h_ExtendedReadSectors.asm	(revision 516)
@@ -0,0 +1,64 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=42h, Extended Read Sectors.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=42h, Extended Read Sectors.
+;
+; AH42h_HandlerForExtendedReadSectors
+;	Parameters:
+;		SI:		Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		DS:SI:	Ptr to Disk Address Packet
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Return with Disk Address Packet in INTPACK:
+;		.wSectorCount	Number of sectors read successfully
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH42h_HandlerForExtendedReadSectors:
+	call	Prepare_ByLoadingDapToESSIandVerifyingForTransfer
+	mov		ah, [cs:bx+g_rgbReadCommandLookup]
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+	call	Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+	; Fall to AH42h_ReturnFromInt13hAfterStoringErrorCodeFromAHandTransferredSectorsFromCX
+
+
+;--------------------------------------------------------------------
+; AH42h_ReturnFromInt13hAfterStoringErrorCodeFromAHandTransferredSectorsFromCX
+;	Parameters:
+;		AH:		INT 13h Error Code
+;		CX:		Number of successfully transferred sectors
+;		SS:BP:	Ptr to IDEPACK
+;	Returns:
+;		Nothing, jumps to Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+;	Corrupts registers:
+;		SI, DS
+;--------------------------------------------------------------------
+AH42h_ReturnFromInt13hAfterStoringErrorCodeFromAHandTransferredSectorsFromCX:
+	mov		ds, [bp+IDEPACK.intpack+INTPACK.ds]
+	mov		si, [bp+IDEPACK.intpack+INTPACK.si]
+	mov		[si+DAP.wSectorCount], cx
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH43h_ExtendedWriteSectors.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH43h_ExtendedWriteSectors.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH43h_ExtendedWriteSectors.asm	(revision 516)
@@ -0,0 +1,56 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=43h, Extended Write Sectors.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=43h, Extended Write Sectors.
+;
+; AH43h_HandlerForExtendedWriteSectors
+;	Parameters:
+;		SI:		Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		AL:		0 or 1 to write with verify off
+;				2 to write with verify (if supported)
+;		DS:SI:	Ptr to Disk Address Packet
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Return with Disk Address Packet in INTPACK:
+;		.wSectorCount	Number of sectors written successfully
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH43h_HandlerForExtendedWriteSectors:
+	cmp		BYTE [bp+IDEPACK.intpack+INTPACK.al], 2	; Verify requested?
+	jae		SHORT Prepare_ReturnFromInt13hWithInvalidFunctionError
+
+	call	Prepare_ByLoadingDapToESSIandVerifyingForTransfer
+	mov		ah, [cs:bx+g_rgbWriteCommandLookup]
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+%ifdef USE_186
+	push	AH42h_ReturnFromInt13hAfterStoringErrorCodeFromAHandTransferredSectorsFromCX
+	jmp		Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+%else
+	call	Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+	jmp		SHORT AH42h_ReturnFromInt13hAfterStoringErrorCodeFromAHandTransferredSectorsFromCX
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH44h_ExtendedVerifySectors.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH44h_ExtendedVerifySectors.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH44h_ExtendedVerifySectors.asm	(revision 516)
@@ -0,0 +1,51 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=44h, Extended Verify Sectors.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=44h, Extended Verify Sectors.
+;
+; AH44h_HandlerForExtendedVerifySectors
+;	Parameters:
+;		SI:		Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		DS:SI:	Ptr to Disk Address Packet
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;	Return with Disk Address Packet in INTPACK:
+;		.wSectorCount	Number of sectors verified successfully
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH44h_HandlerForExtendedVerifySectors:
+	call	Prepare_ByLoadingDapToESSIandVerifyingForTransfer
+	mov		ah, [cs:bx+g_rgbVerifyCommandLookup]
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+%ifdef USE_186
+	push	AH42h_ReturnFromInt13hAfterStoringErrorCodeFromAHandTransferredSectorsFromCX
+	jmp		Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+%else
+	call	Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+	jmp		SHORT AH42h_ReturnFromInt13hAfterStoringErrorCodeFromAHandTransferredSectorsFromCX
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH47h_ExtendedSeek.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH47h_ExtendedSeek.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH47h_ExtendedSeek.asm	(revision 516)
@@ -0,0 +1,53 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=47h, Extended Seek.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=47h, Extended Seek.
+;
+; AH47h_HandlerForExtendedSeek
+;	Parameters:
+;		SI:		Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		DS:SI:	Ptr to Disk Address Packet
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AH47h_HandlerForExtendedSeek:
+	; Note that there is no Seek command for LBA48 addressing!
+	mov		es, [bp+IDEPACK.intpack+INTPACK.ds]	; ES:SI to point Disk Address Packet
+	cmp		BYTE [es:si+DAP.bSize], MINIMUM_DAP_SIZE
+	jb		SHORT Prepare_ReturnFromInt13hWithInvalidFunctionError
+
+	mov		ah, COMMAND_SEEK
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+%else
+	call	Idepack_ConvertDapToIdepackAndIssueCommandFromAH
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH48h_GetExtendedDriveParameters.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH48h_GetExtendedDriveParameters.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH48h_GetExtendedDriveParameters.asm	(revision 516)
@@ -0,0 +1,85 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 13h function AH=48h, Get Extended Drive Parameters.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int 13h function AH=48h, Get Extended Drive Parameters.
+;
+; AH48h_GetExtendedDriveParameters
+;	Parameters:
+;		SI:		Same as in INTPACK
+;		DL:		Translated Drive number
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		DS:SI:	Ptr to Extended Drive Information Table to fill
+;	Returns with INTPACK:
+;		AH:		Int 13h return status
+;		DS:SI:	Ptr to Extended Drive Information Table
+;		CF:		0 if successful, 1 if error
+;--------------------------------------------------------------------
+AH48h_HandlerForGetExtendedDriveParameters:
+	call	AccessDPT_GetLbaSectorCountToBXDXAX
+
+	; Point DS:SI to Extended Drive Information Table to fill
+	push	ds
+	pop		es			; DPT now in ES:DI
+	mov		ds, [bp+IDEPACK.intpack+INTPACK.ds]
+	mov		cx, MINIMUM_EDRIVEINFO_SIZE
+	cmp		[si+EDRIVE_INFO.wSize], cx
+	jb		Prepare_ReturnFromInt13hWithInvalidFunctionError
+	je		SHORT .SkipEddConfigurationParameters
+
+	; We do not support EDD Configuration Parameters so set to FFFF:FFFFh
+	sub		cx, BYTE MINIMUM_EDRIVEINFO_SIZE+1	; CX => FFFFh
+	mov		[si+EDRIVE_INFO.fpEDDparams], cx
+	mov		[si+EDRIVE_INFO.fpEDDparams+2], cx
+	mov		cx, EDRIVE_INFO_size
+
+	; Fill Extended Drive Information Table in DS:SI
+.SkipEddConfigurationParameters:
+	mov		[si+EDRIVE_INFO.wSize], cx
+	mov		WORD [si+EDRIVE_INFO.wFlags], FLG_DMA_BOUNDARY_ERRORS_HANDLED_BY_BIOS | FLG_CHS_INFORMATION_IS_VALID
+
+	; Store total sector count
+	mov		[si+EDRIVE_INFO.qwTotalSectors], ax
+	xor		ax, ax									; Return with success
+	mov		[si+EDRIVE_INFO.qwTotalSectors+2], dx
+	mov		[si+EDRIVE_INFO.qwTotalSectors+4], bx
+	mov		[si+EDRIVE_INFO.qwTotalSectors+6], ax	; Always zero
+	mov		WORD [si+EDRIVE_INFO.wSectorSize], 512
+
+	; Store P-CHS
+	eMOVZX	dx, BYTE [es:di+DPT.bPchsHeads]
+	xor		ax, ax									; Also a return code
+	mov		[si+EDRIVE_INFO.dwHeads], dx
+	mov		[si+EDRIVE_INFO.dwHeads+2], ax
+
+	mov		dl, [es:di+DPT.bPchsSectorsPerTrack]
+	mov		[si+EDRIVE_INFO.dwSectorsPerTrack], dx
+	mov		[si+EDRIVE_INFO.dwSectorsPerTrack+2], ax
+
+	mov		dx, [es:di+DPT.wPchsCylinders]
+	mov		[si+EDRIVE_INFO.dwCylinders], dx
+	mov		[si+EDRIVE_INFO.dwCylinders+2], ax
+
+.ReturnWithError:
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Tools/Address.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Tools/Address.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Tools/Address.asm	(revision 516)
@@ -0,0 +1,180 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for address translations.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;				
+
+; Section containing code
+SECTION .text
+
+;---------------------------------------------------------------------
+; Address_ExtractLCHSparametersFromOldInt13hAddress
+;	Parameters:
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Sector number
+;		DH:		Head number
+;	Returns:
+;		BL:		Sector number (1...63)
+;		BH:		Head number (0...255)
+;		CX:		Cylinder number (0...1023)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Address_ExtractLCHSparametersFromOldInt13hAddress:
+	mov		bl, cl				; Copy sector number...
+	and		bl, 3Fh				; ...and limit to 1...63
+	sub		cl, bl				; Remove from cylinder number high
+	eROL_IM	cl, 2				; High bits to beginning
+	mov		bh, dh				; Copy Head number
+	xchg	cl, ch				; Cylinder number now in CX
+	ret
+
+
+;---------------------------------------------------------------------
+; Converts LARGE addressing mode LCHS parameters to IDE P-CHS parameters.
+; PCylinder	= (LCylinder << n) + (LHead / PHeadCount)
+; PHead		= LHead % PHeadCount
+; PSector	= LSector
+;
+; ConvertLargeModeLCHStoPCHS:
+;	Parameters:
+;		BL:		Sector number (1...63)
+;		BH:		Head number (0...239)
+;		CX:		Cylinder number (0...1023)
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		BL:		Sector number (1...63)
+;		BH:		Head number (0...15)
+;		CX:		Cylinder number (0...16382)
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConvertLargeModeLCHStoPCHS:
+	; LHead / PHeadCount and LHead % PHeadCount
+	eMOVZX	ax, bh					; Copy L-CHS Head number to AX
+	div		BYTE [di+DPT.bPchsHeads]; AL = LHead / PHeadCount, AH = LHead % PHeadCount
+	mov		bh, ah					; Copy P-CHS Head number to BH
+	xor		ah, ah					; AX = LHead / PHeadCount
+
+	; (LCylinder << n) + (LHead / PHeadCount)
+	mov		dx, cx					; Copy L-CHS Cylinder number to DX
+	mov		cl, [di+DPT.bFlagsLow]	; Load shift count
+	and		cl, MASKL_DPT_CHS_SHIFT_COUNT
+	shl		dx, cl					; DX = LCylinder << n
+	add		ax, dx					; AX = P-CHS Cylinder number
+	xchg	cx, ax					; Move P-CHS Cylinder number to CX
+DoNotConvertLCHS:
+	ret
+
+
+;--------------------------------------------------------------------
+; Address_OldInt13hAddressToIdeAddress
+;	Parameters:
+;		CH:		Cylinder number, bits 7...0
+;		CL:		Bits 7...6: Cylinder number bits 9 and 8
+;				Bits 5...0:	Starting sector number (1...63)
+;		DH:		Starting head number (0...255)
+;		DS:DI:	Ptr to DPT
+;	Returns:
+;		BL:		LBA Low Register / Sector Number Register (LBA 7...0)
+;		CL:		LBA Mid Register / Low Cylinder Register (LBA 15...8)
+;		CH:		LBA High Register / High Cylinder Register (LBA 23...16)
+;		BH:		Drive and Head Register (LBA 27...24)
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Address_OldInt13hAddressToIdeAddress:
+		call	Address_ExtractLCHSparametersFromOldInt13hAddress
+		ACCESSDPT__GET_UNSHIFTED_TRANSLATE_MODE_TO_AXZF
+
+;;; 0: ADDRESSING_MODE_NORMAL
+		jz		SHORT DoNotConvertLCHS
+
+;;; 1: ADDRESSING_MODE_LARGE
+		test	al, FLGL_DPT_ASSISTED_LBA
+		jz		SHORT ConvertLargeModeLCHStoPCHS
+
+;;; 2: ADDRESSING_MODE_ASSISTED_LBA
+		; Fall through to ConvertAssistedLBAModeLCHStoLBARegisterValues
+
+
+;---------------------------------------------------------------------
+; Converts LCHS parameters to 28-bit LBA address.
+; Only 24-bits are used since LHCS to LBA28 conversion has 8.4GB limit.
+; LBA = ((cylToSeek*headsPerCyl+headToSeek)*sectPerTrack)+sectToSeek-1
+;
+; Returned address is in same registers that
+; DoNotConvertLCHS and ConvertLargeModeLCHStoPCHS returns.
+;
+; ConvertAssistedLBAModeLCHStoLBARegisterValues:
+;	Parameters:
+;		BL:		Sector number (1...63)
+;		BH:		Head number (0...254)
+;		CX:		Cylinder number (0...1023)
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		BL:		LBA Low Register / Sector Number Register (LBA 7...0)
+;		CL:		LBA Mid Register / Low Cylinder Register (LBA 15...8)
+;		CH:		LBA High Register / High Cylinder Register (LBA 23...16)
+;		BH:		Drive and Head Register (LBA 27...24)
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ConvertAssistedLBAModeLCHStoLBARegisterValues:
+	; cylToSeek*headsPerCyl (18-bit result)
+	; Max = 1023 * 255 = 260,865 = 3FB01h
+	mov		ax, LBA_ASSIST_SPT		; Load Sectors per Track
+	xchg	cx, ax					; Cylinder number to AX, Sectors per Track to CX
+%ifdef USE_386
+	movzx	dx, [di+DPT.bLchsHeads]
+%else
+	cwd
+	mov		dl, [di+DPT.bLchsHeads]
+%endif
+	mul		dx						; DX:AX = cylToSeek*headsPerCyl
+
+	; +=headToSeek (18-bit result)
+	; Max = 260,865 + 254 = 261,119 = 3FBFFh
+	add		al, bh					; Add Head number to DX:AX
+	adc		ah, dh					; DH = Zero after previous multiplication
+	adc		dl, dh
+
+	; *=sectPerTrack (18-bit by 6-bit multiplication with 24-bit result)
+	; Max = 261,119 * 63 = 16,450,497 = FB03C1h
+	xchg	ax, dx					; Hiword to AX, loword to DX
+	mul		cl						; AX = hiword * Sectors per Track
+	mov		bh, al					; Backup hiword * Sectors per Track
+	xchg	ax, dx					; Loword back to AX
+	mul		cx						; DX:AX = loword * Sectors per Track
+	add		dl, bh					; DX:AX = (cylToSeek*headsPerCyl+headToSeek)*sectPerTrack
+
+	; +=sectToSeek-1 (24-bit result)
+	; Max = 16,450,497 + 63 - 1 = 16,450,559 = FB03FFh
+	xor		bh, bh					; Sector number now in BX
+	dec		bx						; sectToSeek-=1
+	add		ax, bx					; Add to loword
+	adc		dl, bh					; Add possible carry to byte2, BH=zero
+
+	; Copy DX:AX to proper return registers
+	xchg	bx, ax					; BL = Sector Number Register (LBA 7...0)
+	mov		cl, bh					; Low Cylinder Register (LBA 15...8)
+	mov		ch, dl					; High Cylinder Register (LBA 23...16)
+	mov		bh, dh					; Drive and Head Register (LBA 27...24)
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Tools/Prepare.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Tools/Prepare.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Tools/Prepare.asm	(revision 516)
@@ -0,0 +1,158 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for preparing data buffer for transfer.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Prepare_ByLoadingDapToESSIandVerifyingForTransfer
+;	Parameters:
+;		SI:		Offset to DAP
+;		DS:DI:	Ptr to DPT
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		DS:SI:	Ptr to Disk Address Packet
+;	Returns:
+;		BX:		Index to command lookup table
+;		ES:SI:	Ptr to Disk Address Packet (DAP)
+;		Exits from INT 13h if invalid DAP
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+%ifdef MODULE_EBIOS
+ALIGN JUMP_ALIGN
+Prepare_ByLoadingDapToESSIandVerifyingForTransfer:
+	; Load pointer to DAP to ES:SI and make sure it is valid
+	mov		es, [bp+IDEPACK.intpack+INTPACK.ds]	; ES:SI to point Disk Address Packet
+	cmp		BYTE [es:si+DAP.bSize], MINIMUM_DAP_SIZE
+	jb		SHORT InvalidDAP
+
+	; Make sure that sector count is valid
+	mov		ax, [es:si+DAP.wSectorCount]
+	test	ax, ax
+	jz		SHORT ZeroSectorsRequestedSoNoErrors
+	cmp		ax, BYTE 127
+	ja		SHORT InvalidNumberOfSectorsRequested
+
+	; Get EBIOS command index to BX
+	; LBA28 or LBA48 command
+	call	Prepare_GetOldInt13hCommandIndexToBX
+	mov		al, [di+DPT.bFlagsLow]
+	eSHL_IM	al, 1					; Set CF if LBA48 supported
+	adc		bl, bh					; LBA48 EXT commands
+	ret
+%endif ; MODULE_EBIOS
+
+
+;--------------------------------------------------------------------
+; Prepare_GetOldInt13hCommandIndexToBX
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;	Returns:
+;		BX:		Index to command lookup table
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Prepare_GetOldInt13hCommandIndexToBX:
+	; Block mode or single sector
+	mov		bl, [di+DPT.bFlagsHigh]
+	and		bx, BYTE FLGH_DPT_BLOCK_MODE_SUPPORTED	; Bit 1
+	ret
+
+
+;---------------------------------------------------------------------
+; Prepare_BufferToESSIforOldInt13hTransfer
+;	Parameters:
+;		AL:		Number of sectors to transfer
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		ES:BX:	Ptr to data buffer
+;	Returns:
+;		ES:SI:	Ptr to normalized data buffer
+;		Exits INT 13h if error
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Prepare_BufferToESSIforOldInt13hTransfer:
+	mov		si, [bp+IDEPACK.intpack+INTPACK.bx]	; Load offset
+	mov		es, [bp+IDEPACK.intpack+INTPACK.es]	; Load segment
+	; Fall to Prepare_ByValidatingSectorsInALforOldInt13h
+
+;---------------------------------------------------------------------
+; Prepare_ByValidatingSectorsInALforOldInt13h
+;	Parameters:
+;		AL:		Number of sectors to transfer
+;	Returns:
+;		Exits INT 13h if invalid number of sectors in AL
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Prepare_ByValidatingSectorsInALforOldInt13h:
+	test	al, al
+	js		SHORT .CheckZeroOffsetFor128Sectors		; 128 or more
+	jz		SHORT InvalidNumberOfSectorsRequested	; Zero not allowed for old INT 13h
+	ret		; Continue with transfer
+
+ALIGN JUMP_ALIGN
+.CheckZeroOffsetFor128Sectors:
+	cmp		al, 128
+	ja		SHORT InvalidNumberOfSectorsRequested
+	test	si, si								; Offset must be zero to xfer 128 sectors
+	jnz		SHORT CannotAlignPointerProperly
+	ret		; Continue with transfer
+
+InvalidDAP:
+InvalidNumberOfSectorsRequested:
+Prepare_ReturnFromInt13hWithInvalidFunctionError:
+	mov		ah, RET_HD_INVALID
+	SKIP2B	f
+CannotAlignPointerProperly:
+	mov		ah, RET_HD_BOUNDARY
+ZeroSectorsRequestedSoNoErrors:
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+
+
+
+; Command lookup tables
+g_rgbReadCommandLookup:
+	db		COMMAND_READ_SECTORS		; 00b, CHS or LBA28 single sector
+	db		COMMAND_READ_SECTORS_EXT	; 01b, LBA48 single sector
+	db		COMMAND_READ_MULTIPLE		; 10b, CHS or LBA28 block mode
+%ifdef MODULE_EBIOS
+	db		COMMAND_READ_MULTIPLE_EXT	; 11b, LBA48 block mode
+%endif
+
+g_rgbWriteCommandLookup:
+	db		COMMAND_WRITE_SECTORS
+	db		COMMAND_WRITE_SECTORS_EXT
+	db		COMMAND_WRITE_MULTIPLE
+%ifdef MODULE_EBIOS
+	db		COMMAND_WRITE_MULTIPLE_EXT
+%endif
+
+g_rgbVerifyCommandLookup:
+	db		COMMAND_VERIFY_SECTORS
+	db		COMMAND_VERIFY_SECTORS_EXT
+	db		COMMAND_VERIFY_SECTORS
+%ifdef MODULE_EBIOS
+	db		COMMAND_VERIFY_SECTORS_EXT
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h.asm	(revision 516)
@@ -0,0 +1,231 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 19h Handler (Boot Loader).
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Int19h_BootLoaderHandler
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Never returns (loads operating system)
+;--------------------------------------------------------------------
+Int19h_BootLoaderHandler:
+	sti									; Enable interrupts
+	cld									; String instructions to increment pointers
+	LOAD_BDA_SEGMENT_TO	es, ax			; Load BDA segment (zero) to ES
+	; Fall to .PrepareBootLoaderStack
+
+
+;--------------------------------------------------------------------
+; Drive detection and boot menu use lots of stack so it is
+; wise to relocate stack. Otherwise something important from
+; interrupt vectors are likely corrupted, likely our own DPTs if
+; they are located to 30:0h.
+;
+; .PrepareBootLoaderStack
+;	Parameters:
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		Never returns (loads operating system)
+;--------------------------------------------------------------------
+.PrepareBootLoaderStack:
+	STORE_POST_STACK_POINTER
+	SWITCH_TO_BOOT_MENU_STACK
+	; Fall to .InitializeDisplay
+
+
+;--------------------------------------------------------------------
+; .InitializeDisplay
+;	Parameters:
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		Never returns (loads operating system)
+;--------------------------------------------------------------------
+.InitializeDisplay:
+	; Change display mode if necessary
+	mov		ax, [cs:ROMVARS.wDisplayMode]	; AH 00h = Set Video Mode
+	cmp		al, DEFAULT_TEXT_MODE
+	je		SHORT .InitializeDisplayLibrary
+	int		BIOS_VIDEO_INTERRUPT_10h
+.InitializeDisplayLibrary:
+	call	DetectPrint_InitializeDisplayContext
+	; Fall to .InitializeBiosAndDetectDrives
+
+
+;--------------------------------------------------------------------
+; .InitializeBiosAndDetectDrives
+;	Parameters:
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		DS:		RAMVARS segment
+;--------------------------------------------------------------------
+%ifdef MODULE_HOTKEYS
+	call	TimerTicks_ReadFromBdaToAX
+	add		ax, MIN_TIME_TO_DISPLAY_HOTKEY_BAR
+	mov		[es:BOOTVARS.hotkeyVars+HOTKEYVARS.wTimeToClose], ax
+%endif
+
+	call	Initialize_AndDetectDrives
+
+%ifdef MODULE_HOTKEYS
+.WaitUntilTimeToCloseHotkeyBar:
+	call	TimerTicks_ReadFromBdaToAX
+	cmp		ax, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wTimeToClose]
+	jb		SHORT .WaitUntilTimeToCloseHotkeyBar
+%endif
+	; Fall to SelectDriveToBootFrom
+
+
+;--------------------------------------------------------------------
+; SelectDriveToBootFrom
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		Never returns (loads operating system)
+;--------------------------------------------------------------------
+SelectDriveToBootFrom:
+
+; The following macro could be easily inlined below.  Why a macro?  Depending on the combination
+; of MODULE_HOTKEYS or MODULE_BOOT_MENU, this code needs to either come before or after the
+; call to the boot menu.
+;
+%macro TRY_TO_BOOT_DL_AND_DH_DRIVES 0
+	push	dx									; it's OK if this is left on the stack, if we are
+												; successful, the following call does not return
+	call	TryToBootFromPrimaryOrSecondaryBootDevice_AndBoot
+	pop		dx
+	mov		dl, dh
+	call	TryToBootFromPrimaryOrSecondaryBootDevice_AndBoot
+%endmacro
+
+%ifdef MODULE_HOTKEYS
+	call	HotkeyBar_ScanHotkeysFromKeyBufferAndStoreToBootvars
+	cmp		al, ROM_BOOT_HOTKEY_SCANCODE
+	je		.RomBoot							; CF clear so ROM boot
+%ifdef MODULE_BOOT_MENU
+	cmp		al, BOOT_MENU_HOTKEY_SCANCODE
+	je		.BootMenu
+%endif
+	call	HotkeyBar_GetBootDriveNumbersToDX
+.TryUsingHotKeysCode:
+	TRY_TO_BOOT_DL_AND_DH_DRIVES
+	;; falls through to boot menu, if it is present.  If not present, falls through to rom boot.
+%endif ; MODULE_HOTKEYS
+
+%ifdef MODULE_BOOT_MENU
+.BootMenu:
+	call	BootMenu_DisplayAndReturnDriveInDLRomBootClearCF
+	jnc		.RomBoot							; CF clear so ROM boot
+
+	mov		dh, dl								; Setup for secondary drive
+	not		dh									; Floppy goes to HD, or vice versa
+	and		dh, 80h								; Go to first drive of the floppy or HD set
+
+%ifdef MODULE_HOTKEYS
+	jmp		.TryUsingHotKeysCode
+%else
+	TRY_TO_BOOT_DL_AND_DH_DRIVES
+	jmp		.BootMenu
+%endif
+%endif ; MODULE_BOOT_MENU
+
+%ifndef MODULE_HOTKEYS OR MODULE_BOOT_MENU
+	xor		dl, dl			; Try to boot from Floppy Drive A
+	call	TryToBootFromPrimaryOrSecondaryBootDevice_AndBoot
+	mov		dl, 80h			; Try to boot from Hard Drive C
+	call	TryToBootFromPrimaryOrSecondaryBootDevice_AndBoot
+%endif
+
+.RomBoot:
+%ifdef MODULE_DRIVEXLATE
+	call	DriveXlate_Reset					; Clean up any drive mappings before Rom Boot
+%endif
+	clc
+	;; fall through to JumpToBootSector_or_RomBoot
+
+;--------------------------------------------------------------------
+; JumpToBootSector_or_RomBoot
+;
+; Switches back to the POST stack, clears the DS and ES registers,
+; and either jumps to the MBR (Master Boot Record) that was just read,
+; or calls the ROM's boot routine on interrupt 18.
+;
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;       CF:     Set for Boot Sector Boot
+;               Clear for ROM Boot
+;	   	ES:BX:	(if CF set) Ptr to boot sector
+;
+;	Returns:
+;		Never returns
+;--------------------------------------------------------------------
+JumpToBootSector_or_RomBoot:
+	mov		cx, es		; Preserve MBR segment (can't push because of stack change)
+	mov		ax, 0		; NOTE: can't use XOR (LOAD_BDA_SEGMENT_TO) as it impacts CF
+	SWITCH_BACK_TO_POST_STACK
+
+; clear segment registers before boot sector or rom call
+	mov		ds, ax
+	mov		es, ax
+%ifdef USE_386
+	mov		fs, ax
+	mov		gs, ax
+%endif
+	jnc		SHORT .romboot
+
+; jump to boot sector
+	push	cx			; sgment address for MBR
+	push	bx			; offset address for MBR
+	retf				; NOTE:	DL is set to the drive number
+
+; Boot by calling INT 18h (ROM Basic of ROM DOS)
+.romboot:
+	int		BIOS_BOOT_FAILURE_INTERRUPT_18h	; Never returns
+
+
+;--------------------------------------------------------------------
+; TryToBootFromPrimaryOrSecondaryBootDevice_AndBoot
+;	Parameters
+;		DL:		Drive selected as boot device
+;		DS:		RAMVARS segment
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;       CF:     Set for Boot Sector Boot
+;               Clear for ROM Boot
+;	   	ES:BX:	(if CF set) Ptr to boot sector
+;	Corrupts registers:
+;		AX, CX, DH, SI, DI, (DL if failed to read boot sector)
+;--------------------------------------------------------------------
+%ifndef MODULE_DRIVEXLATE
+TryToBootFromPrimaryOrSecondaryBootDevice_AndBoot	EQU		BootSector_TryToLoadFromDriveDL_AndBoot
+
+%else
+TryToBootFromPrimaryOrSecondaryBootDevice_AndBoot:
+	call	DriveXlate_SetDriveToSwap
+	call	DriveXlate_ToOrBack
+	; fall through to TryToBoot_FallThroughTo_BootSector_TryToLoadFromDriveDL_AndBoot
+
+TryToBoot_FallThroughTo_BootSector_TryToLoadFromDriveDL_AndBoot:
+; fall through to BootSector_TryToLoadFromDriveDL_AndBoot
+%endif
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h/BootSector.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h/BootSector.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h/BootSector.asm	(revision 516)
@@ -0,0 +1,105 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Reading and jumping to boot sector.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; BootSector_TryToLoadFromDriveDL_AndBoot
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;		DS:		RAMVARS segment
+;	Returns:
+;		ES:BX:	Ptr to boot sector (if successful)
+;		CF:		Set if boot sector loaded successfully
+;				Cleared if failed to load boot sector
+;	Corrupts registers:
+;		AX, CX, DH, SI, DI, (DL if failed to read boot sector)
+;--------------------------------------------------------------------
+BootSector_TryToLoadFromDriveDL_AndBoot:
+	call	DetectPrint_TryToBootFromDL
+	call	LoadFirstSectorFromDriveDL
+%ifndef USE_386
+	jc		SHORT .FailedToLoadFirstSector
+%else
+	jc		DetectPrint_FailedToLoadFirstSector
+%endif
+
+	test	dl, dl
+	jns		SHORT .AlwaysBootFromFloppyDriveForBooterGames
+	cmp		WORD [es:bx+510], 0AA55h		; Valid boot sector?
+	jne		SHORT .FirstHardDiskSectorNotBootable
+.AlwaysBootFromFloppyDriveForBooterGames:
+	stc
+	jmp		SHORT JumpToBootSector_or_RomBoot
+
+%ifndef USE_386
+.FailedToLoadFirstSector:
+	jmp		DetectPrint_FailedToLoadFirstSector
+%endif
+
+.FirstHardDiskSectorNotBootable:
+	mov		si, g_szBootSectorNotFound
+	jmp		DetectPrint_NullTerminatedStringFromCSSIandSetCF
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+  %ifdef MODULE_DRIVEXLATE
+    %if TryToBoot_FallThroughTo_BootSector_TryToLoadFromDriveDL_AndBoot <> BootSector_TryToLoadFromDriveDL_AndBoot
+	  %error "TryToBoot_FallThroughTo_BootSector_TryToLoadFromDriveDL_AndBoot <> BootSector_TryToLoadFromDriveDL_AndBoot, BootSector must come immediately after int19h.asm"
+    %endif
+  %endif
+%endif
+
+;--------------------------------------------------------------------
+; LoadFirstSectorFromDriveDL
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;	Returns:
+;		AH:		INT 13h error code
+;		ES:BX:	Ptr to boot sector (if successful)
+;		CF:		Cleared if read successful
+;				Set if any error
+;	Corrupts registers:
+;		AL, CX, DH, DI
+;--------------------------------------------------------------------
+LoadFirstSectorFromDriveDL:
+	LOAD_BDA_SEGMENT_TO	es, bx				; ES:BX now points to...
+	mov		bx, BOOTVARS.rgbBootSect		; ...boot sector location
+	mov		di, BOOT_READ_RETRY_TIMES		; Initialize retry counter
+
+.ReadRetryLoop:
+	mov		ax, 0201h						; Read 1 sector
+	mov		cx, 1							; Cylinder 0, Sector 1
+	xor		dh, dh							; Head 0
+	int		BIOS_DISK_INTERRUPT_13h
+	jc		SHORT .FailedToLoadFirstSector
+.Return:
+	ret
+
+.FailedToLoadFirstSector:
+	dec		di								; Decrement retry counter (preserve CF)
+	jz		SHORT .Return					; Loop while retries left
+
+	; Reset drive and retry
+	xor		ax, ax							; AH=00h, Disk Controller Reset
+	test	dl, dl							; Floppy drive?
+	eCMOVS	ah, RESET_HARD_DISK				; AH=0Dh, Reset Hard Disk (Alternate reset)
+	int		BIOS_DISK_INTERRUPT_13h
+	jmp		SHORT .ReadRetryLoop
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h/Int19hReset.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h/Int19hReset.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Handlers/Int19h/Int19hReset.asm	(revision 516)
@@ -0,0 +1,35 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 19h Handler (Boot Loader).
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; INT 19h handler that properly reboots the computer when
+; INT 19h is called.
+;
+; Int19hReset_Handler
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Never returns (reboots computer)
+;--------------------------------------------------------------------
+Int19hReset_Handler:
+	mov		ax, BOOT_FLAG_WARM				; Skip memory tests
+	jmp		Reboot_ComputerWithBootFlagInAX
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/AdvAtaInit.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/AdvAtaInit.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/AdvAtaInit.asm	(revision 516)
@@ -0,0 +1,142 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Common functions for initializing different
+;					VLB and PCI IDE Controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; AdvAtaInit_DetectControllerForIdeBaseInBX
+;	Parameters:
+;		BX:		IDE Controller base port
+;	Returns:
+;		AX:		ID WORD specific for detected controller
+;				Zero if no controller detected
+;		DX:		Controller base port (not IDE)
+;		CF:		Set if controller detected
+;				Cleared if no controller
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+AdvAtaInit_DetectControllerForIdeBaseInBX:
+	call	Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
+	jne		SHORT .NoAdvancedControllerForPortBX
+	call	Vision_DoesIdePortInBXbelongToControllerWithIDinAX
+	jne		SHORT .NoAdvancedControllerForPortBX
+
+	stc		; Advanced Controller found for port BX
+	ret
+
+.NoAdvancedControllerForPortBX:
+	xor		ax, ax
+	ret
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_GetControllerMaxPioModeToAL
+;	Parameters:
+;		AX:		ID WORD specific for detected controller
+;	Returns:
+;		AL:		Max supported PIO mode
+;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
+;		CF:		Set if PIO limit necessary
+;				Cleared if no need to limit timings
+;	Corrupts registers:
+;		(AX if CF cleared)
+;--------------------------------------------------------------------
+AdvAtaInit_GetControllerMaxPioModeToAL	equ	Vision_GetMaxPioModeToAL
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_InitializeControllerForDPTinDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;	Returns:
+;		AH:		Int 13h return status
+;		CF:		Cleared if success or no controller to initialize
+;				Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+AdvAtaInit_InitializeControllerForDPTinDSDI:
+	; Call Controller Specific initialization function
+	mov		ax, [di+DPT_ADVANCED_ATA.wControllerID]
+	test	ax, ax
+	jz		SHORT .NoAdvancedController	; Return with CF cleared
+
+	push	bp
+	push	si
+
+	; We only support Vision at the moment so no need to identify ID
+	call	AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
+	call	Vision_InitializeWithIDinAHandConfigInAL
+
+	pop		si
+	pop		bp
+
+.NoAdvancedController:
+	xor		ax, ax						; Success
+	ret
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;	Returns:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;		SI:		Offset to Master DPT if Slave Drive present
+;				Zero if Slave Drive not present
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI:
+	; Must be Slave Drive if previous DPT has same IDEVARS offset
+	lea		si, [di-LARGEST_DPT_SIZE]	; DS:SI points to previous DPT
+	mov		al, [di+DPT.bIdevarsOffset]
+	cmp		al, [si+DPT.bIdevarsOffset]
+	je		SHORT .MasterAndSlaveDrivePresent
+
+	; We only have single drive so zero SI
+	xor		si, si
+.MasterAndSlaveDrivePresent:
+	ret
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;		SI:		Offset to Master DPT if Slave Drive present
+;				Zero if Slave Drive not present
+;	Returns:
+;		BX:		Best common PIO mode
+;		CX:		Slowest common PIO Cycle Time in nanosecs
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI:
+	eMOVZX	bx, [di+DPT_ADVANCED_ATA.bPioMode]
+	mov		cx, [di+DPT_ADVANCED_ATA.wMinPioCycleTime]
+	test	si, si
+	jz		SHORT .PioTimingsLoadedToAXandCX
+	MIN_U	bl, [si+DPT_ADVANCED_ATA.bPioMode]
+	MAX_U	cx, [si+DPT_ADVANCED_ATA.wMinPioCycleTime]
+.PioTimingsLoadedToAXandCX:
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.asm	(revision 516)
@@ -0,0 +1,251 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for initializing QDI Vision
+;					QD6500 and QD6580 VLB IDE Controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AX:		ID WORD specific for QDI Vision Controllers
+;				(AL = QD65xx Config Register contents)
+;				(AH = QDI Vision Controller ID (bits 4...7))
+;		DX:		Controller port (not IDE port)
+;		ZF:		Set if controller found
+;				Cleared if supported controller not found (AX,DX = undefined)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent:
+	; Check QD65xx base port
+	mov		dx, QD65XX_BASE_PORT
+	in		al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
+	call	IsConfigRegisterWithIDinAL
+	je		SHORT VisionControllerDetected
+
+	; Check QD65xx alternative base port
+	or		dl, QD65XX_ALTERNATIVE_BASE_PORT
+	in		al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
+	; Fall to IsConfigRegisterWithIDinAL
+
+;--------------------------------------------------------------------
+; IsConfigRegisterWithIDinAL
+;	Parameters:
+;		AL:		Possible QD65xx Config Register contents
+;	Returns:
+;		AH		QDI Vision Controller ID or undefined
+;		ZF:		Set if controller found
+;				Cleared if supported controller not found (AH = undefined)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+IsConfigRegisterWithIDinAL:
+	mov		ah, al
+	and		al, MASK_QDCONFIG_CONTROLLER_ID
+	cmp		al, ID_QD6500 << 4
+	je		SHORT VisionControllerDetected
+	cmp		al, ID_QD6580 << 4
+	je		SHORT VisionControllerDetected
+	cmp		al, ID_QD6580_ALTERNATE << 4
+VisionControllerDetected:
+	xchg	ah, al
+	ret
+
+
+;--------------------------------------------------------------------
+; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
+;	Parameters:
+;		AL:		QD65xx Config Register contents
+;		AH:		QDI Vision Controller ID (bits 4...7)
+;		BX:		IDE Base port to check
+;		DX:		Vision Controller port
+;	Returns:
+;		ZF:		Set if port belongs to controller
+;				Cleared if port belongs to another controller
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
+	cmp		ah, ID_QD6500 << 4
+	je		SHORT .DoesIdePortInDXbelongToQD6500
+
+	; QD6580 always have Primary IDE at 1F0h
+	; Secondary IDE at 170h can be enabled or disabled
+	cmp		bx, DEVICE_ATA_PRIMARY_PORT
+	je		SHORT .ReturnResultInZF
+
+	; Check if Secondary IDE channel is enabled
+	push	ax
+	add		dx, BYTE QD6580_CONTROL_REGISTER
+	in		al, dx
+	sub		dx, BYTE QD6580_CONTROL_REGISTER
+	test	al, FLG_QDCONTROL_SECONDARY_DISABLED_in
+	pop		ax
+	jz		SHORT .CompareBXtoSecondaryIDE
+	ret
+
+	; QD6500 has only one IDE channel that can be at 1F0h or 170h
+.DoesIdePortInDXbelongToQD6500:
+	test	al, FLG_QDCONFIG_PRIMARY_IDE
+	jz		SHORT .CompareBXtoSecondaryIDE
+	cmp		bx, DEVICE_ATA_PRIMARY_PORT
+	ret
+
+.CompareBXtoSecondaryIDE:
+	cmp		bx, DEVICE_ATA_SECONDARY_PORT
+.ReturnResultInZF:
+	ret
+
+
+;--------------------------------------------------------------------
+; Vision_GetMaxPioModeToAL
+;	Parameters:
+;		AL:		QD65xx Config Register contents
+;		AH:		QDI Vision Controller ID (bits 4...7)
+;	Returns:
+;		AL:		Max supported PIO mode
+;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
+;		CF:		Set if PIO limit necessary
+;				Cleared if no need to limit timings
+;	Corrupts registers:
+;		(AX if CF cleared)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Vision_GetMaxPioModeToAL:
+	cmp		ah, ID_QD6500 << 4
+	clc
+	jne		SHORT .NoNeedToLimitForQD6580
+
+	mov		ax, 2	; Limit to PIO 2 because QD6500 does not support IORDY
+	stc
+.NoNeedToLimitForQD6580:
+	ret
+
+
+;--------------------------------------------------------------------
+; Vision_InitializeWithIDinAHandConfigInAL
+;	Parameters:
+;		AL:		QD65xx Config Register contents
+;		AH:		QDI Vision Controller ID (bits 4...7)
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;		SI:		Offset to Master DPT if Slave Drive present
+;				Zero if Slave Drive not present
+;	Returns:
+;		CF:		Cleared if success
+;				Set if error
+;	Corrupts registers:
+;		AX, BX, CX, DX, BP
+;--------------------------------------------------------------------
+Vision_InitializeWithIDinAHandConfigInAL:
+	; QD6580 has a Control Register that needs to be programmed
+	mov		dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
+	cmp		ah, ID_QD6500 << 4
+	je		SHORT .CalculateTimingForQD6500
+
+	; Program QD6580 Control Register (not available on QD6500) to
+	; Enable or Disable Read-Ahead and Post-Write Buffer to match
+	; jumper setting on the multi I/O card.
+	xor		ax, ax
+	add		dx, BYTE QD6580_CONTROL_REGISTER
+	in		al, dx									; Read to get ATAPI jumper status
+	test	al, FLG_QDCONTROL_HDONLY_in
+	eCMOVNZ	ah, FLG_QDCONTROL_NONATAPI				; Enable Read-Ahead and Post-Write Buffers
+	or		ah, MASK_QDCONTROL_FLAGS_TO_SET
+	mov		al, ah
+	out		dx, al
+	sub		dx, BYTE QD6580_CONTROL_REGISTER
+
+	; Now we need to determine is the drive connected to the Primary or Secondary channel.
+	; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
+	; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
+	mov		bx, [di+DPT.wBasePort]
+	cmp		bx, DEVICE_ATA_PRIMARY_PORT
+	je		SHORT .CalculateTimingTicksForQD6580	; Primary Channel so no need to modify DX
+	times 2 inc dx									; Secondary Channel IDE Timing Register
+
+	; QD6500 and QD6580 require slightly different calculations.
+.CalculateTimingTicksForQD6580:
+	mov		bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)
+	jmp		SHORT .CalculateTimingsForQD65xx
+
+.CalculateTimingForQD6500:
+	mov		bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)
+
+	; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
+.CalculateTimingsForQD65xx:
+	call	AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
+
+	; Calculate Active Time value for QD65xx IDE Timing Register
+	call	AtaID_GetActiveTimeToAXfromPioModeInBX
+	call	ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
+	xchg	bp, ax
+
+	; Calculate Recovery Time value for QD65xx IDE Timing Register
+	call	AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
+	mov		bx, bp						; Active Time value now in BL
+	mov		bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
+	call	ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
+
+	; Merge the values to a single byte to output
+	eSHIFT_IM	al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
+	or		al, bl
+	out		dx, al
+	ret									; Return with CF cleared
+
+
+;--------------------------------------------------------------------
+; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
+;	Parameters:
+;		AX:		Nanosecs to convert
+;		BP:		Low Byte:	Maximum allowed ticks
+;				High Byte:	Minimum allowed ticks
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;	Returns:
+;		AL:		Timing value for QD65xx register
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
+	push	cx
+
+	; Get VLB Cycle Time in nanosecs
+	mov		cl, VLB_33MHZ_CYCLE_TIME	; Assume 33 MHz or slower VLB bus
+	test	BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
+	eCMOVZ	cl, VLB_40MHZ_CYCLE_TIME
+
+	; Convert value in AX to VLB ticks
+	div		cl							; AL = VLB ticks
+	inc		ax							; Round up
+
+	; Limit value to QD65xx limits
+	mov		cx, bp
+	MAX_U	al, ch						; Make sure not below minimum
+	MIN_U	al, cl						; Make sure not above maximum
+
+	; Not done yet, we need to invert the ticks since 0 is the slowest
+	; value on the timing register
+	sub		cl, al
+	xchg	ax, cx						; Return in AL
+
+	pop		cx
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AtaID.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AtaID.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/AtaID.asm	(revision 516)
@@ -0,0 +1,193 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for accessing ATA information read with
+;					IDENTIFY DEVICE command.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; AtaID_VerifyFromESSI
+;	Parameters:
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		CF:		Set if failed to verify ATA-ID
+;				Cleared if ATA-ID verified successfully
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+AtaID_VerifyFromESSI:
+	; We cannot start by reading ATA version since the ID might be
+	; corrupted. We start by making sure P-CHS values are valid.
+	; If they are, we assume the ATA ID to be valid. Fortunately we can do
+	; further checking for ATA-5 and later since they contain signature and
+	; checksum bytes. Those are not available for ATA-4 and older.
+
+	; Verify P-CHS cylinders
+	mov		bx, ATA1.wCylCnt
+	mov		cx, MAX_VALID_PCHS_CYLINDERS
+	call	.CompareCHorSfromOffsetBXtoMaxValueInCX
+
+	mov		bl, ATA1.wHeadCnt & 0FFh
+	mov		cx, MAX_VALID_PCHS_HEADS
+	call	.CompareCHorSfromOffsetBXtoMaxValueInCX
+
+	mov		bl, ATA1.wSPT & 0FFh
+	mov		cl, MAX_VALID_PCHS_SECTORS_PER_TRACK
+	call	.CompareCHorSfromOffsetBXtoMaxValueInCX
+
+	; Check signature byte. It is only found on ATA-5 and later. It should be zero on
+	; ATA-4 and older.
+	mov		al, [es:si+ATA6.bSignature]
+	test	al, al
+	jz		SHORT .AtaIDverifiedSuccessfully	; Old ATA so Signature and Checksum is not available
+	cmp		al, A6_wIntegrity_SIGNATURE
+	jne		SHORT .FailedToVerifyAtaID
+
+	; Check checksum byte since signature was present
+	mov		cx, ATA6_size
+	call	Memory_SumCXbytesFromESSItoAL		; Returns with ZF set according to result
+	jnz		SHORT .FailedToVerifyAtaID
+
+	; ATA-ID is now verified to be valid
+.AtaIDverifiedSuccessfully:
+	clc
+	ret
+
+;--------------------------------------------------------------------
+; .CompareCHorSfromOffsetBXtoMaxValueInCX
+;	Parameters:
+;		BX:		C, H or S offset to ATA-ID
+;		CX:		Maximum valid C, H or S value
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		Exits from AtaID_VerifyFromESSI with CF set if invalid value
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.CompareCHorSfromOffsetBXtoMaxValueInCX:
+	mov		ax, [es:bx+si]
+	test	ax, ax
+	jz		SHORT .InvalidPCHorSinOffsetBX
+	cmp		ax, cx			; Compare to max valid value
+	jbe		SHORT .ValidPCHorSinOffsetBX
+.InvalidPCHorSinOffsetBX:
+	add		sp, BYTE 2		; Clear return address for this function
+.FailedToVerifyAtaID:
+	stc						; Set carry to indicate invalid ATA-ID
+.ValidPCHorSinOffsetBX:
+	ret
+
+
+%ifdef MODULE_ADVANCED_ATA
+;--------------------------------------------------------------------
+; AtaID_GetMaxPioModeToAXandMinCycleTimeToCX
+;	Parameters:
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		AL:		Max supported PIO mode
+;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
+;		CX:		Minimum Cycle Time in nanosecs
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+AtaID_GetMaxPioModeToAXandMinCycleTimeToCX:
+	; Get PIO mode and cycle time for PIO 0...2
+	mov		bx, [es:si+ATA1.bPioMode]
+	mov		ax, bx					; AH = 0, AL = PIO mode 0, 1 or 2
+	eSHL_IM	bx, 1					; Shift for WORD lookup
+	mov		cx, [cs:bx+.rgwPio0to2CycleTimeInNanosecs]
+
+	; Check if IORDY is supported
+	test	BYTE [es:si+ATA2.wCaps+1], A2_wCaps_IORDY >> 8
+	jz		SHORT .ReturnPioTimings	; No PIO 3 or higher if no IORDY
+	mov		ah, FLGH_DPT_IORDY
+
+	; Check if Advanced PIO modes are supported (3 and above)
+	test	BYTE [es:si+ATA2.wFields], A2_wFields_64to70
+	jz		SHORT .ReturnPioTimings
+
+	; Get Advanced PIO mode
+	; (Hard Disks supports up to 4 but CF cards can support 5 and 6)
+	mov		bl, [es:si+ATA2.bPIOSupp]
+.CheckNextFlag:
+	inc		ax
+	shr		bl, 1
+	jnz		SHORT .CheckNextFlag
+	MIN_U	al, 6						; Make sure not above lookup tables
+	mov		cx, [es:si+ATA2.wPIOMinCyF]	; Advanced modes use IORDY
+.ReturnPioTimings:
+	ret
+
+.rgwPio0to2CycleTimeInNanosecs:
+	dw		PIO_0_MIN_CYCLE_TIME_NS
+	dw		PIO_1_MIN_CYCLE_TIME_NS
+	dw		PIO_2_MIN_CYCLE_TIME_NS
+
+
+;--------------------------------------------------------------------
+; AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
+;	Parameters:
+;		BX:		PIO Mode
+;		CX:		PIO Cycle Time in nanosecs
+;	Returns:
+;		AX:		Active Time in nanosecs
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX:
+	call	AtaID_GetActiveTimeToAXfromPioModeInBX
+	mov		bl, [cs:bx+.rgbPioModeToAddressValidTimeNs]
+	sub		cx, bx	; Cycle Time (t0) - Address Valid Time (t1)
+	sub		cx, ax	; - Active Time (t2)
+	xchg	ax, cx	; AX = Recovery Time (t2i)
+	ret
+
+.rgbPioModeToAddressValidTimeNs:
+	db		PIO_0_MIN_ADDRESS_VALID_NS
+	db		PIO_1_MIN_ADDRESS_VALID_NS
+	db		PIO_2_MIN_ADDRESS_VALID_NS
+	db		PIO_3_MIN_ADDRESS_VALID_NS
+	db		PIO_4_MIN_ADDRESS_VALID_NS
+	db		PIO_5_MIN_ADDRESS_VALID_NS
+	db		PIO_6_MIN_ADDRESS_VALID_NS
+
+
+;--------------------------------------------------------------------
+; AtaID_GetActiveTimeToAXfromPioModeInBX
+;	Parameters:
+;		BX:		PIO Mode
+;	Returns:
+;		AX:		Active Time in nanosecs
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AtaID_GetActiveTimeToAXfromPioModeInBX:
+	eMOVZX	ax, [cs:bx+.rgbPioModeToActiveTimeNs]
+	ret
+
+.rgbPioModeToActiveTimeNs:
+	db		PIO_0_MIN_ACTIVE_TIME_NS
+	db		PIO_1_MIN_ACTIVE_TIME_NS
+	db		PIO_2_MIN_ACTIVE_TIME_NS
+	db		PIO_3_MIN_ACTIVE_TIME_NS
+	db		PIO_4_MIN_ACTIVE_TIME_NS
+	db		PIO_5_MIN_ACTIVE_TIME_NS
+	db		PIO_6_MIN_ACTIVE_TIME_NS
+
+%endif ; MODULE_ADVANCED_ATA
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm	(revision 516)
@@ -0,0 +1,305 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for detecting drive for the BIOS.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Detects all IDE hard disks to be controlled by this BIOS.
+;
+; DetectDrives_FromAllIDEControllers
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All (not segments)
+;--------------------------------------------------------------------
+DetectDrives_FromAllIDEControllers:
+	call	RamVars_GetIdeControllerCountToCX
+	mov		bp, ROMVARS.ideVars0			; CS:BP now points to first IDEVARS
+
+.DriveDetectLoop:							; Loop through IDEVARS
+	push	cx
+
+	mov		cx, g_szDetectMaster
+	mov		bh, MASK_DRVNHEAD_SET								; Select Master drive
+	call	StartDetectionWithDriveSelectByteInBHandStringInCX	; Detect and create DPT + BOOTNFO
+
+	mov		cx, g_szDetectSlave
+	mov		bh, MASK_DRVNHEAD_SET | FLG_DRVNHEAD_DRV
+	call	StartDetectionWithDriveSelectByteInBHandStringInCX
+
+%ifdef MODULE_HOTKEYS
+	call	HotkeyBar_ScanHotkeysFromKeyBufferAndStoreToBootvars		; Done here while CX is still protected
+%endif
+
+	pop		cx
+
+	add		bp, BYTE IDEVARS_size			; Point to next IDEVARS
+
+%ifdef MODULE_SERIAL
+	jcxz	.AddHardDisks					; Set to zero on .ideVarsSerialAuto iteration (if any)
+%endif
+	loop	.DriveDetectLoop
+
+%ifdef MODULE_SERIAL
+;----------------------------------------------------------------------
+;
+; if serial drive detected, do not scan (avoids duplicate drives and isn't needed - we already have a connection)
+;
+	call	FindDPT_ToDSDIforSerialDevice   ; does not modify AX
+	jnc		.AddHardDisks
+
+	mov		bp, ROMVARS.ideVarsSerialAuto	; Point to our special IDEVARS structure, just for serial scans
+
+%ifdef MODULE_HOTKEYS
+	cmp		al, COM_DETECT_HOTKEY_SCANCODE  ; Set by last call to HotkeyBar_UpdateDuringDriveDetection above
+	je		.DriveDetectLoop
+%endif
+
+	mov		al,[cs:ROMVARS.wFlags]			; Configurator set to always scan?
+	or		al,[es:BDA.bKBFlgs1]			; Or, did the user hold down the ALT key?
+	and		al,8							; 8 = alt key depressed, same as FLG_ROMVARS_SERIAL_ALWAYSDETECT
+	jnz		.DriveDetectLoop
+%endif
+
+.AddHardDisks:
+;----------------------------------------------------------------------
+;
+; Add in hard disks to BDA, finalize our Count and First variables
+;
+; Note that we perform the add to bHDCount and store bFirstDrv even if the count is zero.
+; This is done because we use the value of .bFirstDrv to know how many drives were in the system
+; at the time of boot, and to return that number on int13h/8h calls.  Because the count is zero,
+; FindDPT_ForDriveNumber will not find any drives that are ours.
+;
+	mov		cx, [RAMVARS.wDrvCntAndFlopCnt]		; Our count of hard disks
+
+	mov		al, [es:BDA.bHDCount]
+	add		cl, al						; Add our drives to the system count
+	mov		[es:BDA.bHDCount], cl
+	or		al, 80h						; Or in hard disk flag
+	mov		[RAMVARS.bFirstDrv], al		; Store first drive number
+
+.AddFloppies:
+%ifdef MODULE_SERIAL_FLOPPY
+;----------------------------------------------------------------------
+;
+; Add in any emulated serial floppy drives, finalize our packed Count and First variables
+;
+	dec		ch
+	mov		al, ch
+	js		.NoFloppies						; if no drives are present, we store 0ffh
+
+	call	FloppyDrive_GetCountFromBIOS_or_BDA
+
+	push	ax
+
+	add		al, ch							; Add our drives to existing drive count
+	cmp		al, 3							; For BDA, max out at 4 drives (ours is zero based)
+	jb		.MaxBDAFloppiesExceeded
+	mov		al, 3
+.MaxBDAFloppiesExceeded:
+	eROR_IM	al, 2							; move to bits 6-7
+	inc		ax								; low order bit, indicating floppy drive exists
+
+	mov		ah, [es:BDA.wEquipment]			; Load Equipment WORD low byte
+	and		ah, 03eh						; Mask off drive number and drives present bit
+	or		al, ah							; Or in new values
+	mov		[es:BDA.wEquipment], al			; and store
+
+	mov		al, 1eh							; BDA pointer to Floppy DPT
+	mov		si, AH8h_FloppyDPT
+	call	Interrupts_InstallHandlerToVectorInALFromCSSI
+
+	pop		ax
+
+	shr		ch, 1							; number of drives, 1 or 2 only, to CF flag (clear=1, set=2)
+	rcl		al, 1							; starting drive number in upper 7 bits, number of drives in low bit
+.NoFloppies:
+	mov		[RAMVARS.xlateVars+XLATEVARS.bFlopCntAndFirst], al
+%endif
+
+	ret
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if FLG_ROMVARS_SERIAL_SCANDETECT != 8
+		%error "DetectDrives is currently coded to assume that FLG_ROMVARS_SERIAL_SCANDETECT is the same bit as the ALT key code in the BDA.  Changes in the code will be needed if these values are no longer the same."
+	%endif
+%endif
+
+
+;--------------------------------------------------------------------
+; StartDetectionWithDriveSelectByteInBHandStringInCX
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Register
+;		CX:		Offset to "Master" or "Slave" string
+;		CS:BP:	Ptr to IDEVARS for the drive
+;		DS:		RAMVARS segment
+;		ES:		Zero (BDA segment)
+;	Returns:
+;       None
+;	Corrupts registers:
+;		AX, BL, CX, DX, SI, DI
+;--------------------------------------------------------------------
+StartDetectionWithDriveSelectByteInBHandStringInCX:
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	; Autodetect port for XT-CF
+	call	DetectDrives_DoesIdevarsInCSBPbelongToXTCF
+	jne		SHORT .SkipXTCFportDetection
+
+	; XT-CF do not support slave drives so skip detection
+	test	bh, FLG_DRVNHEAD_DRV
+	jnz		SHORT NoSlaveDriveAvailable
+
+	; XT-CF do not support slave drives so we can safely update port
+	; for next drive (another XT-CF card on same system)
+.DetectNextPort:
+	mov		dx, [es:BOOTVARS.wNextXTCFportToScan]
+	xor		dl, 40h
+	jnz		SHORT .StoreNextXTCFportToScan
+	inc		dh
+	cmp		dh, XTCF_BASE_PORT_4 >> 8
+	ja		SHORT .SkipXTCFportDetection		; XT-CF not found from any port
+.StoreNextXTCFportToScan:
+	mov		[es:BOOTVARS.wNextXTCFportToScan], dx
+
+	call	AH1Eh_DetectXTCFwithBasePortInDX
+	jc		SHORT .DetectNextPort				; XT-CF not found from this port
+
+	; We now have autodetected port in DX
+	push	dx
+	xchg	ax, dx								; Port to print in AX
+	call	DetectPrint_StartDetectWithAutodetectedBasePortInAXandIdeVarsInCSBP
+	jmp		SHORT .DriveDetectionStringPrintedOnScreen
+
+	; Print detect string for devices that do not support autodetection
+.SkipXTCFportDetection:
+	push	dx
+%endif ; MODULE_8BIT_IDE_ADVANCED
+
+	call	DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP
+.DriveDetectionStringPrintedOnScreen:
+%ifdef MODULE_HOTKEYS
+	call	HotkeyBar_UpdateDuringDriveDetection
+%endif
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	pop		dx
+%endif
+	; Fall to .ReadAtaInfoFromHardDisk
+
+
+;--------------------------------------------------------------------
+; .ReadAtaInfoFromHardDisk
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Register
+;		DX:		Autodetected port (for devices that support autodetection)
+;		CS:BP:	Ptr to IDEVARS for the drive
+;		DS:		RAMVARS segment
+;		ES:		Zero (BDA segment)
+;	Returns:
+;		CF:		Cleared if ATA-information read successfully
+;				Set if any error
+;	Corrupts registers:
+;		AX, BL, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.ReadAtaInfoFromHardDisk:
+	mov		si, BOOTVARS.rgbAtaInfo		; ES:SI now points to ATA info location
+	push	es
+	push	si
+	push	dx
+	push	bx
+	call	Device_IdentifyToBufferInESSIwithDriveSelectByteInBH
+	pop		bx
+	pop		dx
+	pop		si
+	pop		es
+	jnc		SHORT CreateBiosTablesForHardDisk
+	; Fall to .ReadAtapiInfoFromDrive
+
+.ReadAtapiInfoFromDrive:				; Not yet implemented
+	;call	ReadAtapiInfoFromDrive		; Assume CD-ROM
+	;jnc	SHORT _CreateBiosTablesForCDROM
+
+	;jmp	short DetectDrives_DriveNotFound
+;;; fall-through instead of previous jmp instruction
+;--------------------------------------------------------------------
+; DetectDrives_DriveNotFound
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CF:     Set (from DetectPrint_NullTerminatedStringFromCSSIandSetCF)
+;	Corrupts registers:
+;		AX, SI
+;--------------------------------------------------------------------
+DetectDrives_DriveNotFound:
+	mov		si, g_szNotFound
+	jmp		DetectPrint_NullTerminatedStringFromCSSIandSetCF
+
+
+;--------------------------------------------------------------------
+; CreateBiosTablesForHardDisk
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Register
+;		DX:		Autodetected port (for devices that support autodetection)
+;		CS:BP:	Ptr to IDEVARS for the drive
+;		ES:SI	Ptr to ATA information for the drive
+;		DS:		RAMVARS segment
+;		ES:		BDA segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+CreateBiosTablesForHardDisk:
+	push	bx
+	call	AtaID_VerifyFromESSI
+	pop		bx
+	jc		SHORT DetectDrives_DriveNotFound
+	call	CreateDPT_FromAtaInformation
+	jc		SHORT DetectDrives_DriveNotFound
+	call	DriveDetectInfo_CreateForHardDisk
+	jmp		SHORT DetectPrint_DriveNameFromDrvDetectInfoInESBX
+
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+;--------------------------------------------------------------------
+; DetectDrives_DoesIdevarsInCSBPbelongToXTCF
+;	Parameters:
+;		CS:BP:	Ptr to IDEVARS for the drive
+;	Returns:
+;		ZF:		Set if IDEVARS belongs to XT-CF device
+;				Cleared if some other device
+;	Corrupts registers:
+;		AL
+;--------------------------------------------------------------------
+DetectDrives_DoesIdevarsInCSBPbelongToXTCF:
+	mov		al, [cs:bp+IDEVARS.bDevice]
+	cmp		al, DEVICE_8BIT_XTCF_PIO8
+	je		SHORT .DeviceIsXTCF
+	cmp		al, DEVICE_8BIT_XTCF_DMA
+	je		SHORT .DeviceIsXTCF
+	cmp		al, DEVICE_8BIT_XTCF_MEMMAP
+.DeviceIsXTCF:
+NoSlaveDriveAvailable:
+	ret
+%endif ; MODULE_8BIT_IDE_ADVANCED
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/DetectPrint.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/DetectPrint.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/DetectPrint.asm	(revision 516)
@@ -0,0 +1,297 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for printing drive detection strings.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DetectPrint_InitializeDisplayContext
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+DetectPrint_InitializeDisplayContext:
+	JMP_DISPLAY_LIBRARY InitializeDisplayContext
+
+
+%ifdef MODULE_HOTKEYS
+;--------------------------------------------------------------------
+; DetectPrint_GetSoftwareCoordinatesToAX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+DetectPrint_GetSoftwareCoordinatesToAX:
+	JMP_DISPLAY_LIBRARY GetSoftwareCoordinatesToAX
+%endif
+
+
+;--------------------------------------------------------------------
+; DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP
+;	Parameters:
+;		CS:CX:	Ptr to "Master" or "Slave" string
+;		CS:BP:	Ptr to IDEVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP:
+	mov		ax, [cs:bp+IDEVARS.wBasePort]   ; for IDE: AX=port address, DH=.bDevice
+	; fall through to DetectPrint_StartDetectWithAutodetectedBasePortInAXandIdeVarsInCSBP
+
+;--------------------------------------------------------------------
+; DetectPrint_StartDetectWithAutodetectedBasePortInAXandIdeVarsInCSBP
+;	Parameters:
+;		AX:		Base Port Address
+;		CS:CX:	Ptr to "Master" or "Slave" string
+;		CS:BP:	Ptr to IDEVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+DetectPrint_StartDetectWithAutodetectedBasePortInAXandIdeVarsInCSBP:
+	mov		dx, [cs:bp+IDEVARS.bDevice-1]   ; for Serial: AL=port address>>2, AH=baud rate
+											;			  DL=COM number character, DH=.bDevice
+	push	bp								; setup stack for call to
+	mov		bp, sp							; BootMenuPrint_FormatCSSIfromParamsInSSBP
+
+	push 	cx								; Push "Master" or "Slave"
+
+	mov		cl, (g_szDetectPort-$$) & 0xff	; Setup print string for standard IDE
+											; Note that we modify only the low order bits of CX a lot here,
+											; saving code space rather than reloading CX completely.
+											; This optimization requires that all the g_szDetect* strings are
+											; on the same 256 byte page, which is checked in strings.asm.
+
+%ifdef MODULE_SERIAL
+	cmp		dh, DEVICE_SERIAL_PORT		  	; Check if this is a serial device
+
+	jnz		.pushAndPrint					; CX = string to print, AX = port address, DX won't be used
+
+	mov		cl, (g_szDetectCOM-$$) & 0xff	; Setup print string for COM ports
+	push	cx								; And push now.  We use the fact that format strings can contain
+											; themselves format strings.
+
+	push	dx								; Push COM number character
+											; If the string is going to be "Auto", we will push a NULL (zero)
+											; here for the COM port number, which will be eaten by the
+											; print routine (DisplayPrint_CharacterFromAL), resulting in
+											; just "COM" being printed without a character after it.
+
+ 	mov		cl, (g_szDetectCOMAuto-$$) & 0xff	; Setup secondary print string for "Auto"
+
+	test	dl, dl							; Check if serial port "Auto"
+	jz		.pushAndPrintSerial				; CX = string to print, AX and DX won't be used
+
+	mov		cl, (g_szDetectCOMLarge-$$) & 0xff	; Setup secondary print string for "COMn/xx.yK"
+
+	mov		al,ah							; baud rate divisor to AL
+	cbw										; clear AH, AL will always be less than 128
+	xchg	si,ax							; move AX to SI for divide
+	mov		ax,1152							; baud rate to display is 115200/divisor, the "00" is handled
+											; in the print strings
+	cwd										; clear top 16-bits of dividend
+	div		si								; and divide...  Now AX = baud rate/100, DX = 0 (always a clean divide)
+
+	mov		si,10							; Now separate the whole portion from the fractional for "K" display
+	div		si								; and divide...  Now AX = baud rate/1000, DX = low order digit
+
+	cmp		ax,si							; < 10: "2400", "9600", etc.; >= 10: "19.2K", "38.4K", etc.
+	jae		.pushAndPrintSerial
+
+	mov		cl, (g_szDetectCOMSmall-$$) & 0xff	; Setup secondary print string for "COMn/XXy00"
+
+.pushAndPrintSerial:
+.pushAndPrint:
+%endif
+
+	push	cx								; Push print string
+	push	ax								; Push high order digits, or port address, or N/A
+	push	dx								; Push low order digit, or N/A
+
+	mov		si, g_szDetectOuter				; Load SI with default wrapper string "IDE %s at %s: "
+
+	jmp		SHORT DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; DetectPrint_DriveNameFromDrvDetectInfoInESBX
+;	Parameters:
+;		ES:BX:	Ptr to DRVDETECTINFO (if drive found)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+DetectPrint_DriveNameFromDrvDetectInfoInESBX:
+	push	bp
+	mov		bp,sp
+	lea		si,[bx+DRVDETECTINFO.szDrvName]
+	push	si
+	mov		si,g_szDriveName
+	jmp		SHORT DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; Prints BIOS name and segment address where it is found.
+;
+; DetectPrint_RomFoundAtSegment
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+DetectPrint_RomFoundAtSegment:
+	mov		si, g_szRomAt
+	mov		di, cs						; BIOS segment address, for later inclusion in the output, parameterized
+										; so that it can be a different value when using .BootMenuEntry
+
+.BootMenuEntry:
+	push	bp
+	mov		bp, sp
+
+%ifndef USE_186
+	mov		ax, ROMVARS.szTitle
+	push	ax
+	push	di							; BIOS segment
+	add		al, ROMVARS.szVersion - ROMVARS.szTitle
+	push	ax
+%else
+	; szTitle and szVersion have the high order byte of their addresses zero,
+	; so these push instructions are only 2 bytes
+	;
+	push	ROMVARS.szTitle
+	push	di							; BIOS segment
+	push	ROMVARS.szVersion
+%endif
+
+	jmp		SHORT DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; DetectPrint_FailedToLoadFirstSector
+;	Parameters:
+;		AH:		INT 13h error code
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, SI, DI
+;--------------------------------------------------------------------
+DetectPrint_FailedToLoadFirstSector:
+	push	bp
+	mov		bp, sp
+	eMOVZX	cx, ah
+	push	cx					; Push INT 13h error code
+	mov		si, g_szReadError
+	jmp		SHORT DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; DetectPrint_TryToBootFromDL
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DH, SI, DI
+;--------------------------------------------------------------------
+DetectPrint_TryToBootFromDL:
+	push	bp
+	mov		bp, sp
+
+%ifdef MODULE_DRIVEXLATE
+
+	call	DriveXlate_ToOrBack	; DL = Untranslated Drive number
+	mov		dh, dl
+	call	DriveXlate_ToOrBack	; DL = Translated Drive number
+
+	call	DriveXlate_ConvertDriveNumberFromDLtoDriveLetter	; DL = Translated letter
+	xchg	dl, dh
+	call	DriveXlate_ConvertDriveNumberFromDLtoDriveLetter	; DL = Untranslated letter
+	push	dx
+	xchg	dl, dh
+	push	dx
+
+	call	DriveXlate_ConvertDriveLetterInDLtoDriveNumber	; Restore DL
+
+%else
+	ePUSH_T	ax, ' '			; No drive translation so print space
+
+	; Get boot drive letters
+	call	FloppyDrive_GetCountToAX
+	mov		ah, 'A'			; AH = First Floppy Drive letter (always 'A')
+	add		al, ah
+	MAX_U	al, 'C'			; AL = First Hard Drive letter ('C', 'D', or 'E')
+	test	dl, dl
+	eCMOVNS	al, ah
+	push	ax
+
+%endif ; MODULE_DRIVEXLATE
+
+	mov		si, g_szTryToBoot
+	jmp		SHORT DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; DetectPrint_NullTerminatedStringFromCSSIandSetCF
+;	Parameters:
+;		CS:SI:	Ptr to NULL terminated string to print
+;	Returns:
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+DetectPrint_NullTerminatedStringFromCSSIandSetCF:
+;
+; We send all CSSI strings through the Format routine for the case of
+; compressed strings, but this doesn't hurt in the non-compressed case either
+; (perhaps a little slower, but shouldn't be noticeable to the user)
+; and results in smaller code size.
+;
+	push	bp
+	mov		bp,sp
+	; Fall to DetectPrint_FormatCSSIfromParamsInSSBP
+
+;--------------------------------------------------------------------
+; DetectPrint_FormatCSSIfromParamsInSSBP
+;	Parameters:
+;		CS:SI:	Ptr to string to format
+;		BP:		SP before pushing parameters
+;	Returns:
+;		BP:		Popped from stack
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+DetectPrint_FormatCSSIfromParamsInSSBP:
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	stc				; Successful return from menu event
+	pop		bp
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/FloppyDrive.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/FloppyDrive.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/FloppyDrive.asm	(revision 516)
@@ -0,0 +1,223 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Various floppy drive related functions that
+;					Boot Menu uses.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Checks is floppy drive handler installed to interrupt vector 40h.
+;
+; FloppyDrive_IsInt40hInstalled
+;	Parameters:
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		CF:		Set if INT 40h is installed
+;				Cleared if INT 40h is not installed
+;	Corrupts registers:
+;		BX, CX, DI
+;--------------------------------------------------------------------
+FloppyDrive_IsInt40hInstalled:
+	cmp		WORD [es:BIOS_DISKETTE_INTERRUPT_40h*4+2], 0C000h	; Any ROM segment?
+%ifdef USE_AT	; No need to verify on XT systems.
+	jb		SHORT .Int40hHandlerIsNotInstalled
+	call	.VerifyInt40hHandlerSinceSomeBiosesSimplyReturnFromInt40h
+.Int40hHandlerIsNotInstalled:
+%endif
+	cmc
+	ret
+
+;--------------------------------------------------------------------
+; .VerifyInt40hHandlerSinceSomeBiosesSimplyReturnFromInt40h
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CF:		Cleared if INT 40h is installed
+;				Set if INT 40h is not installed
+;	Corrupts registers:
+;		BX, CX, DI
+;--------------------------------------------------------------------
+%ifdef USE_AT
+.VerifyInt40hHandlerSinceSomeBiosesSimplyReturnFromInt40h:
+	push	es
+	push	dx
+	push	ax
+
+	call	.LoadInt40hVerifyParameters
+	int		BIOS_DISK_INTERRUPT_13h
+	jc		SHORT .Int40hIsInstalled	; Maybe there are not any floppy drives at all
+	push	es
+	push	di
+
+	call	.LoadInt40hVerifyParameters
+	int		BIOS_DISKETTE_INTERRUPT_40h
+
+	pop		dx
+	pop		cx
+	cmp		dx, di						; Difference in offsets?
+	jne		SHORT .Int40hNotInstalled
+	mov		dx, es
+	cmp		cx, dx						; Difference in segments?
+	je		SHORT .Int40hIsInstalled
+.Int40hNotInstalled:
+	stc
+.Int40hIsInstalled:
+	pop		ax
+	pop		dx
+	pop		es
+	ret
+
+;--------------------------------------------------------------------
+; .LoadInt40hVerifyParameters
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AH:		08h (Get Drive Parameters)
+;		DL:		00h (floppy drive)
+;		ES:DI:	0:0h (to guard against BIOS bugs)
+;	Corrupts registers:
+;		DH
+;--------------------------------------------------------------------
+.LoadInt40hVerifyParameters:
+	mov		ah, 08h				; Get Drive Parameters
+	cwd							; Floppy drive 0
+	mov		di, dx
+	mov		es, dx				; ES:DI = 0000:0000h to guard against BIOS bugs
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Returns floppy drive type.
+; PC/XT system do not support AH=08h but FLOPPY_TYPE_525_OR_35_DD
+; is still returned for them.
+;
+; FloppyDrive_GetType
+;	Parameters:
+;		DL:		Floppy Drive number
+;	Returns:
+;		BX:		Floppy Drive Type:
+;					FLOPPY_TYPE_525_OR_35_DD
+;					FLOPPY_TYPE_525_DD
+;					FLOPPY_TYPE_525_HD
+;					FLOPPY_TYPE_35_DD
+;					FLOPPY_TYPE_35_HD
+;					FLOPPY_TYPE_35_ED
+;		CF:		Set if AH=08h not supported (XT systems) or error
+;				Cleared if type read correctly (AT systems)
+;	Corrupts registers:
+;		AX, CX, DX, DI, ES
+;--------------------------------------------------------------------
+%ifdef MODULE_BOOT_MENU
+FloppyDrive_GetType:
+	mov		ah, 08h			; Get Drive Parameters
+	xor		bx, bx			; FLOPPY_TYPE_525_OR_35_DD when function not supported
+	int		BIOS_DISKETTE_INTERRUPT_40h
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Returns number of Floppy Drives in system.
+;
+; FloppyDrive_GetCountToAX
+;	Parameters:
+;		DS:		RAMVARS Segment
+;	Returns:
+;		AX:		Number of Floppy Drives
+;--------------------------------------------------------------------
+FloppyDrive_GetCountToAX:
+%ifdef MODULE_SERIAL_FLOPPY
+	call	RamVars_UnpackFlopCntAndFirstToAL
+	js		.UseBIOSorBDA				; We didn't add in any drives, counts here are not valid
+
+	adc		al,1						; adds in the drive count bit, and adds 1 for count vs. 0-index,
+	jmp		.FinishCalc					; need to clear AH on the way out, and add in minimum drive numbers
+
+.UseBIOSorBDA:
+%endif
+	call	FloppyDrive_GetCountFromBIOS_or_BDA
+
+.FinishCalc:
+	mov		ah, [cs:ROMVARS.bMinFddCnt]
+	MAX_U	al, ah
+	cbw
+
+	ret
+
+FloppyDrive_GetCountFromBIOS_or_BDA:
+	push	es
+
+;--------------------------------------------------------------------
+; Reads Floppy Drive Count from BIOS.
+; Does not work on most XT systems. Call .GetCountFromBDA
+; if this function fails.
+;
+; .GetCountFromBIOS
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AL:		Number of Floppy Drives
+;		CF:		Cleared if successful
+;				Set if BIOS function not supported
+;	Corrupts registers:
+;		ES
+;--------------------------------------------------------------------
+%ifdef USE_AT
+.GetCountFromBIOS:
+	push	di
+	push	bx
+	push	cx
+	push	dx
+
+	mov		ah, 08h					; Get Drive Parameters
+	cwd								; Floppy Drive 00h
+	int		BIOS_DISKETTE_INTERRUPT_40h
+	mov		al, dl					; Number of Floppy Drives to AL
+
+	pop		dx
+	pop		cx
+	pop		bx
+	pop		di
+%endif
+
+;--------------------------------------------------------------------
+; Reads Floppy Drive Count (0...4) from BIOS Data Area.
+; This function should be used only if .GetCountFromBIOS fails.
+;
+; .GetCountFromBDA
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AL:		Number of Floppy Drives
+;	Corrupts registers:
+;		AH, ES
+;--------------------------------------------------------------------
+%ifndef USE_AT
+.GetCountFromBDA:
+	LOAD_BDA_SEGMENT_TO	es, ax
+	mov		al, [es:BDA.wEquipment]			; Load Equipment WORD low byte
+	mov		ah, al							; Copy it to AH
+	and		ax, 0C001h						; Leave bits 15..14 and 0
+	eROL_IM	ah, 2							; EW low byte bits 7..6 to 1..0
+	add		al, ah							; AL = Floppy Drive count
+%endif
+
+	pop		es
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm	(revision 516)
@@ -0,0 +1,98 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for initializing the BIOS.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Initializes the BIOS.
+; This function is called from main BIOS ROM search routine.
+;
+; Initialize_FromMainBiosRomSearch
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Initialize_FromMainBiosRomSearch:		; unused entrypoint ok
+	pushf								; To store IF
+	push	ds
+
+%ifndef USE_186
+	push	ax
+	LOAD_BDA_SEGMENT_TO	ds, ax
+%else
+	push	BYTE 0
+	pop		ds
+%endif
+
+	sti									; Enable interrupts for keystrokes
+	test	BYTE [BDA.bKBFlgs1], (1<<2)	; Clears ZF if CTRL is held down
+	jnz		SHORT .SkipRomInitialization
+
+	; Install INT 19h handler (boot loader) where drives are detected
+	mov		WORD [BIOS_BOOT_LOADER_INTERRUPT_19h*4], Int19h_BootLoaderHandler
+	mov		[BIOS_BOOT_LOADER_INTERRUPT_19h*4+2], cs
+
+.SkipRomInitialization:
+%ifndef USE_186
+	pop		ax
+%endif
+	pop		ds
+	popf
+	retf
+
+
+;--------------------------------------------------------------------
+; Initializes the BIOS variables and detects IDE drives.
+;
+; Initialize_AndDetectDrives
+;	Parameters:
+;		ES:		BDA Segment
+;	Returns:
+;		DS:		RAMVARS segment
+;	Corrupts registers:
+;		All, except ES
+;--------------------------------------------------------------------
+Initialize_AndDetectDrives:
+	call	DetectPrint_InitializeDisplayContext
+	call	DetectPrint_RomFoundAtSegment
+	call	RamVars_Initialize
+	call	BootVars_Initialize
+	call	DetectDrives_FromAllIDEControllers
+	call	Interrupts_InitializeInterruptVectors
+	; Fall to .ResetDetectedDrives
+
+;--------------------------------------------------------------------
+; .ResetDetectedDrives
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except DS and ES
+;--------------------------------------------------------------------
+.ResetDetectedDrives:
+	call	Idepack_FakeToSSBP
+	call	AH0h_ResetAllOurHardDisksAtTheEndOfDriveInitialization
+	add		sp, BYTE SIZE_OF_IDEPACK_WITHOUT_INTPACK
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm	(revision 516)
@@ -0,0 +1,255 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for initializing the BIOS.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Drives must be detected before this function is called!
+;
+; Interrupts_InitializeInterruptVectors
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All except segments
+;--------------------------------------------------------------------
+Interrupts_InitializeInterruptVectors:
+	; Install INT 19h handler to properly reset the system
+	mov		al, BIOS_BOOT_LOADER_INTERRUPT_19h	; INT 19h interrupt vector offset
+	mov		si, Int19hReset_Handler				; INT 19h handler to reboot the system
+	call	Interrupts_InstallHandlerToVectorInALFromCSSI
+
+	; If no drives detected, leave system INT 13h and 40h handlers
+	; in place. We need our INT 13h handler to swap drive letters.
+%ifndef MODULE_DRIVEXLATE
+	cmp		BYTE [RAMVARS.bDrvCnt], 0
+	je		SHORT Interrupts_InstallHandlerToVectorInALFromCSSI.Interrupts_Return
+%endif
+	; Fall to .InitializeInt13hAnd40h
+
+;--------------------------------------------------------------------
+; .InitializeInt13hAnd40h
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.InitializeInt13hAnd40h:
+	mov		ax, [es:BIOS_DISK_INTERRUPT_13h*4+2]; Load old INT 13h segment
+	mov		[RAMVARS.fpOldI13h+2], ax			; Store old INT 13h segment
+	xchg	dx, ax
+	mov		ax, [es:BIOS_DISK_INTERRUPT_13h*4]	; Load old INT 13h offset
+	mov		[RAMVARS.fpOldI13h], ax				; Store old INT 13h offset
+
+	; NOTE! Installing INT 40h handler is currently uncommented to test
+	; if it is really needed. I suspect that it is not. Many bytes can be
+	; saved if INT 40h related code can be removed.
+%if 0
+
+	; Only store INT 13h handler to 40h if 40h is not already installed.
+	; At least AMI BIOS for 286 stores 40h handler by itself and calls
+	; 40h from 13h. That system locks to infinite loop if we copy 13h to 40h.
+	call	FloppyDrive_IsInt40hInstalled
+	jc		SHORT .Int40hAlreadyInstalled
+	mov		[es:BIOS_DISKETTE_INTERRUPT_40h*4], ax		; Store old INT 13h offset
+	mov		[es:BIOS_DISKETTE_INTERRUPT_40h*4+2], dx	; Store old INT 13h segment
+.Int40hAlreadyInstalled:
+%endif ; 0
+
+	mov		al, BIOS_DISK_INTERRUPT_13h			; INT 13h interrupt vector offset
+	mov		si, Int13h_DiskFunctionsHandler
+%ifdef RELOCATE_INT13H_STACK
+	test	BYTE [cs:ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
+	eCMOVNZ	si, Int13h_DiskFunctionsHandlerWithStackChange
+%endif
+
+%ifndef MODULE_IRQ
+	; Fall to Interrupts_InstallHandlerToVectorInALFromCSSI
+%else
+	call	Interrupts_InstallHandlerToVectorInALFromCSSI
+	; Fall to .InitializeHardwareIrqHandlers
+
+;--------------------------------------------------------------------
+; .InitializeHardwareIrqHandlers
+;	Parameters:
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, AX
+;--------------------------------------------------------------------
+.InitializeHardwareIrqHandlers:
+	call	RamVars_GetIdeControllerCountToCX
+	mov		di, ROMVARS.ideVars0+IDEVARS.bIRQ	; CS:SI points to first IDEVARS
+.IdeControllerLoop:
+	mov		al, [cs:di]
+	add		di, BYTE IDEVARS_size			; Increment to next controller
+	call	.InstallLowOrHighIrqHandler
+	loop	.IdeControllerLoop
+.Return:
+	ret		; This ret is shared with .InstallLowOrHighIrqHandler
+
+;--------------------------------------------------------------------
+; .InstallLowOrHighIrqHandler
+;	Parameters:
+;		AL:		IRQ number, 0 if IRQ disabled
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, SI
+;--------------------------------------------------------------------
+.InstallLowOrHighIrqHandler:
+	test	al, al
+	jz		SHORT .Return	; IRQ not used
+	cmp		al, 8
+	jb		SHORT .InstallLowIrqHandler
+	; Fall to .InstallHighIrqHandler
+
+;--------------------------------------------------------------------
+; .InstallHighIrqHandler
+;	Parameters:
+;		BX:		IRQ number (8...15)
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AL, BX, SI
+;--------------------------------------------------------------------
+.InstallHighIrqHandler:
+	add		al, BYTE HARDWARE_IRQ_8_INTERRUPT_70h - 8	; Interrupt vector number
+	mov		si, IdeIrq_InterruptServiceRoutineForIrqs8to15
+	jmp		SHORT Interrupts_InstallHandlerToVectorInALFromCSSI
+
+;--------------------------------------------------------------------
+; .InstallLowIrqHandler
+;	Parameters:
+;		AL:		IRQ number (0...7)
+;		ES:		BDA and Interrupt Vector segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AL, BX, SI
+;--------------------------------------------------------------------
+.InstallLowIrqHandler:
+	add		al, BYTE HARDWARE_IRQ_0_INTERRUPT_08h		; Interrupt vector number
+	mov		si, IdeIrq_InterruptServiceRoutineForIrqs2to7
+	; Fall to Interrupts_InstallHandlerToVectorInALFromCSSI
+%endif ; MODULE_IRQ
+
+
+;--------------------------------------------------------------------
+; Interrupts_InstallHandlerToVectorInALFromCSSI
+;	Parameters:
+;		AL:		Interrupt vector number (for example 13h)
+;		ES:		BDA and Interrupt Vector segment (zero)
+;		CS:SI:	Ptr to interrupt handler
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+Interrupts_InstallHandlerToVectorInALFromCSSI:
+	mov		bl, 4					; Shift for DWORD offset, MUL smaller than other alternatives
+	mul		bl
+	xchg	ax, bx
+	mov		[es:bx], si				; Store offset
+	mov		[es:bx+2], cs			; Store segment
+.Interrupts_Return:
+	ret
+
+
+%ifdef MODULE_IRQ
+;--------------------------------------------------------------------
+; Interrupts_UnmaskInterruptControllerForDriveInDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+Interrupts_UnmaskInterruptControllerForDriveInDSDI:
+	eMOVZX	bx, [di+DPT.bIdevarsOffset]
+	mov		al, [cs:bx+IDEVARS.bIRQ]
+	test	al, al
+	jz		SHORT .Return	; Interrupts disabled
+	cmp		al, 8
+	jb		SHORT .UnmaskLowIrqController
+	; Fall to .UnmaskHighIrqController
+
+;--------------------------------------------------------------------
+; .UnmaskHighIrqController
+;	Parameters:
+;		AL:		IRQ number (8...15)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+.UnmaskHighIrqController:
+	sub		al, 8				; Slave interrupt number
+	mov		dx, SLAVE_8259_IMR
+	call	.ClearBitFrom8259MaskRegister
+	mov		al, 2				; Master IRQ 2 to allow slave IRQs
+	; Fall to .UnmaskLowIrqController
+
+;--------------------------------------------------------------------
+; .UnmaskLowIrqController
+;	Parameters:
+;		AL:		IRQ number (0...7)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+.UnmaskLowIrqController:
+	mov		dx, MASTER_8259_IMR
+	; Fall to .ClearBitFrom8259MaskRegister
+
+;--------------------------------------------------------------------
+; .ClearBitFrom8259MaskRegister
+;	Parameters:
+;		AL:		8259 interrupt index (0...7)
+;		DX:		Port address to Interrupt Mask Register
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.ClearBitFrom8259MaskRegister:
+	push	cx
+	xchg	ax, cx				; IRQ index to CL
+	mov		ch, 1				; Load 1 to be shifted
+	shl		ch, cl				; Shift bit to correct position
+	not		ch					; Invert to create bit mask for clearing
+	in		al, dx				; Read Interrupt Mask Register
+	and		al, ch				; Clear wanted bit
+	out		dx, al				; Write modified Interrupt Mask Register
+	pop		cx
+.Return:
+	ret
+
+%endif ; MODULE_IRQ
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Main.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Main.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Main.asm	(revision 516)
@@ -0,0 +1,286 @@
+; Project name	:	XTIDE Universal BIOS
+; Authors		:	Tomi Tilli
+;				:	aitotat@gmail.com
+;				:
+;				:	Greg Lindhorst
+;				:	gregli@hotmail.com
+;				;
+;				:	Krister Nordvall
+;				:	krille_n_@hotmail.com
+;				:
+; Description	:	Main file for BIOS. This is the only file that needs
+;					to be compiled since other files are included to this
+;					file (so no linker needed, Nasm does it all).
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+	ORG 0							; Code start offset 0000h
+
+	; We must define included libraries before including "AssemblyLibrary.inc".
+%define	EXCLUDE_FROM_XTIDE_UNIVERSAL_BIOS	; Exclude unused library functions
+%ifdef MODULE_BOOT_MENU
+	%define MENUEVENT_INLINE_OFFSETS    	; Only one menu required, save space and inline offsets
+	%define INCLUDE_MENU_LIBRARY
+	%define MENU_NO_ESC					    ; User cannot 'esc' out of the menu
+%else	; If no boot menu included
+	%define	INCLUDE_DISPLAY_LIBRARY
+	%define INCLUDE_KEYBOARD_LIBRARY
+	%define INCLUDE_TIME_LIBRARY
+%endif
+
+
+	; Included .inc files
+	%include "AssemblyLibrary.inc"	; Assembly Library. Must be included first!
+	%include "ModuleDependency.inc"	; Dependency checks for optional modules
+	%include "Version.inc"
+	%include "ATA_ID.inc"			; For ATA Drive Information structs
+	%include "IdeRegisters.inc"		; For ATA Registers, flags and commands
+	%include "Int13h.inc"			; Equates for INT 13h functions
+	%include "CustomDPT.inc"		; For Disk Parameter Table
+	%include "RomVars.inc"			; For ROMVARS and IDEVARS structs
+	%include "RamVars.inc"			; For RAMVARS struct
+	%include "BootVars.inc"			; For BOOTVARS struct
+	%include "IdeIO.inc"			; Macros for IDE port I/O
+	%include "DeviceIDE.inc"		; For IDE device equates
+
+
+
+; Section containing code
+SECTION .text
+
+; ROM variables (must start at offset 0)
+CNT_ROM_BLOCKS		EQU		BIOS_SIZE / 512		; number of 512B blocks, 16 = 8kB BIOS
+istruc ROMVARS
+	at	ROMVARS.wRomSign,	dw	0AA55h			; PC ROM signature
+	at	ROMVARS.bRomSize,	db	CNT_ROM_BLOCKS	; ROM size in 512B blocks
+	at	ROMVARS.rgbJump,	jmp	Initialize_FromMainBiosRomSearch
+	at	ROMVARS.rgbSign,	db	FLASH_SIGNATURE
+	at	ROMVARS.szTitle,	db	TITLE_STRING
+	at	ROMVARS.szVersion,	db	ROM_VERSION_STRING
+
+;---------------------------;
+; AT Build default settings ;
+;---------------------------;
+%ifdef USE_AT
+	at	ROMVARS.wFlags,			dw	FLG_ROMVARS_FULLMODE | MASK_ROMVARS_INCLUDED_MODULES
+	at	ROMVARS.wDisplayMode,	dw	DEFAULT_TEXT_MODE
+%ifdef MODULE_BOOT_MENU
+	at	ROMVARS.wBootTimeout,	dw	BOOT_MENU_DEFAULT_TIMEOUT
+%endif
+	at	ROMVARS.bIdeCnt,		db	2						; Number of supported controllers
+	at	ROMVARS.bBootDrv,		db	80h						; Boot Menu default drive
+	at	ROMVARS.bMinFddCnt, 	db	0						; Do not force minimum number of floppy drives
+	at	ROMVARS.bStealSize,		db	1						; Steal 1kB from base memory
+	at	ROMVARS.bIdleTimeout,	db	0						; Standby timer disabled by default
+
+	at	ROMVARS.ideVars0+IDEVARS.wBasePort,			dw	DEVICE_ATA_PRIMARY_PORT 		; Controller Command Block base port
+	at	ROMVARS.ideVars0+IDEVARS.wControlBlockPort,	dw	DEVICE_ATA_PRIMARY_PORTCTRL 	; Controller Control Block base port
+	at	ROMVARS.ideVars0+IDEVARS.bDevice,			db	DEVICE_16BIT_ATA
+	at	ROMVARS.ideVars0+IDEVARS.bIRQ,				db	0
+	at	ROMVARS.ideVars0+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars0+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+
+	at	ROMVARS.ideVars1+IDEVARS.wBasePort,			dw	DEVICE_ATA_SECONDARY_PORT
+	at	ROMVARS.ideVars1+IDEVARS.wControlBlockPort,	dw	DEVICE_ATA_SECONDARY_PORTCTRL
+	at	ROMVARS.ideVars1+IDEVARS.bDevice,			db	DEVICE_16BIT_ATA
+	at	ROMVARS.ideVars1+IDEVARS.bIRQ,				db	0
+	at	ROMVARS.ideVars1+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars1+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+
+	at	ROMVARS.ideVars2+IDEVARS.wBasePort,			dw	DEVICE_ATA_TERTIARY_PORT
+	at	ROMVARS.ideVars2+IDEVARS.wControlBlockPort,	dw	DEVICE_ATA_TERTIARY_PORTCTRL
+	at	ROMVARS.ideVars2+IDEVARS.bDevice,			db	DEVICE_16BIT_ATA
+	at	ROMVARS.ideVars2+IDEVARS.bIRQ,				db	0
+	at	ROMVARS.ideVars2+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars2+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+
+	at	ROMVARS.ideVars3+IDEVARS.wBasePort,			dw	DEVICE_ATA_QUATERNARY_PORT
+	at	ROMVARS.ideVars3+IDEVARS.wControlBlockPort,	dw	DEVICE_ATA_QUATERNARY_PORTCTRL
+	at	ROMVARS.ideVars3+IDEVARS.bDevice,			db	DEVICE_16BIT_ATA
+	at	ROMVARS.ideVars3+IDEVARS.bIRQ,				db	0
+	at	ROMVARS.ideVars3+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars3+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	dw	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+
+%ifdef MODULE_SERIAL
+	at	ROMVARS.ideVarsSerialAuto+IDEVARS.bDevice,		db	DEVICE_SERIAL_PORT
+%endif
+%else
+;-----------------------------------;
+; XT and XT+ Build default settings ;
+;-----------------------------------;
+	at	ROMVARS.wFlags,			dw	MASK_ROMVARS_INCLUDED_MODULES
+	at	ROMVARS.wDisplayMode,	dw	DEFAULT_TEXT_MODE
+%ifdef MODULE_BOOT_MENU
+	at	ROMVARS.wBootTimeout,	dw	BOOT_MENU_DEFAULT_TIMEOUT
+%endif
+%ifdef MODULE_8BIT_IDE_ADVANCED		
+	at	ROMVARS.bIdeCnt,		db	2						; Number of supported controllers
+%else
+	at  ROMVARS.bIdeCnt,		db	1
+%endif
+	at	ROMVARS.bBootDrv,		db	80h						; Boot Menu default drive
+	at	ROMVARS.bMinFddCnt, 	db	0						; Do not force minimum number of floppy drives
+	at	ROMVARS.bStealSize,		db	1						; Steal 1kB from base memory in full mode
+	at	ROMVARS.bIdleTimeout,	db	0						; Standby timer disabled by default
+
+	at	ROMVARS.ideVars0+IDEVARS.wBasePort,			dw	DEVICE_XTIDE_DEFAULT_PORT			; Controller Command Block base port
+	at	ROMVARS.ideVars0+IDEVARS.wControlBlockPort,	dw	DEVICE_XTIDE_DEFAULT_PORTCTRL		; Controller Control Block base port
+	at	ROMVARS.ideVars0+IDEVARS.bDevice,			db	DEVICE_8BIT_XTIDE_REV1
+	at	ROMVARS.ideVars0+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars0+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	at	ROMVARS.ideVars1+IDEVARS.bXTCFcontrolRegister,	db	XTCF_8BIT_PIO_MODE
+	at	ROMVARS.ideVars1+IDEVARS.bDevice,				db	DEVICE_8BIT_XTCF_PIO8
+	at	ROMVARS.ideVars1+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars1+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+%else
+	at	ROMVARS.ideVars1+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars1+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+%endif		
+
+	at	ROMVARS.ideVars2+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars2+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+
+	at	ROMVARS.ideVars3+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+	at	ROMVARS.ideVars3+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	DISABLE_WRITE_CACHE | FLG_DRVPARAMS_BLOCKMODE | (TRANSLATEMODE_AUTO<<TRANSLATEMODE_FIELD_POSITION)
+
+%ifdef MODULE_SERIAL
+	at	ROMVARS.ideVarsSerialAuto+IDEVARS.bDevice,		db	DEVICE_SERIAL_PORT
+%endif
+%endif
+iend
+
+	; Strings are first to avoid them moving unnecessarily when code is turned on and off with %ifdef's
+	; since some groups of strings need to be on the same 256-byte page.
+	;
+%ifdef MODULE_STRINGS_COMPRESSED
+	%define STRINGSCOMPRESSED_STRINGS
+	%include "StringsCompressed.asm"
+%else
+	%include "Strings.asm"			; For BIOS message strings
+%endif
+
+	; Libraries, data, Initialization and drive detection
+
+	%include "AssemblyLibrary.asm"
+
+	; String compression tables need to come after the AssemblyLibrary (since they depend on addresses
+	; established in the assembly library), and are unnecessary if strings are not compressed.
+	;
+%ifdef MODULE_STRINGS_COMPRESSED
+	%undef  STRINGSCOMPRESSED_STRINGS
+	%define STRINGSCOMPRESSED_TABLES
+	%include "StringsCompressed.asm"
+%endif
+
+	%include "Initialize.asm"		; For BIOS initialization
+	%include "Interrupts.asm"		; For Interrupt initialization
+	%include "RamVars.asm"			; For RAMVARS initialization and access
+	%include "BootVars.asm"			; For initializing variables used during init and boot
+	%include "FloppyDrive.asm"		; Floppy Drive related functions
+	%include "CreateDPT.asm"		; For creating DPTs
+	%include "FindDPT.asm"			; For finding DPTs
+	%include "AccessDPT.asm"		; For accessing DPTs
+	%include "AtaGeometry.asm"		; For generating L-CHS parameters
+	%include "DrvDetectInfo.asm"	; For creating DRVDETECTINFO structs
+	%include "AtaID.asm"			; For ATA Identify Device information
+	%include "DetectDrives.asm"		; For detecting IDE drives
+	%include "DetectPrint.asm"		; For printing drive detection strings
+
+	; Hotkey Bar
+%ifdef MODULE_HOTKEYS
+	%include "HotkeyBar.asm"		; For hotkeys during drive detection and boot menu
+%endif		
+%ifdef MODULE_DRIVEXLATE
+	%include "DriveXlate.asm"		; For swapping drive numbers, must come immediately after HotkeyBar.asm
+%endif
+
+	; Boot menu
+%ifdef MODULE_BOOT_MENU
+	%include "BootMenu.asm"			; For Boot Menu operations
+	%include "BootMenuEvent.asm"	; For menu library event handling
+									; NOTE: BootMenuPrint needs to come immediately after BootMenuEvent
+									;       so that jump table entries in BootMenuEvent stay within 8-bits
+	%include "BootMenuPrint.asm"	; For printing Boot Menu strings, also includes "BootMenuPrintCfg.asm"
+%endif
+
+	; Boot loader
+	%include "Int19h.asm"			; For Int 19h, Boot Loader
+	%include "BootSector.asm"		; For loading boot sector
+	%include "Int19hReset.asm"		; INT 19h handler for proper system reset
+
+	; For all device types
+	%include "Idepack.asm"
+	%include "Device.asm"
+	%include "Timer.asm"			; For timeout and delay
+
+	; IDE Device support
+%ifdef MODULE_ADVANCED_ATA
+	%include "AdvAtaInit.asm"		; For initializing VLB and PCI controllers
+	%include "Vision.asm"			; QDI Vision QD6500 and QD6580 support
+%endif
+	%include "IdeCommand.asm"
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	%include "JrIdeTransfer.asm"	; Must be included after IdeCommand.asm
+	%include "IdeDmaBlock.asm"
+%endif
+	%include "IdeTransfer.asm"
+	%include "IdePioBlock.asm"
+	%include "IdeWait.asm"
+	%include "IdeError.asm"			; Must be included after IdeWait.asm
+	%include "IdeDPT.asm"
+	%include "IdeIO.asm"
+%ifdef MODULE_IRQ
+	%include "IdeIrq.asm"
+%endif
+
+	; Serial Device support
+%ifdef MODULE_SERIAL				; Serial Port Device support
+	%include "SerialCommand.asm"
+	%include "SerialDPT.asm"
+%endif
+
+	; INT 13h Hard Disk BIOS functions
+	%include "Int13h.asm"			; For Int 13h, Disk functions
+	%include "AH0h_HReset.asm"		; Required by Int13h_Jump.asm
+	%include "AH1h_HStatus.asm"		; Required by Int13h_Jump.asm
+	%include "AH2h_HRead.asm"		; Required by Int13h_Jump.asm
+	%include "AH3h_HWrite.asm"		; Required by Int13h_Jump.asm
+	%include "AH4h_HVerify.asm"		; Required by Int13h_Jump.asm
+	%include "AH8h_HParams.asm"		; Required by Int13h_Jump.asm
+	%include "AH9h_HInit.asm"		; Required by Int13h_Jump.asm
+	%include "AHCh_HSeek.asm"		; Required by Int13h_Jump.asm
+	%include "AH10h_HReady.asm"		; Required by Int13h_Jump.asm
+	%include "AH11h_HRecal.asm"		; Required by Int13h_Jump.asm
+	%include "AH15h_HSize.asm"		; Required by Int13h_Jump.asm
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	%include "AH1Eh_XTCF.asm"
+%endif
+	%include "AH23h_HFeatures.asm"	; Required by Int13h_Jump.asm
+	%include "AH24h_HSetBlocks.asm"	; Required by Int13h_Jump.asm
+	%include "AH25h_HDrvID.asm"		; Required by Int13h_Jump.asm
+	%include "Address.asm"			; For sector address translations
+	%include "Prepare.asm"			; For buffer pointer normalization
+%ifdef MODULE_EBIOS
+	%include "AH42h_ExtendedReadSectors.asm"
+	%include "AH43h_ExtendedWriteSectors.asm"
+	%include "AH44h_ExtendedVerifySectors.asm"
+	%include "AH47h_ExtendedSeek.asm"
+	%include "AH48h_GetExtendedDriveParameters.asm"
+	%include "AH41h_CheckIfExtensionsPresent.asm"
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenu.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenu.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenu.asm	(revision 516)
@@ -0,0 +1,79 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Displays Boot Menu.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Displays Boot Menu and returns Drive or Function number.
+;
+; BootMenu_DisplayAndReturnDriveInDLRomBootClearCF
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		DL:		Drive number selected
+;		CF:		Set if selected item is an actual drive, DL is valid
+;				Clear if selected item is Rom Boot, DL is invalid
+;	Corrupts registers:
+;		All General Purpose Registers
+;--------------------------------------------------------------------
+BootMenu_DisplayAndReturnDriveInDLRomBootClearCF:
+	call	DriveXlate_Reset
+
+	mov		bx, BootMenuEvent_Handler
+	CALL_MENU_LIBRARY	DisplayWithHandlerInBXandUserDataInDXAX
+
+	xchg	cx, ax
+
+	; Clear Boot Menu from screen
+	mov		ax, ' ' | (MONO_NORMAL<<8)
+	CALL_DISPLAY_LIBRARY	ClearScreenWithCharInALandAttrInAH
+
+	; fall through to BootMenu_GetDriveToDXforMenuitemInCX
+
+;--------------------------------------------------------------------
+; BootMenu_GetDriveToDXforMenuitemInCX
+;	Parameters:
+;		CX:		Index of menuitem selected from Boot Menu
+;		DS:		RAMVARS segment
+;	Returns:
+;		DX:		Drive number to be used for booting
+;       CF:     Set: There is a selected menu item, DL is valid
+;               Clear: The item selected is Rom Boot, DL is not valid
+;	Corrupts registers:
+;		AX, BX
+;
+; NOTE: We can't use the menu structure in here, as we are falling through
+; from BootMenu_DisplayAndReturnDriveInDLRomBootClearCF when the
+; menu structure has already been destroyed.
+;--------------------------------------------------------------------
+BootMenu_GetDriveToDXforMenuitemInCX:
+	mov		dl, cl							; Copy menuitem index to DX
+	call	FloppyDrive_GetCountToAX
+	cmp		dl, al							; Floppy drive?
+	jb		SHORT .ReturnFloppyDriveInDX	; Set CF if branch taken
+	or		al, 80h							; Or 80h into AL before the sub
+											; shorter instruction than or'ing it in afterward
+	sub		dl, al							; Remove floppy drives from index
+	call	RamVars_GetHardDiskCountFromBDAtoAX
+	or		al, 80h							; Or 80h into AL before the sub
+	cmp		dl, al							; Set CF if hard disk
+											; Clear CF if last item, beyond hard disk list, which indicates ROM boot
+.ReturnFloppyDriveInDX:
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuEvent.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuEvent.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuEvent.asm	(revision 516)
@@ -0,0 +1,225 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Boot Menu event handler for menu library callbacks.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html		
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; GetMenuitemToDXforDriveInDL
+;	Parameters:
+;		DL:		Drive number
+;	Returns:
+;		DX:		Menuitem index (assuming drive is available)
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+GetMenuitemToDXforDriveInDL:
+	xor		dh, dh						; Drive number now in DX
+	test	dl, dl
+	jns		SHORT .ReturnItemIndexInDX	; Return if floppy drive (HD bit not set)
+	call	FloppyDrive_GetCountToAX
+	and		dl, ~80h					; Clear HD bit
+	add		dx, ax
+.ReturnItemIndexInDX:
+	ret
+
+
+;--------------------------------------------------------------------
+; BootMenuEvent_Handler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Menu library handle
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+BootMenuEvent_Handler:
+	LOAD_BDA_SEGMENT_TO	es, di
+	call	RamVars_GetSegmentToDS
+
+%ifdef MENUEVENT_INLINE_OFFSETS
+
+	add		bx, FirstEvent
+	jmp		bx
+
+.EventNotHandled:
+.DoNotSetDefaultMenuitem:
+	xor		dx, dx		; Clear CF (and menuitem index for DoNotSetDefaultMenuitem)
+	ret
+
+MENUEVENT_InitializeMenuinitFromDSSI equ  (EventInitializeMenuinitFromSSBP - FirstEvent)
+MENUEVENT_ExitMenu equ  (BootMenuEvent_Completed - FirstEvent)
+MENUEVENT_ItemHighlightedFromCX equ (EventItemHighlightedFromCX - FirstEvent)
+MENUEVENT_ItemSelectedFromCX equ (EventItemSelectedFromCX - FirstEvent)
+MENUEVENT_RefreshTitle equ (BootMenuPrint_TitleStrings - FirstEvent)
+MENUEVENT_RefreshInformation equ (BootMenuPrint_RefreshInformation - FirstEvent)
+MENUEVENT_RefreshItemFromCX equ (BootMenuPrint_RefreshItem - FirstEvent)
+;
+; Note that there is no entry for MENUEVENT_IdleProcessing.  If MENUEVENT_IDLEPROCESSING_ENABLE is not %defined,
+; then the entry point will not be called (saving memory on this end and at the CALL point).
+;
+
+%else
+
+	cmp		bx, BYTE MENUEVENT.RefreshItemFromCX	; Above last supported item?
+	ja		SHORT .EventNotHandled
+	jmp		[cs:bx+rgfnEventSpecificHandlers]
+
+.EventNotHandled:
+.DoNotSetDefaultMenuitem:
+	xor		dx, dx		; Clear CF (and menuitem index for DoNotSetDefaultMenuitem)
+	ret
+
+rgfnEventSpecificHandlers:
+	dw		EventInitializeMenuinitFromSSBP		; MENUEVENT.InitializeMenuinitFromDSSI
+	dw		EventCompleted						; MENUEVENT.ExitMenu
+	dw		EventNotHandled						; MENUEVENT.IdleProcessing
+	dw		EventItemHighlightedFromCX			; MENUEVENT.ItemHighlightedFromCX
+	dw		EventItemSelectedFromCX				; MENUEVENT.ItemSelectedFromCX
+	dw		EventKeyStrokeInAX					; MENUEVENT.KeyStrokeInAX
+	dw		BootMenuPrint_TitleStrings			; MENUEVENT.RefreshTitle
+	dw		BootMenuPrint_RefreshInformation	; MENUEVENT.RefreshInformation
+	dw		BootMenuPrint_RefreshItem			; MENUEVENT.RefreshItemFromCX
+
+%endif
+
+
+;--------------------------------------------------------------------
+; EventInitializeMenuinitFromSSBP
+;	Parameters
+;		DS:		Ptr to RAMVARS
+;		ES:		Ptr to BDA (zero)
+;		SS:BP:	Ptr to MENUINIT struct to initialize
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+FirstEvent:	
+EventInitializeMenuinitFromSSBP:
+	; Store default Menuitem (=default drive to boot from)
+	xor		dx, dx
+	mov		[bp+MENUINIT.wHighlightedItem], dx
+
+	; Store number of Menuitems
+	call	RamVars_GetHardDiskCountFromBDAtoAX
+	xchg	ax, cx
+	call	FloppyDrive_GetCountToAX
+	add		ax, cx
+	inc		ax								; extra entry for ROM Boot item
+	mov		[bp+MENUINIT.wItems], ax
+				
+	; Store menu size
+	mov		WORD [bp+MENUINIT.wTitleAndInfoLines], BOOT_MENU_TITLE_AND_INFO_LINES
+	mov		BYTE [bp+MENUINIT.bWidth], BOOT_MENU_WIDTH
+	add		al, BOOT_MENU_HEIGHT_WITHOUT_ITEMS
+	xchg	cx, ax
+	CALL_DISPLAY_LIBRARY	GetColumnsToALandRowsToAH
+	MIN_U	ah, cl
+	mov		[bp+MENUINIT.bHeight], ah
+
+	; Store selection timeout
+	mov		ax, [cs:ROMVARS.wBootTimeout]
+	CALL_MENU_LIBRARY StartSelectionTimeoutWithTicksInAX
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; EventItemHighlightedFromCX
+;	Parameters
+;		CX:		Index of new highlighted item
+;		DX:		Index of previously highlighted item or NO_ITEM_HIGHLIGHTED
+;		DS:		Ptr to RAMVARS
+;		ES:		Ptr to BDA (zero)
+;		SS:BP:	Menu library handle
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+EventItemHighlightedFromCX:
+	push	cx
+	call	BootMenu_GetDriveToDXforMenuitemInCX		
+	jnc		.noDriveSwap		
+	call	DriveXlate_SetDriveToSwap
+.noDriveSwap:	
+		
+	; Redraw changes in drive numbers
+	xor		ax, ax	; Update first floppy drive (for translated drive number)
+	CALL_MENU_LIBRARY	RefreshItemFromAX
+	mov		dl, 80h
+	call	GetMenuitemToDXforDriveInDL
+	xchg	ax, dx	; Update first hard disk (for translated drive number)
+	CALL_MENU_LIBRARY	RefreshItemFromAX
+	pop		ax		; Update new item (for translated drive number)
+	CALL_MENU_LIBRARY	RefreshItemFromAX
+	CALL_MENU_LIBRARY	RefreshInformation
+	stc
+	ret
+
+		
+;--------------------------------------------------------------------
+; EventItemSelectedFromCX
+;	Parameters
+;		CX:		Index of selected item
+;		DS:		Ptr to RAMVARS
+;		ES:		Ptr to BDA (zero)
+;		SS:BP:	Menu library handle
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+EventItemSelectedFromCX:
+	; Fall to CloseBootMenu
+
+
+;--------------------------------------------------------------------
+; CloseBootMenu
+;	Parameters
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+CloseBootMenu:
+	CALL_MENU_LIBRARY	Close
+	; Fall to BootMenuEvent_Completed
+
+		
+;--------------------------------------------------------------------
+; BootMenuEvent_Completed
+;	Parameters
+;		Nothing
+;	Returns:
+;		CF:		Set to exit from menu
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+BootMenuEvent_Completed:
+	stc
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrint.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrint.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrint.asm	(revision 516)
@@ -0,0 +1,243 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for printing boot menu strings.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; BootMenuPrint_RefreshItem
+;
+;	Parameters:
+;		CX:		Index of highlighted item
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+BootMenuPrint_RefreshItem:
+	push	bp
+	mov		bp, sp
+
+	call	BootMenu_GetDriveToDXforMenuitemInCX
+	mov		si, g_szRomBootDash						; Standard "Rom Boot" but with a "-" at the front
+	mov		al, 20h									; The space between "Rom" and "Boot"
+	jnc		.ROMBoot								; display "Rom Boot" option for last entry
+
+	call	FindDPT_ForDriveNumberInDL
+	jc		.notOurs
+
+	call	DriveDetectInfo_ConvertDPTtoBX
+	mov		si, g_szDriveNumBOOTNFO					; special g_szDriveNum that prints from BDA
+	jmp		.go
+
+.notOurs:
+	mov		si,g_szDriveNum
+	mov		bx,g_szForeignHD						; assume a hard disk for the moment
+
+	test	dl, dl
+	js		.go
+	mov		bl,((g_szFloppyDrv)-$$ & 0xff)			; and revisit the earlier assumption...
+
+.go:
+	mov		ax, dx									; preserve DL for the floppy drive letter addition
+	call	DriveXlate_ToOrBack
+
+	test	dl, 0f0h								; if there is a character in the upper nibble
+	jnz		.noSpace
+	dec		si										; backup a character to a leading space
+.noSpace:
+
+	push	dx										; translated drive number
+	push	bx										; sub string
+	add		al, 'A'									; floppy drive letter (we always push this although
+													; the hard disks don't ever use it, but it does no harm)
+.ROMBoot:		
+	push	ax										
+
+	jmp		SHORT BootMenuPrint_RefreshInformation.FormatRelay
+
+;--------------------------------------------------------------------
+; Prints Boot Menu title strings.
+;
+; BootMenuPrint_TitleStrings
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CF:		Set since menu event handled
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+BootMenuPrint_TitleStrings:
+	xor		di,di						; Null character will be eaten
+	mov		si, g_szBootMenuTitle
+	jmp		DetectPrint_RomFoundAtSegment.BootMenuEntry
+
+
+;--------------------------------------------------------------------
+; BootMenuPrint_RefreshInformation
+;	Parameters:
+;		CX:		Index of highlighted item
+;		DS:		RAMVARS segment
+;	Returns:
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+BootMenuPrint_RefreshInformation:
+	CALL_MENU_LIBRARY ClearInformationArea
+
+	call	BootMenu_GetDriveToDXforMenuitemInCX
+	jnc		BootMenuEvent_Completed						; nothing to display if "Rom Boot" option
+
+	push	bp
+	mov		bp, sp
+
+	mov		si, g_szCapacity							; Setup print string now, carries through to print call
+
+	call	FindDPT_ForDriveNumberInDL
+
+	inc		dl											; are we a hard disk?
+	dec		dl											; inc/dec will set SF, without modifying CF or DL
+	js		.HardDiskRefreshInformation
+
+	jnc		.ours										; Based on CF from FindDPT_ForDriveNumberInDL above
+	call	FloppyDrive_GetType							; Get Floppy Drive type to BX
+	jmp		.around
+.ours:
+	call	AH8h_GetDriveParameters
+.around:
+
+	mov		ax, g_szFddSizeOr	        				; .PrintXTFloppyType
+	test	bl, bl										; Two possibilities? (FLOPPY_TYPE_525_OR_35_DD)
+	jz		SHORT .PushAXAndOutput
+
+	mov		al, (g_szFddUnknown - $$) & 0xff	        ; .PrintUnknownFloppyType
+	cmp		bl, FLOPPY_TYPE_35_ED
+	ja		SHORT .PushAXAndOutput
+
+	; Fall to .PrintKnownFloppyType
+
+;--------------------------------------------------------------------
+; .PrintKnownFloppyType
+;	Parameters:
+;		BX:		Floppy drive type
+;	Returns:
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		AX, BX, SI, DI
+;
+; Floppy Drive Types:
+;
+;   0  Handled above
+;   1  FLOPPY_TYPE_525_DD          5 1/4   360K
+;   2  FLOPPY_TYPE_525_HD          5 1/4   1.2M
+;   3  FLOPPY_TYPE_35_DD           3 1/2   720K
+;   4  FLOPPY_TYPE_35_HD           3 1/2   1.44M
+;   5  3.5" ED on some BIOSes      3 1/2   2.88M
+;   6  FLOPPY_TYPE_35_ED		   3 1/2   2.88M
+;   >6 Unknown, handled above
+;
+;--------------------------------------------------------------------
+.PrintKnownFloppyType:
+	mov		al, (g_szFddSize - $$) & 0xff
+	push	ax
+
+	mov		al, (g_szFddThreeHalf - $$) & 0xff
+	cmp		bl, FLOPPY_TYPE_525_HD
+	ja		.ThreeHalf
+	mov		al, (g_szFddFiveQuarter - $$) & 0xff
+.ThreeHalf:
+	push	ax											; "5 1/4" or "3 1/2"
+
+	xor		bh, bh
+	mov		al,FloppyTypes.rgbCapacityMultiplier
+	mul		BYTE [cs:bx+FloppyTypes.rgbCapacity - 1]    ; -1 since 0 is handled above and not in the table
+
+.PushAXAndOutput:
+	push	ax
+
+.FormatRelay:
+	jmp		DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; Prints Hard Disk Menuitem information strings.
+;
+; BootMenuPrint_HardDiskMenuitemInformation
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+.HardDiskRefreshInformation:
+	jc		.HardDiskMenuitemInfoForForeignDrive		; Based on CF from FindDPT_ForDriveNumberInDL (way) above
+
+.HardDiskMenuitemInfoForOurDrive:
+	ePUSH_T ax, g_szInformation							; Add substring for our hard disk information
+	call	GetTotalSectorCount
+	jmp		.ConvertSectorCountInBXDXAXtoSizeAndPushForFormat
+
+.HardDiskMenuitemInfoForForeignDrive:
+	call	DriveXlate_ToOrBack
+	call	AH15h_GetSectorCountFromForeignDriveToDXAX
+
+.ConvertSectorCountInBXDXAXtoSizeAndPushForFormat:
+	ePUSH_T	cx, g_szCapacityNum		; Push format substring
+	call	Size_ConvertSectorCountInBXDXAXtoKiB
+	mov		cx, BYTE_MULTIPLES.kiB
+	call	Size_GetSizeToAXAndCharToDLfromBXDXAXwithMagnitudeInCX
+	push	ax						; Size in magnitude
+	push	cx						; Tenths
+	push	dx						; Magnitude character
+
+	test	di, di					; Zero if foreign drive
+	jz		SHORT BootMenuPrint_RefreshInformation.FormatRelay
+
+%include "BootMenuPrintCfg.asm"		; Inline of code to fill out remainder of information string
+	jmp		DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+FloppyTypes:
+.rgbCapacityMultiplier equ 120		; Multiplier to reduce word sized values to byte size
+.rgbCapacity:
+	db		360   / FloppyTypes.rgbCapacityMultiplier    ;  type 1
+	db		1200  / FloppyTypes.rgbCapacityMultiplier    ;  type 2
+	db		720   / FloppyTypes.rgbCapacityMultiplier    ;  type 3
+	db		1440  / FloppyTypes.rgbCapacityMultiplier    ;  type 4
+	db		2880  / FloppyTypes.rgbCapacityMultiplier    ;  type 5
+	db		2880  / FloppyTypes.rgbCapacityMultiplier    ;  type 6
+
+
+;--------------------------------------------------------------------
+; GetTotalSectorCount
+;	Parameters:
+;		DS:DI:		DPT Pointer
+;	Returns:
+;		BX:DX:AX:	48-bit sector count
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+%ifdef MODULE_EBIOS
+GetTotalSectorCount		EQU		AccessDPT_GetLbaSectorCountToBXDXAX
+%else
+GetTotalSectorCount		EQU		AH15h_GetSectorCountToBXDXAX
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrintCfg.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrintCfg.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrintCfg.asm	(revision 516)
@@ -0,0 +1,158 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for printing drive configuration
+;					information on Boot Menu.
+;
+; Included by BootMenuPrint.asm, this routine is to be inserted into
+; BootMenuPrint_HardDiskRefreshInformation.
+;
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;;; fall-into from BootMenuPrint_HardDiskRefreshInformation.
+
+;--------------------------------------------------------------------
+; Prints Hard Disk configuration for drive handled by our BIOS.
+; Cursor is set to configuration header string position.
+;
+; BootMenuPrintCfg_ForOurDrive
+;	Parameters:
+;		DS:DI:		Pointer to DPT
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+.BootMenuPrintCfg_ForOurDrive:
+	eMOVZX	ax, [di+DPT.bIdevarsOffset]
+	xchg	bx, ax						; CS:BX now points to IDEVARS
+	; Fall to .PushAddressingMode
+
+;--------------------------------------------------------------------
+; .PushAddressingMode
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX, CX, DX
+;--------------------------------------------------------------------
+.PushAddressingMode:
+	ACCESSDPT__GET_UNSHIFTED_TRANSLATE_MODE_TO_AXZF
+	;;
+	;; This multiply both shifts the addressing mode bits down to low order bits, and
+	;; at the same time multiplies by the size of the string displacement.  The result is in AH,
+	;; with AL clear, and so we exchange AL and AH after the multiply for the final result.
+	;;
+	mov		cx, g_szAddressingModes_Displacement << (8-TRANSLATEMODE_FIELD_POSITION)
+	mul		cx
+	xchg	al, ah		; AL = always zero after above multiplication
+	add		ax, g_szAddressingModes
+	push	ax
+	; Fall to .PushBlockMode
+
+;--------------------------------------------------------------------
+; .PushBlockMode
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.PushBlockMode:
+	mov		ax, 1
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_BLOCK_MODE_SUPPORTED
+	jz		SHORT .PushBlockSizeFromAX
+	mov		al, [di+DPT_ATA.bBlockSize]
+.PushBlockSizeFromAX:
+	push	ax
+	; Fall to .PushDeviceType
+
+;--------------------------------------------------------------------
+; .PushDeviceType
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.PushDeviceType:
+%ifndef MODULE_SERIAL
+	mov		al, g_szDeviceTypeValues_Displacement
+	mul		BYTE [di+DPT_ATA.bDevice]
+%else
+	mov		ah, [cs:bx+IDEVARS.bDevice]
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_SERIAL_DEVICE	; Clears CF
+	eCMOVZ	ah, [di+DPT_ATA.bDevice]	; DPT_ATA contains up to date device information for IDE drives
+%ifdef USE_UNDOC_INTEL
+	eSALC	; Clear AL using CF (from TEST above)
+	eAAD	g_szDeviceTypeValues_Displacement
+%else
+	mov		al, g_szDeviceTypeValues_Displacement
+	mul		ah
+%endif ; USE_UNDOC_INTEL
+%endif ; MODULE_SERIAL
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if (COUNT_OF_ALL_IDE_DEVICES * 2 * g_szDeviceTypeValues_Displacement) > 255
+		%error "The USE_UNDOC_INTEL block in .PushDeviceType needs to be removed (would cause an overflow)!"
+	%endif
+%endif
+
+	shr		ax, 1	; Divide by 2 since IDEVARS.bDevice is multiplied by 2
+	add		ax, g_szDeviceTypeValues
+	push	ax
+	; Fall to .PushIRQ
+
+;--------------------------------------------------------------------
+; .PushIRQ
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.PushIRQ:
+	mov		al, [cs:bx+IDEVARS.bIRQ]
+	cbw
+	push	ax
+	; Fall to .PushResetStatus
+
+;--------------------------------------------------------------------
+; .PushResetStatus
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX, BX, DX, ES
+;--------------------------------------------------------------------
+.PushResetStatus:
+	mov		al, [di+DPT.bInitError]
+	push	ax
+
+;;; fall-out to BootMenuPrint_HardDiskRefreshInformation.
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/DriveXlate.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/DriveXlate.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/DriveXlate.asm	(revision 516)
@@ -0,0 +1,172 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for swapping drive letters.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DriveXlate_ConvertDriveLetterInDLtoDriveNumber
+;	Parameters:
+;		DS:		RAMVARS segment
+;		DL:		Drive letter ('A'...)
+;	Returns:
+;		DL:		Drive number (0xh for Floppy Drives, 8xh for Hard Drives)
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+DriveXlate_ConvertDriveLetterInDLtoDriveNumber:
+	call	DriveXlate_GetLetterForFirstHardDriveToAX
+	cmp		dl, al
+	jb		SHORT .ConvertLetterInDLtoFloppyDriveNumber
+
+	; Convert letter in DL to Hard Drive number
+	sub		dl, al
+	or		dl, 80h
+	ret
+
+.ConvertLetterInDLtoFloppyDriveNumber:
+	sub		dl, DEFAULT_FLOPPY_DRIVE_LETTER
+	ret
+
+%ifdef MODULE_HOTKEY
+%if HotkeyBar_FallThroughTo_DriveXlate_ConvertDriveLetterInDLtoDriveNumber <> DriveXlate_ConvertDriveLetterInDLtoDriveNumber
+	%error "DriveXlate_ConvertDriveLetterInDLtoDriveNumber must be at the top of DriveXlate.asm, and that file must immediately follow HotKeys.asm"
+%endif
+%endif
+
+;--------------------------------------------------------------------
+; DriveXlate_ConvertDriveNumberFromDLtoDriveLetter
+;	Parameters:
+;		DL:		Drive number (0xh for Floppy Drives, 8xh for Hard Drives)
+;		DS:		RAMVARS Segment
+;	Returns:
+;		DL:		Drive letter ('A'...)
+;		CF:		Set if Hard Drive
+;				Clear if Floppy Drive
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+DriveXlate_ConvertDriveNumberFromDLtoDriveLetter:
+	xor		dl, 80h
+	js		SHORT .GetDefaultFloppyDrive
+
+	; Store default hard drive to boot from
+	call	DriveXlate_GetLetterForFirstHardDriveToAX
+	add		dl, al
+	stc
+	ret
+
+.GetDefaultFloppyDrive:
+	sub		dl, 80h - DEFAULT_FLOPPY_DRIVE_LETTER	; Clears CF
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns letter for first hard disk. Usually it will be 'C' but it
+; can be higher if more than two floppy drives are found.
+;
+; DriveXlate_GetLetterForFirstHardDriveToAX
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		AX:		Upper case letter for first hard disk
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+DriveXlate_GetLetterForFirstHardDriveToAX:
+	call	FloppyDrive_GetCountToAX
+	add		al, DEFAULT_FLOPPY_DRIVE_LETTER
+	MAX_U	al, DEFAULT_HARD_DRIVE_LETTER
+	ret
+
+
+;--------------------------------------------------------------------
+; DriveXlate_ToOrBack
+;	Parameters:
+;		DL:		Drive number to be possibly translated
+;		DS:		RAMVARS segment
+;	Returns:
+;		DL:		Translated drive number
+;	Corrupts registers:
+;		DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DriveXlate_ToOrBack:
+	xchg	di, ax					; Backup AX
+
+	mov		ah, 80h					; Assume hard disk
+	mov		al, [RAMVARS.xlateVars+XLATEVARS.bHDSwap]
+	test	dl, ah					; Hard disk?
+	jnz		SHORT .SwapDrive		; If so, jump to swap
+	mov		al, [RAMVARS.xlateVars+XLATEVARS.bFDSwap]
+	cbw
+
+ALIGN JUMP_ALIGN
+.SwapDrive:
+	cmp		ah, dl					; Swap DL from 00h/80h to xxh?
+	je		SHORT .SwapToXXhInAL
+	cmp		al, dl					; Swap DL from xxh to 00h/80h?
+	jne		SHORT .RestoreAXandReturn
+	mov		al, ah
+ALIGN JUMP_ALIGN
+.SwapToXXhInAL:
+	mov		dl, al
+ALIGN JUMP_ALIGN
+.RestoreAXandReturn:
+	xchg	ax, di					; Restore AX
+	ret
+
+
+;--------------------------------------------------------------------
+; Resets drive swapping variables to defaults (no swapping).
+;
+; DriveXlate_Reset
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI, DL
+;--------------------------------------------------------------------
+DriveXlate_Reset:
+	xor		dl, dl				; no translation for a floppy
+	;; fall through to DriveXlate_SetDriveToSwap
+
+;--------------------------------------------------------------------
+; Stores drive to be swapped.
+;
+; DriveXlate_SetDriveToSwap
+;	Parameters:
+;		DL:		Drive to swap to 00h or 80h
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+DriveXlate_SetDriveToSwap:
+	mov		ax, 8000h			; Default mapping (no translation)
+	test	dl, dl				; Floppy drive?
+	js		SHORT .SetHardDriveToSwap
+	mov		al, dl				; Store floppy translation
+	SKIP2B	di
+.SetHardDriveToSwap:
+	mov		ah, dl				; Store HD translation
+	mov		WORD [RAMVARS.xlateVars+XLATEVARS.wFDandHDswap], ax
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/HotkeyBar.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/HotkeyBar.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Menus/HotkeyBar.asm	(revision 516)
@@ -0,0 +1,416 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Hotkey Bar related functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; HotkeyBar_UpdateDuringDriveDetection
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+HotkeyBar_UpdateDuringDriveDetection:
+	call	HotkeyBar_ScanHotkeysFromKeyBufferAndStoreToBootvars
+	; Fall to HotkeyBar_DrawToTopOfScreen
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_DrawToTopOfScreen
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+HotkeyBar_DrawToTopOfScreen:
+	; Store current screen coordinates to be restored
+	; when Hotkey Bar is rendered
+	call	DetectPrint_GetSoftwareCoordinatesToAX
+	push	ax
+
+	call	MoveCursorToScreenTopLeftCorner
+	; Fall to .PrintFloppyDriveHotkeys
+
+;--------------------------------------------------------------------
+; .PrintFloppyDriveHotkeys
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.PrintFloppyDriveHotkeys:
+	call	FloppyDrive_GetCountToAX
+	test	ax, ax		; Any Floppy Drives?
+	jz		SHORT .SkipFloppyDriveHotkeys
+
+	mov		ax, (ANGLE_QUOTE_RIGHT << 8) | DEFAULT_FLOPPY_DRIVE_LETTER
+	mov		cl, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFddLetter]
+	mov		di, g_szFDD
+	call	FormatDriveHotkeyString
+
+.SkipFloppyDriveHotkeys:
+	; Fall to .PrintHardDriveHotkeys
+
+;--------------------------------------------------------------------
+; .PrintHardDriveHotkeys
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+	call	DriveXlate_GetLetterForFirstHardDriveToAX
+	mov		ah, ANGLE_QUOTE_RIGHT
+	mov		cl, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bHddLetter]
+	mov		di, g_szHDD
+	call	FormatDriveHotkeyString
+	; Fall to .PrintBootMenuHotkey
+
+;--------------------------------------------------------------------
+; .PrintBootMenuHotkey
+;	Parameters:
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.PrintBootMenuHotkey:
+%ifdef MODULE_BOOT_MENU
+	mov		ax, BOOT_MENU_HOTKEY_SCANCODE | ('2' << 8)
+	mov		di, g_szBootMenu
+	call	FormatFunctionHotkeyString
+%endif
+	; Fall to .PrintComDetectHotkey
+
+;--------------------------------------------------------------------
+; .PrintComDetectHotkey
+;	Parameters:
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.PrintComDetectHotkey:
+%ifdef MODULE_SERIAL
+	mov		ax, COM_DETECT_HOTKEY_SCANCODE | ('6' << 8)
+	mov		di, g_szHotComDetect
+	call	FormatFunctionHotkeyString
+%endif
+	; Fall to .PrintRomBootHotkey
+
+;--------------------------------------------------------------------
+; .PrintRomBootHotkey
+;	Parameters:
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.PrintRomBootHotkey:
+	mov		ax, ROM_BOOT_HOTKEY_SCANCODE | ('8' << 8)
+	mov		di, g_szRomBoot
+	call	FormatFunctionHotkeyString
+	; Fall to .EndHotkeyBarRendering
+
+;--------------------------------------------------------------------
+; .EndHotkeyBarRendering
+;	Parameters:
+;		Stack:	Screen coordinates before drawing Hotkey Bar
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+.EndHotkeyBarRendering:
+	call	HotkeyBar_ClearRestOfTopRow
+	pop		ax
+	jmp		SHORT HotkeyBar_RestoreCursorCoordinatesFromAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_ClearRestOfTopRow
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+HotkeyBar_ClearRestOfTopRow:
+	CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
+	eMOVZX	cx, al
+	CALL_DISPLAY_LIBRARY GetSoftwareCoordinatesToAX
+	sub		cl, al
+	mov		al, ' '
+	JMP_DISPLAY_LIBRARY PrintRepeatedCharacterFromALwithCountInCX
+
+
+;--------------------------------------------------------------------
+; FormatDriveHotkeyString
+;	Parameters:
+;		CL:			Drive letter hotkey from BOOTVARS
+;		AL:			First character for drive key string
+;		AH:			Second character for drive key string (ANGLE_QUOTE_RIGHT)
+;		SI:			Offset to hotkey description string
+;		ES:			BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+;; No work to do before going into FormatFunctionHotkeyString
+FormatDriveHotkeyString  equ  GetNonSelectedHotkeyDescriptionAttributeToDX
+
+;--------------------------------------------------------------------
+; FormatFunctionHotkeyString
+;	Parameters:
+;		AL:			Scancode of function key, to know which if any to show as selected
+;					Later replaced with an 'F' for the call to the output routine
+;		AH:			Second character for drive key string
+;		SI:			Offset to hotkey description string
+;		ES:			BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+FormatFunctionHotkeyString:
+	xor		cx, cx		; Null character, eaten in output routines
+
+	cmp		[es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode], al
+	mov		al, 'F'		; Replace scancode with character for output
+
+%ifdef MODULE_BOOT_MENU
+
+	mov		si, ATTRIBUTE_CHARS.cHurryTimeout		; Selected hotkey
+	je		SHORT GetDescriptionAttributeToDX		; From compare with bScancode above
+
+GetNonSelectedHotkeyDescriptionAttributeToDX:
+	mov		si, ATTRIBUTE_CHARS.cHighlightedItem	; Unselected hotkey
+
+	; Display Library should not be called like this
+GetDescriptionAttributeToDX:
+	xchg	dx, ax
+	call	MenuAttribute_GetToAXfromTypeInSI
+	xchg	dx, ax					; DX = Description attribute
+	;;  fall through to PushHotkeyParamsAndFormat
+
+
+%else ; if no MODULE_BOOT_MENU - No boot menu so use simpler attributes
+
+	mov		dx, (COLOR_ATTRIBUTE(COLOR_YELLOW, COLOR_CYAN) << 8) | MONO_REVERSE_BLINK
+	je		SHORT SelectAttributeFromDHorDLbasedOnVideoMode		; From compare with bScancode above
+
+GetNonSelectedHotkeyDescriptionAttributeToDX:
+	mov		dx, (COLOR_ATTRIBUTE(COLOR_BLACK, COLOR_CYAN) << 8) | MONO_REVERSE
+
+SelectAttributeFromDHorDLbasedOnVideoMode:
+	mov		ch, [es:BDA.bVidMode]		; We only need to preserve CL
+	shr		ch, 1
+	jnc		SHORT .AttributeLoadedToDL	; Black & White modes
+	shr		ch, 1
+	jnz		SHORT .AttributeLoadedToDL	; MDA
+	mov		dl, dh
+.AttributeLoadedToDL:
+	;;  fall through to PushHotkeyParamsAndFormat
+
+%endif ; MODULE_BOOT_MENU
+
+
+;--------------------------------------------------------------------
+; PushHotkeyParamsAndFormat
+;	Parameters:
+;		AL:			First character
+;		AH:			Second character
+;		DX:			Description Attribute
+;		CX:			Description string parameter
+;		CS:DI:		Description string
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+PushHotkeyParamsAndFormat:
+	push	bp
+	mov		bp, sp
+
+	mov		si, MONO_BRIGHT
+
+	push	si				; Key attribute
+	push	ax				; First Character
+	mov		al, ah
+	push	ax				; Second Character
+
+	push	dx				; Description attribute
+	push	di				; Description string
+	push	cx				; Description string parameter
+
+	push	si				; Key attribute for last space
+
+	mov		si, g_szHotkey
+	jmp		DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; MoveCursorToScreenTopLeftCorner
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+MoveCursorToScreenTopLeftCorner:
+	xor		ax, ax			; Top left corner (0, 0)
+	; Fall to HotkeyBar_RestoreCursorCoordinatesFromAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_RestoreCursorCoordinatesFromAX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+HotkeyBar_RestoreCursorCoordinatesFromAX:
+	JMP_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_StoreHotkeyToBootvarsForDriveLetterInDL
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;		DL:		Drive Letter ('A'...)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+HotkeyBar_StoreHotkeyToBootvarsForDriveLetterInDL:
+	eMOVZX	ax, dl
+	or		al, 32	; Upper case drive letter to lower case keystroke
+	jmp		SHORT HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_ScanHotkeysFromKeyBufferAndStoreToBootvars
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		AL:		Last scancode value
+;	Corrupts registers:
+;		AH, CX
+;--------------------------------------------------------------------
+HotkeyBar_ScanHotkeysFromKeyBufferAndStoreToBootvars:
+	call	Keyboard_GetKeystrokeToAX
+	jz		SHORT NoHotkeyToProcess
+
+	ePUSH_T	cx, HotkeyBar_ScanHotkeysFromKeyBufferAndStoreToBootvars
+	; Fall to HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
+;	Parameters:
+;		AL:		Hotkey ASCII code
+;		AH:		Hotkey Scancode
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;       AL:     Last scancode seen
+;	Corrupts registers:
+;		AH, CX, DI
+;--------------------------------------------------------------------
+HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX:
+	mov		di, BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode
+
+	; All scancodes are saved, even if it wasn't a drive letter,
+	; which also covers our function key case.  Invalid function keys
+	; will not do anything (won't be printed, won't be accepted as input)
+	mov		[es:di], ah
+
+	; Drive letter hotkeys remaining, allow 'a' to 'z'
+	call	Char_IsLowerCaseLetterInAL
+	jnc		SHORT .KeystrokeIsNotValidDriveLetter
+	and		al, ~32					; We want to print upper case letters
+
+	; Clear HD First flag to assume Floppy Drive hotkey
+	dec		di
+	and		BYTE [es:di], ~FLG_HOTKEY_HD_FIRST
+
+	; Determine if Floppy or Hard Drive hotkey
+	xchg	cx, ax
+	call	DriveXlate_GetLetterForFirstHardDriveToAX
+	cmp		cl, al
+	jb		SHORT .StoreDriveLetter	; Store Floppy Drive letter
+
+	; Store Hard Drive letter
+	or		BYTE [es:di], FLG_HOTKEY_HD_FIRST
+
+.StoreDriveLetter:
+	sbb		di, BYTE 1				; Sub CF if Floppy Drive
+	xchg	ax, cx
+	mov		[es:di], al
+
+.KeystrokeIsNotValidDriveLetter:
+NoHotkeyToProcess:
+	mov		al, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode]
+	ret
+
+;--------------------------------------------------------------------
+; HotkeyBar_GetBootDriveNumbersToDX
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		DX:		Drives selected as boot device, DL is primary
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+HotkeyBar_GetBootDriveNumbersToDX:
+	mov		dx, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wFddAndHddLetters]
+	test	BYTE [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFlags], FLG_HOTKEY_HD_FIRST
+	jnz		.noflip
+	xchg	dl, dh
+.noflip:
+	call	DriveXlate_ConvertDriveLetterInDLtoDriveNumber
+	xchg	dl, dh
+	; Fall to HotkeyBar_FallThroughTo_DriveXlate_ConvertDriveLetterInDLtoDriveNumber
+
+HotkeyBar_FallThroughTo_DriveXlate_ConvertDriveLetterInDLtoDriveNumber:
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Strings.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Strings.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/Strings.asm	(revision 516)
@@ -0,0 +1,291 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Strings and equates for BIOS messages.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifdef MODULE_STRINGS_COMPRESSED_PRECOMPRESS
+	%include "Display.inc"
+%endif
+
+; Section containing code
+SECTION .text
+
+; The following strings are used by DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP
+; To support an optimization in that code, these strings must start on the same 256 byte page,
+; which is checked at assembly time below.
+;
+g_szDetectStart:
+g_szDetectMaster:		db	"Master",NULL
+g_szDetectSlave:		db	"Slave ",NULL
+g_szDetectOuter:		db	"%s at %s: ",NULL
+%ifdef MODULE_SERIAL
+g_szDetectCOM:			db	"COM%c%s",NULL
+g_szDetectCOMAuto:		db	" Detect",NULL
+g_szDetectCOMSmall:		db	"/%u%u00",NULL					; IDE Master at COM1/9600:
+g_szDetectCOMLarge:		db	"/%u.%uK",NULL					; IDE Master at COM1/19.2K:
+%endif
+g_szDetectEnd:
+g_szDetectPort:			db	"%x",NULL						; IDE Master at 1F0h:
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if ((g_szDetectEnd-$$) & 0xff00) <> ((g_szDetectStart-$$) & 0xff00)
+		%error "g_szDetect* strings must start on the same 256 byte page, required by DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP.  Please move this block up or down within Strings.asm"
+	%endif
+%endif
+
+
+; POST drive detection strings
+g_szDashForZero:	db	"- ",NULL	; Required by Display Library
+g_szRomAt:			db	LF,CR
+					db	"%s @ %x",LF,CR						; -=XTIDE ... =- @ Segment
+					db	"%s",LF,CR							; version string
+					db	"Released under GNU GPL v2",LF,CR
+					db	LF,CR,NULL
+%ifdef MODULE_BOOT_MENU
+g_szBootMenuTitle:	db	"%s%c",LF,CR						; -=XTIDE ... =- and null (eaten)
+					db	"%s",NULL							; version string
+%endif
+g_szDriveName:		db	"%z",LF,CR,NULL
+
+
+; Boot loader strings
+g_szTryToBoot:			db	"Booting %c",ANGLE_QUOTE_RIGHT,"%c",LF,CR,NULL
+g_szBootSectorNotFound:	db	"Boot sector " 			; String fall through...
+g_szNotFound:			db	"not found",LF,CR,NULL
+g_szReadError:			db	"Error %x!",LF,CR,NULL
+
+
+%ifdef MODULE_HOTKEYS
+; Hotkey Bar strings
+g_szFDD:				db	"FDD [%c]",NULL			; "FDD [A]"
+g_szHDD:				db	"HDD [%c]",NULL			; "HDD [C]"
+%ifdef MODULE_BOOT_MENU
+g_szBootMenu:			db	"BootMnu%c",NULL		; "BootMnu", location of %c doesn't matter
+%endif ; MODULE_BOOT_MENU
+g_szHotkey:				db	"%A%c%c%A%s%A ",NULL	; "C»HDD [A] ", "F2BootMnu " or "F8RomBoot "
+%ifdef MODULE_SERIAL
+g_szHotComDetect:		db	"ComDtct%c",NULL		; "ComDtct", location of %c doesn't matter
+%endif ; MODULE_SERIAL
+%endif ; MODULE_HOTKEYS
+
+%ifdef MODULE_BOOT_MENU
+g_szRomBootDash:		db	" -  "					; String fall through to g_szRomBoot
+%endif
+%ifdef MODULE_HOTKEYS OR MODULE_BOOT_MENU
+g_szRomBoot:			db	"Rom%cBoot",NULL		; "RomBoot" or "Rom Boot"
+%endif
+
+
+%ifdef MODULE_BOOT_MENU
+; Boot Menu Floppy Disk strings
+;
+; The following strings are used by BootMenuPrint_RefreshInformation
+; To support optimizations in that code, these strings must start on the same 256 byte page,
+; which is checked at assembly time below.
+;
+g_szFddStart:
+g_szFddUnknown:		db	"Unknown",NULL
+g_szFddSizeOr:		db	"5",ONE_QUARTER,QUOTATION_MARK," or 3",ONE_HALF,QUOTATION_MARK," DD",NULL
+g_szFddSize:		db	"%s",QUOTATION_MARK,", %u kiB",NULL	; 3½", 1440 kiB
+g_szFddThreeHalf:	db	"3",ONE_HALF,NULL
+g_szFddEnd:
+g_szFddFiveQuarter:	db	"5",ONE_QUARTER,NULL
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if ((g_szFddStart-$$) & 0xff00) <> ((g_szFddEnd-$$) & 0xff00)
+		%error "g_szFdd* strings must start on the same 256 byte page, required by the BootMenuPrint_RefreshInformation routines for floppy drives.  Please move this block up or down within Strings.asm"
+	%endif
+%endif
+
+
+g_szAddressingModes:
+g_szNORMAL:		db	"NORMAL",NULL
+g_szLARGE:		db	"LARGE ",NULL
+g_szLBA:		db	"LBA   ",NULL
+g_szAddressingModes_Displacement equ (g_szLARGE - g_szAddressingModes)
+;
+; Ensure that addressing modes are correctly spaced in memory
+;
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if g_szNORMAL <> g_szAddressingModes
+		%error "g_szAddressingModes Displacement Incorrect 1"
+	%endif
+	%if g_szLARGE <> g_szNORMAL + g_szAddressingModes_Displacement
+		%error "g_szAddressingModes Displacement Incorrect 2"
+	%endif
+	%if g_szLBA <> g_szLARGE + g_szAddressingModes_Displacement
+		%error "g_szAddressingModes Displacement Incorrect 3"
+	%endif
+%endif
+
+
+g_szDeviceTypeValues:
+g_szDeviceTypeValues_16bit:		db	" 16",NULL
+g_szDeviceTypeValues_32bit:		db	" 32",NULL
+g_szDeviceTypeValues_8bit:		db	"  8",NULL
+g_szDeviceTypeValues_XTIDEr1:	db	"D8 ",NULL	; Dual 8-bit
+g_szDeviceTypeValues_XTIDEr2:	db	"X8 ",NULL	; A0<->A3 swapped 8-bit
+g_szDeviceTypeValues_XTCFpio8:	db	"T8 ",NULL	; True 8-bit
+g_szDeviceTypeValues_XTCFdma:	db	"8MA",NULL	; DMA 8-bit
+g_szDeviceTypeValues_XTCFmem:	db	"M8 ",NULL	; Memory Mapped 8-bit
+g_szDeviceTypeValues_JrIde:		db	"M8 ",NULL
+g_szDeviceTypeValues_Serial:	db	"SER",NULL
+
+g_szDeviceTypeValues_Displacement equ (g_szDeviceTypeValues_32bit - g_szDeviceTypeValues)
+;
+; Ensure that device type strings are correctly spaced in memory
+;
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if g_szDeviceTypeValues_16bit <> g_szDeviceTypeValues
+		%error "g_szDeviceTypeValues Displacement Incorrect 1"
+	%endif
+	%if g_szDeviceTypeValues_32bit <> g_szDeviceTypeValues_16bit + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 2"
+	%endif
+	%if g_szDeviceTypeValues_8bit <> g_szDeviceTypeValues_32bit + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 2"
+	%endif
+	%if g_szDeviceTypeValues_XTIDEr1 <> g_szDeviceTypeValues_8bit + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 3"
+	%endif
+	%if g_szDeviceTypeValues_XTIDEr2 <> g_szDeviceTypeValues_XTIDEr1 + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 4"
+	%endif
+	%if g_szDeviceTypeValues_XTCFpio8 <> g_szDeviceTypeValues_XTIDEr2 + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 5"
+	%endif
+	%if g_szDeviceTypeValues_XTCFdma <> g_szDeviceTypeValues_XTCFpio8 + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 6"
+	%endif
+	%if g_szDeviceTypeValues_XTCFmem <> g_szDeviceTypeValues_XTCFdma + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 7"
+	%endif
+	%if g_szDeviceTypeValues_JrIde <> g_szDeviceTypeValues_XTCFmem + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 8"
+	%endif
+	%if g_szDeviceTypeValues_Serial <> g_szDeviceTypeValues_JrIde + g_szDeviceTypeValues_Displacement
+		%error "g_szDeviceTypeValues Displacement Incorrect 9"
+	%endif
+%endif
+
+
+g_szSelectionTimeout:	db	DOUBLE_BOTTOM_LEFT_CORNER,DOUBLE_LEFT_HORIZONTAL_TO_SINGLE_VERTICAL,"%ASelection in %2-u s",NULL
+
+
+; Boot Menu information strings
+g_szCapacity:			db	"Capacity : %s",NULL
+g_szCapacityNum:		db	"%5-u.%u %ciB",NULL
+g_szInformation:		db	"%s",LF,CR
+	db	"Addr. ",SINGLE_VERTICAL,"Block",SINGLE_VERTICAL,"Bus",SINGLE_VERTICAL,"IRQ",SINGLE_VERTICAL,"Reset",LF,CR
+	db	"%s",SINGLE_VERTICAL,"%5-u",SINGLE_VERTICAL,"%s",SINGLE_VERTICAL," %2-I",SINGLE_VERTICAL,"%5-x",NULL
+
+
+; Boot Menu menuitem strings
+;
+; The following strings are used by BootMenuPrint_* routines.
+; To support optimizations in that code, these strings must start on the same 256 byte page,
+; which is checked at assembly time below.
+;
+g_szDriveNumSpace:		db	" "							; leading space, used if drive number is less than 0fh
+														; must come immediately before g_szDriveNum!
+g_szBootMenuPrintStart:
+g_szDriveNum:			db	"%x %s",NULL
+g_szDriveNumBNSpace:	db	" "							; leading space, used if drive number is less than 0fh
+														; must come immediately before g_szDriveNumBOOTNFO!
+g_szDriveNumBOOTNFO:	db	"%x %z",NULL
+g_szFloppyDrv:			db	"Floppy Drive %c",NULL
+g_szBootMenuPrintEnd:
+g_szForeignHD:			db	"Foreign Hard Disk",NULL
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+	%if ((g_szBootMenuPrintStart-$$) & 0xff00) <> ((g_szBootMenuPrintEnd-$$) & 0xff00)
+		%error "g_szBootMenuPrint* strings must start on the same 256 byte page, required by the BootMenuPrint_* routines.  Please move this block up or down within Strings.asm"
+	%endif
+	%if g_szDriveNumSpace+1 != g_szDriveNum || g_szDriveNumBNSpace+1 != g_szDriveNumBOOTNFO
+		%error "g_szDriveNumSpace or g_szDriveNumBNSpace are out of position"
+	%endif
+%endif
+
+%endif ; MODULE_BOOT_MENU
+
+
+;------------------------------------------------------------------------------------------
+;
+; Tables for StringsCompress.pl
+;
+; Items can be added and removed from this table as needed, with the following rules:
+;  * Formats follow the special characters.  But other than that, order makes no difference.
+;  * Some of the formats require "even" and "odd" numbering.  Even tells the code that
+;    it is a "number-" format, otherwise it doesn't interpret a number first.  The easiest
+;    way to maintain this is to move one of the "n/a" items to/from the front of the format
+;    list to maintain the even/odd.
+;  * Values do not need to remain consistent across versions.  This table is only used
+;    internally to this file.
+;  * There can only be 32 of these (0-31).
+;  * Keeping the list short is good - this translates to a table in the compressed version.
+;    An error will be reported if a character or format is no longer being used by any
+;    strings above.
+;  * Please keep items sequential for ease of further editing.
+;
+;$translate{ord(' ')} = 0;
+;$translate{172}      = 1;     # ONE_QUARTER
+;$translate{171}      = 2;     # ONE_HALF
+;$translate{179}      = 3;     # SINGLE_VERTICAL
+;$translate{175}      = 4;     # ANGLE_QUOTE_RIGHT
+;$translate{ord('!')} = 5;
+;$translate{ord('"')} = 6;
+;$translate{ord(',')} = 7;
+;$translate{ord('-')} = 8;
+;$translate{ord('.')} = 9;
+;$translate{ord('/')} = 10;
+;$translate{ord('1')} = 11;
+;$translate{ord('2')} = 12;
+;$translate{ord('3')} = 13;
+;$translate{ord('5')} = 14;
+;$translate{ord('6')} = 15;
+;$translate{ord('8')} = 16;
+;$translate{200}      = 17;    # DOUBLE_BOTTOM_LEFT_CORNER
+;$translate{181}      = 18;    # DOUBLE_LEFT_HORIZONTAL_TO_SINGLE_VERTICAL
+;$translate{ord('0')} = 19;
+;
+; Formats begin immediately after the last Translated character (they are in the same table)
+;
+;$format_begin = 20;
+;
+;$format{"2-I"} = 20;        # must be even
+;$format{"u"}   = 21;        # must be odd
+;$format{"5-u"} = 22;        # must be even
+;$format{"x"}   = 23;        # must be odd
+;$format{"5-x"} = 24;        # must be even
+;$format{"nl"}  = 25;        # n/a
+;$format{"2-u"} = 26;        # must be even
+;$format{"A"}   = 27;        # n/a
+;$format{"c"}   = 28;        # n/a
+;$format{"s"}   = 29;        # n/a, normal string from DS
+;$format{"z"}   = 30;        # n/a, boot string from BDA
+;
+; NOTE: The last $format cannot exceed 31 (stored in a 5-bit quantity).
+;
+; Starting point for the "normal" range, typically around 0x40 to cover upper and lower case
+; letters.  If lower case 'z' is not used, 0x3a can be a good choice as it adds ':' to the
+; front end.
+;
+;$normal_base = 0x3a;
+;
+; End of StringsCompress.pl information
+;
+;------------------------------------------------------------------------------------------
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/StringsCompressed.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/StringsCompressed.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/StringsCompressed.asm	(revision 516)
@@ -0,0 +1,658 @@
+;;;======================================================================
+;;;
+;;; This file is generated by StringsCompress.pl from source in Strings.asm
+;;; DO NOT EDIT DIRECTLY - See the makefile for how to rebuild this file.
+;;; This file only needs to be rebuilt if Strings.asm is changed.
+;;;
+;;;======================================================================
+
+%ifdef STRINGSCOMPRESSED_STRINGS
+
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Strings and equates for BIOS messages.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifdef MODULE_STRINGS_COMPRESSED_PRECOMPRESS
+%include "Display.inc"
+%endif
+
+; Section containing code
+SECTION .text
+
+; The following strings are used by DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP
+; To support an optimization in that code, these strings must start on the same 256 byte page,
+; which is checked at assembly time below.
+;
+g_szDetectStart:
+g_szDetectMaster:		; db	"Master",NULL
+                 		; db	 4dh,  61h,  73h,  74h,  65h,  72h,  00h    ; uncompressed
+                 		  db	 53h,  67h,  79h,  7ah,  6bh, 0b8h          ; compressed
+
+g_szDetectSlave:		; db	"Slave ",NULL
+                		; db	 53h,  6ch,  61h,  76h,  65h,  20h,  00h    ; uncompressed
+                		  db	 59h,  72h,  67h,  7ch,  6bh,  00h          ; compressed
+
+g_szDetectOuter:		; db	"%s at %s: ",NULL
+                		; db	 25h,  73h,  20h,  61h,  74h,  20h,  25h,  73h,  3ah,  20h,  00h    ; uncompressed
+                		  db	 3dh,  20h,  67h, 0fah,  3dh,  40h,  00h                            ; compressed
+
+%ifdef MODULE_SERIAL
+g_szDetectCOM:			; db	"COM%c%s",NULL
+              			; db	 43h,  4fh,  4dh,  25h,  63h,  25h,  73h,  00h    ; uncompressed
+              			  db	 49h,  55h,  53h,  3ch,  1dh                      ; compressed
+
+g_szDetectCOMAuto:		; db	" Detect",NULL
+                  		; db	 20h,  44h,  65h,  74h,  65h,  63h,  74h,  00h    ; uncompressed
+                  		  db	 20h,  4ah,  6bh,  7ah,  6bh,  69h, 0bah          ; compressed
+
+g_szDetectCOMSmall:		; db	"/%u%u00",NULL					; IDE Master at COM1/9600:
+                   		; db	 2fh,  25h,  75h,  25h,  75h,  30h,  30h,  00h    ; uncompressed
+                   		  db	 2ah,  35h,  35h,  33h,  13h                      ; compressed
+
+g_szDetectCOMLarge:		; db	"/%u.%uK",NULL					; IDE Master at COM1/19.2K:
+                   		; db	 2fh,  25h,  75h,  2eh,  25h,  75h,  4bh,  00h    ; uncompressed
+                   		  db	 2ah,  35h,  29h,  35h,  91h                      ; compressed
+
+%endif
+g_szDetectEnd:
+g_szDetectPort:			; db	"%x",NULL						; IDE Master at 1F0h:
+               			; db	 25h,  78h,  00h    ; uncompressed
+               			  db	 17h                ; compressed
+
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if ((g_szDetectEnd-$$) & 0xff00) <> ((g_szDetectStart-$$) & 0xff00)
+%error "g_szDetect* strings must start on the same 256 byte page, required by DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP.  Please move this block up or down within Strings.asm"
+%endif
+%endif
+
+
+; POST drive detection strings
+g_szDashForZero:	; db	"- ",NULL	; Required by Display Library
+                	; db	 2dh,  20h,  00h    ; uncompressed
+                	  db	 28h,  00h          ; compressed
+
+g_szRomAt:			; db	LF,CR
+          			; db	 0ah,  0dh    ; uncompressed
+          			  db	 39h          ; compressed
+
+	; db	"%s @ %x",LF,CR						; -=XTIDE ... =- @ Segment
+	; db	 25h,  73h,  20h,  40h,  20h,  25h,  78h,  0ah,  0dh    ; uncompressed
+	  db	 3dh,  20h, 0c6h,  37h,  39h                            ; compressed
+
+	; db	"%s",LF,CR							; version string
+	; db	 25h,  73h,  0ah,  0dh    ; uncompressed
+	  db	 3dh,  39h                ; compressed
+
+	; db	"Released under GNU GPL v2",LF,CR
+	; db	 52h,  65h,  6ch,  65h,  61h,  73h,  65h,  64h,  20h,  75h,  6eh,  64h,  65h,  72h,  20h,  47h,  4eh,  55h,  20h,  47h,  50h,  4ch,  20h,  76h,  32h,  0ah,  0dh    ; uncompressed
+	  db	 58h,  6bh,  72h,  6bh,  67h,  79h,  6bh, 0eah,  7bh,  74h,  6ah,  6bh, 0f8h,  4dh,  54h, 0dbh,  4dh,  56h, 0d2h,  7ch,  2ch,  39h                                  ; compressed
+
+	; db	LF,CR,NULL
+	; db	 0ah,  0dh,  00h    ; uncompressed
+	  db	 19h                ; compressed
+
+%ifdef MODULE_BOOT_MENU
+g_szBootMenuTitle:	; db	"%s%c",LF,CR						; -=XTIDE ... =- and null (eaten)
+                  	; db	 25h,  73h,  25h,  63h,  0ah,  0dh    ; uncompressed
+                  	  db	 3dh,  3ch,  39h                      ; compressed
+
+	; db	"%s",NULL							; version string
+	; db	 25h,  73h,  00h    ; uncompressed
+	  db	 1dh                ; compressed
+
+%endif
+g_szDriveName:		; db	"%z",LF,CR,NULL
+              		; db	 25h,  7ah,  0ah,  0dh,  00h    ; uncompressed
+              		  db	 3eh,  19h                      ; compressed
+
+
+
+; Boot loader strings
+g_szTryToBoot:			; db	"Booting %c",ANGLE_QUOTE_RIGHT,"%c",LF,CR,NULL
+              			; db	 42h,  6fh,  6fh,  74h,  69h,  6eh,  67h,  20h,  25h,  63h, 0afh,  25h,  63h,  0ah,  0dh,  00h    ; uncompressed
+              			  db	 48h,  75h,  75h,  7ah,  6fh,  74h, 0edh,  3ch,  24h,  3ch,  19h                                  ; compressed
+
+g_szBootSectorNotFound:	; db	"Boot sector " 			; String fall through...
+                       	; db	 42h,  6fh,  6fh,  74h,  20h,  73h,  65h,  63h,  74h,  6fh,  72h,  20h    ; uncompressed
+                       	  db	 48h,  75h,  75h, 0fah,  79h,  6bh,  69h,  7ah,  75h, 0f8h                ; compressed
+
+g_szNotFound:			; db	"not found",LF,CR,NULL
+             			; db	 6eh,  6fh,  74h,  20h,  66h,  6fh,  75h,  6eh,  64h,  0ah,  0dh,  00h    ; uncompressed
+             			  db	 74h,  75h, 0fah,  6ch,  75h,  7bh,  74h,  6ah,  19h                      ; compressed
+
+g_szReadError:			; db	"Error %x!",LF,CR,NULL
+              			; db	 45h,  72h,  72h,  6fh,  72h,  20h,  25h,  78h,  21h,  0ah,  0dh,  00h    ; uncompressed
+              			  db	 4bh,  78h,  78h,  75h, 0f8h,  37h,  25h,  19h                            ; compressed
+
+
+
+%ifdef MODULE_HOTKEYS
+; Hotkey Bar strings
+g_szFDD:				; db	"FDD [%c]",NULL			; "FDD [A]"
+        				; db	 46h,  44h,  44h,  20h,  5bh,  25h,  63h,  5dh,  00h    ; uncompressed
+        				  db	 4ch,  4ah, 0cah,  61h,  3ch, 0a3h                      ; compressed
+
+g_szHDD:				; db	"HDD [%c]",NULL			; "HDD [C]"
+        				; db	 48h,  44h,  44h,  20h,  5bh,  25h,  63h,  5dh,  00h    ; uncompressed
+        				  db	 4eh,  4ah, 0cah,  61h,  3ch, 0a3h                      ; compressed
+
+%ifdef MODULE_BOOT_MENU
+g_szBootMenu:			; db	"BootMnu%c",NULL		; "BootMnu", location of %c doesn't matter
+             			; db	 42h,  6fh,  6fh,  74h,  4dh,  6eh,  75h,  25h,  63h,  00h    ; uncompressed
+             			  db	 48h,  75h,  75h,  7ah,  53h,  74h,  7bh,  1ch                ; compressed
+
+%endif ; MODULE_BOOT_MENU
+g_szHotkey:				; db	"%A%c%c%A%s%A ",NULL	; "C»HDD [A] ", "F2BootMnu " or "F8RomBoot "
+           				; db	 25h,  41h,  25h,  63h,  25h,  63h,  25h,  41h,  25h,  73h,  25h,  41h,  20h,  00h    ; uncompressed
+           				  db	 3bh,  3ch,  3ch,  3bh,  3dh,  3bh,  00h                                              ; compressed
+
+%ifdef MODULE_SERIAL
+g_szHotComDetect:		; db	"ComDtct%c",NULL		; "ComDtct", location of %c doesn't matter
+                 		; db	 43h,  6fh,  6dh,  44h,  74h,  63h,  74h,  25h,  63h,  00h    ; uncompressed
+                 		  db	 49h,  75h,  73h,  4ah,  7ah,  69h,  7ah,  1ch                ; compressed
+
+%endif ; MODULE_SERIAL
+%endif ; MODULE_HOTKEYS
+
+%ifdef MODULE_BOOT_MENU
+g_szRomBootDash:		; db	" -  "					; String fall through to g_szRomBoot
+                		; db	 20h,  2dh,  20h,  20h    ; uncompressed
+                		  db	 20h,  28h,  20h,  20h    ; compressed
+
+%endif
+%ifdef MODULE_HOTKEYS OR MODULE_BOOT_MENU
+g_szRomBoot:			; db	"Rom%cBoot",NULL		; "RomBoot" or "Rom Boot"
+            			; db	 52h,  6fh,  6dh,  25h,  63h,  42h,  6fh,  6fh,  74h,  00h    ; uncompressed
+            			  db	 58h,  75h,  73h,  3ch,  48h,  75h,  75h, 0bah                ; compressed
+
+%endif
+
+
+%ifdef MODULE_BOOT_MENU
+; Boot Menu Floppy Disk strings
+;
+; The following strings are used by BootMenuPrint_RefreshInformation
+; To support optimizations in that code, these strings must start on the same 256 byte page,
+; which is checked at assembly time below.
+;
+g_szFddStart:
+g_szFddUnknown:		; db	"Unknown",NULL
+               		; db	 55h,  6eh,  6bh,  6eh,  6fh,  77h,  6eh,  00h    ; uncompressed
+               		  db	 5bh,  74h,  71h,  74h,  75h,  7dh, 0b4h          ; compressed
+
+g_szFddSizeOr:		; db	"5",ONE_QUARTER,QUOTATION_MARK," or 3",ONE_HALF,QUOTATION_MARK," DD",NULL
+              		; db	 35h, 0ach,  22h,  20h,  6fh,  72h,  20h,  33h, 0abh,  22h,  20h,  44h,  44h,  00h    ; uncompressed
+              		  db	 2eh,  21h,  26h,  20h,  75h, 0f8h,  2dh,  22h,  26h,  20h,  4ah,  8ah                ; compressed
+
+g_szFddSize:		; db	"%s",QUOTATION_MARK,", %u kiB",NULL	; 3½", 1440 kiB
+            		; db	 25h,  73h,  22h,  2ch,  20h,  25h,  75h,  20h,  6bh,  69h,  42h,  00h    ; uncompressed
+            		  db	 3dh,  26h,  27h,  20h,  35h,  20h,  71h,  6fh,  88h                      ; compressed
+
+g_szFddThreeHalf:	; db	"3",ONE_HALF,NULL
+                 	; db	 33h, 0abh,  00h    ; uncompressed
+                 	  db	 2dh,  02h          ; compressed
+
+g_szFddEnd:
+g_szFddFiveQuarter:	; db	"5",ONE_QUARTER,NULL
+                   	; db	 35h, 0ach,  00h    ; uncompressed
+                   	  db	 2eh,  01h          ; compressed
+
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if ((g_szFddStart-$$) & 0xff00) <> ((g_szFddEnd-$$) & 0xff00)
+%error "g_szFdd* strings must start on the same 256 byte page, required by the BootMenuPrint_RefreshInformation routines for floppy drives.  Please move this block up or down within Strings.asm"
+%endif
+%endif
+
+
+g_szAddressingModes:
+g_szNORMAL:		; db	"NORMAL",NULL
+           		; db	 4eh,  4fh,  52h,  4dh,  41h,  4ch,  00h    ; uncompressed
+           		  db	 54h,  55h,  58h,  53h,  47h,  92h          ; compressed
+
+g_szLARGE:		; db	"LARGE ",NULL
+          		; db	 4ch,  41h,  52h,  47h,  45h,  20h,  00h    ; uncompressed
+          		  db	 52h,  47h,  58h,  4dh,  4bh,  00h          ; compressed
+
+g_szLBA:		; db	"LBA   ",NULL
+        		; db	 4ch,  42h,  41h,  20h,  20h,  20h,  00h    ; uncompressed
+        		  db	 52h,  48h, 0c7h,  20h,  00h                ; compressed
+
+g_szAddressingModes_Displacement equ (g_szLARGE - g_szAddressingModes)
+;
+; Ensure that addressing modes are correctly spaced in memory
+;
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if g_szNORMAL <> g_szAddressingModes
+%error "g_szAddressingModes Displacement Incorrect 1"
+%endif
+%if g_szLARGE <> g_szNORMAL + g_szAddressingModes_Displacement
+%error "g_szAddressingModes Displacement Incorrect 2"
+%endif
+%if g_szLBA <> g_szLARGE + g_szAddressingModes_Displacement
+%error "g_szAddressingModes Displacement Incorrect 3"
+%endif
+%endif
+
+
+g_szDeviceTypeValues:
+g_szDeviceTypeValues_16bit:		; db	" 16",NULL
+                           		; db	 20h,  31h,  36h,  00h    ; uncompressed
+                           		  db	 20h,  2bh,  0fh          ; compressed
+
+g_szDeviceTypeValues_32bit:		; db	" 32",NULL
+                           		; db	 20h,  33h,  32h,  00h    ; uncompressed
+                           		  db	 20h,  2dh,  0ch          ; compressed
+
+g_szDeviceTypeValues_8bit:		; db	"  8",NULL
+                          		; db	 20h,  20h,  38h,  00h    ; uncompressed
+                          		  db	 20h,  20h,  10h          ; compressed
+
+g_szDeviceTypeValues_XTIDEr1:	; db	"D8 ",NULL	; Dual 8-bit
+                             	; db	 44h,  38h,  20h,  00h    ; uncompressed
+                             	  db	 4ah,  30h,  00h          ; compressed
+
+g_szDeviceTypeValues_XTIDEr2:	; db	"X8 ",NULL	; A0<->A3 swapped 8-bit
+                             	; db	 58h,  38h,  20h,  00h    ; uncompressed
+                             	  db	 5eh,  30h,  00h          ; compressed
+
+g_szDeviceTypeValues_XTCFpio8:	; db	"T8 ",NULL	; True 8-bit
+                              	; db	 54h,  38h,  20h,  00h    ; uncompressed
+                              	  db	 5ah,  30h,  00h          ; compressed
+
+g_szDeviceTypeValues_XTCFdma:	; db	"8MA",NULL	; DMA 8-bit
+                             	; db	 38h,  4dh,  41h,  00h    ; uncompressed
+                             	  db	 30h,  53h,  87h          ; compressed
+
+g_szDeviceTypeValues_XTCFmem:	; db	"M8 ",NULL	; Memory Mapped 8-bit
+                             	; db	 4dh,  38h,  20h,  00h    ; uncompressed
+                             	  db	 53h,  30h,  00h          ; compressed
+
+g_szDeviceTypeValues_JrIde:		; db	"M8 ",NULL
+                           		; db	 4dh,  38h,  20h,  00h    ; uncompressed
+                           		  db	 53h,  30h,  00h          ; compressed
+
+g_szDeviceTypeValues_Serial:	; db	"SER",NULL
+                            	; db	 53h,  45h,  52h,  00h    ; uncompressed
+                            	  db	 59h,  4bh,  98h          ; compressed
+
+
+g_szDeviceTypeValues_Displacement equ (g_szDeviceTypeValues_32bit - g_szDeviceTypeValues)
+;
+; Ensure that device type strings are correctly spaced in memory
+;
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if g_szDeviceTypeValues_16bit <> g_szDeviceTypeValues
+%error "g_szDeviceTypeValues Displacement Incorrect 1"
+%endif
+%if g_szDeviceTypeValues_32bit <> g_szDeviceTypeValues_16bit + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 2"
+%endif
+%if g_szDeviceTypeValues_8bit <> g_szDeviceTypeValues_32bit + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 2"
+%endif
+%if g_szDeviceTypeValues_XTIDEr1 <> g_szDeviceTypeValues_8bit + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 3"
+%endif
+%if g_szDeviceTypeValues_XTIDEr2 <> g_szDeviceTypeValues_XTIDEr1 + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 4"
+%endif
+%if g_szDeviceTypeValues_XTCFpio8 <> g_szDeviceTypeValues_XTIDEr2 + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 5"
+%endif
+%if g_szDeviceTypeValues_XTCFdma <> g_szDeviceTypeValues_XTCFpio8 + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 6"
+%endif
+%if g_szDeviceTypeValues_XTCFmem <> g_szDeviceTypeValues_XTCFdma + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 7"
+%endif
+%if g_szDeviceTypeValues_JrIde <> g_szDeviceTypeValues_XTCFmem + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 8"
+%endif
+%if g_szDeviceTypeValues_Serial <> g_szDeviceTypeValues_JrIde + g_szDeviceTypeValues_Displacement
+%error "g_szDeviceTypeValues Displacement Incorrect 9"
+%endif
+%endif
+
+
+g_szSelectionTimeout:	; db	DOUBLE_BOTTOM_LEFT_CORNER,DOUBLE_LEFT_HORIZONTAL_TO_SINGLE_VERTICAL,"%ASelection in %2-u s",NULL
+                     	; db	0c8h, 0b5h,  25h,  41h,  53h,  65h,  6ch,  65h,  63h,  74h,  69h,  6fh,  6eh,  20h,  69h,  6eh,  20h,  25h,  32h,  2dh,  75h,  20h,  73h,  00h    ; uncompressed
+                     	  db	 31h,  32h,  3bh,  59h,  6bh,  72h,  6bh,  69h,  7ah,  6fh,  75h, 0f4h,  6fh, 0f4h,  3ah,  20h, 0b9h                                              ; compressed
+
+
+
+; Boot Menu information strings
+g_szCapacity:			; db	"Capacity : %s",NULL
+             			; db	 43h,  61h,  70h,  61h,  63h,  69h,  74h,  79h,  20h,  3ah,  20h,  25h,  73h,  00h    ; uncompressed
+             			  db	 49h,  67h,  76h,  67h,  69h,  6fh,  7ah, 0ffh, 0c0h,  1dh                            ; compressed
+
+g_szCapacityNum:		; db	"%5-u.%u %ciB",NULL
+                		; db	 25h,  35h,  2dh,  75h,  2eh,  25h,  75h,  20h,  25h,  63h,  69h,  42h,  00h    ; uncompressed
+                		  db	 36h,  29h,  35h,  20h,  3ch,  6fh,  88h                                        ; compressed
+
+g_szInformation:		; db	"%s",LF,CR
+                		; db	 25h,  73h,  0ah,  0dh    ; uncompressed
+                		  db	 3dh,  39h                ; compressed
+
+	; db	"Addr. ",SINGLE_VERTICAL,"Block",SINGLE_VERTICAL,"Bus",SINGLE_VERTICAL,"IRQ",SINGLE_VERTICAL,"Reset",LF,CR
+	; db	 41h,  64h,  64h,  72h,  2eh,  20h, 0b3h,  42h,  6ch,  6fh,  63h,  6bh, 0b3h,  42h,  75h,  73h, 0b3h,  49h,  52h,  51h, 0b3h,  52h,  65h,  73h,  65h,  74h,  0ah,  0dh    ; uncompressed
+	  db	 47h,  6ah,  6ah,  78h,  29h,  20h,  23h,  48h,  72h,  75h,  69h,  71h,  23h,  48h,  7bh,  79h,  23h,  4fh,  58h,  57h,  23h,  58h,  6bh,  79h,  6bh,  7ah,  39h          ; compressed
+
+	; db	"%s",SINGLE_VERTICAL,"%5-u",SINGLE_VERTICAL,"%s",SINGLE_VERTICAL," %2-I",SINGLE_VERTICAL,"%5-x",NULL
+	; db	 25h,  73h, 0b3h,  25h,  35h,  2dh,  75h, 0b3h,  25h,  73h, 0b3h,  20h,  25h,  32h,  2dh,  49h, 0b3h,  25h,  35h,  2dh,  78h,  00h    ; uncompressed
+	  db	 3dh,  23h,  36h,  23h,  3dh,  23h,  20h,  34h,  23h,  18h                                                                            ; compressed
+
+
+
+; Boot Menu menuitem strings
+;
+; The following strings are used by BootMenuPrint_* routines.
+; To support optimizations in that code, these strings must start on the same 256 byte page,
+; which is checked at assembly time below.
+;
+g_szDriveNumSpace:		; db	" "							; leading space, used if drive number is less than 0fh
+                  		; db	 20h    ; uncompressed
+                  		  db	 20h    ; compressed
+
+; must come immediately before g_szDriveNum!
+g_szBootMenuPrintStart:
+g_szDriveNum:			; db	"%x %s",NULL
+             			; db	 25h,  78h,  20h,  25h,  73h,  00h    ; uncompressed
+             			  db	 37h,  20h,  1dh                      ; compressed
+
+g_szDriveNumBNSpace:	; db	" "							; leading space, used if drive number is less than 0fh
+                    	; db	 20h    ; uncompressed
+                    	  db	 20h    ; compressed
+
+; must come immediately before g_szDriveNumBOOTNFO!
+g_szDriveNumBOOTNFO:	; db	"%x %z",NULL
+                    	; db	 25h,  78h,  20h,  25h,  7ah,  00h    ; uncompressed
+                    	  db	 37h,  20h,  1eh                      ; compressed
+
+g_szFloppyDrv:			; db	"Floppy Drive %c",NULL
+              			; db	 46h,  6ch,  6fh,  70h,  70h,  79h,  20h,  44h,  72h,  69h,  76h,  65h,  20h,  25h,  63h,  00h    ; uncompressed
+              			  db	 4ch,  72h,  75h,  76h,  76h, 0ffh,  4ah,  78h,  6fh,  7ch, 0ebh,  1ch                            ; compressed
+
+g_szBootMenuPrintEnd:
+g_szForeignHD:			; db	"Foreign Hard Disk",NULL
+              			; db	 46h,  6fh,  72h,  65h,  69h,  67h,  6eh,  20h,  48h,  61h,  72h,  64h,  20h,  44h,  69h,  73h,  6bh,  00h    ; uncompressed
+              			  db	 4ch,  75h,  78h,  6bh,  6fh,  6dh, 0f4h,  4eh,  67h,  78h, 0eah,  4ah,  6fh,  79h, 0b1h                      ; compressed
+
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if ((g_szBootMenuPrintStart-$$) & 0xff00) <> ((g_szBootMenuPrintEnd-$$) & 0xff00)
+%error "g_szBootMenuPrint* strings must start on the same 256 byte page, required by the BootMenuPrint_* routines.  Please move this block up or down within Strings.asm"
+%endif
+%if g_szDriveNumSpace+1 != g_szDriveNum || g_szDriveNumBNSpace+1 != g_szDriveNumBOOTNFO
+%error "g_szDriveNumSpace or g_szDriveNumBNSpace are out of position"
+%endif
+%endif
+
+%endif ; MODULE_BOOT_MENU
+
+
+;------------------------------------------------------------------------------------------
+;
+; Tables for StringsCompress.pl
+;
+; Items can be added and removed from this table as needed, with the following rules:
+;  * Formats follow the special characters.  But other than that, order makes no difference.
+;  * Some of the formats require "even" and "odd" numbering.  Even tells the code that
+;    it is a "number-" format, otherwise it doesn't interpret a number first.  The easiest
+;    way to maintain this is to move one of the "n/a" items to/from the front of the format
+;    list to maintain the even/odd.
+;  * Values do not need to remain consistent across versions.  This table is only used
+;    internally to this file.
+;  * There can only be 32 of these (0-31).
+;  * Keeping the list short is good - this translates to a table in the compressed version.
+;    An error will be reported if a character or format is no longer being used by any
+;    strings above.
+;  * Please keep items sequential for ease of further editing.
+;
+;$translate{ord(' ')} = 0;    [StringsCompress Processed]
+;$translate{172}      = 1;     # ONE_QUARTER    [StringsCompress Processed]
+;$translate{171}      = 2;     # ONE_HALF    [StringsCompress Processed]
+;$translate{179}      = 3;     # SINGLE_VERTICAL    [StringsCompress Processed]
+;$translate{175}      = 4;     # ANGLE_QUOTE_RIGHT    [StringsCompress Processed]
+;$translate{ord('!')} = 5;    [StringsCompress Processed]
+;$translate{ord('"')} = 6;    [StringsCompress Processed]
+;$translate{ord(',')} = 7;    [StringsCompress Processed]
+;$translate{ord('-')} = 8;    [StringsCompress Processed]
+;$translate{ord('.')} = 9;    [StringsCompress Processed]
+;$translate{ord('/')} = 10;    [StringsCompress Processed]
+;$translate{ord('1')} = 11;    [StringsCompress Processed]
+;$translate{ord('2')} = 12;    [StringsCompress Processed]
+;$translate{ord('3')} = 13;    [StringsCompress Processed]
+;$translate{ord('5')} = 14;    [StringsCompress Processed]
+;$translate{ord('6')} = 15;    [StringsCompress Processed]
+;$translate{ord('8')} = 16;    [StringsCompress Processed]
+;$translate{200}      = 17;    # DOUBLE_BOTTOM_LEFT_CORNER    [StringsCompress Processed]
+;$translate{181}      = 18;    # DOUBLE_LEFT_HORIZONTAL_TO_SINGLE_VERTICAL    [StringsCompress Processed]
+;$translate{ord('0')} = 19;    [StringsCompress Processed]
+;
+; Formats begin immediately after the last Translated character (they are in the same table)
+;
+;$format_begin = 20;    [StringsCompress Processed]
+;
+;$format{"2-I"} = 20;        # must be even    [StringsCompress Processed]
+;$format{"u"}   = 21;        # must be odd    [StringsCompress Processed]
+;$format{"5-u"} = 22;        # must be even    [StringsCompress Processed]
+;$format{"x"}   = 23;        # must be odd    [StringsCompress Processed]
+;$format{"5-x"} = 24;        # must be even    [StringsCompress Processed]
+;$format{"nl"}  = 25;        # n/a    [StringsCompress Processed]
+;$format{"2-u"} = 26;        # must be even    [StringsCompress Processed]
+;$format{"A"}   = 27;        # n/a    [StringsCompress Processed]
+;$format{"c"}   = 28;        # n/a    [StringsCompress Processed]
+;$format{"s"}   = 29;        # n/a, normal string from DS    [StringsCompress Processed]
+;$format{"z"}   = 30;        # n/a, boot string from BDA    [StringsCompress Processed]
+;
+; NOTE: The last $format cannot exceed 31 (stored in a 5-bit quantity).
+;
+; Starting point for the "normal" range, typically around 0x40 to cover upper and lower case
+; letters.  If lower case 'z' is not used, 0x3a can be a good choice as it adds ':' to the
+; front end.
+;
+;$normal_base = 0x3a;    [StringsCompress Processed]
+;
+; End of StringsCompress.pl information
+;
+;;; end of input stream
+
+%endif ; STRINGSCOMPRESSED_STRINGS
+
+%ifdef STRINGSCOMPRESSED_TABLES
+
+StringsCompressed_NormalBase     equ   58
+
+StringsCompressed_FormatsBegin   equ   20
+
+StringsCompressed_TranslatesAndFormats: 
+        db     32  ; 0
+        db     172  ; 1
+        db     171  ; 2
+        db     179  ; 3
+        db     175  ; 4
+        db     33  ; 5
+        db     34  ; 6
+        db     44  ; 7
+        db     45  ; 8
+        db     46  ; 9
+        db     47  ; 10
+        db     49  ; 11
+        db     50  ; 12
+        db     51  ; 13
+        db     53  ; 14
+        db     54  ; 15
+        db     56  ; 16
+        db     200  ; 17
+        db     181  ; 18
+        db     48  ; 19
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_2_I)    ; 20
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_u)    ; 21
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_5_u)    ; 22
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_x)    ; 23
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_5_x)    ; 24
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_nl)    ; 25
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_2_u)    ; 26
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_A)    ; 27
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_c)    ; 28
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_s)    ; 29
+        db     (DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_z)    ; 30
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_2_I || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_2_I > 255
+%error "DisplayFormatCompressed_Format_2_I is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_u || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_u > 255
+%error "DisplayFormatCompressed_Format_u is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_5_u || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_5_u > 255
+%error "DisplayFormatCompressed_Format_5_u is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_x || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_x > 255
+%error "DisplayFormatCompressed_Format_x is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_5_x || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_5_x > 255
+%error "DisplayFormatCompressed_Format_5_x is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_nl || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_nl > 255
+%error "DisplayFormatCompressed_Format_nl is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_2_u || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_2_u > 255
+%error "DisplayFormatCompressed_Format_2_u is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_A || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_A > 255
+%error "DisplayFormatCompressed_Format_A is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_c || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_c > 255
+%error "DisplayFormatCompressed_Format_c is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_s || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_s > 255
+%error "DisplayFormatCompressed_Format_s is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%if DisplayFormatCompressed_BaseFormatOffset < DisplayFormatCompressed_Format_z || DisplayFormatCompressed_BaseFormatOffset - DisplayFormatCompressed_Format_z > 255
+%error "DisplayFormatCompressed_Format_z is out of range of DisplayFormatCompressed_BaseFormatOffset"
+%endif
+%endif
+
+;; translated usage stats
+;; 33:1
+;; 32:34
+;; 181:1
+;; 53:2
+;; 48:2
+;; 200:1
+;; 46:3
+;; 179:8
+;; 44:1
+;; 50:2
+;; 51:3
+;; 47:2
+;; 172:2
+;; 34:3
+;; 49:1
+;; 56:7
+;; 45:2
+;; 175:1
+;; 171:2
+;; 54:1
+;; total translated: 20
+
+;; format usage stats
+;; A:4
+;; 2-u:1
+;; 5-u:2
+;; x:5
+;; s:14
+;; 5-x:1
+;; nl:12
+;; 2-I:1
+;; u:6
+;; c:13
+;; z:2
+;; total format: 11
+
+;; alphabet usage stats
+;; 58,::2
+;; 59,;:
+;; 60,<:
+;; 61,=:
+;; 62,>:
+;; 63,?:
+;; 64,@:1
+;; 65,A:5
+;; 66,B:9
+;; 67,C:3
+;; 68,D:11
+;; 69,E:3
+;; 70,F:3
+;; 71,G:3
+;; 72,H:2
+;; 73,I:1
+;; 74,J:
+;; 75,K:1
+;; 76,L:4
+;; 77,M:7
+;; 78,N:2
+;; 79,O:2
+;; 80,P:1
+;; 81,Q:1
+;; 82,R:7
+;; 83,S:3
+;; 84,T:1
+;; 85,U:2
+;; 86,V:
+;; 87,W:
+;; 88,X:1
+;; 89,Y:
+;; 90,Z:
+;; 91,[:2
+;; 92,\:
+;; 93,]:2
+;; 94,^:
+;; 95,_:
+;; 96,`:
+;; 97,a:7
+;; 98,b:
+;; 99,c:6
+;; 100,d:6
+;; 101,e:15
+;; 102,f:1
+;; 103,g:2
+;; 104,h:
+;; 105,i:9
+;; 106,j:
+;; 107,k:4
+;; 108,l:5
+;; 109,m:2
+;; 110,n:11
+;; 111,o:20
+;; 112,p:3
+;; 113,q:
+;; 114,r:11
+;; 115,s:7
+;; 116,t:15
+;; 117,u:4
+;; 118,v:3
+;; 119,w:1
+;; 120,x:
+;; 121,y:2
+;; alphabet used count: 45
+%endif ; STRINGSCOMPRESSED_TABLES
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AccessDPT.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AccessDPT.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AccessDPT.asm	(revision 516)
@@ -0,0 +1,204 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for accessing DPT data.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; AccessDPT_GetDriveSelectByteForOldInt13hToAL
+; AccessDPT_GetDriveSelectByteForEbiosToAL
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		AL:		Drive Select Byte
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AccessDPT_GetDriveSelectByteForOldInt13hToAL:
+	mov		al, [di+DPT.bFlagsLow]
+	test	al, FLGL_DPT_ASSISTED_LBA
+	jnz		SHORT GetDriveSelectByteForAssistedLBAtoAL
+
+	and		al, FLG_DRVNHEAD_DRV	; Clear all but drive select bit
+	or		al, MASK_DRVNHEAD_SET	; Bits set to 1 for old drives
+	ret
+
+%ifdef MODULE_EBIOS
+ALIGN JUMP_ALIGN
+AccessDPT_GetDriveSelectByteForEbiosToAL:
+	mov		al, [di+DPT.bFlagsLow]
+	; Fall to GetDriveSelectByteForAssistedLBAtoAL
+%endif ; MODULE_EBIOS
+
+ALIGN JUMP_ALIGN
+GetDriveSelectByteForAssistedLBAtoAL:
+	and		al, FLG_DRVNHEAD_DRV	; Master / Slave select
+	or		al, FLG_DRVNHEAD_LBA | MASK_DRVNHEAD_SET
+	ret
+
+
+;--------------------------------------------------------------------
+; AccessDPT_GetDeviceControlByteToAL
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		AL:		Device Control Byte
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AccessDPT_GetDeviceControlByteToAL:
+%ifdef MODULE_IRQ
+
+%ifndef USE_UNDOC_INTEL
+	xor		al, al
+%endif
+
+	test	BYTE [di+DPT.bFlagsLow], FLGL_DPT_ENABLE_IRQ	; Clears CF
+
+%ifdef USE_UNDOC_INTEL
+	eSALC	; Clears AL using CF while preserving flags
+%endif
+
+	jnz		SHORT .EnableDeviceIrq
+	or		al, FLG_DEVCONTROL_nIEN	; Disable IRQ
+.EnableDeviceIrq:
+%else
+	mov		al, FLG_DEVCONTROL_nIEN	; Disable IRQ
+%endif ; MODULE_IRQ
+	ret
+
+
+;--------------------------------------------------------------------
+; AccessDPT_GetLCHStoAXBLBH
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		AX:		Number of L-CHS cylinders
+;		BL:		Number of L-CHS heads
+;		BH:		Number of L-CHS sectors per track
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AccessDPT_GetLCHStoAXBLBH:
+	mov		ax, [di+DPT.wLchsCylinders]
+	mov		bx, [di+DPT.wLchsHeadsAndSectors]
+	ret
+
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+;--------------------------------------------------------------------
+; AccessDPT_IsThisDeviceXTCF
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		AH:		Device Type
+;		ZF:		Set if XTCF
+;				Cleared if some other device
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AccessDPT_IsThisDeviceXTCF:
+	mov		ah, [di+DPT_ATA.bDevice]
+	cmp		ah, DEVICE_8BIT_XTCF_PIO8
+	je		SHORT .DeviceIsXTCF
+	cmp		ah, DEVICE_8BIT_XTCF_DMA
+	je		SHORT .DeviceIsXTCF
+	cmp		ah, DEVICE_8BIT_XTCF_MEMMAP
+.DeviceIsXTCF:
+	ret
+%endif ; MODULE_8BIT_IDE_ADVANCED
+
+
+%ifdef MODULE_EBIOS
+;--------------------------------------------------------------------
+; AccessDPT_GetLbaSectorCountToBXDXAX
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		BX:DX:AX:	48-bit sector count
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AccessDPT_GetLbaSectorCountToBXDXAX:
+	mov		ax, [di+DPT.twLbaSectors]
+	mov		dx, [di+DPT.twLbaSectors+2]
+	mov		bx, [di+DPT.twLbaSectors+4]
+	ret
+%endif ; MODULE_EBIOS
+
+
+;--------------------------------------------------------------------
+; Returns pointer to DRVPARAMS for master or slave drive.
+;
+; AccessDPT_GetPointerToDRVPARAMStoCSBX
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		CS:BX:	Ptr to DRVPARAMS
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AccessDPT_GetPointerToDRVPARAMStoCSBX:
+	call	AccessDPT_GetIdevarsToCSBX
+	add		bx, BYTE IDEVARS.drvParamsMaster	; CS:BX points to Master Drive DRVPARAMS
+	test	BYTE [di+DPT.bFlagsLow], FLGL_DPT_SLAVE
+	jz		SHORT .ReturnPointerToDRVPARAMS
+	add		bx, BYTE DRVPARAMS_size				; CS:BX points to Slave Drive DRVPARAMS
+.ReturnPointerToDRVPARAMS:
+	ret
+
+
+;--------------------------------------------------------------------
+; Needed many times during initialization so it is better to
+; make it as a function to save bytes.
+;
+; AccessDPT_GetIdevarsToCSBX
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		CS:BX:	Ptr to IDEVARS for the drive
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AccessDPT_GetIdevarsToCSBX:
+	eMOVZX	bx, BYTE [di+DPT.bIdevarsOffset]
+	ret
+
+
+;--------------------------------------------------------------------
+; ACCESSDPT__GET_UNSHIFTED_TRANSLATE_MODE_TO_AXZF
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		AX:		Translate Mode (TRANSLATEMODE_NORMAL, TRANSLATEMODE_LARGE or TRANSLATEMODE_ASSISTED_LBA)
+;               unshifted (still shifted where it is in bFlagsLow)
+;       ZF:     Set based on value in AL
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+;
+; Converted to a macro since only called in two places, and the call/ret overhead
+; is not worth it for these two instructions (4 bytes total)
+;
+%macro ACCESSDPT__GET_UNSHIFTED_TRANSLATE_MODE_TO_AXZF 0
+	mov		al, [di+DPT.bFlagsLow]
+	and		ax, BYTE MASKL_DPT_TRANSLATEMODE
+%endmacro
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AtaGeometry.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AtaGeometry.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AtaGeometry.asm	(revision 516)
@@ -0,0 +1,316 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for generating L-CHS parameters for
+;					drives with more than 1024 cylinders.
+;
+; 					These algorithms are taken from: http://www.mossywell.com/boot-sequence
+; 					Take a look at it for more detailed information.
+;
+;					This file is shared with BIOS Drive Information Tool.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+%ifdef MODULE_EBIOS
+;--------------------------------------------------------------------
+; AtaGeometry_GetLbaSectorCountToBXDXAXfromAtaInfoInESSI
+;	Parameters:
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		BX:DX:AX:	48-bit sector count
+;		CL:			FLGL_DPT_LBA48 if LBA48 supported
+;					Zero if only LBA28 is supported
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AtaGeometry_GetLbaSectorCountToBXDXAXfromAtaInfoInESSI:
+	mov		bx, Registers_ExchangeDSSIwithESDI
+	call	bx	; ATA info now in DS:DI
+	push	bx	; We will return via Registers_ExchangeDSSIwithESDI
+
+	; Check if LBA48 supported
+	test	BYTE [di+ATA6.wSetSup83+1], A6_wSetSup83_LBA48>>8
+	jz		SHORT .GetLba28SectorCount
+
+	; Get LBA48 sector count
+	mov		cl, FLGL_DPT_LBA48
+	mov		ax, [di+ATA6.qwLBACnt]
+	mov		dx, [di+ATA6.qwLBACnt+2]
+	mov		bx, [di+ATA6.qwLBACnt+4]
+	ret
+
+.GetLba28SectorCount:
+	xor		cl, cl
+	xor		bx, bx
+	mov		ax, [di+ATA1.dwLBACnt]
+	mov		dx, [di+ATA1.dwLBACnt+2]
+	ret
+%endif	; MODULE_EBIOS
+
+
+;--------------------------------------------------------------------
+; AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSIandTranslateModeInDX
+; AtaGeometry_GetLCHStoAXBLBHfromPCHSinAXBLBHandTranslateModeInDX
+;	Parameters:
+;		DX:		Wanted translate mode or TRANSLATEMODE_AUTO to autodetect
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		AX:		Number of L-CHS cylinders (1...1027, yes 1027)
+;		BL:		Number of L-CHS heads (1...255)
+;		BH:		Number of L-CHS sectors per track (1...63)
+;		CX:		Number of bits shifted (0...3)
+;		DL:		CHS Translate Mode
+;	Corrupts registers:
+;		DH
+;--------------------------------------------------------------------
+AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSIandTranslateModeInDX:
+	call	AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
+	; Fall to AtaGeometry_GetLCHStoAXBLBHfromPCHSinAXBLBHandTranslateModeInDX
+
+AtaGeometry_GetLCHStoAXBLBHfromPCHSinAXBLBHandTranslateModeInDX:
+	; Check if user defined translate mode
+	dec		dx						; Set ZF if TRANSLATEMODE_LARGE, SF if TRANSLATEMODE_NORMAL
+	jns		SHORT .CheckIfLargeTranslationWanted
+	MIN_U	ax, MAX_LCHS_CYLINDERS	; TRANSLATEMODE_NORMAL maximum cylinders
+	inc		dx
+.CheckIfLargeTranslationWanted:
+	jz		SHORT ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL
+	dec		dx						; Set ZF if TRANSLATEMODE_ASSISTED_LBA
+	jz		SHORT .UseAssistedLBA
+	; TRANSLATEMODE_AUTO set
+
+	; Generate L-CHS using simple bit shift algorithm (ECHS) if
+	; 8192 or less cylinders.
+	cmp		ax, 8192
+	jbe		SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
+
+	; We have 8193 or more cylinders so two algorithms are available:
+	; Revised ECHS or Assisted LBA. The Assisted LBA provides larger
+	; capacity but requires LBA support from drive (drives this large
+	; always support LBA but user might have unintentionally set LBA).
+.UseAssistedLBA:
+	test	BYTE [es:si+ATA1.wCaps+1], A1_wCaps_LBA>>8
+	jz		SHORT ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL
+
+	; Drive supports LBA
+	call	GetSectorCountToDXAXfromCHSinAXBLBH
+	call	ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH
+	xor		cx, cx		; No bits to shift
+	mov		dl, TRANSLATEMODE_ASSISTED_LBA
+	ret
+
+
+;--------------------------------------------------------------------
+; AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
+;	Parameters:
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		AX:		Number of P-CHS cylinders (1...16383)
+;		BL:		Number of P-CHS heads (1...16)
+;		BH:		Number of P-CHS sectors per track (1...63)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI:
+	mov		ax, [es:si+ATA1.wCylCnt]	; Cylinders (1...16383)
+	mov		bl, [es:si+ATA1.wHeadCnt]	; Heads (1...16)
+	mov		bh, [es:si+ATA1.wSPT]		; Sectors per Track (1...63)
+	ret
+
+
+;--------------------------------------------------------------------
+; GetSectorCountToDXAXfromCHSinAXBLBH
+;	Parameters:
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		AX:		Number of cylinders (1...16383)
+;		BL:		Number of heads (1...255)
+;		BH:		Number of sectors per track (1...63)
+;	Returns:
+;		DX:AX:	Total number of CHS addressable sectors
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+GetSectorCountToDXAXfromCHSinAXBLBH:
+	xchg	ax, bx
+	mul		ah			; AX = Heads * Sectors per track
+	mul		bx
+	ret
+
+
+;--------------------------------------------------------------------
+; Revised Enhanced CHS calculation (Revised ECHS)
+;
+; This algorithm translates P-CHS sector count to L-CHS sector count
+; with bit shift algorithm. Since 256 heads are not allowed
+; (DOS limit), this algorithm makes translations so that maximum of
+; 240 L-CHS heads can be used. This makes the maximum addressable capacity
+; to 7,927,234,560 bytes ~ 7.38 GiB. LBA addressing needs to be used to
+; get more capacity.
+;
+; L-CHS parameters generated here require the drive to use CHS addressing.
+;
+; Here is the algorithm:
+; If cylinders > 8192 and heads = 16
+;  Heads = 15
+;  Cylinders = cylinders * 16 / 15 (losing the fraction component)
+;  Do a standard ECHS translation
+;
+; ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
+;	Parameters:
+;		AX:		Number of P-CHS cylinders (8193...16383)
+;		BL:		Number of P-CHS heads (1...16)
+;	Returns:
+;		AX:		Number of L-CHS cylinders (?...1024)
+;		BL:		Number of L-CHS heads (?...240)
+;		CX:		Number of bits shifted (0...3)
+;		DL:		ADDRESSING_MODE_NORMAL or ADDRESSING_MODE_LARGE
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
+	; Generate L-CHS using simple bit shift algorithm (ECHS) if
+	; 8192 or less cylinders
+	cmp		ax, 8192
+	jbe		SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
+	cmp		bl, 16	; Drives with 8193 or more cylinders can report 15 heads
+	jb		SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
+
+	eMOVZX	cx, bl	; CX = 16
+	dec		bx		; Heads = 15
+	mul		cx		; DX:AX = Cylinders * 16
+	dec		cx		; CX = 15
+	div		cx		; AX = (Cylinders * 16) / 15
+	; Fall to ConvertPCHfromAXBXtoEnhancedCHinAXBX
+
+
+;--------------------------------------------------------------------
+; Enhanced CHS calculation (ECHS)
+;
+; This algorithm translates P-CHS sector count to L-CHS sector count
+; with simple bit shift algorithm. Since 256 heads are not allowed
+; (DOS limit), this algorithm require that there are at most 8192
+; P-CHS cylinders. This makes the maximum addressable capacity
+; to 4,227,858,432 bytes ~ 3.94 GiB. Use Revised ECHS or Assisted LBA
+; algorithms if there are more than 8192 P-CHS cylinders.
+;
+; L-CHS parameters generated here require the drive to use CHS addressing.
+;
+; Here is the algorithm:
+;  Multiplier = 1
+;  Cylinder = Cylinder - 1
+;  Is Cylinder < 1024? If not:
+;  Do a right bitwise rotation on the cylinder (i.e., divide by 2)
+;  Do a left bitwise rotation on the multiplier (i.e., multiply by 2)
+;  Use the multiplier on the Cylinder and Head values to obtain the translated values.
+;
+; ConvertPCHfromAXBLtoEnhancedCHinAXBL:
+;	Parameters:
+;		AX:		Number of P-CHS cylinders (1...8192)
+;		BL:		Number of P-CHS heads (1...16)
+;	Returns:
+;		AX:		Number of L-CHS cylinders (?...1024)
+;		BL:		Number of L-CHS heads (?...128)
+;		CX:		Number of bits shifted (0...3)
+;		DL:		TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ConvertPCHfromAXBLtoEnhancedCHinAXBL:
+	xor		cx, cx		; No bits to shift initially
+	xor		dl, dl		; Assume TRANSLATEMODE_NORMAL
+.ShiftIfMoreThan1024Cylinder:
+	cmp		ax, MAX_LCHS_CYLINDERS
+	jbe		SHORT ReturnLCHSinAXBLBH
+	shr		ax, 1		; Halve cylinders
+	eSHL_IM	bl, 1		; Double heads
+	inc		cx			; Increment bit shift count
+	mov		dl, TRANSLATEMODE_LARGE
+	jmp		SHORT .ShiftIfMoreThan1024Cylinder
+
+
+;--------------------------------------------------------------------
+; LBA assist calculation (or Assisted LBA)
+;
+; This algorithm translates P-CHS sector count up to largest possible
+; L-CHS sector count (1024, 255, 63). Note that INT 13h interface allows
+; 256 heads but DOS supports up to 255 head. That is why BIOSes never
+; use 256 heads.
+;
+; L-CHS parameters generated here require the drive to use LBA addressing.
+;
+; Here is the algorithm:
+; If cylinders > 8192
+;  Variable CH = Total CHS Sectors / 63
+;  Divide (CH  1) by 1024 and add 1
+;  Round the result up to the nearest of 16, 32, 64, 128 and 255. This is the value to be used for the number of heads.
+;  Divide CH by the number of heads. This is the value to be used for the number of cylinders.
+;
+; ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
+;	Parameters:
+;		DX:AX:	Total number of P-CHS sectors for CHS addressing
+;				(max = 16383 * 16 * 63 = 16,514,064)
+;	Returns:
+;		AX:		Number of cylinders (?...1027)
+;		BL:		Number of heads (16, 32, 64, 128 or 255)
+;		BH:		Number of sectors per track (always 63)
+;	Corrupts registers:
+;		CX, DX
+;--------------------------------------------------------------------
+ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
+	; Value CH = Total sector count / 63
+	; Max = 16,514,064 / 63 = 262128
+	mov		cx, LBA_ASSIST_SPT			; CX = 63
+	call	Math_DivDXAXbyCX
+	push	dx
+	push	ax							; Value CH stored for later use
+
+	; BX:DX:AX = Value CH - 1
+	; Max = 262128 - 1 = 262127
+	xor		bx, bx
+	sub		ax, BYTE 1
+	sbb		dx, bx
+
+	; AX = Number of heads = ((Value CH - 1) / 1024) + 1
+	; Max = (262127 / 1024) + 1 = 256
+	push	si
+	call	Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
+	pop		si
+	inc		ax							; + 1
+
+	; Heads must be 16, 32, 64, 128 or 255 (round up to the nearest)
+	; Max = 255
+	mov		cx, 16						; Min number of heads
+.CompareNextValidNumberOfHeads:
+	cmp		ax, cx
+	jbe		SHORT .NumberOfHeadsNowInCX
+	eSHL_IM	cl, 1						; Double number of heads
+	jnz		SHORT .CompareNextValidNumberOfHeads	; Reached 256 heads?
+	dec		cl							;  If so, limit heads to 255
+.NumberOfHeadsNowInCX:
+	mov		bx, cx						; Number of heads are returned in BL
+	mov		bh, LBA_ASSIST_SPT			; Sectors per Track
+
+	; DX:AX = Number of cylinders = Value CH (without - 1) / number of heads
+	; Max = 262128 / 255 = 1027
+	pop		ax
+	pop		dx							; Value CH back to DX:AX
+	div		cx
+
+	; Return L-CHS
+ReturnLCHSinAXBLBH:
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootVars.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootVars.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootVars.asm	(revision 516)
@@ -0,0 +1,73 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for accessings BOOTVARS.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; BootVars_Initialize
+;	Parameters:
+;		DS:		RAMVARS Segment
+;		ES:		BDA Segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, DI
+;--------------------------------------------------------------------
+BootVars_Initialize:
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	mov		WORD [es:BOOTVARS.wNextXTCFportToScan], XTCF_BASE_PORT_DETECTION_SEED
+%endif
+
+	; Clear to zero
+	mov		al, DRVDETECTINFO_size
+	mul		BYTE [cs:ROMVARS.bIdeCnt]
+	mov		di, BOOTVARS.clearToZeroFromThisPoint	; We must not initialize anything before this!
+	add		ax, BOOTVARS_size
+	sub		ax, di
+	xchg	cx, ax
+
+%ifdef MODULE_HOTKEYS
+	call	Memory_ZeroESDIwithSizeInCX
+
+	; Store default drives to boot from
+	mov		dl, [cs:ROMVARS.bBootDrv]
+
+	; fall through to BootVars_StoreHotkeyForDriveNumberInDL
+
+;--------------------------------------------------------------------
+; BootVars_StoreHotkeyForDriveNumberInDL
+;	Parameters:
+;		DL:		Floppy or Hard Drive number
+;		DS:		RAMVARS Segment
+;		ES:		BDA Segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+BootVars_StoreHotkeyForDriveNumberInDL:
+	mov		WORD [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wFddAndHddLetters], DEFAULT_FLOPPY_DRIVE_LETTER | (DEFAULT_HARD_DRIVE_LETTER<<8)
+	call	DriveXlate_ConvertDriveNumberFromDLtoDriveLetter
+	jmp		HotkeyBar_StoreHotkeyToBootvarsForDriveLetterInDL
+
+%else
+	jmp		Memory_ZeroESDIwithSizeInCX
+
+%endif ; MODULE_HOTKEYS
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/CreateDPT.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/CreateDPT.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/CreateDPT.asm	(revision 516)
@@ -0,0 +1,310 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for creating Disk Parameter Table.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Creates new Disk Parameter Table for detected hard disk.
+; Drive is then fully accessible using any BIOS function.
+;
+; CreateDPT_FromAtaInformation
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Register
+;		DX:		Autodetected port (for devices that support autodetection)
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;		DS:		RAMVARS segment
+;		ES:		BDA Segment
+;	Returns:
+;		DS:DI:	Ptr to Disk Parameter Table (if successful)
+;		CF:		Cleared if DPT created successfully
+;				Set if any error
+;	Corrupts registers:
+;		AX, BX, CX, DH
+;--------------------------------------------------------------------
+CreateDPT_FromAtaInformation:
+	call	FindDPT_ForNewDriveToDSDI
+	; Fall to .InitializeDPT
+
+;--------------------------------------------------------------------
+; .InitializeDPT
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Register
+;		DX:		Autodetected port (for devices that support autodetection)
+;		DS:DI:	Ptr to Disk Parameter Table
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.InitializeDPT:
+	call	CreateDPT_StoreIdevarsOffsetAndBasePortFromCSBPtoDPTinDSDI
+	; Fall to .StoreDriveSelectAndDriveControlByte
+
+;--------------------------------------------------------------------
+; .StoreDriveSelectAndDriveControlByte
+;	Parameters:
+;		BH:		Drive Select byte for Drive and Head Register
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.StoreDriveSelectAndDriveControlByte:
+	mov		al, bh
+	and		ax, BYTE FLG_DRVNHEAD_DRV		; AL now has Master/Slave bit
+%ifdef MODULE_IRQ
+	cmp		[cs:bp+IDEVARS.bIRQ], ah		; Interrupts enabled?
+	jz		SHORT .StoreFlags				;  If not, do not set interrupt flag
+	or		al, FLGL_DPT_ENABLE_IRQ
+.StoreFlags:
+%endif
+	mov		[di+DPT.wFlags], ax
+	; Fall to .StoreCHSparametersAndAddressingMode
+
+;--------------------------------------------------------------------
+; .StoreCHSparametersAndAddressingMode
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+.StoreCHSparametersAndAddressingMode:
+	; Check if CHS defined in ROMVARS
+	call	GetUserDefinedCapacityToBXAXandFlagsToCXandModeToDXfromROMVARS
+	test	cl, FLG_DRVPARAMS_USERCHS
+	jz		SHORT .AutodetectPCHSvalues
+
+	; Translate P-CHS to L-CHS
+	call	AtaGeometry_GetLCHStoAXBLBHfromPCHSinAXBLBHandTranslateModeInDX
+	jmp		SHORT .StoreLCHStoDPT
+.AutodetectPCHSvalues:
+	call	AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSIandTranslateModeInDX
+
+.StoreLCHStoDPT:
+	eSHL_IM	dl, TRANSLATEMODE_FIELD_POSITION
+	or		cl, dl
+	or		[di+DPT.bFlagsLow], cl		; Shift count and addressing mode
+	mov		[di+DPT.wLchsCylinders], ax
+	mov		[di+DPT.wLchsHeadsAndSectors], bx
+
+	; Store P-CHS to DPT
+	call	AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
+	mov		[di+DPT.bPchsHeads], bl
+%ifdef MODULE_EBIOS
+	mov		[di+DPT.wPchsCylinders], ax
+	mov		[di+DPT.bPchsSectorsPerTrack], bh
+	; Fall to .StoreNumberOfLbaSectors
+
+;--------------------------------------------------------------------
+; .StoreNumberOfLbaSectors
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+	; Check if LBA supported
+	test	BYTE [es:si+ATA1.wCaps+1], A1_wCaps_LBA>>8
+	jz		SHORT .NoLbaSupportedSoNoEBIOS
+
+	; Store LBA 28/48 total sector count
+	call	AtaGeometry_GetLbaSectorCountToBXDXAXfromAtaInfoInESSI
+	call	StoreLba48AddressingFromCLandTotalSectorCountFromBXDXAX
+
+	; Load user defined LBA
+	call	GetUserDefinedCapacityToBXAXandFlagsToCXandModeToDXfromROMVARS
+	test	cl, FLG_DRVPARAMS_USERLBA
+	jz		SHORT .KeepTotalSectorsFromAtaID
+
+	; Compare user defined and ATA-ID sector count and select smaller
+	mov		dx, bx
+	xor		bx, bx		; User defined LBA now in BX:DX:AX
+	cmp		bx, [di+DPT.twLbaSectors+4]
+	jb		SHORT .StoreUserDefinedSectorCountToDPT
+	cmp		dx, [di+DPT.twLbaSectors+2]
+	jb		SHORT .StoreUserDefinedSectorCountToDPT
+	ja		SHORT .KeepTotalSectorsFromAtaID
+	cmp		ax, [di+DPT.twLbaSectors]
+	jae		SHORT .KeepTotalSectorsFromAtaID
+.StoreUserDefinedSectorCountToDPT:
+	; CL bit FLGL_DPT_LBA48 is clear at this point
+	call	StoreLba48AddressingFromCLandTotalSectorCountFromBXDXAX
+
+.KeepTotalSectorsFromAtaID:
+.NoLbaSupportedSoNoEBIOS:
+%endif ; MODULE_EBIOS
+	; Fall to .StoreBlockMode
+
+;--------------------------------------------------------------------
+; .StoreBlockMode
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+.StoreBlockMode:
+	cmp		BYTE [es:si+ATA1.bBlckSize], 1	; Max block size in sectors
+	jbe		SHORT .BlockModeTransfersNotSupported
+	or		BYTE [di+DPT.bFlagsHigh], FLGH_DPT_BLOCK_MODE_SUPPORTED
+.BlockModeTransfersNotSupported:
+	; Fall to .StoreDeviceSpecificParameters
+
+;--------------------------------------------------------------------
+; .StoreDeviceSpecificParameters
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+.StoreDeviceSpecificParameters:
+	call	Device_FinalizeDPT
+
+;----------------------------------------------------------------------
+; Update drive counts (hard and floppy)
+;----------------------------------------------------------------------
+
+%ifdef MODULE_SERIAL_FLOPPY
+;
+; These two instructions serve two purposes:
+; 1. If the drive is a floppy drive (CF set), then we effectively increment the counter.
+; 2. If this is a hard disk, and there have been any floppy drives previously added, then the hard disk is
+;    effectively discarded.  This is more of a safety check then code that should ever normally be hit (see below).
+;    Since the floppy DPT's come after the hard disk DPT's, without expensive (code size) code to relocate a DPT,
+;    this was necessary.  Now, this situation shouldn't happen in normal operation, for a couple of reasons:
+; 		A. xtidecfg always puts configured serial ports at the end of the IDEVARS list
+;       B. the auto serial code is always executed last
+;       C. the serial server always returns floppy drives last
+;
+	adc		byte [RAMVARS.xlateVars+XLATEVARS.bFlopCreateCnt], 0
+	jnz		.AllDone
+%else
+;
+; Even without floppy support enabled, we shouldn't try to mount a floppy image as a hard disk, which
+; could lead to unpredictable results since no MBR will be present, etc.  The server doesn't know that
+; floppies are supported, so it is important to still fail here if a floppy is seen during the drive scan.
+;
+	jc		.AllDone
+%endif
+
+	inc		BYTE [RAMVARS.bDrvCnt]		; Increment drive count to RAMVARS
+
+.AllDone:
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; CreateDPT_StoreIdevarsOffsetAndBasePortFromCSBPtoDPTinDSDI
+;	Parameters:
+;		DX:		Autodetected port (for devices that support autodetection)
+;		DS:DI:	Ptr to Disk Parameter Table
+;		CS:BP:	Ptr to IDEVARS for the controller
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+CreateDPT_StoreIdevarsOffsetAndBasePortFromCSBPtoDPTinDSDI:
+	mov		[di+DPT.bIdevarsOffset], bp		; IDEVARS must start in first 256 bytes of ROM
+
+%ifdef MODULE_8BIT_IDE_ADVANCED
+	call	DetectDrives_DoesIdevarsInCSBPbelongToXTCF
+	jne		SHORT .DeviceUsesPortSpecifiedInIDEVARS
+	mov		[di+DPT.wBasePort], dx
+	ret
+.DeviceUsesPortSpecifiedInIDEVARS:
+%endif ; MODULE_8BIT_IDE_ADVANCED
+
+	mov		ax, [cs:bp+IDEVARS.wBasePort]
+	mov		[di+DPT.wBasePort], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; GetUserDefinedCapacityToBXAXandFlagsToCXandModeToDXfromROMVARS
+;	Parameters:
+;		DS:DI:		Ptr to Disk Parameter Table
+;	Returns:
+;		AX:			User defined P-CHS Cylinders or LBA low word
+;		BX:			User defined P-CHS Heads and Sectors or LBA high word
+;		DX:			Translate mode or TRANSLATEMODE_AUTO
+;		CX:			FLG_DRVPARAMS_USERCHS if user defined CHS in BX:AX
+;					FLG_DRVPARAMS_USERLBA if user defined LBA in BX:AX
+;					Zero if user has not defined capacity
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+GetUserDefinedCapacityToBXAXandFlagsToCXandModeToDXfromROMVARS:
+	call	AccessDPT_GetPointerToDRVPARAMStoCSBX
+
+	; Get settings
+	mov		cx, [cs:bx+DRVPARAMS.wFlags]
+	mov		dx, cx
+	and		cx, BYTE FLG_DRVPARAMS_USERCHS | FLG_DRVPARAMS_USERLBA
+	and		dx, BYTE MASK_DRVPARAMS_TRANSLATEMODE
+	eSHR_IM	dx, TRANSLATEMODE_FIELD_POSITION
+
+	; Get capacity
+	mov		ax, [cs:bx+DRVPARAMS.wCylinders]		; Or .dwMaximumLBA
+	mov		bx, [cs:bx+DRVPARAMS.wHeadsAndSectors]	; Or .dwMaximumLBA+2
+	ret
+
+
+%ifdef MODULE_EBIOS
+;--------------------------------------------------------------------
+; StoreLba48AddressingFromCLandTotalSectorCountFromBXDXAX
+;	Parameters:
+;		BX:DX:AX:	Total Sector Count
+;		CL:			FLGL_DPT_LBA48 if LBA48 supported
+;		DS:DI:		Ptr to Disk Parameter Table
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		CL
+;--------------------------------------------------------------------
+StoreLba48AddressingFromCLandTotalSectorCountFromBXDXAX:
+	or		cl, FLGL_DPT_LBA_AND_EBIOS_SUPPORTED
+	and		BYTE [di+DPT.bFlagsLow], ~FLGL_DPT_LBA48
+	or		[di+DPT.bFlagsLow], cl
+	mov		[di+DPT.twLbaSectors], ax
+	mov		[di+DPT.twLbaSectors+2], dx
+	mov		[di+DPT.twLbaSectors+4], bx
+	ret
+%endif ; MODULE_EBIOS
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/DrvDetectInfo.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/DrvDetectInfo.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/DrvDetectInfo.asm	(revision 516)
@@ -0,0 +1,81 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for generating and accessing drive
+;					information to be displayed on boot menu.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Creates new DRVDETECTINFO struct for detected hard disk.
+;
+; DriveDetectInfo_CreateForHardDisk
+;	Parameters:
+;		DL:		Drive number
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		ES:BX:	Ptr to DRVDETECTINFO (if successful)
+;	Corrupts registers:
+;		AX, BX, CX, DX, DI
+;--------------------------------------------------------------------
+DriveDetectInfo_CreateForHardDisk:
+	call	DriveDetectInfo_ConvertDPTtoBX		; ES:BX now points to new DRVDETECTINFO
+
+	; Store Drive Name
+	push	ds									; Preserve RAMVARS
+	push	si
+
+	push	es									; ES copied to DS
+	pop		ds
+
+	add		si, BYTE ATA1.strModel				; DS:SI now points drive name (Clears CF)
+	lea		di, [bx+DRVDETECTINFO.szDrvName]	; ES:DI now points to name destination
+	mov		cx, MAX_HARD_DISK_NAME_LENGTH / 2	; Max number of WORDs allowed
+.CopyNextWord:
+	lodsw
+	xchg	al, ah								; Change endianness
+	stosw
+	loop	.CopyNextWord
+	xchg	cx, ax								; Zero AX (CF already cleared from the ADD above)
+	stosw										; Terminate with NULL
+
+	pop		si
+	pop		ds
+
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns offset to DRVDETECTINFO based on DPT pointer.
+;
+; DriveDetectInfo_ConvertDPTtoBX
+;	Parameters:
+;		DS:DI:	DPT Pointer
+;	Returns:
+;		BX:		Offset to DRVDETECTINFO struct
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+DriveDetectInfo_ConvertDPTtoBX:
+	lea		ax, [di-RAMVARS_size]					; subtract off base of DPTs
+	mov		bl, DPT_DRVDETECTINFO_SIZE_MULTIPLIER	; DRVDETECTINFO are a whole number multiple of DPT size
+	mul		bl
+	add		ax, BOOTVARS.rgDrvDetectInfo			; add base of DRVDETECTINFO
+	xchg	bx, ax
+	ret
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/FindDPT.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/FindDPT.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/FindDPT.asm	(revision 516)
@@ -0,0 +1,295 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for finding Disk Parameter Table.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Checks if drive is handled by this BIOS, and return DPT pointer.
+;
+; FindDPT_ForDriveNumberInDL
+;	Parameters:
+;		DL:		Drive number
+;		DS:		RAMVARS segment
+;	Returns:
+;		CF:		Cleared if drive is handled by this BIOS
+;				Set if drive belongs to some other BIOS
+;		DI:		DPT Pointer if drive is handled by this BIOS
+;				Zero if drive belongs to some other BIOS
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FindDPT_ForDriveNumberInDL:
+	xchg	di, ax								; Save the contents of AX in DI
+
+;
+; Check Our Hard Disks
+;
+	mov		ax, [RAMVARS.wFirstDrvAndCount]		; Drive count to AH, First number to AL
+	add		ah, al								; One past last drive to AH
+
+%ifdef MODULE_SERIAL_FLOPPY
+	cmp		dl, ah								; Above last supported?
+	jae		SHORT .HardDiskNotHandledByThisBIOS
+
+	cmp		dl, al								; Below first supported?
+	jae		SHORT .CalcDPTForDriveNumber
+
+ALIGN JUMP_ALIGN
+.HardDiskNotHandledByThisBIOS:
+;
+; Check Our Floppy Disks
+;
+	call	RamVars_UnpackFlopCntAndFirstToAL
+	js		SHORT .DiskIsNotHandledByThisBIOS
+
+	cbw											; Always 0h (no floppy drive covered above)
+	adc		ah, al								; Add in first drive number and number of drives
+
+	cmp		ah, dl								; Check second drive if two, first drive if only one
+	jz		SHORT .CalcDPTForDriveNumber
+	cmp		al, dl								; Check first drive in all cases, redundant but OK to repeat
+	jnz		SHORT .DiskIsNotHandledByThisBIOS
+%else
+	cmp		dl, ah								; Above last supported?
+	jae		SHORT .DiskIsNotHandledByThisBIOS
+
+	cmp		dl, al								; Below first supported?
+	jb		SHORT .DiskIsNotHandledByThisBIOS
+%endif
+	; fall-through to CalcDPTForDriveNumber
+
+;--------------------------------------------------------------------
+; Finds Disk Parameter Table for drive number.
+; Not intended to be called except by FindDPT_ForDriveNumberInDL
+;
+; CalcDPTForDriveNumber
+;	Parameters:
+;		DL:		Drive number
+;		DS:		RAMVARS segment
+;       DI:     Saved copy of AX from entry at FindDPT_ForDriveNumberInDL
+;	Returns:
+;		DS:DI:	Ptr to DPT
+;       CF:     Clear
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.CalcDPTForDriveNumber:
+	push	dx
+
+%ifdef MODULE_SERIAL_FLOPPY
+	mov		ax, [RAMVARS.wFirstDrvAndCount]
+
+	test	dl, dl
+	js		.harddisk
+
+	call	RamVars_UnpackFlopCntAndFirstToAL
+	add		dl, ah						; add in end of hard disk DPT list, floppies start immediately after
+
+ALIGN JUMP_ALIGN
+.harddisk:
+	sub		dl, al						; subtract off beginning of either hard disk or floppy list (as appropriate)
+%else
+	sub		dl, [RAMVARS.bFirstDrv]		; subtract off beginning of hard disk list
+%endif
+
+.CalcDPTForNewDrive:
+	mov		al, LARGEST_DPT_SIZE
+
+	mul		dl
+	add		ax, BYTE RAMVARS_size		; Clears CF (will not overflow)
+
+	pop		dx
+
+	xchg	di, ax						; Restore AX from entry at FindDPT_ForDriveNumber, put DPT pointer in DI
+	ret
+
+ALIGN JUMP_ALIGN
+.DiskIsNotHandledByThisBIOS:
+;
+; Drive not found...
+;
+	xor		ax, ax								; Clear DPT pointer
+	stc											; Is not supported by our BIOS
+
+	xchg	di, ax								; Restore AX from save at top
+	ret
+
+
+;--------------------------------------------------------------------
+; FindDPT_ForIdevarsOffsetInDL
+;	Parameters:
+;		DL:		Offset to IDEVARS to search for
+;		DS:		RAMVARS segment
+;	Returns:
+;		DS:DI:		Ptr to first DPT with same IDEVARS as in DL
+;		CF:			Clear if wanted DPT found
+;					Set if DPT not found, or no DPTs present
+;	Corrupts registers:
+;		SI
+;--------------------------------------------------------------------
+FindDPT_ForIdevarsOffsetInDL:
+	mov		si, IterateFindFirstDPTforIdevars			; iteration routine (see below)
+	jmp		SHORT FindDPT_IterateAllDPTs				; look for the first drive on this controller, if any
+
+;--------------------------------------------------------------------
+; Iteration routine for FindDPT_ForIdevarsOffsetInDL,
+; for use with IterateAllDPTs
+;
+; Returns when DPT is found on the controller with Idevars offset in DL
+;
+; IterateFindFirstDPTforIdevars
+;       DL:		Offset to IDEVARS to search from DPTs
+;		DS:DI:	Ptr to DPT to examine
+;	Returns:
+;		CF:		Clear if wanted DPT found
+;				Set if wrong DPT
+;--------------------------------------------------------------------
+IterateFindFirstDPTforIdevars:
+	cmp		dl, [di+DPT.bIdevarsOffset]			; Clears CF if matched
+	je		.done
+	stc											; Set CF for not found
+.done:
+	ret
+
+
+;--------------------------------------------------------------------
+; Finds pointer to first unused Disk Parameter Table.
+; Should only be used before DetectDrives is complete (not valid after this time).
+;
+; FindDPT_ForNewDriveToDSDI
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		DS:DI:	Ptr to first unused DPT
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FindDPT_ForNewDriveToDSDI:
+	push	dx
+
+%ifdef MODULE_SERIAL_FLOPPY
+	mov		dx, [RAMVARS.wDrvCntAndFlopCnt]
+	add		dl, dh
+%else
+	mov		dl, [RAMVARS.bDrvCnt]
+%endif
+
+	jmp		short FindDPT_ForDriveNumberInDL.CalcDPTForNewDrive
+
+;--------------------------------------------------------------------
+; IterateToDptWithFlagsHighInBL
+;	Parameters:
+;		DS:DI:	Ptr to DPT to examine
+;       BL:		Bit(s) to test in DPT.bFlagsHigh
+;	Returns:
+;		CF:		Clear if wanted DPT found
+;				Set if wrong DPT
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IterateToDptWithFlagsHighInBL:
+	test	[di+DPT.bFlagsHigh], bl				; Clears CF
+	jnz		SHORT .ReturnRightDPT
+	stc
+.ReturnRightDPT:
+	ret
+
+;--------------------------------------------------------------------
+; FindDPT_ToDSDIforSerialDevice
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		DS:DI:	Ptr to DPT
+;		CF:		Set if wanted DPT found
+;				Cleared if DPT not found
+;	Corrupts registers:
+;		SI
+;--------------------------------------------------------------------
+%ifdef MODULE_SERIAL
+ALIGN JUMP_ALIGN
+FindDPT_ToDSDIforSerialDevice:
+	mov		bl, FLGH_DPT_SERIAL_DEVICE
+; fall-through
+%endif
+
+;--------------------------------------------------------------------
+; FindDPT_ToDSDIforFlagsHigh
+;	Parameters:
+;		DS:		RAMVARS segment
+;       BL:		Bit(s) to test in DPT.bFlagsHigh
+;	Returns:
+;		DS:DI:	Ptr to DPT
+;		CF:		Set if wanted DPT found
+;				Cleared if DPT not found
+;	Corrupts registers:
+;		SI
+;--------------------------------------------------------------------
+%ifdef MODULE_IRQ		
+ALIGN JUMP_ALIGN
+FindDPT_ToDSDIforFlagsHighInBL:	
+%endif
+	mov		si, IterateToDptWithFlagsHighInBL
+	; Fall to IterateAllDPTs
+
+;--------------------------------------------------------------------
+; Iterates all Disk Parameter Tables.
+;
+; FindDPT_IterateAllDPTs
+;	Parameters:
+;		AX,BX,DX:	Parameters to callback function
+;		CS:SI:		Ptr to callback function
+;                   Callback routine should return CF=clear if found
+;		DS:			RAMVARS segment
+;	Returns:
+;		DS:DI:		Ptr to wanted DPT (if found)
+;					If not found, points to first empty DPT
+;		CF:			Clear if wanted DPT found
+;					Set if DPT not found, or no DPTs present
+;	Corrupts registers:
+;		Nothing unless corrupted by callback function
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FindDPT_IterateAllDPTs:
+	push	cx
+
+	mov		di, RAMVARS_size			; Point DS:DI to first DPT
+	eMOVZX	cx, [RAMVARS.bDrvCnt]
+	jcxz	.NotFound					; Return if no drives
+
+ALIGN JUMP_ALIGN
+.LoopWhileDPTsLeft:
+	call	si							; Is wanted DPT?
+	jnc		SHORT .Found				;  If so, return
+	add		di, BYTE LARGEST_DPT_SIZE	; Point to next DPT
+	loop	.LoopWhileDPTsLeft
+
+ALIGN JUMP_ALIGN
+.NotFound:
+	stc
+
+ALIGN JUMP_ALIGN
+.Found:
+	pop		cx
+	ret
+
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm	(revision 516)
@@ -0,0 +1,232 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for accessings RAMVARS.
+
+;
+; XTIDE Universal BIOS and Associated Tools
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Initializes RAMVARS.
+; Drive detection can be started after this function returns.
+;
+; RamVars_Initialize
+;	Parameters:
+;		Nothing
+;	Returns:
+;		DS:		RAMVARS segment
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+RamVars_Initialize:
+	push	es
+	; Fall to .StealMemoryForRAMVARS
+
+;--------------------------------------------------------------------
+; .StealMemoryForRAMVARS
+;	Parameters:
+;		Nothing
+;	Returns:
+;		DS:		RAMVARS segment
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.StealMemoryForRAMVARS:
+%ifndef USE_AT
+	mov		ax, LITE_MODE_RAMVARS_SEGMENT
+	test	BYTE [cs:ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
+	jz		SHORT .InitializeRamvars	; No need to steal RAM
+%endif
+
+	LOAD_BDA_SEGMENT_TO	ds, ax, !		; Zero AX
+	mov		al, [cs:ROMVARS.bStealSize]
+	sub		[BDA.wBaseMem], ax
+	mov		ax, [BDA.wBaseMem]
+	eSHL_IM	ax, 6						; Segment to first stolen kB (*=40h)
+	; Fall to .InitializeRamvars
+
+;--------------------------------------------------------------------
+; .InitializeRamvars
+;	Parameters:
+;		AX:		RAMVARS segment
+;	Returns:
+;		DS:		RAMVARS segment
+;	Corrupts registers:
+;		AX, CX, DI, ES
+;--------------------------------------------------------------------
+.InitializeRamvars:
+	mov		ds, ax
+	mov		es, ax
+	mov		cx, RAMVARS_size
+	xor		di, di
+	call	Memory_ZeroESDIwithSizeInCX
+	mov		WORD [RAMVARS.wDrvDetectSignature], RAMVARS_DRV_DETECT_SIGNATURE
+	mov		WORD [RAMVARS.wSignature], RAMVARS_RAM_SIGNATURE
+	; Fall to .InitializeInt13hStackChangeVariables
+
+;--------------------------------------------------------------------
+; .InitializeInt13hStackChangeVariables
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef RELOCATE_INT13H_STACK
+.InitializeInt13hStackChangeVariables:
+	eMOVZX	ax, BYTE [cs:ROMVARS.bStealSize]
+	eSHL_IM	ax, 10			; kiB to Bytes = Top of stack offset
+	mov		[RAMVARS.wNewStackOffset], ax
+%endif
+
+;; There used to be a DriveXlate_Reset call here.  It isn't necessary, as we reset
+;; when entering the boot menu and also before transferring control at boot time and
+;; for ROM boots (in int19h.asm).
+
+	pop		es
+	ret
+
+;--------------------------------------------------------------------
+; Returns segment to RAMVARS.
+; RAMVARS might be located at the top of interrupt vectors (0030:0000h)
+; or at the top of system base RAM.
+;
+; RamVars_GetSegmentToDS
+;	Parameters:
+;		Nothing
+;	Returns:
+;		DS:		RAMVARS segment
+;	Corrupts registers:
+;		DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RamVars_GetSegmentToDS:
+
+%ifndef USE_AT	; Always in Full Mode for AT builds
+	test	BYTE [cs:ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
+	jnz		SHORT .GetStolenSegmentToDS
+	%ifndef USE_186
+		mov		di, LITE_MODE_RAMVARS_SEGMENT
+		mov		ds, di
+	%else
+		push	LITE_MODE_RAMVARS_SEGMENT
+		pop		ds
+	%endif
+	ret
+%endif
+
+ALIGN JUMP_ALIGN
+.GetStolenSegmentToDS:
+	LOAD_BDA_SEGMENT_TO	ds, di
+	mov		di, [BDA.wBaseMem]		; Load available base memory size in kB
+	eSHL_IM	di, 6					; Segment to first stolen kB (*=40h)
+ALIGN JUMP_ALIGN
+.LoopStolenKBs:
+	mov		ds, di					; EBDA segment to DS
+	add		di, BYTE 64				; DI to next stolen kB
+	cmp		WORD [RAMVARS.wSignature], RAMVARS_RAM_SIGNATURE
+	jne		SHORT .LoopStolenKBs	; Loop until sign found (always found eventually)
+	ret
+
+
+;--------------------------------------------------------------------
+; RamVars_GetHardDiskCountFromBDAtoAX
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		AX:		Total hard disk count
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+%ifdef MODULE_BOOT_MENU
+RamVars_GetHardDiskCountFromBDAtoAX:
+	call	RamVars_GetCountOfKnownDrivesToAX
+	push	ds
+	LOAD_BDA_SEGMENT_TO	ds, bx
+	mov		bl, [BDA.bHDCount]
+	MAX_U	al, bl
+	pop		ds
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; RamVars_GetCountOfKnownDrivesToAX
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		AX:		Total hard disk count
+;	Corrupts registers:
+;		None
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RamVars_GetCountOfKnownDrivesToAX:
+	mov		ax, [RAMVARS.wFirstDrvAndCount]
+	add		al, ah
+	and		ax, BYTE 7fh
+	ret
+
+;--------------------------------------------------------------------
+; RamVars_GetIdeControllerCountToCX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CX:		Number of IDE controllers to handle
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RamVars_GetIdeControllerCountToCX:
+	eMOVZX	cx, [cs:ROMVARS.bIdeCnt]
+	ret
+
+
+%ifdef MODULE_SERIAL_FLOPPY
+;--------------------------------------------------------------------
+; RamVars_UnpackFlopCntAndFirstToAL
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		AL:		First floppy drive number supported
+;       CF:		Number of floppy drives supported (clear = 1, set = 2)
+;		SF:		Emulating drives (clear = yes, set = no)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RamVars_UnpackFlopCntAndFirstToAL:
+	mov		al, [RAMVARS.xlateVars+XLATEVARS.bFlopCntAndFirst]
+	sar		al, 1
+	ret
+%endif
+
+
+%if 0							; unused...
+;--------------------------------------------------------------------
+; RamVars_IsDriveDetectionInProgress
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		ZF:		Set if drive detection is in progress (ROM initialization)
+;	Corrupts registers:
+;		None
+;--------------------------------------------------------------------
+RamVars_IsDriveDetectionInProgress:
+	cmp		WORD [RAMVARS.wSignature], RAMVARS_DRV_DETECT_SIGNATURE
+	ret
+%endif
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/gpl-2.0.txt
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/gpl-2.0.txt	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/gpl-2.0.txt	(revision 516)
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
Index: tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/makefile
===================================================================
--- tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/makefile	(revision 516)
+++ tags/v2.0.0_beta_3/XTIDE_Universal_BIOS/makefile	(revision 516)
@@ -0,0 +1,254 @@
+####################################################################################################
+# Makefile to build XTIDE Universal BIOS.                                                          #
+#                                                                                                  #
+# Valid makefile targets are:                                                                      #
+# all       Removes existing files and builds binary files in \Build                               #
+# small     Builds 8 kiB binaries only (without checksum)                                          #
+# large     Builds 12 kiB binaries only (without checksum)                                         #
+# clean     Removes all files from \Build                                                          #
+# checksum* Builds all and then generates checksum byte to all binary files                        #
+# strings*  Compress src\Strings.asm to src\StringsCompressed.asm                                  #
+# unused*   Checks if there are any unused functions that can be removed to save space             #
+#                                                                                                  #
+# * at the end of target name means that Perl is required for the job.                             #
+# Build directory must be created manually if it does not exist.                                   #
+#                                                                                                  #
+#                                                                                                  #
+# Following modules can be included or excluded:                                                   #
+# MODULE_8BIT_IDE             Support for 8-BIT IDE cards like XTIDE                               #
+# MODULE_8BIT_IDE_ADVANCED    Support for memory mapped and DMA based cards like JRIDE and XTCF    #
+# MODULE_ADVANCED_ATA         Native support for some VLB IDE controllers                          #
+# MODULE_BOOT_MENU            Boot Menu for selection of drive to boot from                        #
+# MODULE_EBIOS                Enhanced functions for accessing drives over 8.4 GB                  #
+# MODULE_HOTKEYS              Hotkey Bar to boot from any drive                                    #
+# MODULE_IRQ                  IDE IRQ support                                                      #
+# MODULE_SERIAL               Virtual hard disks using serial port                                 #
+# MODULE_SERIAL_FLOPPY        Virtual floppy drives using serial port (requires MODULE_SERIAL)     #
+# MODULE_STRINGS_COMPRESSED   Use compressed strings to save space                                 #
+# MODULE_FEATURE_SETS         Power Management support                                             #
+#                                                                                                  #
+# Not modules but these affect the assembly:                                                       #
+# ELIMINATE_CGA_SNOW          Prevents CGA snowing at the cost of a few bytes                      #
+# RELOCATE_INT13H_STACK       Relocates INT 13h stack to top of stolen conventional memory         #
+# RESERVE_DIAGNOSTIC_CYLINDER Reserve one L-CHS cylinder for compatibility with old BIOSes         #
+# USE_186                     Use instructions supported by 80188/80186 and V20/V30 and later      #
+# USE_286                     Use instructions supported by 286 and later (defines USE_UNDOC_INTEL)#
+# USE_386                     Use instructions supported by 386 and later (defines USE_286)        #
+# USE_AT                      Use features supported on AT and later systems (not available on XT) #
+# USE_UNDOC_INTEL             Optimizations for Intel CPU:s - do NOT use on NEC V20/V30/Sony CPU:s #
+#                                                                                                  #
+####################################################################################################
+
+###########################################
+# Source files and destination executable #
+###########################################
+
+# Assembly source code file (*.asm):
+SRC_ASM = Src/Main.asm
+
+# Program executable file name without extension:
+PROG = ide
+
+
+#######################################
+# Destination and include directories #
+#######################################
+
+# Directory where binary file will be compiled to
+BUILD_DIR = Build
+
+# Subdirectories where included files are:
+HEADERS = Inc/
+HEADERS += Inc/Controllers/
+HEADERS += Src/
+HEADERS += Src/Handlers/
+HEADERS += Src/Handlers/Int13h/
+HEADERS += Src/Handlers/Int13h/EBIOS/
+HEADERS += Src/Handlers/Int13h/Tools/
+HEADERS += Src/Handlers/Int19h/
+HEADERS += Src/Device/
+HEADERS += Src/Device/IDE/
+HEADERS += Src/Device/MemoryMappedIDE/
+HEADERS += Src/Device/Serial/
+HEADERS += Src/Initialization/
+HEADERS += Src/Initialization/AdvancedAta/
+HEADERS += Src/Menus/
+HEADERS += Src/Menus/BootMenu/
+HEADERS += Src/Libraries/
+HEADERS += Src/VariablesAndDPTs/
+
+# Subdirectories where library files are:
+LIBS = ../Assembly_Library/Inc/
+LIBS += ../Assembly_Library/Src/
+LIBS += ../Assembly_Library/Src/Display/
+LIBS += ../Assembly_Library/Src/File/
+LIBS += ../Assembly_Library/Src/Keyboard/
+LIBS += ../Assembly_Library/Src/Menu/
+LIBS += ../Assembly_Library/Src/Menu/Dialog/
+LIBS += ../Assembly_Library/Src/String/
+LIBS += ../Assembly_Library/Src/Time/
+LIBS += ../Assembly_Library/Src/Util/
+LIBS += ../Assembly_Library/Src/Serial/
+LIBS += ../XTIDE_Universal_BIOS/Inc/
+HEADERS += $(LIBS)
+
+
+#################################################################
+# Assembler preprocessor defines.                               #
+#################################################################
+DEFINES_COMMON = MODULE_STRINGS_COMPRESSED MODULE_HOTKEYS MODULE_8BIT_IDE MODULE_SERIAL MODULE_SERIAL_FLOPPY MODULE_EBIOS MODULE_FEATURE_SETS RESERVE_DIAGNOSTIC_CYLINDER
+DEFINES_COMMON_LARGE = MODULE_BOOT_MENU MODULE_8BIT_IDE_ADVANCED
+
+DEFINES_XT = $(DEFINES_COMMON) ELIMINATE_CGA_SNOW MODULE_8BIT_IDE_ADVANCED
+DEFINES_XTPLUS = $(DEFINES_COMMON) $(DEFINES_XT) USE_186
+DEFINES_AT = $(DEFINES_COMMON) USE_AT USE_286 RELOCATE_INT13H_STACK MODULE_IRQ MODULE_ADVANCED_ATA
+
+DEFINES_XT_LARGE = $(DEFINES_XT) $(DEFINES_COMMON_LARGE)
+DEFINES_XTPLUS_LARGE = $(DEFINES_XTPLUS) $(DEFINES_COMMON_LARGE)
+DEFINES_AT_LARGE = $(DEFINES_AT) $(DEFINES_COMMON_LARGE)
+
+DEFINES_XT_TINY = MODULE_STRINGS_COMPRESSED MODULE_8BIT_IDE
+DEFINES_386_8K = $(DEFINES_AT) USE_386
+
+DEFINES_ALL_FEATURES = MODULE_8BIT_IDE MODULE_8BIT_IDE_ADVANCED MODULE_ADVANCED_ATA MODULE_EBIOS MODULE_BOOT_MENU MODULE_HOTKEYS MODULE_IRQ MODULE_SERIAL MODULE_SERIAL_FLOPPY MODULE_STRINGS_COMPRESSED MODULE_FEATURE_SETS
+
+
+###################
+# Other variables #
+###################
+
+# Target size of the ROM, used in main.asm for number of 512B blocks and by checksum Perl script below
+BIOS_SIZE = 8192		# For BIOS header (use even multiplier!)
+ROMSIZE = $(BIOS_SIZE)	# Size of binary to build when building with make checksum
+BIOS_SIZE_LARGE = 12288
+ROMSIZE_LARGE = $(BIOS_SIZE_LARGE)
+
+# Add -D in front of every preprocessor define declaration
+DEFS_XT = $(DEFINES_XT:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE)
+DEFS_XTPLUS = $(DEFINES_XTPLUS:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE)
+DEFS_AT = $(DEFINES_AT:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE)
+DEFS_XT_LARGE = $(DEFINES_XT_LARGE:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE_LARGE)
+DEFS_XTPLUS_LARGE = $(DEFINES_XTPLUS_LARGE:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE_LARGE)
+DEFS_AT_LARGE = $(DEFINES_AT_LARGE:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE_LARGE)
+DEFS_XT_TINY = $(DEFINES_XT_TINY:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE)
+DEFS_386_8K = $(DEFINES_386_8K:%=-D%) -DBIOS_SIZE=$(BIOS_SIZE)
+DEFS_ALL_FEATURES = $(DEFINES_ALL_FEATURES:%=-D%)
+
+# Add -I in front of all header directories
+IHEADERS = $(HEADERS:%=-I%)
+
+# Path + target file to be built
+TARGET = $(BUILD_DIR)/$(PROG)
+
+#########################
+# Compilers and linkers #
+#########################
+
+# Make
+MAKE = mingw32-make.exe
+
+# Assembler
+AS = nasm.exe
+
+# use this command to erase files.
+RM = -del /Q
+
+
+#############################
+# Compiler and linker flags #
+#############################
+
+# Assembly compiler flags
+ASFLAGS = -f bin				# Produce binary object files
+ASFLAGS += $(IHEADERS)			# Set header file directory paths
+ASFLAGS += -Worphan-labels		# Warn about labels without colon
+ASFLAGS += -Ox					# Optimize operands to their shortest forms
+
+
+############################################
+# Build process. Actual work is done here. #
+############################################
+
+all: clean small large
+	@echo All done!
+
+small: xt_tiny xt xtplus at 386_8k
+	@echo All small binaries built!
+
+large: xt_large xtplus_large at_large
+	@echo All large binaries built!
+
+at:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_AT) -l"$(TARGET)_at.lst" -o"$(TARGET)_at.bin"
+	@echo * Small AT version "$(TARGET)_at.bin" built.
+
+at_large:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_AT_LARGE) -l"$(TARGET)_atl.lst" -o"$(TARGET)_atl.bin"
+	@echo *Large AT version "$(TARGET)_atl.bin" built.
+
+xtplus:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XTPLUS) -l"$(TARGET)_xtp.lst" -o"$(TARGET)_xtp.bin"
+	@echo * Small XT Plus version "$(TARGET)_xtp.bin" built.
+
+xtplus_large:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XTPLUS_LARGE) -l"$(TARGET)_xtpl.lst" -o"$(TARGET)_xtpl.bin"
+	@echo *Large XT Plus version "$(TARGET)_xtpl.bin" built.
+
+xt:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT) -l"$(TARGET)_xt.lst" -o"$(TARGET)_xt.bin"
+	@echo * Small XT version "$(TARGET)_xt.bin" built.
+
+xt_large:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT_LARGE) -l"$(TARGET)_xtl.lst" -o"$(TARGET)_xtl.bin"
+	@echo *Large XT version "$(TARGET)_xtl.bin" built.
+
+xt_tiny:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT_TINY) -l"$(TARGET)_tiny.lst" -o"$(TARGET)_tiny.bin"
+	@echo * Tiny XT version "$(TARGET)_tiny.bin" built.
+
+386_8k:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_386_8K) -l"$(TARGET)_386.lst" -o"$(TARGET)_386.bin"
+	@echo * Small 386 version "$(TARGET)_386.bin" built.
+
+strings: src\Strings.asm
+	@$(AS) src\Strings.asm $(ASFLAGS) $(DEFS_AT_LARGE) -DCHECK_FOR_UNUSED_ENTRYPOINTS -DMODULE_STRINGS_COMPRESSED_PRECOMPRESS -o build\Strings.bin -l build\StringsPrecompress.lst
+	@perl ..\tools\StringsCompress.pl < build\StringsPrecompress.lst > src\StringsCompressed.asm
+	@echo StringsCompressed.asm updated!
+
+clean:
+	@$(RM) $(BUILD_DIR)\*.*
+	@echo Deleted "(*.*)" from "$(BUILD_DIR)/"
+
+checksum: all
+	@perl ..\tools\checksum.pl $(TARGET)_tiny.bin $(ROMSIZE)
+	@perl ..\tools\checksum.pl $(TARGET)_xt.bin $(ROMSIZE)
+	@perl ..\tools\checksum.pl $(TARGET)_xtp.bin $(ROMSIZE)
+	@perl ..\tools\checksum.pl $(TARGET)_at.bin $(ROMSIZE)
+	@perl ..\tools\checksum.pl $(TARGET)_xtl.bin $(ROMSIZE_LARGE)
+	@perl ..\tools\checksum.pl $(TARGET)_xtpl.bin $(ROMSIZE_LARGE)
+	@perl ..\tools\checksum.pl $(TARGET)_atl.bin $(ROMSIZE_LARGE)
+	@perl ..\tools\checksum.pl $(TARGET)_386.bin $(ROMSIZE)
+
+unused:
+	@echo "All Features"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_ALL_FEATURES) $(DEFS_XT) $(DEFS_XT_PLUS) $(DEFS_AT) $(DEFS_XT_LARGE) $(DEFS_XTPLUS_LARGE) $(DEFS_AT_LARGE) $(DEFS_XT_TINY) $(DEFS_386_8K) -o"$(TARGET)_unused.asm" -l"$(TARGET)_unused.lst"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_ALL_FEATURES) $(DEFS_XT) $(DEFS_XT_PLUS) $(DEFS_AT) $(DEFS_XT_LARGE) $(DEFS_XTPLUS_LARGE) $(DEFS_AT_LARGE) $(DEFS_XT_TINY) $(DEFS_386_8K) -o"$(TARGET)_unused.asm" -E -DCHECK_FOR_UNUSED_ENTRYPOINTS
+	@perl ..\tools\unused.pl $(TARGET)_unused.lst $(TARGET)_unused.asm
+	@echo "XT Small"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT) -o"$(TARGET)_unused_xt.asm" -l"$(TARGET)_unused_xt.lst"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT) -o"$(TARGET)_unused_xt.asm" -E -DCHECK_FOR_UNUSED_ENTRYPOINTS
+	@perl ..\tools\unused.pl $(TARGET)_unused_xt.lst $(TARGET)_unused_xt.asm
+	@echo "XT Large"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT_LARGE) -o"$(TARGET)_unused_xtl.asm" -l"$(TARGET)_unused_xtl.lst"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT_LARGE) -o"$(TARGET)_unused_xtl.asm" -E -DCHECK_FOR_UNUSED_ENTRYPOINTS
+	@perl ..\tools\unused.pl $(TARGET)_unused_xtl.lst $(TARGET)_unused_xtl.asm
+	@echo "AT Small"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_AT) -o"$(TARGET)_unused_at.asm" -l"$(TARGET)_unused_at.lst"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_AT) -o"$(TARGET)_unused_at.asm" -E -DCHECK_FOR_UNUSED_ENTRYPOINTS
+	@perl ..\tools\unused.pl $(TARGET)_unused_at.lst $(TARGET)_unused_at.asm
+	@echo "AT Large"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_AT_LARGE) -o"$(TARGET)_unused_atl.asm" -l"$(TARGET)_unused_atl.lst"
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_AT_LARGE) -o"$(TARGET)_unused_atl.asm" -E -DCHECK_FOR_UNUSED_ENTRYPOINTS
+	@perl ..\tools\unused.pl $(TARGET)_unused_atl.lst $(TARGET)_unused_atl.asm
+
+
