Index: trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/IdeAutodetect.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/IdeAutodetect.asm	(revision 502)
+++ trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/IdeAutodetect.asm	(revision 504)
@@ -24,10 +24,9 @@
 ; IdeAutodetect_DetectIdeDeviceFromPortDXAndReturnControlBlockInCX
 ;	Parameters:
-;		DX:		IDE Base Port
+;		DX:		IDE Base Port or segment address (Command Block)
 ;		DS:DI:	Ptr to ROMVARS
 ;	Returns:
 ;		AL:		Device Type
-;		CX:		Control Block Base port (detected since there is no
-;				standard address for Tetriary and Quaternary IDE controllers)
+;		SI:		IDE Control Block Base port (port mapped devices only)
 ;		CF:		Clear if IDE Device found
 ;				Set if IDE Device not found
@@ -35,11 +34,25 @@
 ;		AH, BX
 ;--------------------------------------------------------------------
-IdeAutodetect_DetectIdeDeviceFromPortDXAndReturnControlBlockInCX:
+IdeAutodetect_DetectIdeDeviceFromPortDXAndReturnControlBlockInSI:
 	cmp		dx, FIRST_MEMORY_SEGMENT_ADDRESS
-	jb		SHORT .DetectPortMappedDevices
-
+	jb		SHORT DetectPortMappedDeviceFromPortDX
+	; Fall to DetectMemoryMappedDeviceFromSegmentDX
+
+;--------------------------------------------------------------------
+; DetectMemoryMappedDeviceFromSegmentDX
+;	Parameters:
+;		DX:		Segment address for Memory Mapped Device
+;		DS:DI:	Ptr to ROMVARS
+;	Returns:
+;		AL:		Device Type
+;		CF:		Clear if IDE Device found
+;				Set if IDE Device not found
+;	Corrupts registers:
+;		AH, BX
+;--------------------------------------------------------------------
+DetectMemoryMappedDeviceFromSegmentDX:
 	; *** Try to detect JR-IDE/ISA (only if MODULE_8BIT_IDE_ADVANCED is present) ***
 	test	WORD [di+ROMVARS.wFlags], FLG_ROMVARS_MODULE_8BIT_IDE_ADVANCED
-	jz		SHORT .SkipRestOfDetection
+	jz		SHORT NoIdeDeviceFound
 
 	push	ds
@@ -53,17 +66,33 @@
 	mov		al, DEVICE_8BIT_JRIDE_ISA	; Assume CF was cleared
 	ret									; No need to return Control Block Port
-.DetectPortMappedDevices:
-
-
+
+
+;--------------------------------------------------------------------
+; DetectPortMappedDeviceFromPortDX
+;	Parameters:
+;		DX:		IDE Base Port (Command Block)
+;		DS:DI:	Ptr to ROMVARS
+;	Returns:
+;		AL:		Device Type
+;		SI:		IDE Control Block Base port
+;		CF:		Clear if IDE Device found
+;				Set if IDE Device not found
+;	Corrupts registers:
+;		AH, BX
+;--------------------------------------------------------------------
+DetectPortMappedDeviceFromPortDX:
 	; *** Try to detect Standard 16- and 32-bit IDE Devices ***
-	mov		bh, DEVICE_16BIT_ATA		; Assume 16-bit ISA slot for AT builds
+	mov		al, DEVICE_16BIT_ATA		; Assume 16-bit ISA slot for AT builds
 	call	Buffers_IsXTbuildLoaded
-	eCMOVE	bh, DEVICE_8BIT_ATA			; Assume 8-bit ISA slot for XT builds
-
-	mov		bl, STATUS_REGISTER_in
-	mov		cx, STANDARD_CONTROL_BLOCK_OFFSET + ALTERNATE_STATUS_REGISTER_in
-.RedetectTertiaryOrQuaternaryWithDifferentAlternativeStatusRegisterPort:
-	call	DetectIdeDeviceFromPortDXwithStatusRegOffsetsInBLandCX
-	mov		al, bh
+	eCMOVE	al, DEVICE_8BIT_ATA			; Assume 8-bit ISA slot for XT builds
+
+	; Start with standard Control Block base port used by Primary and Secondary IDE
+	mov		si, dx
+	add		si, STANDARD_CONTROL_BLOCK_OFFSET
+	mov		bx, STATUS_REGISTER_in | (ALTERNATE_STATUS_REGISTER_in << 8)
+.RedetectTertiaryOrQuaternaryWithDifferentControlBlockAddress:
+	push	ax							; Store device type
+	call	DetectIdeDeviceFromPortsDXandSIwithOffsetsInBLandBH
+	pop		ax							; Restore device type
 	jnc		SHORT .IdeDeviceFound
 
@@ -72,26 +101,17 @@
 	; example Promise FloppyMAX has Control Block at STANDARD_CONTROL_BLOCK_OFFSET but Sound Blaster 16 (CT2290)
 	; use DEVICE_ATA_SECONDARY_PORTCTRL for Tertiary and Quaternary even though only Secondary should use that.
-	cmp		cx, STANDARD_CONTROL_BLOCK_OFFSET + ALTERNATE_STATUS_REGISTER_in
-	jne		SHORT .AlreadyTriedAlternativeControlBlock
-	mov		cx, DEVICE_ATA_SECONDARY_PORTCTRL + ALTERNATE_STATUS_REGISTER_in
-	sub		cx, dx						; Offset to add to DX
-	cmp		dx, DEVICE_ATA_TERTIARY_PORT
-	je		SHORT .RedetectTertiaryOrQuaternaryWithDifferentAlternativeStatusRegisterPort
-	cmp		dx, DEVICE_ATA_QUATERNARY_PORT
-	je		SHORT .RedetectTertiaryOrQuaternaryWithDifferentAlternativeStatusRegisterPort
-.AlreadyTriedAlternativeControlBlock:
+	call	ChangeDifferentControlBlockAddressToSI
+	je		SHORT .RedetectTertiaryOrQuaternaryWithDifferentControlBlockAddress
 
 
 	; Detect 8-bit devices only if MODULE_8BIT_IDE is available
 	test	BYTE [di+ROMVARS.wFlags], FLG_ROMVARS_MODULE_8BIT_IDE
-	jz		SHORT .SkipRestOfDetection
+	jz		SHORT NoIdeDeviceFound
 
 	; *** Try to detect XT-CF ***
-	mov		bl, STATUS_REGISTER_in << 1
-	mov		cx, (XTIDE_CONTROL_BLOCK_OFFSET + ALTERNATE_STATUS_REGISTER_in) << 1
-	call	DetectIdeDeviceFromPortDXwithStatusRegOffsetsInBLandCX
-	rcl		ax, 1						; Store CF
-	shr		cx, 1						; XTIDE_CONTROL_BLOCK_OFFSET + ALTERNATE_STATUS_REGISTER_in
-	rcr		ax, 1						; Restore CF
+	mov		si, dx
+	add		si, BYTE XTCF_CONTROL_BLOCK_OFFSET
+	shl		bx, 1						; SHL 1 register offsets for XT-CF
+	call	DetectIdeDeviceFromPortsDXandSIwithOffsetsInBLandBH
 	mov		al, DEVICE_8BIT_XTCF_PIO8
 	jnc		SHORT .IdeDeviceFound
@@ -102,6 +122,8 @@
 	; Status Register addresses. That is why we need another step
 	; to check is this XT-IDE rev 1 or rev 2.
-	call	DetectIdeDeviceFromPortDXwithStatusRegOffsetsInBLandCX
-	jc		SHORT .SkipRestOfDetection	; No XT-IDE rev 1 or rev 2 found
+	sub		si, BYTE XTCF_CONTROL_BLOCK_OFFSET >> 1
+	shr		bx, 1
+	call	DetectIdeDeviceFromPortsDXandSIwithOffsetsInBLandBH
+	jc		SHORT NoIdeDeviceFound		; No XT-IDE rev 1 or rev 2 found
 
 	; Now we can be sure that we have XT-IDE rev 1 or rev 2.
@@ -121,18 +143,14 @@
 	mov		al, DEVICE_8BIT_XTIDE_REV1	; We must have rev 1
 .IdeDeviceFound:
-	sub		cl, ALTERNATE_STATUS_REGISTER_in	; Clear CF
-	add		cx, dx								; CX = Control Block address
 	ret
-.SkipRestOfDetection:
-	stc
-	ret
-
-
-;--------------------------------------------------------------------
-; DetectIdeDeviceFromPortDXwithStatusRegOffsetsInBLandCX
+
+
+;--------------------------------------------------------------------
+; DetectIdeDeviceFromPortsDXandSIwithOffsetsInBLandBH
 ;	Parameters:
 ;		BL:		Offset to IDE Status Register
-;		CX:		Offset to Alternative Status Register
-;		DX:		IDE Base Port
+;		BH:		Offset to Alternative Status Register
+;		DX:		IDE Base Port address
+;		SI:		IDE Control Block address
 ;	Returns:
 ;		CF:		Clear if IDE Device found
@@ -141,20 +159,18 @@
 ;		AX
 ;--------------------------------------------------------------------
-DetectIdeDeviceFromPortDXwithStatusRegOffsetsInBLandCX:
+DetectIdeDeviceFromPortsDXandSIwithOffsetsInBLandBH:
 	; Read Status and Alternative Status Registers
-	push	cx
 	push	dx
 
-	add		cx, dx				; CX = Address to Alternative Status Register
-	add		dl, bl				; DX = Address to Status Register
+	add		dl, bl
 	cli							; Disable Interrupts
-	in		al, dx				; Read Status Register
-	mov		ah, al
-	mov		dx, cx
-	in		al, dx				; Read Alternative Status Register
+	in		al, dx				; Read Status Register...
+	mov		ah, al				; ...to AH
+	mov		dx, si
+	add		dl, bh
+	in		al, dx				; Read Alternative Status Register to AL
 	sti							; Enable Interrupts
 
 	pop		dx
-	pop		cx
 	; Fall to CompareIdeStatusRegistersFromALandAH
 
@@ -163,6 +179,6 @@
 ; CompareIdeStatusRegistersFromALandAH
 ;	Parameters:
-;		AL:		Possible IDE Status Register contents
-;		AH:		Possible IDE Alternative Status Register contents
+;		AH:		Possible IDE Status Register contents
+;		AL:		Possible IDE Alternative Status Register contents
 ;	Returns:
 ;		CF:		Clear if valid Status Register Contents
@@ -180,6 +196,8 @@
 	; example. We must make sure bits are what is expected from valid
 	; IDE Status Register. So far all drives I've tested return 50h
-	; (FLG_STATUS_DRDY and FLG_STATUS_DSC set) but I don't want to assume
-	; just yet that all drives report 50h.
+	; (FLG_STATUS_DRDY and FLG_STATUS_DSC set) unless there is only
+	; one drive present but wrong drive is selected. For example if Master
+	; drive is present but Slave is selected from IDE Drive and Head Select Register,
+	; then the Status Register can be 00h.
 	test	al, FLG_STATUS_BSY | FLG_STATUS_DF | FLG_STATUS_DRQ | FLG_STATUS_ERR
 	jnz		SHORT .InvalidStatusRegister	; Busy or Errors cannot be set
@@ -189,6 +207,38 @@
 
 .InvalidStatusRegister:
-AllPortsAlreadyDetected:
+NoIdeDeviceFound:
 	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; ChangeDifferentControlBlockAddressToSI
+;	Parameters:
+;		DX:		IDE Base Port address
+;		SI:		IDE Control Block address
+;	Returns:
+;		ZF:		Set if SI changed
+;				Cleared if different control block address is not possible
+;	Corrupts registers:
+;		AH
+;--------------------------------------------------------------------
+ChangeDifferentControlBlockAddressToSI:
+	cmp		si, 368h
+	je		SHORT .TrySecondAlternative
+	cmp		si, 3E8h
+	je		SHORT .TrySecondAlternative
+
+	cmp		si, 360h
+	je		SHORT .TryLastAlternative
+	cmp		si, 3E0h
+	je		SHORT .TryLastAlternative
+	ret		; Return with ZF cleared
+
+.TryLastAlternative:
+	mov		si, DEVICE_ATA_SECONDARY_PORTCTRL + 8	; Changes to 370h used by Sound Blaster 16 (CT2290)
+	; Fall to .TrySecondAlternative
+.TrySecondAlternative:
+	sub		si, BYTE 8h		; 368h to 360h, 3E8h to 3E0h
+	xor		ah, ah			; Set ZF
 	ret
 
