Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvAtaInit.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvAtaInit.asm	(revision 363)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvAtaInit.asm	(revision 364)
@@ -7,11 +7,11 @@
 
 ;--------------------------------------------------------------------
-; AdvAtaInit_DetectControllerForIdeBaseInDX
+; AdvAtaInit_DetectControllerForIdeBaseInBX
 ;	Parameters:
-;		DX:		IDE Controller base port
+;		BX:		IDE Controller base port
 ;	Returns:
 ;		AX:		ID WORD specific for detected controller
 ;				Zero if no controller detected
-;		CX:		Controller base port (not IDE)
+;		DX:		Controller base port (not IDE)
 ;		CF:		Set if controller detected
 ;				Cleared if no controller
@@ -19,14 +19,14 @@
 ;		BX
 ;--------------------------------------------------------------------
-AdvAtaInit_DetectControllerForIdeBaseInDX:
-	call	Vision_DetectAndReturnIDinAXandPortInCXifControllerPresent
-	jne		SHORT .NoAdvancedControllerForPortDX
-	call	Vision_DoesIdePortInDXbelongToControllerWithIDinAX
-	jne		SHORT .NoAdvancedControllerForPortDX
+AdvAtaInit_DetectControllerForIdeBaseInBX:
+	call	Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
+	jne		SHORT .NoAdvancedControllerForPortBX
+	call	Vision_DoesIdePortInBXbelongToControllerWithIDinAX
+	jne		SHORT .NoAdvancedControllerForPortBX
 
-	stc		; Advanced Controller found for port DX
+	stc		; Advanced Controller found for port BX
 	ret
 
-.NoAdvancedControllerForPortDX:
+.NoAdvancedControllerForPortBX:
 	xor		ax, ax
 	ret
@@ -38,9 +38,10 @@
 ;		AX:		ID WORD specific for detected controller
 ;	Returns:
-;		AL:		Max supported PIO mode (if CF set)
+;		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:
-;		Nothing
+;		(AX if CF cleared)
 ;--------------------------------------------------------------------
 AdvAtaInit_GetControllerMaxPioModeToAL	equ	Vision_GetMaxPioModeToAL
@@ -58,78 +59,65 @@
 ;--------------------------------------------------------------------
 AdvAtaInit_InitializeControllerForDPTinDSDI:
-	push	ds
+	push	bp
 	push	si
-	push	di
-
-	; PIO and Advanced Controller variables are stored to BOOTMENUINFO
-	; to keep the DPTs as small as possible.
-	call	GetMasterAndSlaveBootMenuInfosToSIandDI
-	cmp		WORD [BOOTVARS.wMagicWord], BOOTVARS_MAGIC_WORD
-	clc
-	jne		SHORT .BootMenuInfosAreNoLongerAvailable
 
 	; Call Controller Specific initialization function
-	mov		ax, [si+BOOTMENUINFO.wControllerID]
+	mov		ax, [di+DPT_ADVANCED_ATA.wControllerID]
 	test	ax, ax
-	jz		SHORT .NoAdvancedController
-	call	Vision_InitializeWithIDinAHandConfigInAL	; The only we support at the moment
+	jz		SHORT .NoAdvancedController	; Return with CF cleared
 
-.BootMenuInfosAreNoLongerAvailable:
+	; We only support Vision at the moment so no need to identify ID
+	call	AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
+	call	Vision_InitializeWithIDinAHandConfigInAL
+
 .NoAdvancedController:
-	pop		di
 	pop		si
-	pop		ds
+	pop		bp
 	ret
 
 
 ;--------------------------------------------------------------------
-; AdvAtaInit_GetMasterAndSlaveBootMenuInfosToSIandDI
+; AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT for Single or Slave Drive
 ;	Returns:
-;		DS:SI:	Ptr to Single or Master Drive BOOTMENUINFO
-;		DI:		Offset to Slave Drive BOOTMENUINFO
+;		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:
-;		BX, DX, (DS will change!)
+;		AX
 ;--------------------------------------------------------------------
-GetMasterAndSlaveBootMenuInfosToSIandDI:
-	call	BootMenuInfo_ConvertDPTtoBX
-	LOAD_BDA_SEGMENT_TO	ds, di, !				; Zero DI to assume no Slave Drive present
+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
 
-	mov		dx, [bx+BOOTMENUINFO.wIdeBasePort]	; Load IDE Port from Single or Slave Drive
-	lea		si, [bx+BOOTMENUINFO_size]			; SI points to Slave Drive if present
-	cmp		dx, [si+BOOTMENUINFO.wIdeBasePort]
-	jne		SHORT .BootMenuInfoForSingleDriveInDSBX
-
-	mov		di, si								; Slave Drive detected, copy pointer to DS:DI
-.BootMenuInfoForSingleDriveInDSBX:
-	mov		si, bx
+	; We only have single drive so zero SI
+	xor		si, si
+.MasterAndSlaveDrivePresent:
 	ret
 
 
 ;--------------------------------------------------------------------
-; AdvAtaInit_SelectSlowestTimingsToBXandCX
+; AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
 ;	Parameters:
-;		DS:SI:	Ptr to BOOTMENUINFO for Master or Single Drive
-;		DI:		Offset to BOOTMENUINFO for Slave Drive
+;		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:		Min Active Time in nanosecs
-;		CX:		Min Recovery Time in nanosecs
+;		BX:		Best common PIO mode
+;		CX:		Slowest common PIO Cycle Time in nanosecs
 ;	Corrupts registers:
 ;		Nothing
 ;--------------------------------------------------------------------
-AdvAtaInit_SelectSlowestTimingsToBXandCX:
-	mov		bx, [si+BOOTMENUINFO.wMinPioActiveTimeNs]
-	mov		cx, [si+BOOTMENUINFO.wMinPioRecoveryTimeNs]
-	test	di, di
-	jz		SHORT .ReturnSlowestTimingInBXandCX	; No Slave Drive
-
-	; If Active Time is greater, then must be the Recovery Time as well
-	cmp		bx, [di+BOOTMENUINFO.wMinPioActiveTimeNs]
-	jbe		SHORT .ReturnSlowestTimingInBXandCX
-	mov		bx, [di+BOOTMENUINFO.wMinPioActiveTimeNs]
-	mov		cx, [di+BOOTMENUINFO.wMinPioRecoveryTimeNs]
-.ReturnSlowestTimingInBXandCX:
+AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI:
+	eMOVZX	bx, BYTE [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: trunk/XTIDE_Universal_BIOS/Src/Initialization/AtaID.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/AtaID.asm	(revision 363)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/AtaID.asm	(revision 364)
@@ -76,20 +76,26 @@
 %ifdef MODULE_ADVANCED_ATA
 ;--------------------------------------------------------------------
-; AtaID_GetMaxPioModeToAXandMinCycleTimeToDX
+; AtaID_GetMaxPioModeToAXandMinCycleTimeToCX
 ;	Parameters:
 ;		ES:SI:	Ptr to 512-byte ATA information read from the drive
 ;	Returns:
-;		AX:		Max supported PIO mode
-;		DX:		Minimum Cycle Time in nanosecs
+;		AL:		Max supported PIO mode
+;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
+;		CX:		Minimum Cycle Time in nanosecs
 ;	Corrupts registers:
 ;		BX
 ;--------------------------------------------------------------------
-AtaID_GetMaxPioModeToAXandMinCycleTimeToDX:
+AtaID_GetMaxPioModeToAXandMinCycleTimeToCX:
 	; Get PIO mode and cycle time for PIO 0...2
 	mov		bx, [es:si+ATA1.bPioMode]
 	shl		bx, 1					; Shift for WORD lookup
-	mov		dx, [cs:bx+.rgwPio0to2CycleTimeInNanosecs]
+	mov		cx, [cs:bx+.rgwPio0to2CycleTimeInNanosecs]
 	shr		bx, 1
-	xchg	ax, bx					; AL = PIO mode 0, 1 or 2
+	xchg	ax, bx					; AH = 0, AL = PIO mode 0, 1 or 2
+
+	; 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)
@@ -98,5 +104,5 @@
 
 	; Get Advanced PIO mode
-	; (Hard Disks supports up to 4 but CF cards might support 5)
+	; (Hard Disks supports up to 4 but CF cards can support 5 and 6)
 	mov		bx, [es:si+ATA2.bPIOSupp]
 .CheckNextFlag:
@@ -104,8 +110,8 @@
 	shr		bx, 1
 	jnz		SHORT .CheckNextFlag
-	mov		dx, [es:si+ATA2.wPIOMinCyF]	; Advanced modes use IORDY
+	MIN_U	al, 6						; Make sure not above lookup tables
+	mov		cx, [es:si+ATA2.wPIOMinCyF]	; Advanced modes use IORDY
 .ReturnPioTimings:
 	ret
-
 
 .rgwPio0to2CycleTimeInNanosecs:
@@ -116,26 +122,20 @@
 
 ;--------------------------------------------------------------------
-; AtaID_ConvertPioModeFromAXandMinCycleTimeFromDXtoActiveAndRecoveryTime
+; AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
 ;	Parameters:
-;		AX:		Max supported PIO mode
-;		DX:		Minimum PIO Cycle Time in nanosecs
+;		BX:		PIO Mode
+;		CX:		PIO Cycle Time in nanosecs
 ;	Returns:
-;		CX:		Minimum Active time in nanosecs
-;		DX:		Minimum Recovery time in nanosecs
+;		AX:		Active Time in nanosecs
 ;	Corrupts registers:
-;		BX
+;		BX, CX
 ;--------------------------------------------------------------------
-AtaID_ConvertPioModeFromAXandMinCycleTimeFromDXtoActiveAndRecoveryTime:
-	; Subtract Address Valid Time (t1) from Cycle Time (t0)
-	mov		bx, ax
-	eMOVZX	cx, BYTE [cs:bx+.rgbPioModeToAddressValidTimeNs]
-	sub		dx, cx
-
-	; Subtract Active Time (t2) from previous result to get Recovery Time (t2i)
-	shl		bx, 1			; Shift PIO Mode for WORD lookup
-	mov		cx, [cs:bx+.rgwPioModeToActiveTimeNs]
-	sub		dx, 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:
@@ -145,4 +145,22 @@
 	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:
+	shl		bx, 1
+	mov		ax, [cs:bx+.rgwPioModeToActiveTimeNs]
+	shr		bx, 1
+	ret
 
 .rgwPioModeToActiveTimeNs:
@@ -152,4 +170,6 @@
 	dw		PIO_3_MIN_ACTIVE_TIME_NS
 	dw		PIO_4_MIN_ACTIVE_TIME_NS
+	dw		PIO_5_MIN_ACTIVE_TIME_NS
+	dw		PIO_6_MIN_ACTIVE_TIME_NS
 
 %endif ; MODULE_ADVANCED_ATA
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm	(revision 363)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm	(revision 364)
@@ -7,5 +7,5 @@
 
 ;--------------------------------------------------------------------
-; Vision_DetectAndReturnIDinAXandPortInCXifControllerPresent
+; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
 ;	Parameters:
 ;		Nothing
@@ -14,5 +14,5 @@
 ;				(AL = QD65xx Config Register contents)
 ;				(AH = QDI Vision Controller ID (bits 4...7))
-;		CX:		Controller port (not IDE port)
+;		DX:		Controller port (not IDE port)
 ;		ZF:		Set if controller found
 ;				Cleared if supported controller not found (AX,DX = undefined)
@@ -20,7 +20,7 @@
 ;		Nothing
 ;--------------------------------------------------------------------
-Vision_DetectAndReturnIDinAXandPortInCXifControllerPresent:
+Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent:
 	; Check QD65xx base port
-	mov		cx, QD65XX_BASE_PORT
+	mov		dx, QD65XX_BASE_PORT
 	in		al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
 	call	IsConfigRegisterWithIDinAL
@@ -28,5 +28,5 @@
 
 	; Check QD65xx alternative base port
-	or		cl, QD65XX_ALTERNATIVE_BASE_PORT
+	or		dl, QD65XX_ALTERNATIVE_BASE_PORT
 	in		al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
 	; Fall to IsConfigRegisterWithIDinAL
@@ -56,18 +56,17 @@
 
 ;--------------------------------------------------------------------
-; Vision_DoesIdePortInDXbelongToControllerWithIDinAX
-;	Parameters:
-;		AX:		ID WORD specific for QDI Vision Controllers
-;				(AL = QD65xx Config Register contents)
-;				(AH = QDI Vision Controller ID (bits 4...7))
-;		CX:		Vision Controller port
-;		DX:		IDE base port to check
+; 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:
-;		BX
-;--------------------------------------------------------------------
-Vision_DoesIdePortInDXbelongToControllerWithIDinAX:
+;		Nothing
+;--------------------------------------------------------------------
+Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
 	cmp		ah, ID_QD6500 << 4
 	je		SHORT .DoesIdePortInDXbelongToQD6500
@@ -75,19 +74,15 @@
 	; QD6580 always have Primary IDE at 1F0h
 	; Secondary IDE at 170h can be enabled or disabled
-	cmp		dx, DEVICE_ATA_DEFAULT_PORT
+	cmp		bx, DEVICE_ATA_DEFAULT_PORT
 	je		SHORT .ReturnResultInZF
 
 	; Check if Secondary IDE channel is enabled
-	xchg	bx, ax		; Backup AX
-	xchg	dx, cx		; Swap ports
-
+	push	ax
 	add		dx, BYTE QD6580_CONTROL_REGISTER
 	in		al, dx
 	sub		dx, BYTE QD6580_CONTROL_REGISTER
-
-	xchg	cx, dx
-	xchg	ax, bx		; Restore AX, Control Register to BL
-	test	bl, FLG_QDCONTROL_SECONDARY_DISABLED_in
-	jz		SHORT .CompareDXtoSecondaryIDE
+	test	al, FLG_QDCONTROL_SECONDARY_DISABLED_in
+	pop		ax
+	jz		SHORT .CompareBXtoSecondaryIDE
 	ret
 
@@ -95,10 +90,10 @@
 .DoesIdePortInDXbelongToQD6500:
 	test	al, FLG_QDCONFIG_PRIMARY_IDE
-	jz		SHORT .CompareDXtoSecondaryIDE
-	cmp		dx, DEVICE_ATA_DEFAULT_PORT
-	ret
-
-.CompareDXtoSecondaryIDE:
-	cmp		dx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
+	jz		SHORT .CompareBXtoSecondaryIDE
+	cmp		bx, DEVICE_ATA_DEFAULT_PORT
+	ret
+
+.CompareBXtoSecondaryIDE:
+	cmp		bx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
 .ReturnResultInZF:
 	ret
@@ -108,11 +103,14 @@
 ; Vision_GetMaxPioModeToAL
 ;	Parameters:
-;		AX:		ID WORD specific for QDI Vision Controllers
-;				(AH = QDI Vision Controller ID (bits 4...7))
-;	Returns:
-;		AL:		Max supported PIO mode (if CF set)
+;		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
 ;--------------------------------------------------------------------
@@ -122,5 +120,5 @@
 	jne		SHORT .NoNeedToLimitForQD6580
 
-	mov		al, 2	; Limit to PIO 2 because QD6500 supports PIO 3 but without IORDY
+	mov		ax, 2	; Limit to PIO 2 because QD6500 does not support IORDY
 	stc
 .NoNeedToLimitForQD6580:
@@ -131,93 +129,106 @@
 ; Vision_InitializeWithIDinAHandConfigInAL
 ;	Parameters:
-;		AX:		ID WORD specific for QDI Vision Controllers
-;				(AL = QD65xx Config Register contents)
-;				(AH = QDI Vision Controller ID (bits 4...7))
-;		DS:SI:	Ptr to BOOTMENUINFO for Single or Master Drive
-;		DS:DI:	Ptr to BOOTMENUINFO for Slave Drive
-;				Zero if Slave not present
+;		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, SI, DI
+;		AX, BX, CX, DX, BP
 ;--------------------------------------------------------------------
 Vision_InitializeWithIDinAHandConfigInAL:
 	; QD6580 has a Control Register that needs to be programmed
-	mov		dx, [si+BOOTMENUINFO.wControllerBasePort]
-	cmp		ah, ID_QD6500 << 4
-	je		SHORT .GetPioTimingsInNanosecs
+	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.
-.ProgramControlRegisterForQD6580:
-	xchg	bx, ax									; Backup AX
+	xor		ax, ax
 	add		dx, BYTE QD6580_CONTROL_REGISTER
 	in		al, dx									; Read to get ATAPI jumper status
 	test	al, FLG_QDCONTROL_HDONLY_in
-	mov		al, MASK_QDCONTROL_FLAGS_TO_SET
-	jz		SHORT .SkipHdonlyBitSinceAtapiPossible
-	or		al, FLG_QDCONTROL_NONATAPI
-.SkipHdonlyBitSinceAtapiPossible:
+	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		; Back to base port
-	xchg	ax, bx									; Restore AX
-
-	; If we have Master and Slave drive in the system, we must select
-	; timings from the slower drive (this is why it is a bad idea to use
-	; fast and slow drive on the same IDE channel)
-.GetPioTimingsInNanosecs:
-	call	AdvAtaInit_SelectSlowestTimingsToBXandCX
+	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.
-	cmp		ah, ID_QD6500 << 4
-	je		SHORT .CalculateTimingTicksForQD6500
-	cmp		WORD [si+BOOTMENUINFO.wIdeBasePort], DEVICE_ATA_DEFAULT_PORT
-	je		SHORT .CalculateTimingTicksForQD6580
+	call	AccessDPT_GetIdeBasePortToBX
+	cmp		bx, DEVICE_ATA_DEFAULT_PORT
+	je		SHORT .CalculateTimingTicksForQD6580	; Primary Channel so no need to modify DX
 	times 2 inc dx									; Secondary Channel IDE Timing Register
 
-	; Now we must translate the PIO timing nanosecs in CX and DX to VLB ticks
-	; suitable for QD65xx IDE Timing Register.
-	; Both of the controllers require slightly different calculations.
+	; QD6500 and QD6580 require slightly different calculations.
 .CalculateTimingTicksForQD6580:
-	mov		si, QD6580_MIN_ACTIVE_TIME_CLOCKS
-	mov		di, QD6580_MAX_ACTIVE_TIME_CLOCKS
-	jmp		SHORT .CalculateTimingForQD65xx
-
-.CalculateTimingTicksForQD6500:
-	mov		si, QD6500_MIN_ACTIVE_TIME_CLOCKS
-	mov		di, QD6500_MAX_ACTIVE_TIME_CLOCKS
-
-.CalculateTimingForQD65xx:
-	test	al, FLG_QDCONFIG_ID3		; Set ZF if 40 MHz VLB bus
-	mov		al, VLB_33MHZ_CYCLE_TIME	; Assume 33 MHz or slower VLB bus
-	xchg	ax, bx						; Active Time to AX
-	eCMOVZ	bl, VLB_40MHZ_CYCLE_TIME
-
-	div		bl
+	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
-	xor		ah, ah
-	xchg	cx, ax						; CX = Active Time in VLB ticks
-	MAX_U	cx, si						; Limit ticks to valid values...
-	MIN_U	cx, di						; ...for QD65xx
-
-	div		bl
-	inc		ax							; Round up
-	xchg	bx, ax						; BL = Recovery Time in VLB ticks
-	mov		al, QD65xx_MAX_RECOVERY_TIME_CLOCKS
-	MAX_U	bl, QD65xx_MIN_RECOVERY_TIME_CLOCKS
-	MIN_U	bl, al
+
+	; 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		di, cx						; DI = Active Time value to program
-	sub		al, bl						; AL = Recovery Time value to program
-
-	; Finally we can shift the values in places and program the Timing Register
-	eSHIFT_IM	al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
-	or		ax, di
-	out		dx, al
-	ret									; Return with CF cleared
+	sub		cl, al
+	xchg	ax, cx						; Return in AL
+
+	pop		cx
+	ret
