Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1Eh_XTCF.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1Eh_XTCF.asm	(revision 544)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1Eh_XTCF.asm	(revision 545)
@@ -1,4 +1,6 @@
 ; Project name	:	XTIDE Universal BIOS
-; Description	:	Int 13h function AH=1Eh, Lo-tech XT-CF features.
+; Description	:	Int 13h function AH=1Eh, Lo-tech XT-CF features
+;
+; More information at http://www.lo-tech.co.uk/XT-CF
 
 ;
@@ -17,4 +19,6 @@
 ; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 ;
+
+; Modified by JJP for XT-CFv3 support, Mar-13
 
 ; Section containing code
@@ -42,5 +46,5 @@
 	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
 %else
-	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	push		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
 	; Fall to ProcessXTCFsubcommandFromAL
 %endif
@@ -56,4 +60,5 @@
 ;		AH:		Int 13h return status
 ;		CF:		0 if successful, 1 if error
+;		DX		Command return values (see XTCF.inc)
 ;	Corrupts registers:
 ;		AL, BX, CX, DX, SI
@@ -62,33 +67,40 @@
 	; IS_THIS_DRIVE_XTCF. We check this for all commands.
 	call	AccessDPT_IsThisDeviceXTCF
-	jne		SHORT XTCFnotFound
+	jne		SHORT .XTCFnotFound
 	and		ax, BYTE 7Fh				; Subcommand now in AX (clears AH and CF)
-	jz		SHORT .ReturnWithSuccess	; IS_THIS_DRIVE_XTCF
+	jz		SHORT .XTCFfound			; Sub-function IS_THIS_DRIVE_XTCF (=0)
 
-	; 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
+	dec		ax							; Test subcommand...
+	jz		SHORT .SetXTCFtransferMode	; ...for value 1 (SET_XTCF_TRANSFER_MODE)
 
-.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
+	dec		ax							; Test subcommand for value 2 (GET_XTCF_TRANSFER_MODE)
+	jnz		SHORT .XTCFnotFound			; Invalid subcommand
+
+	; GET_XTCF_TRANSFER_MODE
+	call	AH1Eh_GetCurrentXTCFmodeToAX
+	mov		dl, [di+DPT_ATA.bBlockSize]
+	mov		[bp+IDEPACK.intpack+INTPACK.dh], al	; return mode value...
+	mov		[bp+IDEPACK.intpack+INTPACK.dl], dl	; ...and block size, via INTPACK...
+.XTCFfound:
+	ret											; ...with AH and CF cleared
+
+.XTCFnotFound:
+.AH1Eh_LoadInvalidCommandToAHandSetCF:
+	stc					; set carry flag since XT-CF not found
+	mov		ah, RET_HD_INVALID
+	ret					; and return
+
+.SetXTCFtransferMode:
+	mov		al, [bp+IDEPACK.intpack+INTPACK.dh]	; get specified mode (eg XTCF_DMA_MODE) 
+	; and fall to AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL
 
 
 ;--------------------------------------------------------------------
-; AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL
+; AH1Eh_ChangeXTCFmodeBasedOnModeInAL
 ;	Parameters:
-;		AL:		XT-CF Control Register
+;		AL:		XT-CF Mode (see XTCF.inc)
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
 ;		SS:BP:	Ptr to IDEPACK
-;	Returns:
+;	Returns:	
 ;		AH:		Int 13h return status
 ;		CF:		0 if successful, 1 if error
@@ -96,66 +108,65 @@
 ;		AL, BX, CX, DX, SI
 ;--------------------------------------------------------------------
-AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL:
-	; Output Control Register
-	mov		dx, [di+DPT.wBasePort]
-	add		dl, XTCF_CONTROL_REGISTER
-	out		dx, al
+AH1Eh_ChangeXTCFmodeBasedOnModeInAL:
+	; Note: Control register (as of XT-CFv3) is now a write-only register,
+	;       whos purpose is *only* to raise DRQ.  The register cannot be read.
+	;       Selected transfer mode is stored in BIOS variable (DPT_ATA.bDevice).
 
 	; We always need to enable 8-bit mode since 16-bit mode is restored
 	; when controller is reset (AH=00h or 0Dh)
+	; 
+	; Note that when selecting 'DEVICE_8BIT_PIO_MODE_WITH_BIU_OFFLOAD' mode,
+	; the ATA device (i.e. CompactFlash card) will operate in 8-bit mode, but
+	; data will be transferred from it's data register using 16-bit CPU instructions
+	; like REP INSW.  This works because XT-CF adapters are 8-bit cards, and
+	; the BIU in the machine splits each WORD requested by the CPU into two 8-bit
+	; ISA cycles at base+0h and base+1h.  The XT-CF cards do not decode A0, hence
+	; both accesses appear the same to the card and the BIU then re-constructs
+	; the data for presentation to the CPU.
+	;
+	; Also note though that some machines, noteably AT&T PC6300, have hardware
+	; errors in the BIU logic, resulting in reversed byte ordering.  Therefore,
+	; mode DEVICE_8BIT_PIO is the default transfer mode for best system
+	; compatibility.
+
 	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
+	; Convert mode to device type (see XTCF.inc for full details)
+	and		ax, 3
+	jz	SHORT .Set8bitPioMode	; XTCF_8BIT_PIO_MODE = 0
+	dec		ax					; XTCF_8BIT_PIO_MODE_WITH_BIU_OFFLOAD = 1
+	jz	SHORT .Set8bitPioModeWithBIUOffload
 
-	; Set DMA Mode
+	; XTCF_DMA_MODE = 2 (allow 3 as well for more optimized code)
 	mov		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_XTCF_DMA
+
+	; DMA transfers have limited block sizee
 	mov		al, [di+DPT_ATA.bBlockSize]
-	cmp		al, XTCF_DMA_MODE_MAX_BLOCK_SIZE
-	jbe		SHORT AH24h_SetBlockSize
-	mov		al, XTCF_DMA_MODE_MAX_BLOCK_SIZE
-	jmp		SHORT AH24h_SetBlockSize
-
-.SetMemoryMappedMode:
-	mov		al, DEVICE_8BIT_XTCF_MEMMAP
-	SKIP2B	bx
+	MIN_U	al, XTCF_DMA_MODE_MAX_BLOCK_SIZE
+	jmp		AH24h_SetBlockSize
+	; exit via ret in AH24_SetBlockSize then through AH23h_Enable8bitPioMode
 
 .Set8bitPioMode:
-	mov		al, DEVICE_8BIT_XTCF_PIO8
-	mov		[di+DPT_ATA.bDevice], al
-	ret		; Via AH23h_Enable8bitPioMode
+	mov		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_XTCF_PIO8
+	ret		; through AH23h_Enable8bitPioMode
+
+.Set8bitPioModeWithBIUOffload:
+	mov		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
+	ret		; through AH23h_Enable8bitPioMode
 
 
 ;--------------------------------------------------------------------
-; AH1Eh_DetectXTCFwithBasePortInDX
+; AH1Eh_GetCurrentXTCFmodeToAX
 ;	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
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:	
+;		AX:		XT-CF mode (XTCF_8BIT_PIO_MODE, XTCF_8BIT_PIO_MODE_WITH_BIU_OFFLOAD or XTCF_DMA_MODE)
+;		CF:		Clear
 ;	Corrupts registers:
-;		AL
+;		Nothing
 ;--------------------------------------------------------------------
-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
+AH1Eh_GetCurrentXTCFmodeToAX:
+	eMOVZX	ax, BYTE [di+DPT_ATA.bDevice]	; get current mode from DPT
+	sub		al, DEVICE_8BIT_XTCF_PIO8
+	shr		ax, 1							; Device type to XT-CF mode
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm	(revision 544)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm	(revision 545)
@@ -63,6 +63,10 @@
 	cmp		al, XTCF_DMA_MODE_MAX_BLOCK_SIZE
 	jbe		SHORT .NoNeedToLimitBlockSize
+
+	; Return error if we tried too large block for XT-CF.
+	; Do not limit it to maximum supported since software calling AH=24h
+	; must know what the actual block size is.
 	cmp		BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_XTCF_DMA
-	je		SHORT AH1Eh_LoadInvalidCommandToAHandSetCF
+	je		SHORT ProcessXTCFsubcommandFromAL.AH1Eh_LoadInvalidCommandToAHandSetCF
 .NoNeedToLimitBlockSize:
 %endif ; MODULE_8BIT_IDE_ADVANCED
@@ -77,5 +81,8 @@
 	pop		bx
 	jnc		SHORT .StoreBlockSize
-	mov		bl, 1		; Block size 1 will always work
+
+	; Drive disabled block mode since we tried unsupported block size.
+	; We must adjust DPT accordingly.
+	mov		bl, 1		; Block size 1 will always work (=Block mode disabled)
 .StoreBlockSize:		; Store new block size to DPT and return
 	mov		[di+DPT_ATA.bBlockSize], bl
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm	(revision 544)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm	(revision 545)
@@ -58,5 +58,5 @@
 
 	test	byte [bp+IDEPACK.intpack+INTPACK.dl], 080h
-	jnz		.Done
+	jnz		SHORT .CalledForHardDrive
 
 	mov		[bp+IDEPACK.intpack+INTPACK.bl], bl
@@ -67,5 +67,5 @@
 	call	FloppyDrive_GetCountToAX
 
-.Done:
+.CalledForHardDrive:
 	mov		ah, dh
 
@@ -133,7 +133,5 @@
 %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
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm	(revision 544)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm	(revision 545)
@@ -114,6 +114,5 @@
 ;;; Set XT-CF mode
 %ifdef MODULE_8BIT_IDE_ADVANCED
-	call	AccessDPT_GetIdevarsToCSBX
-	mov		al, [cs:bx+IDEVARS.bXTCFcontrolRegister]
+	call	AH1Eh_GetCurrentXTCFmodeToAX
 	call	AH9h_SetModeFromALtoXTCF
 	STORE_ERROR_FLAG_TO_DPT		FLG_INITERROR_FAILED_TO_SET_XTCF_MODE
@@ -284,5 +283,5 @@
 	call	AccessDPT_IsThisDeviceXTCF
 	jne		SHORT IgnoreInvalidCommandError
-	jmp		AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL
+	jmp		AH1Eh_ChangeXTCFmodeBasedOnModeInAL
 %endif ; MODULE_8BIT_IDE_ADVANCED
 
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH48h_GetExtendedDriveParameters.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH48h_GetExtendedDriveParameters.asm	(revision 544)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/EBIOS/AH48h_GetExtendedDriveParameters.asm	(revision 545)
@@ -139,7 +139,12 @@
 	sbb		dx, (MAX_SECTOR_COUNT_TO_RETURN_PCHS+1) >> 16
 	sbb		bx, cx		; Zero
-	jnc		SHORT .ReturnWithSuccess
+	jnc		SHORT .DoNotSetChsFlag
 	or		BYTE [di+EDRIVE_INFO.wFlags], FLG_CHS_INFORMATION_IS_VALID
 
+	; We store something to P-CHS anyway since some HW detection programs
+	; ignore the CHS flag. And we should at least clear the variables anyway
+	; since the same buffer is used for all drives so it contains parameters
+	; from previously scanned drive.
+.DoNotSetChsFlag:
 	eMOVZX	dx, BYTE [es:si+DPT.bPchsHeads]
 	mov		[di+EDRIVE_INFO.dwHeads], dx
