Index: trunk/XTIDE_Universal_BIOS/Inc/ATA_ID.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/ATA_ID.inc	(revision 361)
+++ trunk/XTIDE_Universal_BIOS/Inc/ATA_ID.inc	(revision 363)
@@ -3,4 +3,35 @@
 %ifndef ATA_ID_INC
 %define ATA_ID_INC
+
+; PIO Minimum Cycle Times (t0)
+; Timings for Advanced modes 3 and 4 can be read from ATA info WORDs 67 and 68
+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 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 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 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
@@ -32,5 +63,5 @@
 				resw 1	; 50R
 				resb 1	; 51[0-7]X
-	.bPIOTiming	resb 1	; 51[8-15]F, PIO data transfer cycle timing mode
+	.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
@@ -163,4 +194,8 @@
 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)
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Index: trunk/XTIDE_Universal_BIOS/Inc/BootMenu.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/BootMenu.inc	(revision 361)
+++ trunk/XTIDE_Universal_BIOS/Inc/BootMenu.inc	(revision 363)
@@ -24,8 +24,28 @@
 
 struc BOOTMENUINFO
-	.szDrvName		resb	MAX_HARD_DISK_NAME_LENGTH
-					resb	2		; Zero word (ensures string terminates)
-					resb	4		; padding to make BOOTMENUINFO size an even multiple of DPT size
+	.szDrvName				resb	MAX_HARD_DISK_NAME_LENGTH
+							resb	2	; Zero word (ensures string terminates)
+	.wInitErrorFlags		resb	2	; Errors during initialization
+
+%ifdef MODULE_ADVANCED_ATA
+	.wIdeBasePort			resb	2	; IDE Base Port
+	.wMinPioActiveTimeNs	resb	2	; Minimum PIO Active Time in ns
+	.wMinPioRecoveryTimeNs	resb	2	; Minimum PIO Recovery Time in ns
+	.wControllerID			resb	2	; Controller specific ID WORD
+	.wControllerBasePort	resb	2	; Advanced Controller port (not IDE port)
+							resb	12	; padding to make BOOTMENUINFO size an even multiple of DPT size
+
+%else
+							resb	2	; padding to make BOOTMENUINFO size an even multiple of DPT size
+%endif
 endstruc
+
+; Flags for BOOTMENUINFO.wInitErrorFlags
+FLG_INIT_FAILED_TO_SELECT_DRIVE					EQU		(1<<0)
+FLG_INIT_FAILED_TO_INITIALIZE_CHS_PARAMETERS	EQU		(1<<1)
+FLG_INIT_FAILED_TO_SET_WRITE_CACHE				EQU		(1<<2)
+FLG_INIT_FAILED_TO_RECALIBRATE_DRIVE			EQU		(1<<3)
+FLG_INIT_FAILED_TO_SET_BLOCK_MODE				EQU		(1<<4)
+FLG_INIT_FAILED_TO_SET_PIO_MODE					EQU		(1<<5)
 
 DPT_BOOTMENUINFO_SIZE_MULTIPLIER  equ	BOOTMENUINFO_size / LARGEST_DPT_SIZE
Index: trunk/XTIDE_Universal_BIOS/Inc/BootVars.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/BootVars.inc	(revision 361)
+++ trunk/XTIDE_Universal_BIOS/Inc/BootVars.inc	(revision 363)
@@ -19,6 +19,11 @@
 	.rgbMnuStack:
 	.dwPostStack	resb	4		; POST stack pointer when entering INT 19h
+	.wMagicWord		resb	2		; I wish we didn't need this
 	.rgBootNfo:						; Array containing BOOTNFO structs
 endstruc
+
+; Magic WORD to detect when BOOTVARS is available.
+BOOTVARS_MAGIC_WORD			EQU		1110011001100111b
+
 
 
Index: trunk/XTIDE_Universal_BIOS/Inc/Controllers/Vision.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/Controllers/Vision.inc	(revision 363)
+++ trunk/XTIDE_Universal_BIOS/Inc/Controllers/Vision.inc	(revision 363)
@@ -0,0 +1,80 @@
+; 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
+%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: trunk/XTIDE_Universal_BIOS/Inc/CustomDPT.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/CustomDPT.inc	(revision 361)
+++ trunk/XTIDE_Universal_BIOS/Inc/CustomDPT.inc	(revision 363)
@@ -25,28 +25,4 @@
 endstruc
 
-; DPT for ATA devices
-struc DPT_ATA	; 10 + 2 bytes = 12 bytes
-	.dpt						resb	DPT_size
-
-	; Block size is specified in sectors (1, 2, 4, 8, 16, 32, 64 or 128)
-	.wSetAndMaxBlock:
-	.bSetBlock					resb	1	; Current block size (at least 1)
-	.bMaxBlock					resb	1	; Maximum block size, 0 = block mode not supported
-endstruc
-
-%ifdef MODULE_SERIAL
-; DPT for Serial devices
-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
-%endif
-
-LARGEST_DPT_SIZE				EQU		DPT_ATA_size
-
-
 ; Bit definitions for DPT.bFlagsLow
 MASKL_DPT_CHS_SHIFT_COUNT		EQU	(7<<0)	; Bits 0...3, P-CHS to L-CHS bit shift count (0...4)
@@ -62,10 +38,9 @@
 %endif
 FLGH_DPT_INTERRUPT_IN_SERVICE	EQU	(1<<3)	; Set when waiting for IRQ
-FLGH_DPT_RESET_nDRDY			EQU	(1<<4)	; Drive ready to accept commands
-FLGH_DPT_RESET_nINITPRMS		EQU	(1<<5)	; Initialize Device Parameters successful
-FLGH_DPT_RESET_nRECALIBRATE		EQU	(1<<6)	; Recalibrate successful
-FLGH_DPT_RESET_nSETBLOCK		EQU	(1<<7)	; Initialize Block Mode successful
-MASKH_DPT_RESET					EQU	0F0h
 
+; IDE device only
+FLGH_DPT_INITERROR				EQU	(1<<7)
+
+; Serial device only
 FLGH_DPT_SERIAL_FLOPPY						EQU	(1<<4)
 FLGH_DPT_SERIAL_FLOPPY_TYPE_MASK			EQU	0e0h
@@ -78,4 +53,51 @@
 ADDRESSING_MODE_LBA28			EQU		2	; 28-bit LBA Addressing Mode
 ADDRESSING_MODE_LBA48			EQU		3	; 48-bit LBA Addressing Mode
+
+
+; DPT for ATA devices
+struc DPT_ATA	; 10 + 2 bytes = 12 bytes
+	.dpt						resb	DPT_size
+
+	; Block size is specified in sectors (1, 2, 4, 8, 16, 32, 64 or 128)
+	.wSetAndMaxBlock:
+	.bSetBlock					resb	1	; Current block size (do not set to zero!)
+	.bMaxBlock					resb	1	; Maximum block size, 0 = block mode not supported
+
+%ifdef MODULE_ADVANCED_ATA	; +2 extra bytes = 14 bytes
+	.bPioMode					resb	1
+	.bDevice					resb	1
+%endif
+endstruc
+
+
+%ifdef MODULE_ADVANCED_ATA
+; Temporary extension for DPT_ATA. Contents will be copied to BOOTMENUINFO and
+; then these variables will be overridden by next DPT.
+struc DPT_ADVANCED_ATA
+	.dpt_ata				resb	DPT_ATA_size
+	.wIdeBasePort			resb	2	; IDE Base Port
+	.wMinPioActiveTimeNs	resb	2	; Minimum PIO Active Time in ns
+	.wMinPioRecoveryTimeNs	resb	2	; Minimum PIO Recovery Time in ns
+	.wControllerID			resb	2	; Controller specific ID WORD
+	.wControllerBasePort	resb	2	; Advanced Controller port (not IDE port)
+endstruc
+%endif
+
+
+%ifdef MODULE_SERIAL
+; DPT for Serial devices
+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
+%endif
+
+
+; This is the common size for all DPTs. All DPTs must be equal size.
+LARGEST_DPT_SIZE				EQU		DPT_ATA_size
+
 
 ; Number of Sectors per Track is fixed to 63 for LBA assist calculation.
Index: trunk/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc	(revision 361)
+++ trunk/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc	(revision 363)
@@ -4,4 +4,24 @@
 %ifndef IDE_8BIT_INC
 %define IDE_8BIT_INC
+
+;--------------------------------------------------------------------
+; UNROLL_SECTORS_IN_CX_TO_QWORDS
+;	Parameters:
+;		CX:		Number of sectors in block
+;	Returns:
+;		CX:		Number of QWORDs in block
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro UNROLL_SECTORS_IN_CX_TO_QWORDS 0
+%ifdef USE_186
+	shl		cx, 6
+%else
+	xchg	cl, ch		; Sectors to WORDs (SHL CX, 8)
+	shr		cx, 1
+	shr		cx, 1
+%endif
+%endmacro
+
 
 ;--------------------------------------------------------------------
Index: trunk/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc	(revision 361)
+++ trunk/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc	(revision 363)
@@ -84,4 +84,8 @@
 FEATURE_ENABLE_WRITE_CACHE				EQU		02h
 FEATURE_DISABLE_WRITE_CACHE				EQU		82h		; Can also be used to flush cache
+FEATURE_SET_TRANSFER_MODE				EQU		03h		; Transfe 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
 
 
Index: trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 361)
+++ trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 363)
@@ -52,4 +52,5 @@
 												; by holding down the ALT key at the end of drive detection.
 												; (Conveniently, this is 8, a fact we exploit when testing the bit)
+FLG_ROMVARS_MODULE_ADVATA			EQU	(1<<4)	; Here in case the configuration needs to know functionality is present
 FLG_ROMVARS_MODULE_JRIDE			EQU	(1<<5)	; Here in case the configuration needs to know functionality is present
 FLG_ROMVARS_MODULE_SERIAL			EQU (1<<6)	; Here in case the configuration needs to know functionality is present
@@ -97,4 +98,6 @@
 DEVICE_ATA_DEFAULT_PORT					EQU		1F0h
 DEVICE_ATA_DEFAULT_PORTCTRL				EQU		3F0h
+DEVICE_ATA_DEFAULT_SECONDARY_PORT		EQU		170h
+DEVICE_ATA_DEFAULT_SECONDARY_PORTCTRL	EQU		370h
 
 ; Device types for IDEVARS.bDevice
