Index: trunk/XTIDE_Universal_BIOS/Inc/CustomDPT.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/CustomDPT.inc	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Inc/CustomDPT.inc	(revision 150)
@@ -5,72 +5,55 @@
 %define CUSTOMDPT_INC
 
+; Base DPT for all device types
+struc DPT	; 8 bytes
+	; General Disk Parameter Table related
+	.wFlags						resb	2
+	.bIdevarsOffset				resb	1	; Offset to IDEVARS for this drive
 
-; Base Disk Parameter Table for all hard disk drives.
-; DPT might have extensions for specific functions.
-struc DPT
-	; General Disk Parameter Table related
-	.bSize		resb	1	; Size of DPT (with extensions) in bytes
-	.wDrvNumAndFlags:
-	.bDrvNum	resb	1	; Drive number
-	.bFlags		resb	1	; DPT and Drive related flags
-	.bReset		resb	1	; Drive reset status (for debugging)
-	.bIdeOff	resb	1	; Offset to IDEVARS for this drive
+	; L-CHS to P-CHS and L-CHS to LBA28 conversion related
+	.bLchsHeads					resb	1	; Number of L-CHS Heads (1...255)
 
-	; Lookup values for L-CHS to P-CHS and L-CHS to LBA28 conversions
-	.bShLtoP	resb	1	; Bit shift count for L-CHS to P-CHS conversion
-	.wLHeads	resb	2	; Number of L-CHS Heads (1...256)
-
-	; IDE related
-	.wPCyls		resb	2	; Number of P-CHS (IDE) Cylinders (1...16383)
-	.wHeadsAndSectors:
-	.bPHeads	resb	1	; Number of P-CHS (IDE) Heads (1...16)
-	.bPSect		resb	1	; Number of P-CHS (IDE) Sectors per Track (1...63)
-	.bDrvSel	resb	1	; Drive Selection byte for Device/Head Register
-	.bDrvCtrl	resb	1	; Drive Control byte for Device Control Register
-
-	; Related to Block Mode transfers.
-	; Block size is specified in sectors (1, 2, 4, 8, 16, 32, 64 or 128).
-	.wSetAndMaxBlock:
-	.bSetBlock	resb	1	; Currect block size (at least 1)
-	.bMaxBlock	resb	1	; Maximum block size, 0 = block mode not supported
+	; IDE Drive related
+	.wPchsCylinders				resb	2	; Number of P-CHS (IDE) Cylinders (1...16383)
+	.wPchsHeadsAndSectors:
+	.bPchsHeads					resb	1	; Number of P-CHS (IDE) Heads (1...16)
+	.bPchsSectors				resb	1	; Number of P-CHS (IDE) Sectors per Track (1...63)
 endstruc
 
-; Bit definitions for DPT.bFlags
-MASK_DPT_ADDR		EQU		110b	; Bits 1..2, Addressing Mode
-FLG_DPT_EBIOS		EQU		(1<<0)	; EBIOS functions supported for this drive
-FLG_DPT_FIRSTPART	EQU		(1<<3)	; First BIOS Partition of the drive (drive reset allowed)
-FLG_DPT_PARTITION	EQU		(1<<4)	; BIOS Partition
-FLG_DPT_USERCHS		EQU		(1<<5)	; User has specified P-CHS parameters
+; DPT for ATA devices
+struc DPT_ATA	; 8 + 2 bytes = 10 bytes
+	.dpt						resb	DPT_size
 
-; Values for different addressing modes (MASK_DPT_ADDR for DPT.bFlags)
-ADDR_DPT_LCHS		EQU		0		; L-CHS Addressing Mode (NORMAL in many other BIOSes)
-ADDR_DPT_PCHS		EQU		1		; P-CHS Addressing Mode (LARGE in many other BIOSes)
-ADDR_DPT_LBA28		EQU		2		; 28-bit LBA Addressing Mode
-ADDR_DPT_LBA48		EQU		3		; 48-bit LBA Addressing Mode
+	; Block size is specified in sectors (1, 2, 4, 8, 16, 32 or 64).
+	; 128 is not allowed to prevent offset overflow during data transfer.
+	.wSetAndMaxBlock:
+	.bSetBlock					resb	1	; Current block size (at least 1)
+	.bMaxBlock					resb	1	; Maximum block size, 0 = block mode not supported
+endstruc
 
-; Bit definitions for DPT.bReset (inverted)
-FLG_RESET_nDRDY			EQU		(1<<0)	; Drive ready to accept commands
-FLG_RESET_nINITPRMS		EQU		(1<<1)	; Initialize Device Parameters successfull
-FLG_RESET_nRECALIBRATE	EQU		(1<<2)	; Recalibrate successfull
-FLG_RESET_nSETBLOCK		EQU		(1<<3)	; Initialize Block Mode successfull
-MASK_RESET_ALL			EQU		(FLG_RESET_nDRDY | FLG_RESET_nINITPRMS | FLG_RESET_nRECALIBRATE | FLG_RESET_nSETBLOCK)
+LARGEST_DPT_SIZE				EQU		DPT_ATA_size
 
 
-; Extended DPT for XTIDE Universal BIOS partitioned drive.
-; This struct cannot exist with EDPT (EBIOS support).
-struc PART_DPT
-	.dpt		resb	DPT_size
-	.dwStartLBA:
-	.twStartLBA	resb	6	; Starting 28- or 48-bit LBA for BIOS partition
-endstruc
+; Bit definitions for DPT.wFlags
+MASK_DPT_CHS_SHIFT_COUNT		EQU	(7<<0)	; Bits 0...3, P-CHS to L-CHS bit shift count (0...4)
+FLG_DPT_SLAVE					EQU	FLG_DRVNHEAD_DRV	; (1<<4), Drive is slave drive
+MASK_DPT_ADDRESSING_MODE		EQU	(3<<5)	; Bits 5..6, Addressing Mode (bit 6 == FLG_DRVNHEAD_LBA)
+FLG_DPT_ENABLE_IRQ				EQU	(1<<7)
+FLG_DPT_REVERSED_A0_AND_A3		EQU	(1<<8)	; XTIDE mod, Address lines 0 and 3 reversed
+FLG_DPT_SERIAL_DEVICE			EQU	(1<<9)	; Serial Port Device
+FLG_DPT_BLOCK_MODE_SUPPORTED	EQU	(1<<10)	; Use block transfer commands
 
+FLG_DPT_RESET_nDRDY				EQU	(1<<12)	; Drive ready to accept commands
+FLG_DPT_RESET_nINITPRMS			EQU	(1<<13)	; Initialize Device Parameters successfull
+FLG_DPT_RESET_nRECALIBRATE		EQU	(1<<14)	; Recalibrate successfull
+FLG_DPT_RESET_nSETBLOCK			EQU	(1<<15)	; Initialize Block Mode successfull
+MASK_DPT_RESET					EQU	0F000h
 
-; Extended DPT for EBIOS support.
-; This struct cannot exist with PDPT (XTIDE Universal BIOS partitioned drive).
-struc EBDPT
-	.dpt		resb	DPT_size
-	.dwCapacity:
-	.twCapacity	resb	6	; Total drive capacity in sectors
-endstruc
+; Addressing modes for DPT.wFlags
+ADDRESSING_MODE_FIELD_POSITION	EQU		5
+ADDRESSING_MODE_LCHS			EQU		0	; L-CHS Addressing Mode (NORMAL in many other BIOSes)
+ADDRESSING_MODE_PCHS			EQU		1	; P-CHS Addressing Mode (LARGE in many other BIOSes)
+ADDRESSING_MODE_LBA28			EQU		2	; 28-bit LBA Addressing Mode
+ADDRESSING_MODE_LBA48			EQU		3	; 48-bit LBA Addressing Mode
 
 
Index: trunk/XTIDE_Universal_BIOS/Inc/DeviceIDE.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/DeviceIDE.inc	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Inc/DeviceIDE.inc	(revision 150)
@@ -0,0 +1,18 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Device specific equates for IDE drives.
+%ifndef DEVICEIDE_INC
+%define DEVICEIDE_INC
+
+; Reset delays
+HSR0_RESET_WAIT_US		EQU		5		; Delay at least 5us
+HSR1_RESET_WAIT_US		EQU		2000	; Delay at least 2ms
+
+; Polling timeout delays (system timer ticks, 1 tick = 54.9 ms)
+TIMEOUT_BSY				EQU		(2000/55)	; 2000 ms
+TIMEOUT_DRDY			EQU		(2000/55)	; 2000 ms
+TIMEOUT_DRQ				EQU		255			;   14 s (some CF cards occasionally have long write delays)
+TIMEOUT_IDENTIFY_DEVICE	EQU		(500/55)	;  500 ms
+TIMEOUT_MOTOR_STARTUP	EQU		(10000/55)	;   10 s
+
+
+%endif ; DEVICEIDE_INC
Index: trunk/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Inc/IDE_8bit.inc	(revision 150)
@@ -1,39 +1,7 @@
-; File name		:	IDE_8bit.inc
-; Project name	:	IDE BIOS
-; Created date	:	4.4.2010
-; Last update	:	13.4.2010
-; Author		:	Tomi Tilli
+; Project name	:	XTIDE Universal BIOS
 ; Description	:	Macros for accessing data port(s) on 8-bit
 ;					IDE controllers.
 %ifndef IDE_8BIT_INC
 %define IDE_8BIT_INC
-
-;--------------------------------------------------------------------
-; Emulates REP INSW for XTIDE dual (8-bit) data port.
-;
-; eREP_DUAL_BYTE_PORT_INSW
-;	Parameters:
-;		CX:		Loop count
-;		DX:		Port address (must be IDE Data Register)
-;		ES:DI:	Ptr to destination buffer
-;	Returns:
-;		CX:		Zero
-;		DI:		Incremented/decremented
-;	Corrupts registers:
-;		AX, FLAGS
-;--------------------------------------------------------------------
-%macro eREP_DUAL_BYTE_PORT_INSW 0
-	push	bx
-	times 2	shr	cx, 1			; Loop unrolling
-	mov		bx, 8				; Bit mask for toggling data low/high reg
-ALIGN JUMP_ALIGN
-%%InswLoop:
-	eDUAL_BYTE_PORT_INSW
-	eDUAL_BYTE_PORT_INSW
-	eDUAL_BYTE_PORT_INSW
-	eDUAL_BYTE_PORT_INSW
-	loop	%%InswLoop
-	pop		bx
-%endmacro
 
 ;--------------------------------------------------------------------
@@ -66,35 +34,4 @@
 %endmacro
 
-
-;--------------------------------------------------------------------
-; Emulates REP OUTSW for XTIDE dual (8-bit) data port.
-;
-; eREP_DUAL_BYTE_PORT_OUTSW
-;	Parameters:
-;		CX:		Loop count
-;		DX:		Port address (must be IDE Data Register)
-;		ES:SI:	Ptr to source buffer
-;	Returns:
-;		SI:		Incremented/decremented
-;	Corrupts registers:
-;		AX, CX
-;--------------------------------------------------------------------
-%macro eREP_DUAL_BYTE_PORT_OUTSW 0
-	push	ds
-	push	bx
-	times 2	shr	cx, 1			; Loop unrolling
-	mov		bx, 8				; Bit mask for toggling data low/high reg
-	push	es					; Copy ES...
-	pop		ds					; ...to DS
-ALIGN JUMP_ALIGN
-%%OutswLoop:
-	eDUAL_BYTE_PORT_OUTSW
-	eDUAL_BYTE_PORT_OUTSW
-	eDUAL_BYTE_PORT_OUTSW
-	eDUAL_BYTE_PORT_OUTSW
-	loop	%%OutswLoop
-	pop		bx
-	pop		ds
-%endmacro
 
 ;--------------------------------------------------------------------
@@ -130,76 +67,3 @@
 
 
-;--------------------------------------------------------------------
-; Emulates REP INSW for IDE controllers with single 8-bit Data Port.
-;
-; eREP_SINGLE_BYTE_PORT_INSW
-;	Parameters:
-;		CX:		Number of WORDs to transfer
-;		DX:		IDE Data Port address
-;		ES:DI:	Ptr to destination buffer
-;	Returns:
-;		DI:		Incremented/decremented
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-%macro eREP_SINGLE_BYTE_PORT_INSW 0
-%ifdef USE_186	; INS instruction available
-	shl		cx, 1				; WORD count to BYTE count
-	rep insb
-%else			; If 8088/8086
-	shr		cx, 1				; WORD count to DWORD count
-ALIGN JUMP_ALIGN
-%%InsdLoop:
-	in		al, dx
-	stosb						; Store to [ES:DI]
-	in		al, dx
-	stosb
-	in		al, dx
-	stosb
-	in		al, dx
-	stosb
-	loop	%%InsdLoop
-%endif
-%endmacro
-
-
-;--------------------------------------------------------------------
-; Emulates REP OUTSW for IDE controllers with single 8-bit Data Port.
-;
-; eREP_SINGLE_BYTE_PORT_OUTSW
-;	Parameters:
-;		CX:		Number of WORDs to transfer
-;		DX:		IDE Data Port address
-;		ES:SI:	Ptr to source buffer
-;	Returns:
-;		SI:		Incremented/decremented
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-%macro eREP_SINGLE_BYTE_PORT_OUTSW 0
-%ifdef USE_186	; OUTS instruction available
-	shl		cx, 1				; WORD count to BYTE count
-	eSEG	es					; Source is ES segment
-	rep outsb
-%else			; If 8088/8086
-	shr		cx, 1				; WORD count to DWORD count
-	push	ds					; Store DS
-	push	es					; Copy ES...
-	pop		ds					; ...to DS
-ALIGN JUMP_ALIGN
-%%OutsdLoop:
-	lodsb						; Load from [DS:SI] to AL
-	out		dx, al
-	lodsb
-	out		dx, al
-	lodsb
-	out		dx, al
-	lodsb
-	out		dx, al
-	loop	%%OutsdLoop
-	pop		ds					; Restore DS
-%endif
-%endmacro
-
-
 %endif ; IDE_8BIT_INC
Index: trunk/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Inc/IdeRegisters.inc	(revision 150)
@@ -1,7 +1,3 @@
-; File name		:	IdeRegisters.inc
-; Project name	:	IDE BIOS
-; Created date	:	23.3.2010
-; Last update	:	23.3.2010
-; Author		:	Tomi Tilli
+; Project name	:	XTIDE Universal BIOS
 ; Description	:	Equates for IDE registers, flags and commands.
 %ifndef IDEREGISTERS_INC
@@ -9,77 +5,78 @@
 
 ; IDE Register offsets from Command Block base port
-REG_IDE_DATA			EQU		0		; Data Register
-REGR_IDE_ERROR			EQU		1		; Error Register
-REGW_IDE_FEAT			EQU		1		; Features Register (ATA1+)
-;REGW_IDE_WRPC			EQU		1		; Write Precompensation Register (obsolete on ATA1+)
-REG_IDE_CNT				EQU		2		; Sector Count Register
-REG_IDE_SECT			EQU		3		; Sector Number Register (LBA 7...0)
-REG_IDE_LBA_LOW			EQU		3		; LBA Low Register
-REG_IDE_LOCYL			EQU		4		; Low Cylinder Register (LBA 15...8)
-REG_IDE_LBA_MID			EQU		4		; LBA Mid Register
-REG_IDE_HICYL			EQU		5		; High Cylinder Register (LBA 23...16)
-REG_IDE_LBA_HIGH		EQU		5		; LBA High Register
-REG_IDE_DRVHD			EQU		6		; Drive and Head Register (LBA 27...24)
-REGR_IDE_ST				EQU		7		; Status Register
-REGW_IDE_CMD			EQU		7		; Command Register
-REG_IDE_HIDATA			EQU		8		; XTIDE Data High Register (actually first Control Block reg)
+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)
-REGR_IDEC_AST			EQU		6		; Alternate Status Register
-REGW_IDEC_CTRL			EQU		6		; Device Control Register
-;REGR_IDEC_ADDR			EQU		7		; Drive Address Register (obsolete on ATA2+)
+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_IDE_ERR_BBK			EQU		(1<<7)	; Bad Block Detected (reserved on ATA2+, command dependent on ATA4+)
-FLG_IDE_ERR_UNC			EQU		(1<<6)	; Uncorrectable Data Error (command dependent on ATA4+)
-FLG_IDE_ERR_MC			EQU		(1<<5)	; Media Changed (command dependent on ATA4+)
-FLG_IDE_ERR_IDNF		EQU		(1<<4)	; ID Not Found (command dependent on ATA4+)
-FLG_IDE_ERR_MCR			EQU		(1<<3)	; Media Change Request (command dependent on ATA4+)
-FLG_IDE_ERR_ABRT		EQU		(1<<2)	; Command Aborted
-FLG_IDE_ERR_TK0NF		EQU		(1<<1)	; Track 0 Not Found (command dependent on ATA4+)
-FLG_IDE_ERR_AMNF		EQU		(1<<0)	; Address Mark Not Found (command dependent on ATA4+)
+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_IDE_DRVHD_LBA		EQU		(1<<6)	; LBA Addressing enabled (instead of CHS)
-FLG_IDE_DRVHD_DRV		EQU		(1<<4)	; Drive Select (0=Master, 1=Slave)
-MASK_IDE_DRVHD_HEAD		EQU		0Fh		; Head select bits (bits 0...3)
-MASK_IDE_DRVHD_SET		EQU		0A0h	; Bits that must be set to 1 on ATA1 (reserved on ATA2+)
+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_IDE_ST_BSY			EQU		(1<<7)	; Busy (other flags undefined when set)
-FLG_IDE_ST_DRDY			EQU		(1<<6)	; Device Ready
-FLG_IDE_ST_DF			EQU		(1<<5)	; Device Fault (command dependent on ATA4+)
-FLG_IDE_ST_DSC			EQU		(1<<4)	; Device Seek Complete (command dependent on ATA4+)
-FLG_IDE_ST_DRQ			EQU		(1<<3)	; Data Request
-FLG_IDE_ST_CORR			EQU		(1<<2)	; Corrected Data (obsolete on ATA4+)
-FLG_IDE_ST_IDX			EQU		(1<<1)	; Index (vendor specific on ATA2+, obsolete on ATA4+)
-FLG_IDE_ST_ERR			EQU		(1<<0)	; Error
+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_IDE_CTRL_O8H		EQU		(1<<3)	; Drive has more than 8 heads (pre-ATA only, 1 on ATA1, reserved on ATA2+)
-FLG_IDE_CTRL_SRST		EQU		(1<<2)	; Software Reset
-FLG_IDE_CTRL_nIEN		EQU		(1<<1)	; Negated Interrupt Enable (IRQ disabled when set)
-
+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
-;HCMD_RECALIBRATE		EQU		10h		; Recalibrate
-HCMD_READ_SECT			EQU		20h		; Read Sectors (with retries)
-HCMD_WRITE_SECT			EQU		30h		; Write Sectors (with retries)
-HCMD_VERIFY_SECT		EQU		40h		; Read Verify Sectors (with retries)
-;HCMD_FORMAT			EQU		50h		; Format track
-HCMD_SEEK				EQU		70h		; Seek
-;HCMD_DIAGNOSTIC		EQU		90h		; Execute Device Diagnostic
-HCMD_INIT_DEV			EQU		91h		; Initialize Device Parameters
-HCMD_READ_MUL			EQU		0C4h	; Read Multiple (=block)
-HCMD_WRITE_MUL			EQU		0C5h	; Write Multiple (=block)
-HCMD_SET_MUL			EQU		0C6h	; Set Multiple Mode (=block size)
-HCMD_ID_DEV				EQU		0ECh	; Identify Device
-HCMD_SET_FEAT			EQU		0EFh	; Set Features
-
-; Set Features subcommands
-HFEAT_SET_XFER_MODE		EQU		03h		; Set transfer mode based on value in Sector Count register
+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
 
 
Index: trunk/XTIDE_Universal_BIOS/Inc/Int13h.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/Int13h.inc	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Inc/Int13h.inc	(revision 150)
@@ -1,7 +1,3 @@
-; File name		:	Int13h.inc
-; Project name	:	IDE BIOS
-; Created date	:	23.3.2010
-; Last update	:	29.7.2010
-; Author		:	Tomi Tilli
+; Project name	:	XTIDE Universal BIOS
 ; Description	:	Equates used in INT 13h functions.
 %ifndef INT13H_INC
@@ -40,14 +36,4 @@
 
 
-; Timeout values for IDE controller timeout
-; 255 is the maximum value. Zero means immediate timeout.
-B_TIMEOUT_BSY			EQU		(1000/55)	; 1000 ms
-B_TIMEOUT_RDY			EQU		(1000/55)	; 1000 ms
-B_TIMEOUT_DRQ			EQU		255			;   14 s (some CF cards occasionally have long write delays)
-B_TIMEOUT_DRVINFO		EQU		(500/55)	;  500 ms
-B_TIMEOUT_RESET			EQU		255			;   14 s
-
-
-
 ; Floppy Drive types returned by INT 13h, AH=08h
 FLOPPY_TYPE_525_OR_35_DD	EQU	0
@@ -59,3 +45,8 @@
 
 
+MAX_SUPPORTED_BLOCK_SIZE_IN_SECTORS		EQU		64
+
+%define TIMEOUT_AND_STATUS_TO_WAIT(timeout, status)		(((timeout)<<8) | (status))
+
+
 %endif ; INT13H_INC
Index: trunk/XTIDE_Universal_BIOS/Inc/RamVars.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/RamVars.inc	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Inc/RamVars.inc	(revision 150)
@@ -5,5 +5,5 @@
 
 ; Segment when RAMVARS is stored to top of interrupt vectors.
-SEGMENT_RAMVARS_TOP_OF_INTERRUPT_VECTORS		EQU		30h
+LITE_MODE_RAMVARS_SEGMENT	EQU		30h
 
 
@@ -21,6 +21,7 @@
 struc RAMVARS
 	.fpOldI13h			resb	4	; Far pointer to old INT 13h handler
-	.wIdeBase			resb	2	; Base port address for currently handled controller
 	.wTimeoutCounter	resb	2
+	.pInServiceDPT		resb	2	; Ptr to DPT for drive waiting for interrupt
+	.wSignature			resb	2	; Sign for finding stolen 1 kiB
 
 	.wDrvCntAndFirst:
@@ -32,11 +33,37 @@
 endstruc
 
-; Full mode RAM variables.
-struc FULLRAMVARS
-	.ramVars			resb	RAMVARS_size
-	.wSign				resb	2		; FULLRAMVARS signature for finding segment
+RAMVARS_SIGNATURE		EQU	"Xu"	; RAMVARS signature for .wSignature
+
+
+struc IDEPACK
+	.bDrvAndHead			resb	1	; LBA28 27...24
+	.bFeatures				resb	1
+
+	.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
+
+	; Parameters for 48-bit LBA
+	.wSectorCountHighAndLbaLowExt:
+	.bSectorCountHighExt	resb	1	; LBA48 Sector Count 15...8
+	.bLbaLowExt				resb	1	; LBA48 31...24
+
+	.wLbaMiddleAndHighExt:
+	.bLbaMiddleExt			resb	1	; LBA48 39...32
+	.bLbaHighExt			resb	1	; LBA48 47...40
+
+	.intpack				resb	INTPACK_size
 endstruc
 
-W_SIGN_FULLRAMVARS		EQU	"fR"		; FULLRAMVARS signature
+EXTRA_WORDS_TO_RESERVE_FOR_INTPACK	EQU	((IDEPACK_size - INTPACK_size) / 2)
 
 
Index: trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 150)
@@ -41,5 +41,5 @@
 	.wPort				resb	2	; IDE Base Port for Command Block (usual) Registers
 	.wPortCtrl			resb	2	; IDE Base Port for Control Block Registers
-	.bBusType			resb	1	; Bus type
+	.bDevice			resb	1	; Device type
 	.bIRQ				resb	1	; Interrupt Request Number
 	.drvParamsMaster	resb	DRVPARAMS_size
@@ -47,9 +47,11 @@
 endstruc
 
-; Bus types for IDEVARS.bBusType
-BUS_TYPE_8_DUAL			EQU	(0<<1)	; XTIDE transfers with two 8-bit data ports
-BUS_TYPE_16				EQU	(1<<1)	; Normal 16-bit AT-IDE transfers
-BUS_TYPE_32				EQU	(2<<1)	; 32-bit VLB and PCI transfers
-BUS_TYPE_8_SINGLE		EQU	(3<<1)	; 8-bit transfers with single 8-bit data port
+; Device types for IDEVARS.bDeviceType
+DEVICE_8BIT_DUAL_PORT_XTIDE				EQU	(0<<1)
+DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0	EQU	(1<<1)
+DEVICE_8BIT_SINGLE_PORT					EQU	(2<<1)
+DEVICE_16BIT_ATA						EQU	(3<<1)
+DEVICE_32BIT_ATA						EQU	(4<<1)
+DEVICE_SERIAL_PORT						EQU	(5<<1)
 
 
Index: trunk/XTIDE_Universal_BIOS/Src/Boot/BootMenuPrint.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Boot/BootMenuPrint.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Boot/BootMenuPrint.asm	(revision 150)
@@ -111,5 +111,5 @@
 BootMenuPrint_HardDiskMenuitem:
 	call	PrintDriveNumberAfterTranslationFromDL
-	call	FindDPT_ForDriveNumber		; DS:DI to point DPT
+	call	RamVars_IsDriveHandledByThisBIOS
 	jnc		SHORT .HardDiskMenuitemForForeignDrive
 	; Fall to .HardDiskMenuitemForOurDrive
@@ -280,6 +280,7 @@
 ALIGN JUMP_ALIGN
 BootMenuPrint_HardDiskMenuitemInformation:
+	call	RamVars_IsDriveHandledByThisBIOS
+	jnc		SHORT .HardDiskMenuitemInfoForForeignDrive
 	call	FindDPT_ForDriveNumber		; DS:DI to point DPT
-	jnc		SHORT .HardDiskMenuitemInfoForForeignDrive
 	; Fall to .HardDiskMenuitemInfoForOurDrive
 
@@ -303,9 +304,10 @@
 
 	; Get and push L-CHS size
-	call	HCapacity_GetSectorCountFromOurAH08h
+	mov		[RAMVARS.wTimeoutCounter], dl		; Store drive number
+	call	AH15h_GetSectorCountToDXAX
 	call	ConvertSectorCountInBXDXAXtoSizeAndPushForFormat
 
 	; Get and push total LBA size
-	mov		dl, [di+DPT.bDrvNum]
+	mov		dl, [RAMVARS.wTimeoutCounter]		; Restore drive number
 	call	BootInfo_GetTotalSectorCount
 	call	ConvertSectorCountInBXDXAXtoSizeAndPushForFormat
@@ -332,5 +334,5 @@
 
 	call	DriveXlate_ToOrBack
-	call	HCapacity_GetSectorCountFromForeignAH08h
+	call	AH15h_GetSectorCountFromForeignDriveToDXAX
 	call	ConvertSectorCountInBXDXAXtoSizeAndPushForFormat
 
Index: trunk/XTIDE_Universal_BIOS/Src/Boot/BootMenuPrintCfg.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Boot/BootMenuPrintCfg.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Boot/BootMenuPrintCfg.asm	(revision 150)
@@ -17,5 +17,5 @@
 ;		Nothing
 ;	Corrupts registers:
-;		AX, BX, CX, DX, SI, DI, ES
+;		AX, BX, CX, DX, SI, DI
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
@@ -24,7 +24,7 @@
 	mov		si, g_szCfgHeader
 	call	BootMenuPrint_NullTerminatedStringFromCSSIandSetCF
-	call	BootMenuPrintCfg_GetPointers
+	eMOVZX	ax, BYTE [di+DPT.bIdevarsOffset]
+	xchg	si, ax						; CS:SI now points to IDEVARS
 	; Fall to PushAndFormatCfgString
-
 
 ;--------------------------------------------------------------------
@@ -32,5 +32,4 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT
-;		ES:BX:	Ptr to BOOTNFO
 ;		CS:SI:	Ptr to IDEVARS
 ;	Returns:
@@ -48,5 +47,4 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT
-;		ES:BX:	Ptr to BOOTNFO
 ;		CS:SI:	Ptr to IDEVARS
 ;	Returns:
@@ -56,18 +54,6 @@
 ;--------------------------------------------------------------------
 PushAddressingMode:
-	xchg	ax, bx
-	mov		bx, MASK_DPT_ADDR	; Load addressing mode mask
-	and		bl, [di+DPT.bFlags]	; Addressing mode now in BX
-	push	WORD [cs:bx+.rgszAddressingModeString]
-	xchg	bx, ax
-	jmp		SHORT .NextPush
-ALIGN WORD_ALIGN
-.rgszAddressingModeString:
-	dw		g_szLCHS
-	dw		g_szPCHS
-	dw		g_szLBA28
-	dw		g_szLBA48
-ALIGN JUMP_ALIGN
-.NextPush:
+	call	AccessDPT_GetAddressingModeForWordLookToBX
+	push	WORD [cs:bx+rgszAddressingModeString]
 
 ;--------------------------------------------------------------------
@@ -75,5 +61,4 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT
-;		ES:BX:	Ptr to BOOTNFO
 ;		CS:SI:	Ptr to IDEVARS
 ;	Returns:
@@ -83,5 +68,9 @@
 ;--------------------------------------------------------------------
 PushBlockMode:
-	eMOVZX	ax, BYTE [di+DPT.bSetBlock]
+	mov		ax, 1
+	test	WORD [di+DPT.wFlags], FLG_DPT_BLOCK_MODE_SUPPORTED
+	jz		SHORT .PushBlockSizeFromAX
+	mov		al, [di+DPT_ATA.bSetBlock]
+.PushBlockSizeFromAX:
 	push	ax
 
@@ -90,5 +79,4 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT
-;		ES:BX:	Ptr to BOOTNFO
 ;		CS:SI:	Ptr to IDEVARS
 ;	Returns:
@@ -99,19 +87,10 @@
 PushBusType:
 	xchg	ax, bx		; Store BX to AX
-	eMOVZX	bx, BYTE [cs:si+IDEVARS.bBusType]
-	mov		bx, [cs:bx+.rgwBusTypeValues]	; Char to BL, Int to BH
+	eMOVZX	bx, BYTE [cs:si+IDEVARS.bDevice]
+	mov		bx, [cs:bx+rgwBusTypeValues]	; Char to BL, Int to BH
 	eMOVZX	dx, bh
 	push	bx			; Push character
-	push	dx			; Push 8, 16 or 32
+	push	dx			; Push 1, 8, 16 or 32
 	xchg	bx, ax		; Restore BX
-	jmp		SHORT .NextPush
-ALIGN WORD_ALIGN
-.rgwBusTypeValues:
-	db		'D', 8		; BUS_TYPE_8_DUAL
-	db		' ', 16		; BUS_TYPE_16
-	db		' ', 32		; BUS_TYPE_32
-	db		'S', 8		; BUS_TYPE_8_SINGLE
-ALIGN JUMP_ALIGN
-.NextPush:
 
 ;--------------------------------------------------------------------
@@ -119,5 +98,4 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT
-;		ES:BX:	Ptr to BOOTNFO
 ;		CS:SI:	Ptr to IDEVARS
 ;	Returns:
@@ -152,5 +130,4 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT
-;		ES:BX:	Ptr to BOOTNFO
 ;		CS:SI:	Ptr to IDEVARS
 ;	Returns:
@@ -160,5 +137,6 @@
 ;--------------------------------------------------------------------
 PushResetStatus:
-	eMOVZX	ax, BYTE [di+DPT.bReset]
+	mov		ax, [di+DPT.wFlags]
+	and		ax, MASK_DPT_RESET
 	push	ax
 
@@ -177,21 +155,16 @@
 
 
-;--------------------------------------------------------------------
-; BootMenuPrintCfg_GetPointers
-;	Parameters:
-;		DS:DI:	Ptr to DPT
-;	Returns:
-;		DS:DI:	Ptr to DPT
-;		ES:BX:	Ptr to BOOTNFO
-;		CS:SI:	Ptr to IDEVARS
-;	Corrupts registers:
-;		AX, DL
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-BootMenuPrintCfg_GetPointers:
-	mov		dl, [di+DPT.bDrvNum]		; Load Drive number to DL
-	call	BootInfo_GetOffsetToBX		; ES:BX now points...
-	LOAD_BDA_SEGMENT_TO	es, ax, !		; ...to BOOTNFO
-	mov		al, [di+DPT.bIdeOff]
-	xchg	si, ax						; CS:SI now points to IDEVARS
-	ret
+ALIGN WORD_ALIGN
+rgszAddressingModeString:
+	dw		g_szLCHS
+	dw		g_szPCHS
+	dw		g_szLBA28
+	dw		g_szLBA48
+
+rgwBusTypeValues:
+	db		'D', 8		; DEVICE_8BIT_DUAL_PORT_XTIDE
+	db		'X', 8		; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
+	db		'S', 8		; DEVICE_8BIT_SINGLE_PORT
+	db		' ', 16		; DEVICE_16BIT_ATA
+	db		' ', 32		; DEVICE_32BIT_ATA
+	db		' ', 1		; DEVICE_SERIAL_PORT
Index: trunk/XTIDE_Universal_BIOS/Src/Device/Device.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/Device.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/Device.asm	(revision 150)
@@ -0,0 +1,188 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Command and port direction functions for different device types.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Device_FinalizeDPT
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+Device_FinalizeDPT:
+	test	WORD [di+DPT.wFlags], FLG_DPT_SERIAL_DEVICE
+	jnz		SHORT ReturnSuccessForSerialPort
+	jmp		IdeDPT_Finalize
+.FinalizeDptForSerialPortDevice:
+	jmp		SerialDPT_Finalize
+
+
+;--------------------------------------------------------------------
+; 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
+;--------------------------------------------------------------------
+Device_ResetMasterAndSlaveController:
+	test	WORD [di+DPT.wFlags], FLG_DPT_SERIAL_DEVICE
+	jnz		SHORT ReturnSuccessForSerialPort
+	jmp		IdeCommand_ResetMasterAndSlaveController
+
+
+;--------------------------------------------------------------------
+; Device_IdentifyToBufferInESSIwithDriveSelectByteInBH
+;	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:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BL, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+Device_IdentifyToBufferInESSIwithDriveSelectByteInBH:
+	cmp		BYTE [cs:bp+IDEVARS.bDevice], DEVICE_SERIAL_PORT
+	je		SHORT .IdentifyDriveFromSerialPort
+	jmp		IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
+.IdentifyDriveFromSerialPort:
+	jmp		SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
+
+
+;--------------------------------------------------------------------
+; 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
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, (ES:SI for data transfer commands)
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Device_OutputCommandWithParameters:
+	call	IdeIrq_SetInServiceDPTandClearTaskFlag
+	test	WORD [di+DPT.wFlags], FLG_DPT_SERIAL_DEVICE
+	jnz		SHORT .OutputCommandToSerialPort
+	jmp		IdeCommand_OutputWithParameters
+ALIGN JUMP_ALIGN
+.OutputCommandToSerialPort:
+	jmp		SerialCommand_OutputWithParameters
+
+
+;--------------------------------------------------------------------
+; 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
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Device_SelectDrive:
+	test	WORD [di+DPT.wFlags], FLG_DPT_SERIAL_DEVICE
+	jnz		SHORT ReturnSuccessForSerialPort
+	jmp		IdeCommand_SelectDrive
+ReturnSuccessForSerialPort:
+	xor		ax, ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Device_OutputALtoIdeRegisterInDL
+;	Parameters:
+;		AL:		Byte to output
+;		DL:		IDE Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Device_OutputALtoIdeRegisterInDL:
+	mov		bx, IdeIO_OutputALtoIdeRegisterInDX
+	jmp		SHORT TranslateRegisterAddressInDLifNecessaryThenJumpToBX
+
+
+;--------------------------------------------------------------------
+; Device_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
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Device_OutputALtoIdeControlBlockRegisterInDL:
+	mov		bx, IdeIO_OutputALtoIdeControlBlockRegisterInDX
+	jmp		SHORT TranslateRegisterAddressInDLifNecessaryThenJumpToBX
+
+
+;--------------------------------------------------------------------
+; Device_InputToALfromIdeRegisterInDL
+;	Parameters:
+;		DL:		IDE Register
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AL:		Inputted byte
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Device_InputToALfromIdeRegisterInDL:
+	mov		bx, IdeIO_InputToALfromIdeRegisterInDX
+	; Fall to TranslateRegisterAddressInDLifNecessaryThenJumpToBX
+
+
+;--------------------------------------------------------------------
+; TranslateRegisterAddressInDLifNecessaryThenJumpToBX
+;	Parameters:
+;		AL:		Byte to output (if output function in BX)
+;		DL:		IDE Register
+;		BX:		I/O function to jump to
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AL:		Inputted byte (if input function in BX)
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+TranslateRegisterAddressInDLifNecessaryThenJumpToBX:
+	test	WORD [di+DPT.wFlags], FLG_DPT_REVERSED_A0_AND_A3
+	jz		SHORT .JumpToIoFunctionInSI
+
+	; Exchange address lines A0 and A3 from DL
+	mov		dh, MASK_A3_AND_A0_ADDRESS_LINES
+	and		dh, dl							; DH = 0, 1, 8 or 9, we can ignore 0 and 9
+	jz		SHORT .JumpToIoFunctionInSI		; Jump out since DH is 0
+	xor		dh, MASK_A3_AND_A0_ADDRESS_LINES
+	jz		SHORT .JumpToIoFunctionInSI		; Jump out since DH was 9
+	and		dl, ~MASK_A3_AND_A0_ADDRESS_LINES
+	or		dl, dh							; Address lines now reversed
+
+ALIGN JUMP_ALIGN
+.JumpToIoFunctionInSI:
+	push	bx
+	xor		dh, dh
+	eMOVZX	bx, BYTE [di+DPT.bIdevarsOffset]; CS:BX now points to IDEVARS
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeCommand.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeCommand.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeCommand.asm	(revision 150)
@@ -0,0 +1,217 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device Command functions.
+
+; 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
+	mov		dl, DEVICE_CONTROL_REGISTER_out
+	call	Device_OutputALtoIdeControlBlockRegisterInDL
+	mov		ax, HSR0_RESET_WAIT_US
+	call	HTimer_DelayMicrosecondsFromAX
+
+	; HSR1: Clear_wait
+	call	AccessDPT_GetDeviceControlByteToAL
+	or		al, FLG_DEVCONTROL_nIEN
+	and		al, ~FLG_DEVCONTROL_SRST						; Clear reset bit
+	mov		dl, DEVICE_CONTROL_REGISTER_out
+	call	Device_OutputALtoIdeControlBlockRegisterInDL
+	mov		ax, HSR1_RESET_WAIT_US
+	call	HTimer_DelayMicrosecondsFromAX
+
+	; HSR2: Check_status
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_MOTOR_STARTUP, FLG_STATUS_BSY)
+	jmp		IdeWait_PollStatusFlagInBLwithTimeoutInBH
+
+
+;--------------------------------------------------------------------
+; IdeCommand_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:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BL, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH:
+	; Create fake DPT to be able to use Device.asm functions
+	call	FindDPT_ForNewDriveToDSDI
+	xor		ax, ax
+	cmp		BYTE [cs:bp+IDEVARS.bDevice], DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
+	eCMOVE	ax, FLG_DPT_REVERSED_A0_AND_A3
+	or		al, bh
+	mov		[di+DPT.wFlags], ax
+	mov		[di+DPT.bIdevarsOffset], bp
+	mov		BYTE [di+DPT_ATA.bSetBlock], 1	; Block = 1 sector
+
+	; Wait until drive motors have reached max speed
+	cmp		bp, BYTE ROMVARS.ideVars0
+	jne		SHORT .SkipLongWaitSinceDriveIsNotPrimaryMaster
+	test	bh, FLG_DRVNHEAD_DRV
+	jnz		SHORT .SkipLongWaitSinceDriveIsNotPrimaryMaster
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_MOTOR_STARTUP, FLG_STATUS_BSY)
+	call	IdeWait_PollStatusFlagInBLwithTimeoutInBH
+.SkipLongWaitSinceDriveIsNotPrimaryMaster:
+
+	; Create IDEPACK without INTPACK
+	push	bp
+	call	Idepack_FakeToSSBP
+
+	; 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_IDENTIFY_DEVICE, FLG_STATUS_DRQ)
+	call	Idepack_StoreNonExtParametersAndIssueCommandFromAL
+
+	; Clean stack and return
+	rcl		al, 1		; Store CF
+	add		sp, BYTE SIZE_OF_FAKE_IDEPACK
+	rcr		al, 1		; Restore CF
+	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
+;		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		dl, DEVICE_CONTROL_REGISTER_out
+	mov		al, [bp+IDEPACK.bDeviceControl]
+	call	Device_OutputALtoIdeControlBlockRegisterInDL
+
+	; Output Feature Number
+	mov		dl, FEATURES_REGISTER_out
+	mov		al, [bp+IDEPACK.bFeatures]
+	call	Device_OutputALtoIdeRegisterInDL
+
+	; Output Sector Address High (only used by LBA48)
+	mov		ax, [bp+IDEPACK.wSectorCountHighAndLbaLowExt]
+	mov		cx, [bp+IDEPACK.wLbaMiddleAndHighExt]
+	call	OutputSectorCountAndAddress
+
+	; Output Sector Address Low
+	mov		ax, [bp+IDEPACK.wSectorCountAndLbaLow]
+	mov		cx, [bp+IDEPACK.wLbaMiddleAndHigh]
+	call	OutputSectorCountAndAddress
+
+	; Output command
+	mov		dl, COMMAND_REGISTER_out
+	mov		al, [bp+IDEPACK.bCommand]
+	call	Device_OutputALtoIdeRegisterInDL
+
+	; Wait until command completed
+	pop		bx							; Pop status and timeout for polling
+	cmp		bl, FLG_STATUS_DRQ			; Data transfer started?
+	je		SHORT .StartDataTransfer
+	test	BYTE [bp+IDEPACK.bDeviceControl], FLG_DEVCONTROL_nIEN
+	jz		SHORT .WaitForIrqOrRdy
+	jmp		IdeWait_PollStatusFlagInBLwithTimeoutInBH
+
+ALIGN JUMP_ALIGN
+.WaitForIrqOrRdy:
+	jmp		IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
+ALIGN JUMP_ALIGN
+.StartDataTransfer:
+	jmp		IdeTransfer_StartWithCommandInAL
+
+.DriveNotReady:
+	pop		bx							; Clean stack
+ReturnSinceTimeoutWhenPollingBusy:
+	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:
+	; Wait until neither Master or Slave Drive is busy
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_BSY, FLG_STATUS_BSY)
+	cmp		BYTE [bp+IDEPACK.bCommand], COMMAND_IDENTIFY_DEVICE
+	eCMOVE	bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_IDENTIFY_DEVICE, FLG_STATUS_BSY)
+	call	IdeWait_PollStatusFlagInBLwithTimeoutInBH
+	jc		SHORT ReturnSinceTimeoutWhenPollingBusy
+
+	; Select Master or Slave Drive
+	mov		dl, DRIVE_AND_HEAD_SELECT_REGISTER
+	mov		al, [bp+IDEPACK.bDrvAndHead]
+	call	Device_OutputALtoIdeRegisterInDL
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRDY, FLG_STATUS_DRDY)
+	cmp		BYTE [bp+IDEPACK.bCommand], COMMAND_IDENTIFY_DEVICE
+	eCMOVE	bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_IDENTIFY_DEVICE, FLG_STATUS_DRDY)
+	jmp		IdeWait_PollStatusFlagInBLwithTimeoutInBH
+
+
+;--------------------------------------------------------------------
+; 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:
+	mov		dl, SECTOR_COUNT_REGISTER
+	call	Device_OutputALtoIdeRegisterInDL
+
+	mov		al, ah
+	mov		dl, LBA_LOW_REGISTER
+	call	Device_OutputALtoIdeRegisterInDL
+
+	mov		al, cl
+	mov		dl, LBA_MIDDLE_REGISTER
+	call	Device_OutputALtoIdeRegisterInDL
+
+	mov		al, ch
+	mov		dl, LBA_HIGH_REGISTER
+	jmp		Device_OutputALtoIdeRegisterInDL
Index: trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDPT.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDPT.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDPT.asm	(revision 150)
@@ -0,0 +1,38 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Sets IDE Device specific parameters to DPT.
+
+; 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
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+IdeDPT_Finalize:
+	; Fall to .StoreBlockMode
+
+;--------------------------------------------------------------------
+; .StoreBlockMode
+;	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
+;--------------------------------------------------------------------
+.StoreBlockMode:
+	mov		al, 1
+	mov		ah, [es:si+ATA1.bBlckSize]		; Max block size in sectors
+	mov		[di+DPT_ATA.wSetAndMaxBlock], ax
+	; Fall to .EndDPT
+
+
+.EndDPT:
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeError.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeError.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeError.asm	(revision 150)
@@ -0,0 +1,93 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device error functions.
+
+; 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
+	mov		dl, ERROR_REGISTER_in
+	call	Device_InputToALfromIdeRegisterInDL
+	xchg	al, ah			; Status Register now in AL, Error Register now in AH
+
+	; I don't think anything actually reads these from BDA
+	push	ds
+	LOAD_BDA_SEGMENT_TO	ds, dx
+	mov		[HDBDA.wHDStAndErr], ax
+	pop		ds
+
+	; 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: trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIO.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIO.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIO.asm	(revision 150)
@@ -0,0 +1,57 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Register I/O functions.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeIO_OutputALtoIdeRegisterInDX
+;	Parameters:
+;		AL:		Byte to output
+;		DX:		IDE Register
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIO_OutputALtoIdeRegisterInDX:
+	add		dx, [cs:bx+IDEVARS.wPort]
+	out		dx, al
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeIO_OutputALtoIdeControlBlockRegisterInDX
+;	Parameters:
+;		AL:		Byte to output
+;		DX:		IDE Control Block Register
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIO_OutputALtoIdeControlBlockRegisterInDX:
+	add		dx, [cs:bx+IDEVARS.wPortCtrl]
+	out		dx, al
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeIO_InputToALfromIdeRegisterInDX
+;	Parameters:
+;		DX:		IDE Register
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		AL:		Inputted byte
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIO_InputToALfromIdeRegisterInDX:
+	add		dx, [cs:bx+IDEVARS.wPort]
+	in		al, dx
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIrq.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIrq.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeIrq.asm	(revision 150)
@@ -0,0 +1,140 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Interrupt handling related functions.
+
+; 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:
+	pop		ds
+	sti									; Enable interrupts
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeIrq_SetInServiceDPTandClearTaskFlag
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeIrq_SetInServiceDPTandClearTaskFlag:
+	mov		[RAMVARS.pInServiceDPT], di
+	push	ds
+	LOAD_BDA_SEGMENT_TO	ds, ax, !		; Also zero AX
+	mov		[BDA.bHDTaskFlg], al
+	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, CMD_END_OF_INTERRUPT
+	jmp		SHORT AcknowledgeMasterInterruptController
+
+
+ALIGN JUMP_ALIGN
+IdeIrq_InterruptServiceRoutineForIrqs8to15:
+	push	di
+	push	ax
+	call	AcknowledgeIdeInterruptAndSetTaskFlag
+
+	mov		al, CMD_END_OF_INTERRUPT	; Load EOI command to AL
+	out		WPORT_8259SL_COMMAND, al	; Acknowledge Slave 8259
+AcknowledgeMasterInterruptController:
+	out		WPORT_8259MA_COMMAND, 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	dx
+	push	bx
+
+	; Reading Status Register acknowledges IDE interrupt
+	call	RamVars_GetSegmentToDS
+	mov		di, [RAMVARS.pInServiceDPT]		; DS:DI now points to DPT
+	mov		dl, STATUS_REGISTER_in
+	call	Device_InputToALfromIdeRegisterInDL
+
+	; Set Task Flag
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	mov		BYTE [BDA.bHDTaskFlg], 0FFh		; Set task flag
+
+	pop		bx
+	pop		dx
+	pop		ds
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm	(revision 150)
@@ -0,0 +1,366 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device transfer functions.
+
+; Structure containing variables for PIO transfer functions.
+; This struct must not be larger than IDEPACK without INTPACK.
+struc PIOVARS
+	.wBlocksLeft			resb	2
+	.wBlockSize				resb	2	; Block size in WORDs (256...32768)
+	.wDataPort				resb	2
+	.bSectorsInLastBlock:	resb	1
+							resb	1	; Offset 7 = IDEPACK.bDeviceControl
+	.fnXfer					resb	2	; Offset to transfer function
+endstruc
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeTransfer_StartWithCommandInAL
+;	Parameters:
+;		AL:		IDE command that was used to start the transfer
+;		ES:SI:	Ptr to destination buffer or source data
+;		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, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeTransfer_StartWithCommandInAL:
+	mov		ah, [bp+IDEPACK.bSectorCountHighExt]
+
+	; Are we reading or writing
+	cmp		al, COMMAND_WRITE_MULTIPLE
+	je		SHORT .PrepareToWriteDataFromESSI
+	cmp		al, COMMAND_WRITE_MULTIPLE_EXT
+	je		SHORT .PrepareToWriteDataFromESSI
+	cmp		al, COMMAND_WRITE_SECTORS
+	je		SHORT .PrepareToWriteDataFromESSI
+	cmp		al, COMMAND_WRITE_SECTORS_EXT
+	je		SHORT .PrepareToWriteDataFromESSI
+
+	; Prepare to read data to ESSI
+	mov		bx, g_rgfnPioRead
+	mov		al, [bp+IDEPACK.bSectorCount]
+	call	InitializePiovarsInSSBPwithSectorCountInAX
+	xchg	si, di
+	call	Registers_NormalizeESDI
+	jmp		SHORT ReadFromDrive
+
+ALIGN JUMP_ALIGN
+.PrepareToWriteDataFromESSI:
+	mov		bx, g_rgfnPioWrite
+	mov		al, [bp+IDEPACK.bSectorCount]
+	call	InitializePiovarsInSSBPwithSectorCountInAX
+	call	Registers_NormalizeESSI
+	; Fall to WriteToDrive
+
+
+;--------------------------------------------------------------------
+; WriteToDrive
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		ES:SI:	Normalized ptr to buffer containing data
+;		SS:BP:	Ptr to PIOVARS
+;	Returns:
+;		AH:		BIOS Error code
+;		CF:		0 if transfer succesfull
+;				1 if any error
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI, ES
+;--------------------------------------------------------------------
+WriteToDrive:
+	; 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
+ALIGN JUMP_ALIGN
+.WriteNextBlock:
+	mov		dx, [bp+PIOVARS.wDataPort]
+	dec		WORD [bp+PIOVARS.wBlocksLeft]		; Transferring last (possibly partial) block?
+	jz		SHORT .XferLastBlock				;  If so, jump to transfer
+	mov		cx, [bp+PIOVARS.wBlockSize]			; Load block size in WORDs
+	call	[bp+PIOVARS.fnXfer]					; Transfer full block
+
+	; Normalize pointer when necessary
+	mov		ax, si
+	shr		ax, 1								; WORD offset
+	add		ax, [bp+PIOVARS.wBlockSize]
+	jns		SHORT .WaitUntilReadyToTransferNextBlock
+	call	Registers_NormalizeESSI
+
+ALIGN JUMP_ALIGN
+.WaitUntilReadyToTransferNextBlock:
+%ifdef USE_186
+	push	.WriteNextBlock
+	jmp		IdeWait_IRQorDRQ
+%else
+	call	IdeWait_IRQorDRQ
+	jnc		SHORT .WriteNextBlock
+%endif
+.ReturnWithTransferErrorInAH:
+	ret
+
+ALIGN JUMP_ALIGN
+.XferLastBlock:
+	xor		cx, cx
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+	mov		ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
+%ifdef USE_186
+	push	IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
+	jmp		[bp+PIOVARS.fnXfer]
+%else
+	call	[bp+PIOVARS.fnXfer]					; Transfer possibly partial block
+	jmp		IdeWait_IRQorStatusFlagInBLwithTimeoutInBH	; Check for errors
+%endif
+
+
+;--------------------------------------------------------------------
+; ReadFromDrive
+;	Parameters:
+;		ES:DI:	Normalized ptr to buffer to recieve data
+;		DS:SI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to PIOVARS
+;	Returns:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		AH:		BIOS Error code
+;		CF:		0 if transfer succesfull
+;				1 if any error
+;	Corrupts registers:
+;		AL, BX, CX, DX, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ReadFromDrive:
+	; Wait until drive is ready to transfer
+	xchg	di, si								; DS:DI now points DPT
+	call	IdeWait_IRQorDRQ					; Wait until ready to transfer
+	jc		SHORT WriteToDrive.ReturnWithTransferErrorInAH
+	xchg	si, di								; ES:DI now points buffer
+
+	; Transfer full or last (possible partial) block
+	mov		dx, [bp+PIOVARS.wDataPort]
+	dec		WORD [bp+PIOVARS.wBlocksLeft]
+	jz		SHORT .XferLastBlock
+	mov		cx, [bp+PIOVARS.wBlockSize]			; Load block size in WORDs
+	call	[bp+PIOVARS.fnXfer]					; Transfer full block
+
+	; Normalize pointer when necessary
+	mov		ax, di
+	shr		ax, 1								; WORD offset
+	add		ax, [bp+PIOVARS.wBlockSize]
+	jns		SHORT ReadFromDrive
+	call	Registers_NormalizeESDI
+	jmp		SHORT ReadFromDrive					; Loop while blocks left
+
+ALIGN JUMP_ALIGN
+.XferLastBlock:
+	xor		cx, cx
+	mov		ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
+	call	[bp+PIOVARS.fnXfer]					; Transfer possibly partial block
+	mov		di, si								; DS:DI now points DPT
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+	jmp		IdeWait_PollStatusFlagInBLwithTimeoutInBH
+
+
+;--------------------------------------------------------------------
+; InitializePiovarsInSSBPwithSectorCountInAX
+;	Parameters:
+;		AX:		Number of sectors to transfer (0=65536)
+;		BX:		Offset to transfer function lookup table
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to PIOVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+InitializePiovarsInSSBPwithSectorCountInAX:
+	; Store number of blocks to transfer
+	eMOVZX	cx, BYTE [di+DPT_ATA.bSetBlock]		; Block size in sectors
+	xor		dx, dx
+	test	ax, ax
+	eCMOVZ	dl, 1		; DX:AX = Sectors to transfer (1...65536)
+	div		cx			; AX = Full blocks to transfer
+	test	dx, dx
+	mov		dh, cl		; DH = Full block size if no partial blocks to transfer
+	jz		SHORT .NoPartialBlocksToTransfer
+	inc		ax			; Partial block
+	mov		dh, dl		; DH = Size of partial block in sectors
+.NoPartialBlocksToTransfer:
+	mov		[bp+PIOVARS.wBlocksLeft], ax
+	mov		[bp+PIOVARS.bSectorsInLastBlock], dh
+
+	; Store block size in WORDs
+	xchg	ch, cl		; CX = Block size in WORDs
+	mov		[bp+PIOVARS.wBlockSize], cx
+
+	; Get transfer function based on bus type
+	xchg	ax, bx
+	eMOVZX	bx, BYTE [di+DPT.bIdevarsOffset]	; CS:BX now points to IDEVARS
+	mov		dx, [cs:bx+IDEVARS.wPort]			; Load IDE Data port address
+	mov		bl, [cs:bx+IDEVARS.bDevice]			; Load device type to BX
+	add		bx, ax
+	mov		ax, [cs:bx]							; Load offset to transfer function
+	mov		[bp+PIOVARS.wDataPort], dx
+	mov		[bp+PIOVARS.fnXfer], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; DualByteRead		Dual port 8-bit XTIDE PIO read transfer
+; WordRead			Normal 16-bit IDE PIO read transfer
+; DWordRead			VLB/PCI 32-bit IDE PIO read transfer
+; SingleByteRead	Single port 8-bit PIO read transfer
+;	Parameters:
+;		CX:		Block size in WORDs
+;		DX:		IDE Data port address
+;		ES:DI:	Normalized ptr to buffer to recieve data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DualByteRead:
+	times 2	shr	cx, 1			; Loop unrolling
+	mov		bx, 8				; Bit mask for toggling data low/high reg
+ALIGN JUMP_ALIGN
+.InswLoop:
+	eDUAL_BYTE_PORT_INSW
+	eDUAL_BYTE_PORT_INSW
+	eDUAL_BYTE_PORT_INSW
+	eDUAL_BYTE_PORT_INSW
+	loop	.InswLoop
+	ret
+
+ALIGN JUMP_ALIGN
+WordRead:
+	rep
+	db		6Dh			; INSW
+	ret
+
+ALIGN JUMP_ALIGN
+DWordRead:
+	shr		cx, 1		; WORD count to DWORD count
+	rep
+	db		66h			; Override operand size to 32-bit
+	db		6Dh			; INSW/INSD
+	ret
+
+ALIGN JUMP_ALIGN
+SingleByteRead:
+%ifdef USE_186	; INS instruction available
+	shl		cx, 1				; WORD count to BYTE count
+	rep insb
+%else			; If 8088/8086
+	shr		cx, 1				; WORD count to DWORD count
+ALIGN JUMP_ALIGN
+.InsdLoop:
+	in		al, dx
+	stosb						; Store to [ES:DI]
+	in		al, dx
+	stosb
+	in		al, dx
+	stosb
+	in		al, dx
+	stosb
+	loop	.InsdLoop
+%endif
+	ret
+
+
+;--------------------------------------------------------------------
+; DualByteWrite		Dual port 8-bit XTIDE PIO write transfer
+; WordWrite			Normal 16-bit IDE PIO write transfer
+; DWordWrite		VLB/PCI 32-bit IDE PIO write transfer
+; SingleByteWrite	Single port 8-bit PIO write transfer
+;	Parameters:
+;		CX:		Block size in WORDs
+;		DX:		IDE Data port address
+;		ES:SI:	Normalized ptr to buffer containing data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DualByteWrite:
+	push	ds
+	push	bx
+	times 2	shr	cx, 1			; Loop unrolling
+	mov		bx, 8				; Bit mask for toggling data low/high reg
+	push	es					; Copy ES...
+	pop		ds					; ...to DS
+ALIGN JUMP_ALIGN
+.OutswLoop:
+	eDUAL_BYTE_PORT_OUTSW
+	eDUAL_BYTE_PORT_OUTSW
+	eDUAL_BYTE_PORT_OUTSW
+	eDUAL_BYTE_PORT_OUTSW
+	loop	.OutswLoop
+	pop		bx
+	pop		ds
+	ret
+
+ALIGN JUMP_ALIGN
+WordWrite:
+	eSEG	es			; Source is ES segment
+	rep
+	db		6Fh			; OUTSW
+	ret
+
+ALIGN JUMP_ALIGN
+DWordWrite:
+	shr		cx, 1		; WORD count to DWORD count
+	eSEG	es			; Source is ES segment
+	rep
+	db		66h			; Override operand size to 32-bit
+	db		6Fh			; OUTSW/OUTSD
+	ret
+
+ALIGN JUMP_ALIGN
+SingleByteWrite:
+%ifdef USE_186	; OUTS instruction available
+	shl		cx, 1				; WORD count to BYTE count
+	eSEG	es					; Source is ES segment
+	rep outsb
+%else			; If 8088/8086
+	shr		cx, 1				; WORD count to DWORD count
+	push	ds					; Store DS
+	push	es					; Copy ES...
+	pop		ds					; ...to DS
+ALIGN JUMP_ALIGN
+.OutsdLoop:
+	lodsb						; Load from [DS:SI] to AL
+	out		dx, al
+	lodsb
+	out		dx, al
+	lodsb
+	out		dx, al
+	lodsb
+	out		dx, al
+	loop	.OutsdLoop
+	pop		ds					; Restore DS
+%endif
+	ret
+
+
+; Lookup tables to get transfer function based on bus type
+ALIGN WORD_ALIGN
+g_rgfnPioRead:
+	dw		DualByteRead		; DEVICE_8BIT_DUAL_PORT_XTIDE
+	dw		NULL				; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
+	dw		SingleByteRead		; DEVICE_8BIT_SINGLE_PORT
+	dw		WordRead			; DEVICE_16BIT_ATA
+	dw		DWordRead			; DEVICE_32BIT_ATA
+g_rgfnPioWrite:
+	dw		DualByteWrite		; DEVICE_8BIT_DUAL_PORT_XTIDE
+	dw		NULL				; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
+	dw		SingleByteWrite		; DEVICE_8BIT_SINGLE_PORT
+	dw		WordWrite			; DEVICE_16BIT_ATA
+	dw		DWordWrite			; DEVICE_32BIT_ATA
Index: trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeWait.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeWait.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeWait.asm	(revision 150)
@@ -0,0 +1,129 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	IDE Device wait functions.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; IdeWait_IRQorDRQ
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK or PIOVARS
+;	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)
+	test	BYTE [bp+IDEPACK.bDeviceControl], FLG_DEVCONTROL_nIEN
+	jnz		SHORT IdeWait_PollStatusFlagInBLwithTimeoutInBH	; Interrupt disabled
+	; 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:
+	call	IdeIrq_WaitForIRQ
+	; 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:
+	eMOVZX	cx, bh		; Timeout ticks now in CX
+	mov		ah, bl
+	call	HTimer_InitializeTimeoutWithTicksInCX
+	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	ReadIdeStatusRegisterToAL			; Discard contents for first read
+ALIGN JUMP_ALIGN
+.PollLoop:
+	call	ReadIdeStatusRegisterToAL
+	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	HTimer_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	ReadIdeStatusRegisterToAL			; Discard contents for first read
+ALIGN JUMP_ALIGN
+.PollLoop:
+	call	ReadIdeStatusRegisterToAL
+	test	al, FLG_STATUS_BSY					; Controller busy?
+	jz		SHORT IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL
+	call	HTimer_SetCFifTimeout				; Update timeout counter
+	jnc		SHORT .PollLoop						; Loop if time left (sets CF on timeout)
+	jmp		SHORT IdeError_GetBiosErrorCodeToAHfromPolledStatusRegisterInAL
+
+
+;--------------------------------------------------------------------
+; ReadIdeStatusRegisterToAL
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AL:		IDE Status Register contents
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ReadIdeStatusRegisterToAL:
+	mov		dl, STATUS_REGISTER_in
+	jmp		Device_InputToALfromIdeRegisterInDL
Index: trunk/XTIDE_Universal_BIOS/Src/Device/Idepack.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/Idepack.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/Idepack.asm	(revision 150)
@@ -0,0 +1,104 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for managing IDEPACK struct.
+
+SIZE_OF_FAKE_IDEPACK		EQU		(IDEPACK_size - INTPACK_size)
+
+; 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_FAKE_IDEPACK
+	mov		bp, sp
+	jmp		ax
+
+
+;--------------------------------------------------------------------
+; Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+;	Parameters:
+;		AH:		IDE command to issue
+;		AL:		Number of sectors to transfer (1...255, 0=256)
+;		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)
+;		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
+;		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
+	mov		BYTE [bp+IDEPACK.bSectorCountHighExt], 0
+
+	push	bx
+	call	HAddress_OldInt13hAddressToIdeAddress
+	call	AccessDPT_GetDriveSelectByteToAL
+	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
+
+	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
+	mov		BYTE [bp+IDEPACK.bSectorCountHighExt], 0
+
+	; Drive and Head select byte
+	and		ah, MASK_DRVNHEAD_HEAD		; Keep head bits only
+	call	AccessDPT_GetDriveSelectByteToAL
+	or		al, ah
+	mov		[bp+IDEPACK.bDrvAndHead], al
+
+	; Device Control byte with interrupts disabled
+	call	AccessDPT_GetDeviceControlByteToAL
+	or		al, FLG_DEVCONTROL_nIEN		; Disable interrupt
+	mov		[bp+IDEPACK.bDeviceControl], al
+
+	jmp		Device_OutputCommandWithParameters
Index: trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm	(revision 150)
@@ -0,0 +1,41 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Serial Device Command functions.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; 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:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BL, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH:
+
+
+;--------------------------------------------------------------------
+; SerialCommand_OutputWithParameters
+;	Parameters:
+;		BH:		Non-zero if 48-bit addressing used
+;		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 IDEREGS_AND_INTPACK
+;	Returns:
+;		AH:		INT 13h Error Code
+;		CF:		Cleared if success, Set if error
+;	Corrupts registers:
+;		AL, BX, CX, DX, (ES:SI for data transfer commands)
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SerialCommand_OutputWithParameters:
+
+
Index: trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialDPT.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialDPT.asm	(revision 150)
+++ trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialDPT.asm	(revision 150)
@@ -0,0 +1,17 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Sets Serial Device specific parameters to DPT.
+
+; 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:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+SerialDPT_Finalize:
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h.asm	(revision 150)
@@ -22,5 +22,6 @@
 Int13h_DiskFunctionsHandler:
 	sti									; Enable interrupts
-	SAVE_AND_GET_INTPACK_TO_SSBP
+	cld									; String instructions to increment pointers
+	SAVE_AND_GET_INTPACK_WITH_EXTRA_WORDS_TO_SSBP EXTRA_WORDS_TO_RESERVE_FOR_INTPACK
 
 	call	RamVars_GetSegmentToDS
@@ -46,5 +47,5 @@
 ;		DL:		Translated drive number
 ;		DS:		RAMVARS segment
-;		SS:BP:	Ptr to INTPACK
+;		SS:BP:	Ptr to IDEPACK
 ;		BX, DI:	Corrupted on Int13h_DiskFunctionsHandler
 ;		Other:	Function specific INT 13h parameters 
@@ -58,11 +59,11 @@
 Int13h_DirectCallToAnotherBios:
 	call	ExchangeCurrentInt13hHandlerWithOldInt13hHandler
-	mov		bx, [bp+INTPACK.bx]
-	mov		di, [bp+INTPACK.di]
-	mov		ds, [bp+INTPACK.ds]
-	push	WORD [bp+INTPACK.flags]
+	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+INTPACK.bp]
+	mov		bp, [bp+IDEPACK.intpack+INTPACK.bp]
 	int		BIOS_DISK_INTERRUPT_13h	; Can safely do as much recursion as it wants
 
@@ -70,21 +71,21 @@
 	pop		bp	; Standard INT 13h functions never uses BP as return register
 %ifdef USE_386
-	mov		[bp+INTPACK.gs], gs
-	mov		[bp+INTPACK.fs], fs
+	mov		[bp+IDEPACK.intpack+INTPACK.gs], gs
+	mov		[bp+IDEPACK.intpack+INTPACK.fs], fs
 %endif
-	mov		[bp+INTPACK.es], es
-	mov		[bp+INTPACK.ds], ds
-	mov		[bp+INTPACK.di], di
-	mov		[bp+INTPACK.si], si
-	mov		[bp+INTPACK.bx], bx
-	mov		[bp+INTPACK.dh], dh
-	mov		[bp+INTPACK.cx], cx
-	mov		[bp+INTPACK.ax], ax
+	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
+	mov		[bp+IDEPACK.intpack+INTPACK.dh], dh
+	mov		[bp+IDEPACK.intpack+INTPACK.cx], cx
+	mov		[bp+IDEPACK.intpack+INTPACK.ax], ax
 	pushf
-	pop		WORD [bp+INTPACK.flags]
+	pop		WORD [bp+IDEPACK.intpack+INTPACK.flags]
 	call	RamVars_GetSegmentToDS
 	cmp		dl, [RAMVARS.xlateVars+XLATEVARS.bXlatedDrv]
 	je		SHORT .ExchangeInt13hHandlers
-	mov		[bp+INTPACK.dl], dl		; Something is returned in DL
+	mov		[bp+IDEPACK.intpack+INTPACK.dl], dl		; Something is returned in DL
 ALIGN JUMP_ALIGN
 .ExchangeInt13hHandlers:
@@ -98,5 +99,5 @@
 ;	Parameters:
 ;		AH:		BIOS Error code
-;		SS:BP:	Ptr to INTPACK
+;		SS:BP:	Ptr to IDEPACK
 ;	Returns:
 ;		All registers are loaded from INTPACK
@@ -104,9 +105,9 @@
 ALIGN JUMP_ALIGN
 Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH:
-	call	HError_SetErrorCodeToBdaAndToIntpackInSSBPfromAH
+	call	Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH
 Int13h_ReturnFromHandlerWithoutStoringErrorCode:
-	or		WORD [bp+INTPACK.flags], FLG_FLAGS_IF	; Return with interrupts enabled
+	or		WORD [bp+IDEPACK.intpack+INTPACK.flags], FLG_FLAGS_IF	; Return with interrupts enabled
 	mov		sp, bp									; Now we can exit anytime
-	RESTORE_INTPACK_FROM_SSBP
+	RESTORE_INTPACK_WITH_EXTRA_WORDS_FROM_SSBP EXTRA_WORDS_TO_RESERVE_FOR_INTPACK
 
 
@@ -146,4 +147,5 @@
 	LOAD_BDA_SEGMENT_TO	es, di
 	mov		di, [RAMVARS.fpOldI13h]
+	cli
 	xchg	di, [es:BIOS_DISK_INTERRUPT_13h*4]
 	mov		[RAMVARS.fpOldI13h], di
@@ -152,4 +154,34 @@
 	mov		[RAMVARS.fpOldI13h+2], di
 	pop		es
+	sti
+	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
+Int13h_SetErrorCodeToBdaAndToIntpackInSSBPfromAH:
+	; Store error code to BDA
+	LOAD_BDA_SEGMENT_TO	ds, di
+	mov		[BDA.bHDLastSt], ah
+
+	; 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
 
@@ -224,16 +256,20 @@
 ;	dw	Int13h_UnsupportedFunction						; 3Fh, 
 ;	dw	Int13h_UnsupportedFunction						; 40h, 
-;	dw	Int13h_UnsupportedFunction						; 41h, Check if Extensions Present (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 42h, Extended Read Sectors (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 43h, Extended Write Sectors (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 44h, Extended Verify Sectors (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 45h, Lock and Unlock Drive (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 46h, Eject Media Request (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 47h, Extended Seek (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 48h, Get Extended Drive Parameters (EBIOS)
-;	dw	Int13h_UnsupportedFunction						; 49h, Get Extended Disk Change Status (EBIOS)
+;	dw	Int13h_UnsupportedFunction						; 41h, Check if Extensions Present (EBIOS)*
+;	dw	Int13h_UnsupportedFunction						; 42h, Extended Read Sectors (EBIOS)*
+;	dw	Int13h_UnsupportedFunction						; 43h, Extended Write Sectors (EBIOS)*
+;	dw	Int13h_UnsupportedFunction						; 44h, Extended Verify Sectors (EBIOS)*
+;	dw	Int13h_UnsupportedFunction						; 45h, Lock and Unlock Drive (EBIOS)***
+;	dw	Int13h_UnsupportedFunction						; 46h, Eject Media Request (EBIOS)***
+;	dw	Int13h_UnsupportedFunction						; 47h, Extended Seek (EBIOS)*
+;	dw	Int13h_UnsupportedFunction						; 48h, Get Extended Drive Parameters (EBIOS)*
+;	dw	Int13h_UnsupportedFunction						; 49h, Get Extended Disk Change Status (EBIOS)***
 ;	dw	Int13h_UnsupportedFunction						; 4Ah, Initiate Disk Emulation (Bootable CD-ROM)
 ;	dw	Int13h_UnsupportedFunction						; 4Bh, Terminate Disk Emulation (Bootable CD-ROM)
 ;	dw	Int13h_UnsupportedFunction						; 4Ch, Initiate Disk Emulation and Boot (Bootable CD-ROM)
 ;	dw	Int13h_UnsupportedFunction						; 4Dh, Return Boot Catalog (Bootable CD-ROM)
-;	dw	Int13h_UnsupportedFunction						; 4Eh, Set Hardware Configuration (EBIOS)
+;	dw	Int13h_UnsupportedFunction						; 4Eh, Set Hardware Configuration (EBIOS)**
+;
+;   * = Enhanced Drive Access Support (minimum required EBIOS functions)
+;  ** = Enhanced Disk Drive (EDD) Support
+; *** = Drive Locking and Ejecting Support
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH0h_HReset.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH0h_HReset.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH0h_HReset.asm	(revision 150)
@@ -13,6 +13,6 @@
 ;				If bit 7 is set all hard disks and floppy disks reset.
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
 ;		AH:		Int 13h return status (from drive requested in DL)
 ;		CF:		0 if succesfull, 1 if error
@@ -89,12 +89,13 @@
 
 ;--------------------------------------------------------------------
-; ResetHardDisksHandledByOurBIOS
+; AH0h_ResetHardDisksHandledByOurBIOS
 ;	Parameters:
 ;		BL:		Requested drive (DL when entering AH=00h)
 ;		DS:		RAMVARS segment
+;		SS:BP:	Ptr to IDEPACK
 ;	Returns:
 ;		BH:		Error code from requested drive (if available)
 ;	Corrupts registers:
-;		AX, CX, DX, DI
+;		AX, CX, DX, SI, DI
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
@@ -103,5 +104,5 @@
 	test	dh, dh
 	jz		SHORT .AllDrivesReset		; Return if no drives
-	mov		dl, [RAMVARS.bFirstDrv]		; Load number of first our drive
+	mov		dl, [RAMVARS.bFirstDrv]		; Load number of our first drive
 	add		dh, dl						; DH = one past last drive to reset
 ALIGN JUMP_ALIGN
@@ -132,13 +133,37 @@
 .BackupErrorCodeFromMasterOrSlaveToBH:
 	call	BackupErrorCodeFromTheRequestedDriveToBH
-	mov		cx, [RAMVARS.wIdeBase]		; Load base port for resetted drive
-
+	call	GetBasePortToCX				; Load base port for resetted drive
+	push	cx
 	inc		dx							; DL to next drive
-	call	FindDPT_ForDriveNumber		; Get DPT to DS:DI, store port to RAMVARS
-	jnc		SHORT .NoMoreDrivesOrNoSlaveDrive
-	cmp		cx, [RAMVARS.wIdeBase]		; Next drive is from same controller?
+	call	GetBasePortToCX
+	pop		di
+	cmp		cx, di						; Next drive is from same controller?
 	je		SHORT BackupErrorCodeFromTheRequestedDriveToBH
 .NoMoreDrivesOrNoSlaveDrive:
 	dec		dx
+	ret
+
+;--------------------------------------------------------------------
+; GetBasePortToCX
+;	Parameters:
+;		DL:		Drive number
+;		DS:		RAMVARS segment
+;	Returns:
+;		CX:		Base port address
+;		CF:		Set if valid drive number
+;				Cleared if invalid drive number
+;	Corrupts registers:
+;		DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetBasePortToCX:
+	xchg	cx, bx
+	xor		bx, bx
+	call	FindDPT_ForDriveNumber
+	jnc		SHORT .DptNotFound
+	mov		bl, [di+DPT.bIdevarsOffset]
+	mov		bx, [cs:bx+IDEVARS.wPort]
+.DptNotFound:
+	xchg	bx, cx
 	ret
 
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH10h_HReady.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH10h_HReady.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH10h_HReady.asm	(revision 150)
@@ -12,6 +12,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns with INTPACK:
 ;		AH:		Int 13h return status
 ;		CF:		0 if succesfull, 1 if error
@@ -19,5 +19,9 @@
 ALIGN JUMP_ALIGN
 AH10h_HandlerForCheckDriveReady:
-	call	HStatus_WaitRdyDefTime
-	xor		ah, ah
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		Device_SelectDrive
+%else
+	call	Device_SelectDrive
 	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH11h_HRecal.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH11h_HRecal.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH11h_HRecal.asm	(revision 150)
@@ -12,6 +12,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Returns with INTPACK:
 ;		AH:		BIOS Error code
 ;		CF:		0 if succesfull, 1 if error
@@ -32,4 +32,5 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
 ;	Returns:
 ;		AH:		BIOS Error code
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm	(revision 150)
@@ -12,6 +12,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
 ;		If succesfull:
 ;			AH:		3 (Hard disk accessible)
@@ -25,10 +25,45 @@
 ALIGN JUMP_ALIGN
 AH15h_HandlerForReadDiskDriveSize:
-	call	HCapacity_GetSectorCountFromOurAH08h		; Sector count to DX:AX
-	mov		[bp+INTPACK.cx], dx							; HIWORD to CX
-	mov		[bp+INTPACK.dx], ax							; LOWORD to DX
+	call	AH15h_GetSectorCountToDXAX
+	mov		[bp+IDEPACK.intpack+INTPACK.cx], dx			; HIWORD to CX
+	mov		[bp+IDEPACK.intpack+INTPACK.dx], ax			; LOWORD to DX
 
 	xor		ah, ah
-	call	HError_SetErrorCodeToIntpackInSSBPfromAH	; Store success to BDA and CF
-	mov		BYTE [bp+INTPACK.ah], 3						; Type code = Hard disk
+	call	Int13h_SetErrorCodeToIntpackInSSBPfromAH	; Store success to BDA and CF
+	mov		BYTE [bp+IDEPACK.intpack+INTPACK.ah], 3		; Type code = Hard disk
 	jmp		Int13h_ReturnFromHandlerWithoutStoringErrorCode
+
+
+;--------------------------------------------------------------------
+; AH15h_GetSectorCountFromForeignDriveToDXAX:
+; AH15h_GetSectorCountToDXAX:
+;	Parameters:
+;		DL:		Drive number
+;		DS:		RAMVARS segment
+;		DS:DI:	Ptr to DPT (AH15h_GetSectorCount only)
+;	Returns:
+;		DX:AX:	Total sector count
+;		BX:		Zero
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+AH15h_GetSectorCountFromForeignDriveToDXAX:
+	mov		ah, GET_DRIVE_PARAMETERS
+	call	Int13h_CallPreviousInt13hHandler
+	jmp		SHORT ConvertAH08hReturnValuesToSectorCount
+
+ALIGN JUMP_ALIGN
+AH15h_GetSectorCountToDXAX:
+	call	AH8h_GetDriveParameters
+	; Fall to ConvertAH08hReturnValuesToSectorCount
+
+ConvertAH08hReturnValuesToSectorCount:
+	call	HAddress_ExtractLCHSparametersFromOldInt13hAddress
+	xor		ax, ax			; Zero AX
+	inc		cx				; Max cylinder number to cylinder count
+	xchg	al, bh			; AX=Max head number, BX=Sectors per track
+	inc		ax				; AX=Head count
+	mul		bx				; AX=Head count * Sectors per track
+	mul		cx				; DX:AX = Total sector count
+	xor		bx, bx			; Zero BX for 48-bit sector count (and clear CF)
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1h_HStatus.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1h_HStatus.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH1h_HStatus.asm	(revision 150)
@@ -12,6 +12,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		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)
@@ -21,4 +21,4 @@
 	LOAD_BDA_SEGMENT_TO	ds, ax, !
 	xchg	ah, [BDA.bHDLastSt]		; Load and clear last error
-	call	HError_SetErrorCodeToIntpackInSSBPfromAH
+	call	Int13h_SetErrorCodeToIntpackInSSBPfromAH
 	jmp		Int13h_ReturnFromHandlerWithoutStoringErrorCode
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH23h_HFeatures.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH23h_HFeatures.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH23h_HFeatures.asm	(revision 150)
@@ -14,13 +14,13 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Parameters on INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
 ;		AL:		Feature Number (parameter to Features Register = subcommand)
-;	(Parameter registers are undocumented, there are specific for this BIOS):
-;		BH:		Parameter to Sector Count Register (subcommand specific)
-;		BL:		Parameter to Sector Number Register (subcommand specific)
-;		CL:		Parameter to Low Cylinder Register (subcommand specific)
-;		CH:		Parameter to High Cylinder Register (subcommand specific)
-;	Returns with INTPACK in SS:BP:
+;	(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 succesfull, 1 if error
@@ -28,4 +28,6 @@
 ALIGN JUMP_ALIGN
 AH23h_HandlerForSetControllerFeatures:
+	xchg	si, ax		; SI = Feature Number
+	mov		dx, [bp+IDEPACK.intpack+INTPACK.bx]
 %ifndef USE_186
 	call	AH23h_SetControllerFeatures
@@ -40,44 +42,20 @@
 ; AH23h_SetControllerFeatures
 ;	Parameters:
-;		AL:		Feature Number (parameter to Features Register = subcommand)
-;		BH:		Parameter to Sector Count Register (subcommand specific)
-;		BL:		Parameter to Sector Number Register (subcommand specific)
-;		CL:		Parameter to Low Cylinder Register (subcommand specific)
-;		CH:		Parameter to High Cylinder Register (subcommand specific)
+;		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 succesfull, 1 if error
 ;	Corrupts registers:
-;		AX, BX, CX, DX, SI
+;		AL, BX, CX, DX
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
 AH23h_SetControllerFeatures:
-	; Backup AL and BH to SI
-	mov		ah, bh
-	xchg	si, ax
-
-	; Select Master or Slave and wait until ready
-	call	HDrvSel_SelectDriveAndDisableIRQ
-	jc		SHORT .ReturnWithErrorCodeInAH
-
-	; Output Feature Number
-	mov		ax, si						; Feature number to AL
-	mov		dx, [RAMVARS.wIdeBase]		; Load base port address
-	inc		dx							; REGW_IDE_FEAT
-	out		dx, al
-
-	; Output parameters to Sector Number Register and Cylinder Registers
-	xor		bh, bh						; Zero head number
-	dec		dx							; Back to base port address
-	call	HCommand_OutputTranslatedLCHSaddress
-
-	; Output parameter to Sector Count Register and command
-	xchg	ax, si						; Sector Count Reg param to AH
-	mov		al, ah						; Sector Count Reg param to AL
-	mov		ah, HCMD_SET_FEAT			; Load Set Features command to AH
-	call	HCommand_OutputSectorCountAndCommand
-
-	jmp		HStatus_WaitBsyDefTime		; Wait until drive ready
-.ReturnWithErrorCodeInAH:
-	ret
+	mov		al, COMMAND_SET_FEATURES
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_BSY, FLG_STATUS_BSY)
+	jmp		Idepack_StoreNonExtParametersAndIssueCommandFromAL
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH24h_HSetBlocks.asm	(revision 150)
@@ -13,8 +13,8 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Parameters on INTPACK in SS:BP:
+;		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 in SS:BP:
+;	Returns with INTPACK:
 ;		AH:		Int 13h return status
 ;		CF:		0 if succesfull, 1 if error
@@ -22,4 +22,12 @@
 ALIGN JUMP_ALIGN
 AH24h_HandlerForSetMultipleBlocks:
+	test	WORD [di+DPT.wFlags], FLG_DPT_BLOCK_MODE_SUPPORTED
+	jnz		SHORT .TryToSetBlockMode
+	stc
+	mov		ah, RET_HD_INVALID
+	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+
+ALIGN JUMP_ALIGN
+.TryToSetBlockMode:
 %ifndef USE_186
 	call	AH24h_SetBlockSize
@@ -32,10 +40,9 @@
 
 ;--------------------------------------------------------------------
-; Sets block size for block mode transfers.
-;
 ; 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
@@ -46,24 +53,17 @@
 ALIGN JUMP_ALIGN
 AH24h_SetBlockSize:
-	; Select Master or Slave and wait until ready
-	mov		bl, al								; Backup block size
-	call	HDrvSel_SelectDriveAndDisableIRQ	; Select drive and wait until ready
-	jc		SHORT .ReturnWithErrorCodeInAH		; Return if error
-
-	; Output block size and command
-	mov		al, bl								; Restore block size to AL
-	mov		ah, HCMD_SET_MUL					; Load command to AH
-	mov		dx, [RAMVARS.wIdeBase]				; Load base port address
-	add		dx, BYTE REG_IDE_CNT
-	call	HCommand_OutputSectorCountAndCommand
-	call	HStatus_WaitBsyDefTime				; Wait until drive not busy
+	MIN_U	al, MAX_SUPPORTED_BLOCK_SIZE_IN_SECTORS
+	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
 	jc		SHORT .DisableBlockMode
 
 	; Store new block size to DPT and return
-	mov		[di+DPT.bSetBlock], bl				; Store new block size
-	xor		ah, ah								; Zero AH and CF since success
+	mov		[di+DPT_ATA.bSetBlock], bl				; Store new block size
 	ret
 .DisableBlockMode:
-	mov		BYTE [di+DPT.bSetBlock], 1			; Disable block mode
-.ReturnWithErrorCodeInAH:
+	mov		BYTE [di+DPT_ATA.bSetBlock], 1			; Disable block mode
 	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH25h_HDrvID.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH25h_HDrvID.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH25h_HDrvID.asm	(revision 150)
@@ -13,8 +13,8 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Parameters on INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
 ;		ES:BX:	Ptr to buffer to receive 512-byte drive information
-;	Returns with INTPACK in SS:BP:
+;	Returns with INTPACK:
 ;		AH:		Int 13h return status
 ;		CF:		0 if succesfull, 1 if error
@@ -22,77 +22,13 @@
 ALIGN JUMP_ALIGN
 AH25h_HandlerForGetDriveInformation:
-	; Wait until previously selected drive is ready
-	call	HDrvSel_SelectDriveAndDisableIRQ
-	jc		SHORT .ReturnWithErrorCodeInAH		; Return if error
+	push	bp
 
-	; Get drive information
-	mov		bx, [bp+INTPACK.bx]
-	call	HPIO_NormalizeDataPointer
-	push	bx
-	mov		dx, [RAMVARS.wIdeBase]		; Load base port address
-	eMOVZX	bx, BYTE [di+DPT.bIdeOff]	; Load offset to IDEVARS
-	mov		bl, [cs:bx+IDEVARS.bBusType]; Load bus type to BL
-	mov		bh, [di+DPT.bDrvSel]		; Load drive sel byte to BH
-	pop		di							; Pop buffer offset to DI
-	call	AH25h_GetDriveInfo			; Get drive information
-.ReturnWithErrorCodeInAH:
+	mov		si, [bp+IDEPACK.intpack+INTPACK.bx]
+	call	AccessDPT_GetDriveSelectByteToAL
+	mov		bh, al
+	eMOVZX	ax, BYTE [di+DPT.bIdevarsOffset]
+	xchg	bp, ax
+	call	Device_IdentifyToBufferInESSIwithDriveSelectByteInBH
+
+	pop		bp
 	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
-
-
-;--------------------------------------------------------------------
-; Gets drive information using Identify Device command.
-;
-; AH25h_GetDriveInfo
-;	Parameters:
-;		BH:		Drive Select byte for Drive and Head Select Register
-;		BL:		Bus type
-;		DX:		IDE Controller base port address
-;		DS:		Segment to RAMVARS
-;		ES:DI:	Ptr to buffer to receive 512 byte drive information
-;	Returns:
-;		AH:		Int 13h return status (will be stored to BDA)
-;		CF:		0 if succesfull, 1 if error
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-AH25h_GetDriveInfo:
-	push	di
-	push	dx
-	push	bx
-
-	; Select Master or Slave drive.
-	; DO NOT WAIT UNTIL CURRENTLY SELECTED IS READY!
-	; It makes slave drive detection impossible if master is not present.
-	mov		[RAMVARS.wIdeBase], dx		; Store IDE Base port to RAMVARS
-	add		dx, BYTE REG_IDE_DRVHD		; DX to Drive and Head Sel Register
-	mov		al, bh						; Drive Select byte to AL
-	out		dx, al						; Select Master or Slave drive
-	sub		dx, BYTE REG_IDE_DRVHD		; Back to IDE Base port
-
-	; Wait until ready to accept commands
-	xor		bh, bh						; BX now contains bus type
-	mov		cl, B_TIMEOUT_DRVINFO		; Load short timeout
-	cmp		[RAMVARS.bDrvCnt], bh		; Detecting first drive?
-	eCMOVE	cl, B_TIMEOUT_RESET			;  If so, load long timeout
-	call	HStatus_WaitRdy				; Wait until ready to accept commands
-	jc		SHORT .ReturnWithErrorCodeInAH
-
-	; Output command
-	mov		al, HCMD_ID_DEV				; Load Identify Device command to AL
-	out		dx, al						; Output command
-	call	HStatus_WaitDrqDefTime		; Wait until ready to transfer (no IRQ!)
-	jc		SHORT .ReturnWithErrorCodeInAH
-
-	; Transfer data
-	sub		dx, BYTE REGR_IDE_ST		; DX to IDE Data Reg
-	mov		cx, 256						; Transfer 256 words (single sector)
-	cld									; INSW to increment DI
-	call	[cs:bx+g_rgfnPioRead]		; Read ID sector
-	call	HStatus_WaitRdyDefTime		; Wait until drive ready
-
-.ReturnWithErrorCodeInAH:
-	pop		bx
-	pop		dx
-	pop		di
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH2h_HRead.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH2h_HRead.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH2h_HRead.asm	(revision 150)
@@ -13,7 +13,7 @@
 ;		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 read (1...255)
+;		SS:BP:	Ptr to IDEPACK
+;	Parameters on INTPACK:
+;		AL:		Number of sectors to read (1...255, 0=256)
 ;		CH:		Cylinder number, bits 7...0
 ;		CL:		Bits 7...6: Cylinder number bits 9 and 8
@@ -21,5 +21,5 @@
 ;		DH:		Starting head number (0...255)
 ;		ES:BX:	Pointer to buffer recieving data
-;	Returns with INTPACK in SS:BP:
+;	Returns with INTPACK:
 ;		AH:		Int 13h/40h floppy return status
 ;		AL:		Burst error length if AH returns 11h, undefined otherwise
@@ -28,22 +28,14 @@
 ALIGN JUMP_ALIGN
 AH2h_HandlerForReadDiskSectors:
-	test	al, al						; Invalid sector count?
-	jz		SHORT AH2h_ZeroCntErr		;  If so, return with error
-
-	; Select sector or block mode command
-	mov		ah, HCMD_READ_SECT			; Load sector mode command
-	cmp		BYTE [di+DPT.bSetBlock], 1	; Block mode enabled?
-	eCMOVA	ah, HCMD_READ_MUL			; Load block mode command
-
-	; Transfer data
-	call	HCommand_OutputCountAndLCHSandCommand
-	jc		SHORT .ReturnWithErrorCodeInAH
-	mov		bx, [bp+INTPACK.bx]
-	call	HPIO_ReadBlock				; Read data from IDE-controller
-.ReturnWithErrorCodeInAH:
+	mov		ah, COMMAND_READ_SECTORS	; Load sector mode command
+	test	WORD [di+DPT.wFlags], FLG_DPT_BLOCK_MODE_SUPPORTED
+	eCMOVNZ	ah, COMMAND_READ_MULTIPLE	; Load block mode command
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+	mov		si, [bp+IDEPACK.intpack+INTPACK.bx]
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+%else
+	call	Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
 	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
-
-; Invalid sector count (also for AH=3h and AH=4h)
-AH2h_ZeroCntErr:
-	mov		ah, RET_HD_INVALID			; Invalid value passed
-	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH3h_HWrite.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH3h_HWrite.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH3h_HWrite.asm	(revision 150)
@@ -13,6 +13,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Parameters on INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEREGS_AND_INTPACK
+;	Parameters on INTPACK:
 ;		AL:		Number of sectors to write
 ;		CH:		Cylinder number, bits 7...0
@@ -21,5 +21,5 @@
 ;		DH:		Starting head number (0...255)
 ;		ES:BX:	Pointer to source data
-;	Returns with INTPACK in SS:BP:
+;	Returns with INTPACK:
 ;		AH:		Int 13h/40h floppy return status
 ;		CF:		0 if successfull, 1 if error
@@ -27,17 +27,15 @@
 ALIGN JUMP_ALIGN
 AH3h_HandlerForWriteDiskSectors:
-	test	al, al						; Invalid sector count?
-	jz		SHORT AH2h_ZeroCntErr		;  If so, return with error
-
-	; Select sector or block mode command
-	mov		ah, HCMD_WRITE_SECT			; Load sector mode command
-	cmp		BYTE [di+DPT.bSetBlock], 1	; Block mode enabled?
-	eCMOVA	ah, HCMD_WRITE_MUL			; Load block mode command
-
-	; Transfer data
-	call	HCommand_OutputCountAndLCHSandCommand
-	jc		SHORT .ReturnWithErrorCodeInAH
-	mov		bx, [bp+INTPACK.bx]
-	call	HPIO_WriteBlock				; Write data to IDE-controller
-.ReturnWithErrorCodeInAH:
+	; Prepare parameters
+	mov		ah, COMMAND_WRITE_SECTORS	; Load sector mode command
+	test	WORD [di+DPT.wFlags], FLG_DPT_BLOCK_MODE_SUPPORTED
+	eCMOVNZ	ah, COMMAND_WRITE_MULTIPLE	; Load block mode command
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
+	mov		si, [bp+IDEPACK.intpack+INTPACK.bx]
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+%else
+	call	Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
 	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH4h_HVerify.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH4h_HVerify.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH4h_HVerify.asm	(revision 150)
@@ -26,12 +26,11 @@
 ALIGN JUMP_ALIGN
 AH4h_HandlerForVerifyDiskSectors:
-	test	al, al						; Invalid sector count?
-	jz		SHORT AH2h_ZeroCntErr		;  If so, return with error
-
-	mov		ah, HCMD_VERIFY_SECT		; Load command to AH
-	call	HCommand_OutputCountAndLCHSandCommand
-	jc		SHORT .ReturnWithErrorCodeInAH
-	mov		bx, di						; DS:BX now points to DPT
-	call	HStatus_WaitIrqOrRdy		; Wait for IRQ or RDY
-.ReturnWithErrorCodeInAH:
+	mov		ah, COMMAND_WRITE_SECTORS
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+%ifdef USE_186
+	push	Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
+%else
+	call	Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
 	jmp		Int13h_ReturnFromHandlerAfterStoringErrorCodeFromAH
+%endif
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH8h_HParams.asm	(revision 150)
@@ -12,6 +12,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
 ;		CH:		Maximum cylinder number, bits 7...0
 ;		CL:		Bits 7...6: Cylinder number bits 9...8
@@ -34,6 +34,6 @@
 	call	RamVars_GetCountOfKnownDrivesToDL
 .ReturnAfterStoringValuesToIntpack:
-	mov		[bp+INTPACK.cx], cx
-	mov		[bp+INTPACK.dx], dx
+	mov		[bp+IDEPACK.intpack+INTPACK.cx], cx
+	mov		[bp+IDEPACK.intpack+INTPACK.dx], dx
 	xor		ah, ah
 .ReturnErrorFromPreviousInt13hHandler:
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH9h_HInit.asm	(revision 150)
@@ -12,6 +12,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
 ;		AH:		Int 13h return status
 ;		CF:		0 if succesfull, 1 if error
@@ -34,4 +34,5 @@
 ;	Parameters:
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
 ;	Returns:
 ;		AH:		Int 13h return status
@@ -45,26 +46,27 @@
 
 	; Try to select drive and wait until ready
-	or		BYTE [di+DPT.bReset], MASK_RESET_ALL		; Everything uninitialized
-	call	HDrvSel_SelectDriveAndDisableIRQ
+	or		WORD [di+DPT.wFlags], MASK_DPT_RESET		; Everything uninitialized
+	call	AccessDPT_GetDriveSelectByteToAL
+	mov		[bp+IDEPACK.bDrvAndHead], al
+	call	Device_SelectDrive
 	jc		SHORT .ReturnNotSuccessfull
-	and		BYTE [di+DPT.bReset], ~FLG_RESET_nDRDY		; Clear since success
+	and		WORD [di+DPT.wFlags], ~FLG_DPT_RESET_nDRDY	; Clear since success
 
 	; Initialize CHS parameters if LBA is not used
-	call	AH9h_InitializeDeviceParameters
+	call	InitializeDeviceParameters
 	jc		SHORT .RecalibrateDrive
-	and		BYTE [di+DPT.bReset], ~FLG_RESET_nINITPRMS
+	and		WORD [di+DPT.wFlags], ~FLG_DPT_RESET_nINITPRMS
 
 	; Recalibrate drive by seeking to cylinder 0
-ALIGN JUMP_ALIGN
 .RecalibrateDrive:
 	call	AH11h_RecalibrateDrive
 	jc		SHORT .InitializeBlockMode
-	and		BYTE [di+DPT.bReset], ~FLG_RESET_nRECALIBRATE
+	and		WORD [di+DPT.wFlags], ~FLG_DPT_RESET_nRECALIBRATE
 
 	; Initialize block mode transfers
 .InitializeBlockMode:
-	call	AH9h_InitializeBlockMode
+	call	InitializeBlockMode
 	jc		SHORT .ReturnNotSuccessfull
-	and		BYTE [di+DPT.bReset], ~FLG_RESET_nSETBLOCK	; Keeps CF clear
+	and		WORD [di+DPT.wFlags], ~FLG_DPT_RESET_nSETBLOCK	; Keeps CF clear
 
 .ReturnNotSuccessfull:
@@ -74,45 +76,8 @@
 
 ;--------------------------------------------------------------------
-; Sends Initialize Device Parameters command to IDE Hard Disk.
-; Initialization is used to initialize logical CHS parameters. Drives
-; may not support all CHS values.
-; This command is only supported by drives that supports CHS addressing.
-;
-; AH9h_InitializeDeviceParameters
+; InitializeDeviceParameters
 ;	Parameters:
-;		DS:DI:	Ptr to DPT
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		Cleared if succesfull
-;				Set if any error
-;	Corrupts registers:
-;		AL, BX, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-AH9h_InitializeDeviceParameters:
-	; No need to initialize CHS parameters if LBA mode enabled
-	test	BYTE [di+DPT.bDrvSel], FLG_IDE_DRVHD_LBA	; Clears CF
-	jnz		SHORT .Return
-
-	push	dx
-	mov		bh, [di+DPT.bPHeads]
-	dec		bh						; Max head number
-	mov		dx, [RAMVARS.wIdeBase]
-	call	HCommand_OutputTranslatedLCHSaddress
-	mov		ah, HCMD_INIT_DEV
-	mov		al, [di+DPT.bPSect]		; Sectors per track
-	call	HCommand_OutputSectorCountAndCommand
-	call	HStatus_WaitBsyDefTime	; Wait until drive ready (DRDY won't be set!)
-	pop		dx
-.Return:
-	ret
-
-
-;--------------------------------------------------------------------
-; Initializes block mode transfers.
-;
-; AH9h_InitializeBlockMode
-;	Parameters:
-;		DS:DI:	Ptr to DPT
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;		SS:BP:	Ptr to IDEPACK
 ;	Returns:
 ;		AH:		BIOS Error code
@@ -123,12 +88,36 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-AH9h_InitializeBlockMode:
-	mov		ax, FLG_DRVPARAMS_BLOCKMODE
-	call	AccessDPT_TestIdeVarsFlagsForMasterOrSlaveDrive
-	jz		SHORT .Return				; Block mode disabled (CF cleared)
-	eMOVZX	ax, BYTE [di+DPT.bMaxBlock]	; Load max block size, zero AH
-	test	al, al						; Block mode supported? (clears CF)
-	jz		SHORT .Return				;  If not, return
+InitializeDeviceParameters:
+	; No need to initialize CHS parameters if LBA mode enabled
+	test	BYTE [di+DPT.wFlags], FLG_DRVNHEAD_LBA	; Clear CF
+	jnz		SHORT ReturnSuccessSinceInitializationNotNeeded
+
+	; Initialize Locigal Sectors per Track and Max Head number
+	mov		ah, [di+DPT.bPchsHeads]
+	dec		ah							; Max Head number
+	mov		dl, [di+DPT.bPchsSectors]	; Sectors per Track
+	mov		al, COMMAND_INITIALIZE_DEVICE_PARAMETERS
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_BSY, FLG_STATUS_BSY)
+	jmp		Idepack_StoreNonExtParametersAndIssueCommandFromAL
+
+
+;--------------------------------------------------------------------
+; InitializeBlockMode
+;	Parameters:
+;		DS:DI:	Ptr to DPT (in RAMVARS segment)
+;	Returns:
+;		AH:		BIOS Error code
+;		CF:		Cleared if succesfull
+;				Set if any error
+;	Corrupts registers:
+;		AL, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+InitializeBlockMode:
+	test	WORD [di+DPT.wFlags], FLG_DPT_BLOCK_MODE_SUPPORTED	; Clear CF
+	jz		SHORT ReturnSuccessSinceInitializationNotNeeded
+
+	mov		al, [di+DPT_ATA.bMaxBlock]	; Load max block size, zero AH
 	jmp		AH24h_SetBlockSize
-.Return:
+ReturnSuccessSinceInitializationNotNeeded:
 	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHCh_HSeek.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHCh_HSeek.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHCh_HSeek.asm	(revision 150)
@@ -13,11 +13,11 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Parameters on INTPACK in SS:BP:
+;		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 in SS:BP:
+;	Returns with INTPACK:
 ;		AH:		BIOS Error code
 ;		CF:		0 if succesfull, 1 if error
@@ -33,5 +33,4 @@
 %endif
 
-
 ;--------------------------------------------------------------------
 ; AHCh_SeekToCylinder
@@ -42,4 +41,5 @@
 ;		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
@@ -49,9 +49,5 @@
 ;--------------------------------------------------------------------
 AHCh_SeekToCylinder:
-	mov		ax, HCMD_SEEK<<8			; Load cmd to AH, AL=zero sector cnt
-	call	HCommand_OutputCountAndLCHSandCommand
-	jc		SHORT .ReturnWithErrorCodeInAH
-	mov		bx, di						; DS:BX now points to DPT
-	jmp		HStatus_WaitIrqOrRdy		; Wait for IRQ or RDY
-.ReturnWithErrorCodeInAH:
-	ret
+	mov		ah, COMMAND_SEEK
+	mov		bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
+	jmp		Idepack_TranslateOldInt13hAddressAndIssueCommandFromAH
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHDh_HReset.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHDh_HReset.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AHDh_HReset.asm	(revision 150)
@@ -12,6 +12,6 @@
 ;		DL:		Translated Drive number
 ;		DS:DI:	Ptr to DPT (in RAMVARS segment)
-;		SS:BP:	Ptr to INTPACK
-;	Returns with INTPACK in SS:BP:
+;		SS:BP:	Ptr to IDEPACK
+;	Returns with INTPACK:
 ;		AH:		Int 13h return status
 ;		CF:		0 if succesfull, 1 if error
@@ -35,9 +35,10 @@
 ;		DL:		Drive number
 ;		DS:		RAMVARS segment
+;		SS:BP:	Ptr to IDEPACK
 ;	Returns:
 ;		AH:		Int 13h return status
 ;		CF:		0 if succesfull, 1 if error
 ;	Corrupts registers:
-;		AL, CX, DI
+;		AL, CX, SI, DI
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
@@ -48,11 +49,12 @@
 	call	FindDPT_ForDriveNumber		; DS:DI now points to DPT
 	call	Interrupts_UnmaskInterruptControllerForDriveInDSDI
-	call	AHDh_ResetMasterAndSlave
+	call	Device_ResetMasterAndSlaveController
 	;jc		SHORT .ReturnError			; CF would be set if slave drive present without master
 										; (error register has special values after reset)
 
 	; Initialize Master and Slave drives
-	mov		dx, [RAMVARS.wIdeBase]		; Load base port address
-	call	AHDh_InitializeMasterAndSlave
+	eMOVZX	bx, BYTE [di+DPT.bIdevarsOffset]
+	mov		dx, [cs:bx+IDEVARS.wPort]
+	call	InitializeMasterAndSlaveDriveFromPortInDX
 
 	pop		bx
@@ -62,44 +64,8 @@
 
 ;--------------------------------------------------------------------
-; Resets Master and Slave drives at wanted port.
-; Both IDE drives will be reset. It is not possible to reset
-; Master or Slave only.
-;
-; AHDh_ResetMasterAndSlave
-;	Parameters:
-;		DS:DI:	Ptr to DPT for Master or Slave drive
-;	Returns:
-;		CF:		0 if reset succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AX, BX, CX, DX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-AHDh_ResetMasterAndSlave:
-	; Reset controller
-	; HSR0: Set_SRST
-	mov		al, [di+DPT.bDrvCtrl]		; Load value for ACR
-	or		al, FLG_IDE_CTRL_SRST		; Set Reset bit
-	call	HDrvSel_OutputDeviceControlByte
-	mov		ax, 5						; Delay at least 5us
-	call	HTimer_DelayMicrosecondsFromAX
-
-	; HSR1: Clear_wait
-	mov		al, [di+DPT.bDrvCtrl]		; Load value for ACR
-	out		dx, al						; End Reset
-	mov		ax, 2000					; Delay at least 2ms
-	call	HTimer_DelayMicrosecondsFromAX
-
-	; HSR2: Check_status
-	mov		cl, B_TIMEOUT_RESET			; Reset timeout delay
-	jmp		HStatus_WaitBsy
-
-
-;--------------------------------------------------------------------
-; Initializes Master and Slave drive.
-;
-; AHDh_InitializeMasterAndSlave
+; InitializeMasterAndSlaveDriveFromPortInDX
 ;	Parameters:
 ;		DX:		IDE Base Port address
+;		SS:BP:	Ptr to IDEPACK
 ;	Returns:
 ;		AH:		Error code
@@ -107,11 +73,11 @@
 ;				1 if any error
 ;	Corrupts registers:
-;		AL, BX, CX, DX, DI
+;		AL, BX, CX, DX, SI, DI
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-AHDh_InitializeMasterAndSlave:
+InitializeMasterAndSlaveDriveFromPortInDX:
 	push	dx							; Store base port address
 	xor		cx, cx						; Assume no errors
-	call	FindDPT_ForIdeMasterAtPort
+	call	FindDPT_ToDSDIForIdeMasterAtPortDX
 	jnc		SHORT .InitializeSlave		; Master drive not present
 	call	AH9h_InitializeDriveForUse
@@ -119,5 +85,5 @@
 .InitializeSlave:
 	pop		dx							; Restore base port address
-	call	FindDPT_ForIdeSlaveAtPort
+	call	FindDPT_ToDSDIForIdeSlaveAtPortDX
 	jnc		SHORT .CombineErrors		; Slave drive not present
 	call	AH9h_InitializeDriveForUse
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HAddress.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HAddress.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HAddress.asm	(revision 150)
@@ -1,7 +1,3 @@
-; File name		:	HAddress.asm
-; Project name	:	IDE BIOS
-; Created date	:	11.3.2010
-; Last update	:	4.4.2010
-; Author		:	Tomi Tilli
+; Project name	:	XTIDE Universal BIOS
 ; Description	:	Functions for address translations.
 
@@ -9,9 +5,15 @@
 SECTION .text
 
+; Jump table for conversion functions
+ALIGN WORD_ALIGN
+g_rgfnAddressTranslation:
+	dw		DoNotConvertLCHS					; 0, ADDR_DPT_LCHS
+	dw		ConvertLCHStoPCHS					; 1, ADDR_DPT_PCHS
+	dw		ConvertLCHStoLBARegisterValues		; 2, ADDR_DPT_LBA28
+	dw		ConvertLCHStoLBARegisterValues		; 3, ADDR_DPT_LBA48
+
+
 ;--------------------------------------------------------------------
-; Outputs sector count, L-CHS address and command to IDE registers.
-; This function does not wait until command has been completed.
-;
-; HAddress_ConvertParamsFromBiosLCHStoIDE
+; HAddress_OldInt13hAddressToIdeAddress
 ;	Parameters:
 ;		CH:		Cylinder number, bits 7...0
@@ -28,22 +30,12 @@
 ;		AX, DX
 ;--------------------------------------------------------------------
-ALIGN WORD_ALIGN
-g_rgfnAddressTranslation:
-	dw		HAddress_DoNotConvertLCHS					; 0, ADDR_DPT_LCHS
-	dw		HAddress_ConvertLCHStoPCHS					; 1, ADDR_DPT_PCHS
-	dw		HAddress_ConvertLCHStoLBARegisterValues		; 2, ADDR_DPT_LBA28
-	dw		HAddress_ConvertLCHStoLBARegisterValues		; 3, ADDR_DPT_LBA48
-
 ALIGN JUMP_ALIGN
-HAddress_ConvertParamsFromBiosLCHStoIDE:
-	mov		bl, [di+DPT.bFlags]
-	and		bx, BYTE MASK_DPT_ADDR						; Addressing mode to BX
+HAddress_OldInt13hAddressToIdeAddress:
+	call	AccessDPT_GetAddressingModeForWordLookToBX
 	push	WORD [cs:bx+g_rgfnAddressTranslation]		; Push return address
-	; Fall to HAddress_ExtractLCHSFromBiosParams
+	; Fall to HAddress_ExtractLCHSparametersFromOldInt13hAddress
 
 ;---------------------------------------------------------------------
-; Extracts L-CHS parameters from BIOS function parameters.
-;
-; HAddress_ExtractLCHSFromBiosParams:
+; HAddress_ExtractLCHSparametersFromOldInt13hAddress
 ;	Parameters:
 ;		CH:		Cylinder number, bits 7...0
@@ -58,6 +50,5 @@
 ;		Nothing
 ;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HAddress_ExtractLCHSFromBiosParams:
+HAddress_ExtractLCHSparametersFromOldInt13hAddress:
 	mov		bl, cl				; Copy sector number...
 	and		bl, 3Fh				; ...and limit to 1...63
@@ -70,5 +61,5 @@
 
 ;---------------------------------------------------------------------
-; Converts BIOS LCHS parameters to IDE P-CHS parameters.
+; Converts LCHS parameters to IDE P-CHS parameters.
 ; PCylinder	= (LCylinder << n) + (LHead / PHeadCount)
 ; PHead		= LHead % PHeadCount
@@ -89,8 +80,8 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-HAddress_ConvertLCHStoPCHS:
+ConvertLCHStoPCHS:
 	; LHead / PHeadCount and LHead % PHeadCount
 	eMOVZX	ax, bh					; Copy L-CHS Head number to AX
-	div		BYTE [di+DPT.bPHeads]	; AL = LHead / PHeadCount, AH = LHead % PHeadCount
+	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
@@ -98,10 +89,10 @@
 	; (LCylinder << n) + (LHead / PHeadCount)
 	mov		dx, cx					; Copy L-CHS Cylinder number to DX
-	mov		cl, [di+DPT.bShLtoP]	; Load shift count
+	mov		cl, [di+DPT.wFlags]		; Load shift count
+	and		cl, MASK_DPT_CHS_SHIFT_COUNT
 	shl		dx, cl					; DX = LCylinder << n
 	add		ax, dx					; AX = P-CHS Cylinder number
 	mov		cx, ax					; Copy P-CHS Cylinder number to CX
-ALIGN JUMP_ALIGN
-HAddress_DoNotConvertLCHS:
+DoNotConvertLCHS:
 	ret
 
@@ -109,8 +100,11 @@
 ;---------------------------------------------------------------------
 ; 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
 ; HAddress_DoNotConvertLCHS and HAddress_ConvertLCHStoPCHS returns.
 ;
-; HAddress_ConvertLCHStoLBARegisterValues:
+; ConvertLCHStoLBARegisterValues:
 ;	Parameters:
 ;		BL:		Sector number (1...63)
@@ -127,33 +121,9 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-HAddress_ConvertLCHStoLBARegisterValues:
-	call	HAddress_ConvertLCHStoLBA28
-	mov		bl, al					; Sector Number Register (LBA 7...0)
-	mov		cl, ah					; 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
-
-;---------------------------------------------------------------------
-; 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
-;
-; HAddress_ConvertLCHStoLBA28:
-;	Parameters:
-;		BL:		Sector number (1...63)
-;		BH:		Head number (0...255)
-;		CX:		Cylinder number (0...1023)
-;		DS:DI:	Ptr to Disk Parameter Table
-;	Returns:
-;		DX:AX:	28-bit LBA address (DH is always zero)
-;	Corrupts registers:
-;		BX, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HAddress_ConvertLCHStoLBA28:
+ConvertLCHStoLBARegisterValues:
 	; cylToSeek*headsPerCyl (18-bit result)
 	mov		ax, cx					; Copy Cylinder number to AX
-	mul		WORD [di+DPT.wLHeads]	; DX:AX = cylToSeek*headsPerCyl
+	eMOVZX	dx, BYTE [di+DPT.bLchsHeads]
+	mul		dx						; DX:AX = cylToSeek*headsPerCyl
 
 	; +=headToSeek (18-bit result)
@@ -163,5 +133,5 @@
 
 	; *=sectPerTrack (18-bit by 6-bit multiplication with 24-bit result)
-	eMOVZX	cx, BYTE [di+DPT.bPSect]; Load Sectors per Track
+	eMOVZX	cx, BYTE [di+DPT.bPchsSectors]	; Load Sectors per Track
 	xchg	ax, dx					; Hiword to AX, loword to DX
 	mul		cl						; AX = hiword * Sectors per Track
@@ -176,3 +146,9 @@
 	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: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HCapacity.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HCapacity.asm	(revision 149)
+++ 	(revision )
@@ -1,42 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	Functions for hard disk capacity calculations.
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; Calculates sector count from L-CHS values returned by INT 13h, AH=08h.
-;
-; HCapacity_GetSectorCountFromForeignAH08h:
-; HCapacity_GetSectorCountFromOurAH08h:
-;	Parameters:
-;		DL:		Drive number
-;		DS:		RAMVARS segment
-;		DS:DI:	Ptr to DPT (HCapacity_GetSectorCountFromOurAH08h)
-;	Returns:
-;		DX:AX:	Total sector count
-;		BX:		Zero
-;	Corrupts registers:
-;		CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HCapacity_GetSectorCountFromForeignAH08h:
-	mov		ah, GET_DRIVE_PARAMETERS
-	call	Int13h_CallPreviousInt13hHandler
-	jmp		SHORT ConvertAH08hReturnValuesToSectorCount
-
-ALIGN JUMP_ALIGN
-HCapacity_GetSectorCountFromOurAH08h:
-	call	AH8h_GetDriveParameters
-	; Fall to ConvertAH08hReturnValuesToSectorCount
-
-ConvertAH08hReturnValuesToSectorCount:
-	call	HAddress_ExtractLCHSFromBiosParams
-	xor		ax, ax			; Zero AX
-	inc		cx				; Max cylinder number to cylinder count
-	xchg	al, bh			; AX=Max head number, BX=Sectors per track
-	inc		ax				; AX=Head count
-	mul		bx				; AX=Head count * Sectors per track
-	mul		cx				; DX:AX = Total sector count
-	xor		bx, bx			; Zero BX for 48-bit sector count (and clear CF)
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HCommand.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HCommand.asm	(revision 149)
+++ 	(revision )
@@ -1,111 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	Functions for outputting IDE commands and parameters.
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; Outputs sector count, L-CHS address and command to IDE registers.
-; This function does not wait until command has been completed.
-;
-; HCommand_OutputCountAndLCHSandCommand
-;	Parameters:
-;		AH:		Seek or data transfer command
-;		AL:		Sector count (1...255, 0=256)
-;		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:
-;		AH:		BIOS Error code (if error)
-;		CF:		0 if succesfull
-;				1 if any error
-;	Corrupts registers:
-;		CX, DX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HCommand_OutputCountAndLCHSandCommand:
-	push	bx
-	push	ax										; Store sector count and command
-	call	HDrvSel_SelectDriveForDataTransfer
-	jc		SHORT .ReturnError
-	call	HIRQ_ClearTaskFlag
-	call	HAddress_ConvertParamsFromBiosLCHStoIDE
-	mov		dx, [RAMVARS.wIdeBase]					; Load IDE Base Port address
-	call	HCommand_OutputTranslatedLCHSaddress	; DX to Sector count register
-	pop		ax										; Restore sector count and command
-	call	HCommand_OutputSectorCountAndCommand
-
-	clc												; Clear CF since success
-	pop		bx
-	ret
-.ReturnError:
-	pop		bx										; Discard pushed AX
-	pop		bx
-	ret
-
-
-;--------------------------------------------------------------------
-; Outputs L-CHS address that has been translated P-CHS or LBA28
-; when necessary.
-;
-; HCommand_OutputTranslatedLCHSaddress
-;	Parameters:
-;		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)
-;		DX:		IDE Base Port address
-;		DS:DI:	Ptr to DPT
-;	Returns:
-;		DX:		IDE Sector Count Register address
-;	Corrupts registers:
-;		AX, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HCommand_OutputTranslatedLCHSaddress:
-	add		dx, BYTE REG_IDE_LBA_LOW
-	mov		al, bl
-	out		dx, al						; Output LBA 7...0
-
-	; Some (VLB) controllers fail to accept WORD write to cylinder
-	; registers so we must output two bytes instead.
-	inc		dx							; REG_IDE_LBA_MID
-	mov		al, cl
-	out		dx, al						; Output LBA 8...15
-
-	inc		dx							; REG_IDE_LBA_HIGH
-	mov		al, ch
-	out		dx, al						; Output LBA 16...23
-
-	inc		dx							; REG_IDE_DRVHD
-	mov		al, [di+DPT.bDrvSel]		; Load other bits for Drive and Head Register
-	or		al, bh
-	out		dx, al						; Output LBA 27...24
-
-	sub		dx, BYTE REG_IDE_DRVHD-REG_IDE_CNT
-	ret
-
-
-;--------------------------------------------------------------------
-; Outputs sector count and seek or data transfer command.
-;
-; HCommand_OutputSectorCountAndCommand
-;	Parameters:
-;		AH:		Seek or data transfer command
-;		AL:		Sector count (1...255, 0=256)
-;		DX:		IDE Sector Count Register address
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AH, DX
-;--------------------------------------------------------------------	
-ALIGN JUMP_ALIGN
-HCommand_OutputSectorCountAndCommand:
-	out		dx, al						; Output sector count
-	add		dx, BYTE REGW_IDE_CMD-REG_IDE_CNT
-	xchg	al, ah						; AL=Command, AH=Sector count
-	out		dx, al
-	mov		al, ah						; Restore sector count to AL
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HDrvSel.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HDrvSel.asm	(revision 149)
+++ 	(revision )
@@ -1,107 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	Functions for selecting Master or Slave drive.
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; Selects Master or Slave drive and disables interrupts. Interrupts should
-; be disabled for commands that do not transfer data.
-; This function returns after drive is ready to accept commands.
-;
-; HDrvSel_SelectDriveAndDisableIRQ
-;	Parameters:
-;		DS:DI:	Ptr to DPT
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if drive selected successfully
-;				1 if any error
-;	Corrupts registers:
-;		AL
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HDrvSel_SelectDriveAndDisableIRQ:
-	push	bx
-	mov		al, [di+DPT.bDrvCtrl]	; Load Device Control Byte
-	or		al, FLG_IDE_CTRL_nIEN	; Disable interrupts
-	call	HDrvSel_SelectDriveAndSetControlByte
-	pop		bx
-	ret
-
-
-;--------------------------------------------------------------------
-; Selects Master or Slave drive for transferring data.
-; This means that interrupts will be enabled if so configured in
-; IDEVARS. This function returns after drive is ready to accept commands.
-;
-; HDrvSel_SelectDriveForDataTransfer
-;	Parameters:
-;		DS:DI:	Ptr to DPT
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if drive selected successfully
-;				1 if any error
-;	Corrupts registers:
-;		AL, BX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HDrvSel_SelectDriveForDataTransfer:
-	mov		al, [di+DPT.bDrvCtrl]			; Load Device Control Byte
-	; Fall to HDrvSel_SelectDriveAndSetControlByte
-
-;--------------------------------------------------------------------
-; Selects Master or Slave drive.
-; Device Control Byte can be used to enable or disable interrupts.
-; This function returns only after drive is ready to accept commands.
-;
-; HDrvSel_SelectDriveAndSetControlByte
-;	Parameters:
-;		AL:		Device Control Byte (to enable/disable interrupts)
-;		DS:DI:	Ptr to DPT
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if drive selected successfully
-;				1 if any error
-;	Corrupts registers:
-;		AL, BX
-;--------------------------------------------------------------------
-;ALIGN JUMP_ALIGN
-HDrvSel_SelectDriveAndSetControlByte:
-	push	dx
-	push	cx
-
-	; Output Device Control Register to enable/disable interrupts
-	call	HDrvSel_OutputDeviceControlByte
-
-	; Select Master or Slave drive
-	mov		dx, [RAMVARS.wIdeBase]
-	add		dx, BYTE REG_IDE_DRVHD
-	mov		al, [di+DPT.bDrvSel]			; Load Master/Slave selection byte
-	out		dx, al							; Select drive
-
-	; Wait until drive is ready to accept commands
-	call	HStatus_WaitRdyDefTime
-	pop		cx
-	pop		dx
-	ret
-
-
-;--------------------------------------------------------------------
-; Outputs Device Control Byte to Device Control Register.
-;
-; HDrvSel_OutputDeviceControlByte
-;	Parameters:
-;		AL:		Device Control Byte
-;		DS:DI:	Ptr to Disk Parameter Table
-;	Returns:
-;		DX:		Device Control Register address
-;	Corrupts registers:
-;		BX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HDrvSel_OutputDeviceControlByte:
-	eMOVZX	bx, BYTE [di+DPT.bIdeOff]		; CS:BX now points to IDEVARS
-	mov		dx, [cs:bx+IDEVARS.wPortCtrl]	; Load Control Block base address
-	add		dx, BYTE REGW_IDEC_CTRL			; Add offset to Device Control Register
-	out		dx, al							; Output Device Control byte
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HError.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HError.asm	(revision 149)
+++ 	(revision )
@@ -1,170 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	Error checking functions for BIOS Hard disk functions.
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; HError_GetErrorCodeToAHforTimeoutWhenPolling
-;	Parameters:
-;		DS:		RAMVARS segment
-;	Returns:
-;		AH:		BIOS error code
-;		CF:		Set if error
-;				Cleared if no error
-;	Corrupts registers:
-;		AL
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HError_GetErrorCodeToAHforTimeoutWhenPolling:
-	call	HError_GetErrorCodeToAHafterPolling
-	jc		SHORT .ReturnErrorCodeInAH
-	mov		ah, RET_HD_TIMEOUT			; Force timeout since no actual error...
-	stc									; ...but wanted bit was never set
-.ReturnErrorCodeInAH:
-	ret
-
-
-;--------------------------------------------------------------------
-; HError_GetErrorCodeToAHafterPolling
-;	Parameters:
-;		DS:		RAMVARS segment
-;	Returns:
-;		AH:		BIOS error code
-;		CF:		Set if error
-;				Cleared if no error
-;	Corrupts registers:
-;		AL
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HError_GetErrorCodeToAHafterPolling:
-%ifndef USE_186
-	call	HError_GetStatusAndErrorRegistersToAXandStoreThemToBDA
-	jmp		SHORT GetBiosErrorCodeToAHfromStatusAndErrorRegistersInAX
-%else
-	push	GetBiosErrorCodeToAHfromStatusAndErrorRegistersInAX
-	; Fall through to HError_GetStatusAndErrorRegistersToAXandStoreThemToBDA
-%endif
-
-
-;--------------------------------------------------------------------
-; HError_GetStatusAndErrorRegistersToAXandStoreThemToBDA
-;	Parameters:
-;		DS:		RAMVARS segment
-;	Returns:
-;		AL:		IDE Status Register contents
-;		AH:		IDE Error Register contents
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HError_GetStatusAndErrorRegistersToAXandStoreThemToBDA:
-	push	ds
-	push	dx
-
-	mov		dx, [RAMVARS.wIdeBase]		; Load IDE base port address
-	inc		dx							; Increment to Error Register
-	in		al, dx						; Read Error Register...
-	mov		ah, al						; ...and copy it to AH
-	add		dx, BYTE REGR_IDE_ST - REGR_IDE_ERROR
-	in		al, dx						; Read Status Register to AL
-
-	LOAD_BDA_SEGMENT_TO	ds, dx
-	mov		[HDBDA.wHDStAndErr], ax
-
-	pop		dx
-	pop		ds
-	ret
-
-
-;--------------------------------------------------------------------
-; 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:
-;		Nothing
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-GetBiosErrorCodeToAHfromStatusAndErrorRegistersInAX:
-	test	al, FLG_IDE_ST_BSY
-	jz		SHORT .CheckErrorBitsFromStatusRegisterInAL
-	mov		ah, RET_HD_TIMEOUT
-	jmp		SHORT .ReturnBiosErrorCodeInAH
-
-ALIGN JUMP_ALIGN
-.CheckErrorBitsFromStatusRegisterInAL:
-	test	al, FLG_IDE_ST_DF | FLG_IDE_ST_CORR | FLG_IDE_ST_ERR
-	jnz		SHORT .ProcessErrorFromStatusRegisterInAL
-	xor		ah, ah					; No errors, zero AH and CF
-	ret
-
-.ProcessErrorFromStatusRegisterInAL:
-	test	al, FLG_IDE_ST_ERR		; Error specified in Error register?
-	jnz		SHORT .ConvertBiosErrorToAHfromErrorRegisterInAH
-	mov		ah, RET_HD_ECC			; Assume ECC corrected error
-	test	al, FLG_IDE_ST_CORR		; ECC corrected error?
-	jnz		SHORT .ReturnBiosErrorCodeInAH
-	mov		ah, RET_HD_CONTROLLER	; Must be Device Fault
-	jmp		SHORT .ReturnBiosErrorCodeInAH
-
-.ConvertBiosErrorToAHfromErrorRegisterInAH:
-	push	bx
-	mov		bx, .rgbRetCodeLookup
-.ErrorBitLoop:
-	rcr		ah, 1					; Set CF if error bit set
-	jc		SHORT .LookupErrorCode
-	inc		bx
-	cmp		bx, .rgbRetCodeLookup + 8
-	jb		SHORT .ErrorBitLoop		; Loop until all bits checked
-.LookupErrorCode:
-	mov		ah, [cs:bx+.rgbRetCodeLookup]
-	pop		bx
-
-.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
-
-
-;--------------------------------------------------------------------
-; HError_SetErrorCodeToBdaAndToIntpackInSSBPfromAH
-; HError_SetErrorCodeToIntpackInSSBPfromAH
-;	Parameters:
-;		AH:		BIOS error code (00h = no error)
-;		SS:BP:	Ptr to INTPACK
-;	Returns:
-;		SS:BP:	Ptr to INTPACK with error condition set
-;	Corrupts registers:
-;		DS, DI
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HError_SetErrorCodeToBdaAndToIntpackInSSBPfromAH:
-	; Store error code to BDA
-	LOAD_BDA_SEGMENT_TO	ds, di
-	mov		[BDA.bHDLastSt], ah
-
-	; Store error code to INTPACK
-HError_SetErrorCodeToIntpackInSSBPfromAH:
-	mov		[bp+INTPACK.ah], ah
-	test	ah, ah
-	jnz		SHORT .SetCFtoIntpack
-	and		BYTE [bp+INTPACK.flags], ~FLG_FLAGS_CF
-	ret
-.SetCFtoIntpack:
-	or		BYTE [bp+INTPACK.flags], FLG_FLAGS_CF
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HIRQ.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HIRQ.asm	(revision 149)
+++ 	(revision )
@@ -1,141 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	Interrupt handling related functions.
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; HIRQ_WaitForIRQ
-;	Parameters:
-;		DS:BX:	Ptr to DPT
-;	Returns:
-;		CF:		Set if wait done by operating system
-;				Cleared if BIOS must perform task flag polling
-;	Corrupts registers:
-;		AX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HIRQ_WaitForIRQ:
-	test	BYTE [bx+DPT.bDrvCtrl], FLG_IDE_CTRL_nIEN	; Clears CF
-	jz		SHORT .NotifyOperatingSystemAboutWaitingForIRQ
-	ret		; Go to poll status register
-
-;--------------------------------------------------------------------
-; .NotifyOperatingSystemAboutWaitingForIRQ
-;	Parameters:
-;		Nothing
-;	Returns:
-;		CF:		Set if wait done by operating system
-;				Cleared if BIOS must perform task flag polling
-;	Corrupts registers:
-;		AX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-.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:
-	pop		ds
-	sti									; Enable interrupts
-	ret
-
-
-;--------------------------------------------------------------------
-; Clears task (interrupt) flag from BIOS Data Area.
-;
-; HIRQ_ClearTaskFlag
-;	Parameters:
-;		Nothing
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HIRQ_ClearTaskFlag:
-	push	ds
-	LOAD_BDA_SEGMENT_TO	ds, ax, !		; Also zero AX
-	mov		[BDA.bHDTaskFlg], al
-	pop		ds
-	ret
-
-
-;--------------------------------------------------------------------
-; IDE Interrupt Service Routines.
-;
-; HIRQ_InterruptServiceRoutineForIrqs2to7
-; HIRQ_InterruptServiceRoutineForIrqs8to15
-;	Parameters:
-;		Nothing
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HIRQ_InterruptServiceRoutineForIrqs2to7:
-	push	ax
-	call	AcknowledgeIdeInterruptAndStoreStatusAndErrorRegistersToBDA
-
-	mov		al, CMD_END_OF_INTERRUPT
-	jmp		SHORT AcknowledgeMasterInterruptController
-
-
-ALIGN JUMP_ALIGN
-HIRQ_InterruptServiceRoutineForIrqs8to15:
-	push	ax
-	call	AcknowledgeIdeInterruptAndStoreStatusAndErrorRegistersToBDA
-
-	mov		al, CMD_END_OF_INTERRUPT	; Load EOI command to AL
-	out		WPORT_8259SL_COMMAND, al	; Acknowledge Slave 8259
-AcknowledgeMasterInterruptController:
-	out		WPORT_8259MA_COMMAND, 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							; Restore AX
-	iret
-
-;--------------------------------------------------------------------
-; Acknowledges IDE interrupt by reading status register and
-; stores Status and Error Registers to BDA. Task flag in BDA will
-; also be set.
-;
-; AcknowledgeIdeInterruptAndStoreStatusAndErrorRegistersToBDA
-;	Parameters:
-;		Nothing
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-AcknowledgeIdeInterruptAndStoreStatusAndErrorRegistersToBDA:
-	push	ds
-	push	di
-
-	; Reading Status Register acknowledges IDE interrupt
-	call	RamVars_GetSegmentToDS
-	call	HError_GetStatusAndErrorRegistersToAXandStoreThemToBDA
-
-	; Set Task Flag
-	LOAD_BDA_SEGMENT_TO	ds, ax
-	mov		BYTE [BDA.bHDTaskFlg], 0FFh		; Set task flag
-
-	pop		di
-	pop		ds
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HPIO.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HPIO.asm	(revision 149)
+++ 	(revision )
@@ -1,291 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	PIO transfer functions.
-
-; Structure containing variables for PIO transfer functions
-struc PIOVARS, -6
-	.fnXfer			resb	2	; Offset to transfer function
-	.wBlockSize		resb	2	; Block size in WORDs
-	.wWordsLeft		resb	2	; Number of WORDs left to transfer
-								; (full sectors, can be partial block)
-endstruc
-
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; Reads sectors from hard disk using PIO transfer mode.
-;
-; HPIO_ReadBlock
-;	Parameters:
-;		AL:		Number of sectors to read (1...255)
-;		ES:BX:	Pointer to buffer to recieve data
-;		DS:DI:	Ptr to Disk Parameter Table
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if transfer succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, BX, CX, DX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HPIO_ReadBlock:
-	push	es
-
-	; Create PIOVARS to stack
-	eENTER	PIOVARS_size, 0
-
-	push	si
-	mov		si, g_rgfnPioRead				; Offset to read function lookup
-	call	HPIO_InitializePIOVARS			; Store word count and block size
-	pop		si
-
-	; Start to read data
-	xchg	bx, di							; DS:BX points DPT, ES:DI points buffer
-	mov		dx, [RAMVARS.wIdeBase]			; Load IDE Base Port address
-	call	HPIO_ReadFromDrive
-
-	; Destroy stack frame
-	eLEAVE
-	mov		di, bx							; Restore DI
-	pop		es
-	ret
-
-
-;--------------------------------------------------------------------
-; Initializes PIOVARS members.
-;
-; HPIO_InitializePIOVARS
-;	Parameters:
-;		AL:		Number of sectors to transfer (1...255)
-;		SI:		Offset to transfer function lookup table
-;		DS:DI:	Ptr to Disk Parameter Table
-;		ES:BX:	Ptr to source or destination data buffer
-;		SS:BP:	Ptr to PIOVARS
-;	Returns:
-;		ES:BX:	Normalized pointer to data buffer
-;	Corrupts registers:
-;		AX, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HPIO_InitializePIOVARS:
-	; Store number of WORDs to transfer
-	mov		ah, al								; Number of WORDs to transfer...
-	xor		al, al								; ...to AX
-	mov		[bp+PIOVARS.wWordsLeft], ax			; Store WORD count
-
-	; Store block size in WORDs
-	mov		ah, [di+DPT.bSetBlock]				; AX = block size in WORDs
-	mov		[bp+PIOVARS.wBlockSize], ax			; Store block size
-
-	; Get transfer function based on bus type
-	xchg	ax, bx								; Backup BX
-	eMOVZX	bx, BYTE [di+DPT.bIdeOff]			; CS:BX now points to IDEVARS
-	mov		bl, BYTE [cs:bx+IDEVARS.bBusType]	; Load bus type to BX
-	mov		bx, [cs:bx+si]						; Load offset to transfer function
-	mov		[bp+PIOVARS.fnXfer], bx				; Store offset to transfer function
-	xchg	bx, ax
-	; Fall to HPIO_NormalizeDataPointer
-
-;--------------------------------------------------------------------
-; Normalizes far pointers so that offset overflows won't happen
-; when transferring data using PIO.
-;
-; HPIO_NormalizeDataPointer
-;	Parameters:
-;		ES:BX:	Ptr to source or destination data buffer
-;	Returns:
-;		ES:BX:	Normalized pointer to data buffer
-;	Corrupts registers:
-;		AX, CX
-;--------------------------------------------------------------------
-;ALIGN JUMP_ALIGN
-HPIO_NormalizeDataPointer:
-	NORMALIZE_FAR_POINTER es, bx, ax, cx
-	ret
-
-
-;--------------------------------------------------------------------
-; Reads blocks using PIO transfers.
-;
-; HPIO_ReadFromDrive
-;	Parameters:
-;		DX:		IDE Data port address
-;		DS:BX:	Ptr to DPT (in RAMVARS segment)
-;		ES:DI:	Normalized ptr to buffer to recieve data
-;		SS:BP:	Ptr to PIOVARS
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if transfer succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, CX, DX, DI
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HPIO_ReadFromDrive:
-	cld									; INS to increment DI
-ALIGN JUMP_ALIGN
-.BlockLoop:
-	call	HStatus_WaitIrqOrDrq		; Wait until ready to transfer
-	jc		SHORT HPIO_WriteToDrive.RetError	; Return if error (code in AH)
-	mov		cx, [bp+PIOVARS.wBlockSize]	; Load block size
-	sub		[bp+PIOVARS.wWordsLeft], cx	; Transferring last (possibly partial) block?
-	jbe		SHORT .XferLastBlock		;  If so, jump to transfer
-	call	[bp+PIOVARS.fnXfer]			; Transfer full block
-	jmp		SHORT .BlockLoop			; Loop while blocks left
-ALIGN JUMP_ALIGN
-.XferLastBlock:
-	add		cx, [bp+PIOVARS.wWordsLeft]	; CX to partial block size
-	call	[bp+PIOVARS.fnXfer]			; Transfer possibly partial block
-	jmp		HStatus_WaitBsyDefTime		; Check for errors
-
-
-;--------------------------------------------------------------------
-; Writes sectors to hard disk using PIO transfer mode.
-;
-; HPIO_WriteBlock
-;	Parameters:
-;		AL:		Number of sectors to write (1...255)
-;		ES:BX:	Pointer to buffer containing data
-;		DS:DI:	Ptr to Disk Parameter Table
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if transfer successfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, BX, CX, DX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HPIO_WriteBlock:
-	push	es
-	push	si
-
-	; Create PIOVARS to stack
-	eENTER	PIOVARS_size, 0
-
-	mov		si, g_rgfnPioWrite				; Offset to write function lookup
-	call	HPIO_InitializePIOVARS			; Store word count and block size
-
-	; Prepare pointers and start transfer
-	mov		si, bx							; ES:SI now points source buffer
-	mov		bx, di							; DS:BX now points DPT
-	call	HPIO_WriteToDrive
-
-	; Destroy stack frame
-	eLEAVE
-
-	pop		si
-	pop		es
-	ret
-
-
-;--------------------------------------------------------------------
-; Writes blocks using PIO transfers.
-;
-; HPIO_WriteToDrive
-;	Parameters:
-;		DS:BX:	Ptr to DPT (in RAMVARS segment)
-;		ES:SI:	Normalized ptr to buffer containing data
-;		SS:BP:	Ptr to PIOVARS
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if transfer succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, CX, DX, SI
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HPIO_WriteToDrive:
-	cld										; OUTS to increment SI
-	call	HStatus_WaitDrqDefTime			; Always poll DRQ for first block, get status reg to DX
-	jc		SHORT .RetError					; Return if error (code in AH)
-	sub		dx, BYTE REGR_IDE_ST			; DX to Data Port address
-ALIGN JUMP_ALIGN
-.BlockLoop:
-	mov		cx, [bp+PIOVARS.wBlockSize]		; Load block size
-	sub		[bp+PIOVARS.wWordsLeft], cx		; Transferring last (possibly partial) block?
-	jbe		SHORT .XferLastBlock			;  If so, jump to transfer
-	call	[bp+PIOVARS.fnXfer]				; Transfer full block
-	call	HStatus_WaitIrqOrDrq			; Wait until ready to transfer
-	jnc		SHORT .BlockLoop				; If no error, loop while blocks left
-.RetError:
-	ret										; This ret is shared with HPIO_ReadFromDrive
-ALIGN JUMP_ALIGN
-.XferLastBlock:
-	add		cx, [bp+PIOVARS.wWordsLeft]		; CX to partial block size
-	call	[bp+PIOVARS.fnXfer]				; Transfer possibly partial block
-	jmp		HStatus_WaitIrqOrRdy			; Check for errors
-
-
-;--------------------------------------------------------------------
-; Bus specific transfer functions and lookup table.
-;
-; HPIO_DualByteRead		Dual port 8-bit XTIDE PIO read transfer
-; HPIO_WordRead			Normal 16-bit IDE PIO read transfer
-; HPIO_DualByteWrite	Dual port 8-bit XTIDE PIO write transfer
-; HPIO_WordWrite		Normal 16-bit IDE PIO write transfer
-;	Parameters:
-;		CX:		Block size in WORDs
-;		DX:		IDE Data port address
-;		ES:DI:	Normalized ptr to buffer to recieve data (read only)
-;		ES:SI:	Normalized ptr to buffer containing data (write only)
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AX, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HPIO_DualByteRead:
-	eREP_DUAL_BYTE_PORT_INSW
-	ret
-ALIGN JUMP_ALIGN
-HPIO_WordRead:
-	rep
-	db		6Dh			; INSW
-	ret
-ALIGN JUMP_ALIGN
-HPIO_DWordRead:
-	shr		cx, 1		; WORD count to DWORD count
-	rep
-	db		66h			; Override operand size to 32-bit
-	db		6Dh			; INSW/INSD
-	ret
-ALIGN JUMP_ALIGN
-HPIO_SingleByteRead:
-	eREP_SINGLE_BYTE_PORT_INSW
-	ret
-
-ALIGN JUMP_ALIGN
-HPIO_DualByteWrite:
-	eREP_DUAL_BYTE_PORT_OUTSW
-	ret
-ALIGN JUMP_ALIGN
-HPIO_WordWrite:
-	eSEG	es			; Source is ES segment
-	rep
-	db		6Fh			; OUTSW
-	ret
-ALIGN JUMP_ALIGN
-HPIO_DWordWrite:
-	shr		cx, 1		; WORD count to DWORD count
-	eSEG	es			; Source is ES segment
-	rep
-	db		66h			; Override operand size to 32-bit
-	db		6Fh			; OUTSW/OUTSD
-	ret
-ALIGN JUMP_ALIGN
-HPIO_SingleByteWrite:
-	eREP_SINGLE_BYTE_PORT_OUTSW
-	ret
-
-ALIGN WORD_ALIGN
-g_rgfnPioRead:
-	dw		HPIO_DualByteRead		; 8-bit dual port reads
-	dw		HPIO_WordRead			; 16-bit reads
-	dw		HPIO_DWordRead			; 32-bit reads
-	dw		HPIO_SingleByteRead		; 8-bit single port reads
-g_rgfnPioWrite:
-	dw		HPIO_DualByteWrite		; 8-bit dual port writes
-	dw		HPIO_WordWrite			; 16-bit writes
-	dw		HPIO_DWordWrite			; 32-bit writes
-	dw		HPIO_SingleByteWrite	; 8-bit single port writes
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HStatus.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HStatus.asm	(revision 149)
+++ 	(revision )
@@ -1,220 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	IDE Status Register polling functions.
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; Waits Hard Disk IRQ when not transferring data.
-; If interrupts are disabled, RDY flag is polled.
-;
-; HStatus_WaitIrqOrRdy
-;	Parameters:
-;		DS:BX:	Ptr to DPT
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if wait succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, CX, DX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HStatus_WaitIrqOrRdy:
-	call	HIRQ_WaitForIRQ			; For OS hook (we still need error processing)
-	jnc		SHORT .PollRdySinceNoWaitingOnOsHook
-	jmp		HError_GetErrorCodeToAHafterPolling
-
-ALIGN JUMP_ALIGN
-.PollRdySinceNoWaitingOnOsHook:
-	mov		cl, B_TIMEOUT_DRQ				; Load DRQ (not RDY) timeout
-	jmp		SHORT HStatus_WaitRdy			; Jump to poll RDY
-
-
-;--------------------------------------------------------------------
-; Waits until Hard Disk is ready to transfer data.
-;
-; HStatus_WaitIrqOrDrq
-;	Parameters:
-;		DS:BX:	Ptr to DPT (in RAMVARS segment)
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		0 if wait succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HStatus_WaitIrqOrDrq:
-	call	HIRQ_WaitForIRQ
-	jnc		SHORT .PollDrqSinceNoWaitingOnOsHook
-	jmp		HError_GetErrorCodeToAHafterPolling
-
-ALIGN JUMP_ALIGN
-.PollDrqSinceNoWaitingOnOsHook:
-	push	dx
-	push	cx
-	call	HStatus_WaitDrqDefTime
-	pop		cx
-	pop		dx
-	ret
-
-
-;--------------------------------------------------------------------
-; Waits until busy flag is cleared from selected Hard Disk drive.
-;
-; HStatus_WaitBsyDefTime	Uses default timeout
-; HStatus_WaitBsy			Uses user defined timeout
-; HStatus_WaitBsyBase		Uses user base port address and timeout
-;	Parameters:
-;		CL:		Timeout value in system timer ticks (not HStatus_WaitBsyDefTime)
-;		DX:		IDE Base port address (HUtil_WaitBsyBase only)
-;		DS:		Segment to RAMVARS
-;	Returns:
-;		AH:		BIOS Error code
-;		DX:		IDE Status Register Address
-;		CF:		0 if wait succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HStatus_WaitBsyDefTime:
-	mov		cl, B_TIMEOUT_BSY			; Load timeout value
-ALIGN JUMP_ALIGN
-HStatus_WaitBsy:
-	mov		dx, [RAMVARS.wIdeBase]		; Load offset to base port
-ALIGN JUMP_ALIGN
-HStatus_WaitBsyBase:
-	add		dx, BYTE REGR_IDE_ST		; Add offset to status reg
-	jmp		SHORT HStatus_PollBsy		; Wait until not busy
-
-
-;--------------------------------------------------------------------
-; Waits until Hard Disk is ready to accept commands.
-;
-; HStatus_WaitRdyDefTime	Uses default timeout
-; HStatus_WaitRdy			Uses user defined timeout
-; HStatus_WaitRdyBase		Uses user base port address and timeout
-;	Parameters:
-;		CL:		Timeout value in system timer ticks (not HStatus_WaitRdyDefTime)
-;		DX:		IDE Base port address (HStatus_WaitRdyBase only)
-;		DS:		Segment to RAMVARS
-;	Returns:
-;		AH:		BIOS Error code
-;		DX:		IDE Status Register Address
-;		CF:		0 if wait succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HStatus_WaitRdyDefTime:
-	mov		cl, B_TIMEOUT_RDY			; Load timeout value
-ALIGN JUMP_ALIGN
-HStatus_WaitRdy:
-	mov		dx, [RAMVARS.wIdeBase]		; Load offset to base port
-ALIGN JUMP_ALIGN
-HStatus_WaitRdyBase:
-	add		dx, BYTE REGR_IDE_ST		; Add offset to status reg
-	mov		ah, FLG_IDE_ST_DRDY			; Flag to poll
-	jmp		SHORT HStatus_PollBsyAndFlg	; Wait until flag set
-
-
-;--------------------------------------------------------------------
-; Waits until Hard Disk is ready to transfer data.
-; Note! This function polls DRQ even if interrupts are enabled!
-;
-; HStatus_WaitDrqDefTime	Uses default timeout
-; HStatus_WaitDrq			Uses user defined timeout
-; HStatus_WaitDrqBase		Uses user base port address and timeout
-;	Parameters:
-;		CL:		Timeout value in system timer ticks (not HStatus_WaitDrqDefTime)
-;		DX:		IDE Base port address (HStatus_WaitDrqBase only)
-;		DS:		Segment to RAMVARS
-;	Returns:
-;		AH:		BIOS Error code
-;		DX:		IDE Status Register Address
-;		CF:		0 if wait succesfull
-;				1 if any error
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HStatus_WaitDrqDefTime:
-	mov		cl, B_TIMEOUT_DRQ			; Load timeout value
-ALIGN JUMP_ALIGN
-HStatus_WaitDrq:
-	mov		dx, [RAMVARS.wIdeBase]		; Load offset to base port
-ALIGN JUMP_ALIGN
-HStatus_WaitDrqBase:
-	add		dx, BYTE REGR_IDE_ST		; Add offset to status reg
-	mov		ah, FLG_IDE_ST_DRQ			; Flag to poll
-	; Fall to HStatus_PollBsyAndFlg
-
-;--------------------------------------------------------------------
-; IDE Status register polling.
-; This function first waits until controller is not busy.
-; When not busy, IDE Status Register is polled until wanted flag is set.
-;
-; HStatus_PollBusyAndFlg
-;	Parameters:
-;		AH:		Status Register Flag to poll (until set) when not busy
-;		CL:		Timeout value in system timer ticks
-;		DX:		IDE Status Register Address
-;		DS:		Segment to RAMVARS
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		Clear if wait completed successfully (no errors)
-;				Set if any error
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HStatus_PollBsyAndFlg:
-	call	HTimer_InitializeTimeoutWithTicksInCL	; Initialize timeout counter
-	in		al, dx									; Discard contents for first read
-													; (should read Alternate Status Register)
-ALIGN JUMP_ALIGN
-.PollLoop:
-	in		al, dx									; Load IDE Status Register
-	test	al, FLG_IDE_ST_BSY						; Controller busy?
-	jnz		SHORT .UpdateTimeout					;  If so, jump to timeout update
-	test	al, ah									; Test secondary flag
-	jnz		SHORT GetErrorCodeFromPollingToAH		; If set, break loop
-ALIGN JUMP_ALIGN
-.UpdateTimeout:
-	call	HTimer_SetCFifTimeout
-	jnc		SHORT .PollLoop							; Loop if time left
-	jmp		HError_GetErrorCodeToAHforTimeoutWhenPolling
-
-;--------------------------------------------------------------------
-; IDE Status register polling.
-; This function waits until controller is not busy.
-;
-; HStatus_PollBsy
-;	Parameters:
-;		CL:		Timeout value in system timer ticks
-;		DX:		IDE Status Register Address
-;		DS:		Segment to RAMVARS
-;	Returns:
-;		AH:		BIOS Error code
-;		CF:		Clear if wait completed successfully (no errors)
-;				Set if any error
-;	Corrupts registers:
-;		AL, CX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-HStatus_PollBsy:
-	call	HTimer_InitializeTimeoutWithTicksInCL	; Initialize timeout counter
-	in		al, dx									; Discard contents for first read
-													; (should read Alternate Status Register)
-ALIGN JUMP_ALIGN
-.PollLoop:
-	in		al, dx									; Load IDE Status Reg
-	test	al, FLG_IDE_ST_BSY						; Controller busy?
-	jz		SHORT GetErrorCodeFromPollingToAH		;  If not, jump to check errors
-	call	HTimer_SetCFifTimeout					; Update timeout counter
-	jnc		SHORT .PollLoop							; Loop if time left (sets CF on timeout)
-ALIGN JUMP_ALIGN
-GetErrorCodeFromPollingToAH:
-	jmp		HError_GetErrorCodeToAHafterPolling
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HTimer.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HTimer.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HTimer.asm	(revision 150)
@@ -6,7 +6,7 @@
 
 ;--------------------------------------------------------------------
-; HTimer_InitializeTimeoutWithTicksInCL
+; HTimer_InitializeTimeoutWithTicksInCX
 ;	Parameters:
-;		CL:		Timeout value in system timer ticks
+;		CX:		Timeout value in system timer ticks
 ;		DS:		Segment to RAMVARS
 ;	Returns:
@@ -16,6 +16,5 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-HTimer_InitializeTimeoutWithTicksInCL:
-	xor		ch, ch							; Timeout ticks now in CX
+HTimer_InitializeTimeoutWithTicksInCX:
 	mov		[RAMVARS.wTimeoutCounter], cx	; Store timeout ticks
 	call	ReadTimeFromBdaToCX
@@ -55,5 +54,5 @@
 HTimer_DelayMicrosecondsFromAX:
 %ifndef USE_AT
-	mov		ax, 1
+	mov		ax, 2
 	; Fall to Delay_TimerTicksFromAX
 %else
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm	(revision 150)
@@ -1,3 +1,3 @@
-; Project name	:	IDE BIOS
+; Project name	:	XTIDE Universal BIOS
 ; Description	:	Functions for detecting drive for the BIOS.
 
@@ -43,9 +43,9 @@
 	push	cx
 	mov		ax, g_szMaster
-	mov		bh, MASK_IDE_DRVHD_SET								; Select Master drive
+	mov		bh, MASK_DRVNHEAD_SET								; Select Master drive
 	call	StartDetectionWithDriveSelectByteInBHandStringInAX	; Detect and create DPT + BOOTNFO
 
 	mov		ax, g_szSlave
-	mov		bh, MASK_IDE_DRVHD_SET | FLG_IDE_DRVHD_DRV
+	mov		bh, MASK_DRVNHEAD_SET | FLG_DRVNHEAD_DRV
 	call	StartDetectionWithDriveSelectByteInBHandStringInAX
 	pop		cx
@@ -78,15 +78,18 @@
 ;		ES:		Zero (BDA segment)
 ;	Returns:
-;		ES:SI	Ptr to ATA information (read with IDENTIFY DEVICE command)
 ;		CF:		Cleared if ATA-information read successfully
 ;				Set if any error
 ;	Corrupts registers:
-;		AX, BL, CX, DX, DI
+;		AX, BL, CX, DX, SI, DI
 ;--------------------------------------------------------------------
 .ReadAtaInfoFromHardDisk:
-	mov		bl, [cs:bp+IDEVARS.bBusType]; Load BUS type
-	mov		dx, [cs:bp+IDEVARS.wPort]	; Load IDE Base Port address
-	mov		di, BOOTVARS.rgbAtaInfo		; ES:DI now points to ATA info location
-	call	AH25h_GetDriveInfo
+	mov		si, BOOTVARS.rgbAtaInfo		; ES:SI now points to ATA info location
+	push	es
+	push	si
+	push	bx
+	call	Device_IdentifyToBufferInESSIwithDriveSelectByteInBH
+	pop		bx
+	pop		si
+	pop		es
 	jnc		SHORT CreateBiosTablesForHardDisk
 	; Fall to .ReadAtapiInfoFromDrive
@@ -103,5 +106,5 @@
 ;		BH:		Drive Select byte for Drive and Head Register
 ;		CS:BP:	Ptr to IDEVARS for the drive
-;		ES:DI	Ptr to ATA information for the drive
+;		ES:SI	Ptr to ATA information for the drive
 ;		DS:		RAMVARS segment
 ;		ES:		BDA/Bootnfo segment
@@ -112,5 +115,4 @@
 ;--------------------------------------------------------------------
 CreateBiosTablesForHardDisk:
-	mov		si, di					; ES:SI now points to ATA information
 	call	CreateDPT_FromAtaInformation
 	jc		SHORT .InvalidAtaInfo
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm	(revision 150)
@@ -108,6 +108,9 @@
 ;		Nothing
 ;	Corrupts registers:
-;		AX, BX, CX, DX, DI
+;		All
 ;--------------------------------------------------------------------
 .ResetDetectedDrives:
-	jmp		AH0h_ResetHardDisksHandledByOurBIOS
+	call	Idepack_FakeToSSBP
+	call	AH0h_ResetHardDisksHandledByOurBIOS
+	add		sp, BYTE SIZE_OF_FAKE_IDEPACK
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm	(revision 150)
@@ -111,5 +111,5 @@
 .InstallHighIrqHandler:
 	add		bx, BYTE INTV_IRQ8 - 8			; Interrupt vector number
-	mov		si, HIRQ_InterruptServiceRoutineForIrqs8to15
+	mov		si, IdeIrq_InterruptServiceRoutineForIrqs8to15
 	jmp		SHORT Interrupts_InstallHandlerToVectorInBXFromCSSI
 
@@ -126,5 +126,5 @@
 .InstallLowIrqHandler:
 	add		bx, BYTE INTV_IRQ0				; Interrupt vector number
-	mov		si, HIRQ_InterruptServiceRoutineForIrqs2to7
+	mov		si, IdeIrq_InterruptServiceRoutineForIrqs2to7
 	; Fall to Interrupts_InstallHandlerToVectorInBXFromCSSI
 
@@ -158,5 +158,5 @@
 ;--------------------------------------------------------------------
 Interrupts_UnmaskInterruptControllerForDriveInDSDI:
-	eMOVZX	bx, BYTE [di+DPT.bIdeOff]
+	eMOVZX	bx, BYTE [di+DPT.bIdevarsOffset]
 	mov		al, [cs:bx+IDEVARS.bIRQ]
 	test	al, al
Index: trunk/XTIDE_Universal_BIOS/Src/Main.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Main.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Main.asm	(revision 150)
@@ -25,4 +25,5 @@
 %include "BootMenu.inc"			; For Boot Menu
 %include "IDE_8bit.inc"			; For IDE 8-bit data port macros
+%include "DeviceIDE.inc"		; For IDE device equates
 
 
@@ -55,5 +56,5 @@
 	at	ROMVARS.wDisplayMode,	dw	DEFAULT_TEXT_MODE
 	at	ROMVARS.wBootTimeout,	dw	30 * TICKS_PER_SECOND	; Boot Menu selection timeout
-	at	ROMVARS.bIdeCnt,		db	3						; Number of supported controllers
+	at	ROMVARS.bIdeCnt,		db	4						; 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
@@ -62,6 +63,6 @@
 	at	ROMVARS.ideVars0+IDEVARS.wPort,			dw	1F0h			; Controller Command Block base port
 	at	ROMVARS.ideVars0+IDEVARS.wPortCtrl,		dw	3F0h			; Controller Control Block base port
-	at	ROMVARS.ideVars0+IDEVARS.bBusType,		db	BUS_TYPE_16		; Bus type
-	at	ROMVARS.ideVars0+IDEVARS.bIRQ,			db	14				; IRQ
+	at	ROMVARS.ideVars0+IDEVARS.bDevice,		db	DEVICE_16BIT_ATA
+	at	ROMVARS.ideVars0+IDEVARS.bIRQ,			db	14
 	at	ROMVARS.ideVars0+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
 	at	ROMVARS.ideVars0+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
@@ -69,6 +70,6 @@
 	at	ROMVARS.ideVars1+IDEVARS.wPort,			dw	170h			; Controller Command Block base port
 	at	ROMVARS.ideVars1+IDEVARS.wPortCtrl,		dw	370h			; Controller Control Block base port
-	at	ROMVARS.ideVars1+IDEVARS.bBusType,		db	BUS_TYPE_16		; Bus type
-	at	ROMVARS.ideVars1+IDEVARS.bIRQ,			db	15				; IRQ
+	at	ROMVARS.ideVars1+IDEVARS.bDevice,		db	DEVICE_16BIT_ATA
+	at	ROMVARS.ideVars1+IDEVARS.bIRQ,			db	15
 	at	ROMVARS.ideVars1+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
 	at	ROMVARS.ideVars1+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
@@ -76,6 +77,6 @@
 	at	ROMVARS.ideVars2+IDEVARS.wPort,			dw	300h			; Controller Command Block base port
 	at	ROMVARS.ideVars2+IDEVARS.wPortCtrl,		dw	308h			; Controller Control Block base port
-	at	ROMVARS.ideVars2+IDEVARS.bBusType,		db	BUS_TYPE_8_DUAL	; Bus type
-	at	ROMVARS.ideVars2+IDEVARS.bIRQ,			db	0				; IRQ
+	at	ROMVARS.ideVars2+IDEVARS.bDevice,		db	DEVICE_8BIT_DUAL_PORT_XTIDE
+	at	ROMVARS.ideVars2+IDEVARS.bIRQ,			db	0
 	at	ROMVARS.ideVars2+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
 	at	ROMVARS.ideVars2+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
@@ -83,6 +84,6 @@
 	at	ROMVARS.ideVars3+IDEVARS.wPort,			dw	168h			; Controller Command Block base port
 	at	ROMVARS.ideVars3+IDEVARS.wPortCtrl,		dw	368h			; Controller Control Block base port
-	at	ROMVARS.ideVars3+IDEVARS.bBusType,		db	BUS_TYPE_16		; Bus type
-	at	ROMVARS.ideVars3+IDEVARS.bIRQ,			db	0				; IRQ
+	at	ROMVARS.ideVars3+IDEVARS.bDevice,		db	DEVICE_16BIT_ATA
+	at	ROMVARS.ideVars3+IDEVARS.bIRQ,			db	0
 	at	ROMVARS.ideVars3+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
 	at	ROMVARS.ideVars3+IDEVARS.drvParamsSlave+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
@@ -101,5 +102,5 @@
 	at	ROMVARS.ideVars0+IDEVARS.wPort,			dw	300h			; Controller Command Block base port
 	at	ROMVARS.ideVars0+IDEVARS.wPortCtrl,		dw	308h			; Controller Control Block base port
-	at	ROMVARS.ideVars0+IDEVARS.bBusType,		db	BUS_TYPE_8_DUAL	; Bus type
+	at	ROMVARS.ideVars0+IDEVARS.bDevice,		db	DEVICE_8BIT_DUAL_PORT_XTIDE
 	at	ROMVARS.ideVars0+IDEVARS.bIRQ,			db	0				; IRQ
 	at	ROMVARS.ideVars0+IDEVARS.drvParamsMaster+DRVPARAMS.wFlags,	db	FLG_DRVPARAMS_BLOCKMODE
@@ -146,11 +147,4 @@
 %include "DriveXlate.asm"		; For swapping drive numbers
 %include "HAddress.asm"			; For sector address translations
-%include "HCapacity.asm"		; For calculating drive capacity
-%include "HError.asm"			; For error checking
-%include "HPIO.asm"				; For PIO transfers
-%include "HIRQ.asm"				; For IRQ handling
-%include "HStatus.asm"			; For reading hard disk status
-%include "HDrvSel.asm"			; For selecting drive to access
-%include "HCommand.asm"			; For outputting command and parameters
 %include "HTimer.asm"			; For timeout and delay
 
@@ -178,5 +172,19 @@
 %include "AH24h_HSetBlocks.asm"	; Required by Int13h_Jump.asm
 %include "AH25h_HDrvID.asm"		; Required by Int13h_Jump.asm
+%include "Device.asm"
+%include "Idepack.asm"
 
+; IDE Device support
+%include "IdeCommand.asm"
+%include "IdeDPT.asm"
+%include "IdeIO.asm"
+%include "IdeIrq.asm"
+%include "IdeTransfer.asm"
+%include "IdeWait.asm"
+%include "IdeError.asm"			; Must be included after IdeWait.asm
+
+; Serial Port Device support
+%include "SerialCommand.asm"
+%include "SerialDPT.asm"
 
 
Index: trunk/XTIDE_Universal_BIOS/Src/Strings.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Strings.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/Strings.asm	(revision 150)
@@ -36,5 +36,5 @@
 g_szSizeDual:	db	"%s%4-u.%u %ciB / %4-u.%u %ciB",LF,CR,NULL
 g_szCfgHeader:	db	"Addr.",SINGLE_VERTICAL,"Block",SINGLE_VERTICAL,"Bus",  SINGLE_VERTICAL,"IRQ",  SINGLE_VERTICAL,"Reset",LF,CR,NULL
-g_szCfgFormat:	db	"%s"   ,SINGLE_VERTICAL,"%5-u",  SINGLE_VERTICAL,"%c%2u",SINGLE_VERTICAL," %c%c",SINGLE_VERTICAL,"%5-x",  NULL
+g_szCfgFormat:	db	"%s"   ,SINGLE_VERTICAL,"%5-u", SINGLE_VERTICAL,"%c%2u",SINGLE_VERTICAL," %c%c",SINGLE_VERTICAL,"%5-x",  NULL
 g_szLCHS:		db	"L-CHS",NULL
 g_szPCHS:		db	"P-CHS",NULL
Index: trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AccessDPT.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AccessDPT.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AccessDPT.asm	(revision 150)
@@ -6,6 +6,57 @@
 
 ;--------------------------------------------------------------------
-; Returns L-CHS values from DPT.
-;
+; AccessDPT_GetDriveSelectByteToAL
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		AL:		Drive Select Byte
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AccessDPT_GetDriveSelectByteToAL:
+	mov		al, [di+DPT.wFlags]
+	and		al, FLG_DRVNHEAD_LBA | FLG_DRVNHEAD_DRV
+	or		al, MASK_DRVNHEAD_SET	; Bits set to 1 for old drives
+	ret
+
+
+;--------------------------------------------------------------------
+; AccessDPT_GetDeviceControlByteToAL
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		AL:		Device Control Byte
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AccessDPT_GetDeviceControlByteToAL:
+	xor		al, al
+	test	BYTE [di+DPT.wFlags], FLG_DPT_ENABLE_IRQ
+	jnz		SHORT .EnableDeviceIrq
+	or		al, FLG_DEVCONTROL_nIEN	; Disable IRQ
+.EnableDeviceIrq:
+	ret
+
+
+;--------------------------------------------------------------------
+; AccessDPT_GetAddressingModeForWordLookToBX
+;	Parameters:
+;		DS:DI:	Ptr to Disk Parameter Table
+;	Returns:
+;		BX:		Addressing Mode (L-CHS, P-CHS, LBA28, LBA48) shifted for WORD lookup
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AccessDPT_GetAddressingModeForWordLookToBX:
+	mov		bl, [di+DPT.wFlags]
+	and		bx, BYTE MASK_DPT_ADDRESSING_MODE
+	eSHR_IM	bx, ADDRESSING_MODE_FIELD_POSITION-1
+	ret
+
+
+;--------------------------------------------------------------------
 ; AccessDPT_GetLCHSfromPCHS
 ;	Parameters:
@@ -21,16 +72,15 @@
 AccessDPT_GetLCHSfromPCHS:
 	xchg	ax, cx
-	mov		cl, [di+DPT.bShLtoP]		; Load shift count
-	mov		bx, [di+DPT.wPCyls]			; Load P-CHS cylinders
-	shr		bx, cl						; Shift to L-CHS cylinders
+	mov		cl, [di+DPT.wFlags]
+	and		cl, MASK_DPT_CHS_SHIFT_COUNT	; Load shift count
+	mov		bx, [di+DPT.wPchsCylinders]		; Load P-CHS cylinders
+	shr		bx, cl							; Shift to L-CHS cylinders
 	xchg	cx, ax
-	mov		dx, [di+DPT.wLHeads]		; Load L-CHS heads
-	eMOVZX	ax, BYTE [di+DPT.bPSect]	; Load Sectors per track
+	eMOVZX	dx, BYTE [di+DPT.bLchsHeads]	; Load L-CHS heads
+	eMOVZX	ax, BYTE [di+DPT.bPchsSectors]	; Load Sectors per track
 	ret
 
 
 ;--------------------------------------------------------------------
-; Tests IDEVARS flags for master or slave drive.
-;
 ; AccessDPT_TestIdeVarsFlagsForMasterOrSlaveDrive
 ;	Parameters:
@@ -63,11 +113,9 @@
 ALIGN JUMP_ALIGN
 AccessDPT_GetPointerToDRVPARAMStoCSBX:
-	eMOVZX	bx, [di+DPT.bIdeOff]		; CS:BX points to IDEVARS
-	test	BYTE [di+DPT.bDrvSel], FLG_IDE_DRVHD_DRV
-	jnz		SHORT .ReturnPointerToSlaveDRVPARAMS
-	add		bx, BYTE IDEVARS.drvParamsMaster
+	eMOVZX	bx, [di+DPT.bIdevarsOffset]			; CS:BX points to IDEVARS
+	add		bx, BYTE IDEVARS.drvParamsMaster	; CS:BX points to Master Drive DRVPARAMS
+	test	BYTE [di+DPT.wFlags], FLG_DPT_SLAVE
+	jz		SHORT .ReturnPointerToDRVPARAMS
+	add		bx, BYTE DRVPARAMS_size				; CS:BX points to Slave Drive DRVPARAMS
+.ReturnPointerToDRVPARAMS:
 	ret
-ALIGN JUMP_ALIGN
-.ReturnPointerToSlaveDRVPARAMS:
-	add		bx, BYTE IDEVARS.drvParamsSlave
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/CreateDPT.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/CreateDPT.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/CreateDPT.asm	(revision 150)
@@ -25,5 +25,5 @@
 ;--------------------------------------------------------------------
 CreateDPT_FromAtaInformation:
-	call	FindDPT_ForNewDrive		; Get new DPT to DS:DI
+	call	FindDPT_ForNewDriveToDSDI
 	; Fall to .InitializeDPT
 
@@ -35,21 +35,15 @@
 ;		CS:BP:	Ptr to IDEVARS for the controller
 ;	Returns:
-;		AX:		Zero
-;	Corrupts registers:
-;		Nothing
+;		Nothing
+;	Corrupts registers:
+;		AX
 ;--------------------------------------------------------------------
 .InitializeDPT:
-	xor		ax, ax
-	mov		BYTE [di+DPT.bSize], DPT_size
-	mov		[di+DPT.wDrvNumAndFlags], ax
-	mov		BYTE [di+DPT.bReset], MASK_RESET_ALL
-	mov		[di+DPT.bIdeOff], bp
-	mov		[di+DPT.bDrvSel], bh
-	; Fall to .StoreDriveControlByte
-
-;--------------------------------------------------------------------
-; .StoreDriveControlByte
-;	Parameters:
-;		AX:		Zero
+	mov		[di+DPT.bIdevarsOffset], bp	; IDEVARS must start in first 256 bytes of ROM
+	; Fall to .StoreDriveSelectAndDriveControlByte
+
+;--------------------------------------------------------------------
+; .StoreDriveSelectAndDriveControlByte
+;	Parameters:
 ;		BH:		Drive Select byte for Drive and Head Register
 ;		DS:DI:	Ptr to Disk Parameter Table
@@ -61,14 +55,12 @@
 ;		AX
 ;--------------------------------------------------------------------
-.StoreDriveControlByte:
-	cmp		BYTE [cs:bp+IDEVARS.bIRQ], al	; Interrupts enabled?
-	jne		SHORT .CheckHeadCount
-	or		al, FLG_IDE_CTRL_nIEN			; Disable interrupts
-.CheckHeadCount:
-	cmp		BYTE [es:si+ATA1.wHeadCnt], 8	; 1...8 heads?
-	jbe		SHORT .StoreDrvCtrlByteToDPT
-	or		al, FLG_IDE_CTRL_O8H			; Over 8 heads (pre-ATA)
-.StoreDrvCtrlByteToDPT:
-	mov		[di+DPT.bDrvCtrl], al
+.StoreDriveSelectAndDriveControlByte:
+	mov		al, bh
+	and		ax, BYTE FLG_DRVNHEAD_DRV		; AL now has Master/Slave bit
+	cmp		[cs:bp+IDEVARS.bIRQ], ah		; Interrupts enabled?
+	jz		SHORT .StoreFlags				;  If not, do not set interrupt flag
+	or		al, FLG_DPT_ENABLE_IRQ
+.StoreFlags:
+	mov		[di+DPT.wFlags], ax
 	; Fall to .StorePCHS
 
@@ -76,5 +68,4 @@
 ; .StorePCHS
 ;	Parameters:
-;		AH:		Zero
 ;		BH:		Drive Select byte for Drive and Head Register
 ;		DS:DI:	Ptr to Disk Parameter Table
@@ -99,9 +90,8 @@
 	mov		ax, [cs:bx+DRVPARAMS.wCylinders]
 	mov		bx, [cs:bx+DRVPARAMS.wHeadsAndSectors]
-	or		BYTE [di+DPT.bFlags], FLG_DPT_USERCHS
 
 .StorePCHStoDPT:
-	mov		[di+DPT.wPCyls], ax
-	mov		[di+DPT.wHeadsAndSectors], bx
+	mov		[di+DPT.wPchsCylinders], ax
+	mov		[di+DPT.wPchsHeadsAndSectors], bx
 	; Fall to .StoreLCHS
 
@@ -129,11 +119,9 @@
 	jmp		SHORT .ShiftLoop
 
-.LimitHeadsTo255:
-	test	bh, bh						; 256 heads?
-	jz		SHORT .StoreLCHStoDPT		;  If less, no correction needed
-	dec		bx							; Limit to 255 heads since DOS does not support 256 heads
-.StoreLCHStoDPT:
-	mov		[di+DPT.bShLtoP], cl
-	mov		[di+DPT.wLHeads], bx
+.LimitHeadsTo255:						; DOS does not support drives with 256 heads
+	rcr		bh, 1						; Set CF if 256 heads
+	sbb		bl, 0						; Decrement to 255 if 256 heads
+	or		[di+DPT.wFlags], cl
+	mov		[di+DPT.bLchsHeads], bl
 	; Fall to .StoreAddressing
 
@@ -146,22 +134,27 @@
 ;		Nothing
 ;	Corrupts registers:
-;		Nothing
+;		AX, BX
 ;--------------------------------------------------------------------
 .StoreAddressing:
-	cmp		WORD [di+DPT.wPCyls], 1024		; L-CHS possible? (no translation needed)
-	jbe		SHORT .StoreBlockMode			;  If so, nothing needs to be changed
-	test	BYTE [di+DPT.bFlags], FLG_DPT_USERCHS
-	jnz		SHORT .StorePCHSaddressing		; Use user defined P-CHS
+	; Check if L-CHS addressing should be used
+	cmp		WORD [di+DPT.wPchsCylinders], 1024	; L-CHS possible? (no translation needed)
+	jbe		SHORT .StoreBlockMode				;  If so, nothing needs to be changed
+
+	; Check if P-CHS addressing should be used
+	mov		al, FLG_DRVPARAMS_USERCHS			; User specified CHS?
+	call	AccessDPT_TestIdeVarsFlagsForMasterOrSlaveDrive
+	jnz		SHORT .StorePCHSaddressing
 	test	WORD [es:si+ATA1.wCaps], A2_wCaps_LBA
-	jz		SHORT .StorePCHSaddressing		; Use P-CHS since LBA not supported
+	jz		SHORT .StorePCHSaddressing			; Use P-CHS since LBA not supported
+
+	; LBA needs to be used. Check if 48-bit LBA is supported
 	test	WORD [es:si+ATA6.wSetSup83], A6_wSetSup83_LBA48
-	jz		SHORT .StoreLBA28addressing		; Use LBA-28 since LBA-48 not supported
-	or		BYTE [di+DPT.bFlags], ADDR_DPT_LBA48<<1
+	jz		SHORT .StoreLBA28addressing			; Use LBA-28 since LBA-48 not supported
+	or		BYTE [di+DPT.wFlags], ADDRESSING_MODE_LBA48<<ADDRESSING_MODE_FIELD_POSITION
 .StoreLBA28addressing:
-	or		BYTE [di+DPT.bFlags], ADDR_DPT_LBA28<<1
-	or		BYTE [di+DPT.bDrvSel], FLG_IDE_DRVHD_LBA
+	or		BYTE [di+DPT.wFlags], ADDRESSING_MODE_LBA28<<ADDRESSING_MODE_FIELD_POSITION
 	jmp		SHORT .StoreBlockMode
 .StorePCHSaddressing:
-	or		BYTE [di+DPT.bFlags], ADDR_DPT_PCHS<<1
+	or		BYTE [di+DPT.wFlags], ADDRESSING_MODE_PCHS<<ADDRESSING_MODE_FIELD_POSITION
 	; Fall to .StoreBlockMode
 
@@ -174,44 +167,25 @@
 ;		Nothing
 ;	Corrupts registers:
-;		AX
+;		Nothing
 ;--------------------------------------------------------------------
 .StoreBlockMode:
-	mov		al, 1						; Minimum block size is 1 sector
-	mov		ah, [es:si+ATA1.bBlckSize]	; Load max block size in sectors
-	mov		[di+DPT.wSetAndMaxBlock], ax
-	; Fall to .StoreEBIOSSupport
-
-;--------------------------------------------------------------------
-; .StoreEBIOSSupport
-;	Parameters:
-;		DS:DI:	Ptr to Disk Parameter Table
-;		ES:SI:	Ptr to 512-byte ATA information read from the drive
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AX, BX, DX
-;--------------------------------------------------------------------
-.StoreEBIOSSupport:
-	test	BYTE [cs:ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
-	jz		SHORT .StoreDriveNumberAndUpdateDriveCount	; No EBIOS support since small DPTs needed
-
-	mov		bl, [di+DPT.bFlags]
-	and		bx, BYTE MASK_DPT_ADDR						; Addressing mode
-	jmp		[cs:bx+.rgwAddrJmp]							; Jump to handle addressing mode
-.rgwAddrJmp:
-	dw		.StoreDriveNumberAndUpdateDriveCount		; ADDR_DPT_LCHS
-	dw		.StoreDriveNumberAndUpdateDriveCount		; ADDR_DPT_PCHS
-	dw		.SupportForLBA28							; ADDR_DPT_LBA28
-	dw		.SupportForLBA48							; ADDR_DPT_LBA48
-
-.SupportForLBA28:
-	sub		BYTE [di+DPT.bSize], 2		; Only 4 bytes for sector count
-.SupportForLBA48:
-	add		BYTE [di+DPT.bSize], EBDPT_size - DPT_size
-	or		BYTE [di+DPT.bFlags], FLG_DPT_EBIOS
-	call	AtaID_GetTotalSectorCount
-	mov		[di+EBDPT.twCapacity], ax
-	mov		[di+EBDPT.twCapacity+2], dx
-	mov		[di+EBDPT.twCapacity+4], bx
+	cmp		BYTE [es:si+ATA1.bBlckSize], 1	; Max block size in sectors
+	jbe		SHORT .BlockModeTransfersNotSupported
+	or		WORD [di+DPT.wFlags], FLG_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
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+.StoreDeviceSpecificParameters:
+	call	Device_FinalizeDPT
 	; Fall to .StoreDriveNumberAndUpdateDriveCount
 
@@ -230,18 +204,14 @@
 ;--------------------------------------------------------------------
 .StoreDriveNumberAndUpdateDriveCount:
-	; Make sure that more drives can be accepted
-	mov		dl, [es:BDA.bHDCount]	; Load number of hard disks
-	test	dl, dl					; Hard disks at maximum?
-	stc								; Assume error
-	js		SHORT .TooManyDrives	;  If so, return
-
-	; Store drive number to DPT
-	or		dl, 80h					; Set bit 7 since hard disk
-	mov		[di+DPT.bDrvNum], dl	; Store drive number
-
-	; Update BDA and RAMVARS
-	inc		BYTE [es:BDA.bHDCount]	; Increment drive count to BDA
-	call	RamVars_IncrementHardDiskCount
+	mov		dl, [es:BDA.bHDCount]
+	or		dl, 80h						; Set bit 7 since hard disk
+
+	inc		BYTE [RAMVARS.bDrvCnt]		; Increment drive count to RAMVARS
+	inc		BYTE [es:BDA.bHDCount]		; Increment drive count to BDA
+
+	cmp		BYTE [RAMVARS.bFirstDrv], 0	; First drive set?
+	ja		SHORT .AllDone				;  If so, return
+	mov		[RAMVARS.bFirstDrv], dl		; Store first drive number
+.AllDone:
 	clc
-.TooManyDrives:
 	ret
Index: trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/FindDPT.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/FindDPT.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/FindDPT.asm	(revision 150)
@@ -1,7 +1,3 @@
-; File name		:	FindDPT.asm
-; Project name	:	IDE BIOS
-; Created date	:	14.3.2010
-; Last update	:	12.4.2010
-; Author		:	Tomi Tilli
+; Project name	:	XTIDE Universal BIOS
 ; Description	:	Functions for finding Disk Parameter Table.
 
@@ -12,5 +8,5 @@
 ; Finds pointer to first unused Disk Parameter Table.
 ;
-; FindDPT_ForNewDrive
+; FindDPT_ForNewDriveToDSDI
 ;	Parameters:
 ;		DS:		RAMVARS segment
@@ -18,86 +14,11 @@
 ;		DS:DI:	Ptr to first unused DPT
 ;	Corrupts registers:
-;		Nothing
+;		DL
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-FindDPT_ForNewDrive:
-	push	si
-	mov		si, FindDPT_ReturnWrongDPT
-	jmp		SHORT FindDPT_StartIterationAndReturnAfterDone
-
-
-;--------------------------------------------------------------------
-; Finds Disk Parameter Table for
-; Master or Slave drive at wanted port.
-;
-; FindDPT_ForIdeSlaveAtPort
-; FindDPT_ForIdeMasterAtPort
-;	Parameters:
-;		DX:		IDE Base Port address
-;		DS:		RAMVARS segment
-;	Returns:
-;		DL:		Drive number (if DPT found)
-;		DS:DI:	Ptr to DPT
-;		CF:		Set if wanted DPT found
-;				Cleared if DPT not found
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-FindDPT_ForIdeSlaveAtPort:
-	push	si
-	mov		si, FindDPT_IterateToSlaveAtPortCallback
-	jmp		SHORT FindDPT_StartIterationAndReturnAfterDone
-
-ALIGN JUMP_ALIGN
-FindDPT_ForIdeMasterAtPort:
-	push	si
-	mov		si, FindDPT_IterateToMasterAtPortCallback
-	jmp		SHORT FindDPT_StartIterationAndReturnAfterDone
-
-;--------------------------------------------------------------------
-; Iteration callback for finding DPT using
-; IDE base port for Master or Slave drive.
-;
-; FindDPT_IterateToSlaveAtPortCallback
-; FindDPT_IterateToMasterAtPortCallback
-;	Parameters:
-;		DX:		IDE Base Port address
-;		DS:DI:	Ptr to DPT to examine
-;	Returns:
-;		DL:		Drive number if correct DPT
-;		CF:		Set if wanted DPT found
-;				Cleared if wrong DPT
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-FindDPT_IterateToSlaveAtPortCallback:
-	test	BYTE [di+DPT.bDrvSel], FLG_IDE_DRVHD_DRV
-	jnz		SHORT FindDPT_IterateToMasterOrSlaveAtPortCallback
-	jmp		SHORT FindDPT_ReturnWrongDPT	; Return if master drive
-
-ALIGN JUMP_ALIGN
-FindDPT_IterateToMasterAtPortCallback:
-	test	BYTE [di+DPT.bDrvSel], FLG_IDE_DRVHD_DRV
-	jnz		SHORT FindDPT_ReturnWrongDPT	; Return if slave drive
-
-	; If BIOS partitioned, ignore all but first partition
-ALIGN JUMP_ALIGN
-FindDPT_IterateToMasterOrSlaveAtPortCallback:
-	test	BYTE [di+DPT.bFlags], FLG_DPT_PARTITION
-	jz		SHORT .CompareBasePortAddress
-	test	BYTE [di+DPT.bFlags], FLG_DPT_FIRSTPART
-	jz		SHORT FindDPT_ReturnWrongDPT
-ALIGN JUMP_ALIGN
-.CompareBasePortAddress:
-	push	bx
-	eMOVZX	bx, BYTE [di+DPT.bIdeOff]		; CS:BX now points to IDEVARS
-	cmp		dx, [cs:bx+IDEVARS.wPort]		; Wanted port?
-	pop		bx
-	jne		SHORT FindDPT_ReturnWrongDPT
-	mov		dl, [di+DPT.bDrvNum]			; Load drive number
-	stc										; Set CF since wanted DPT
-	ret
+FindDPT_ForNewDriveToDSDI:
+	mov		dl, [RAMVARS.bFirstDrv]
+	add		dl, [RAMVARS.bDrvCnt]
+	; Fall to FindDPT_ForDriveNumber
 
 
@@ -112,6 +33,4 @@
 ;	Returns:
 ;		DS:DI:	Ptr to DPT
-;		CF:		Set if wanted DPT found
-;				Cleared if DPT not found
 ;	Corrupts registers:
 ;		Nothing
@@ -119,19 +38,57 @@
 ALIGN JUMP_ALIGN
 FindDPT_ForDriveNumber:
-	push	si
-	mov		si, FindDPT_IterateToDriveNumberCallback
-FindDPT_StartIterationAndReturnAfterDone:
-	call	FindDPT_IterateAllDPTs
-	pop		si
+	push	dx
+	push	ax
+
+	mov		al, LARGEST_DPT_SIZE
+	sub		dl, [RAMVARS.bFirstDrv]
+	mul		dl
+	add		ax, BYTE RAMVARS_size
+	xchg	di, ax
+
+	pop		ax
+	pop		dx
 	ret
 
+
 ;--------------------------------------------------------------------
-; Iteration callback for finding DPT for drive number.
+; Finds Disk Parameter Table for
+; Master or Slave drive at wanted port.
 ;
-; FindDPT_IterateToDriveNumberCallback
+; FindDPT_ToDSDIForIdeMasterAtPortDX
+; FindDPT_ToDSDIForIdeSlaveAtPortDX
 ;	Parameters:
-;		DL:		Drive number to search for
+;		DX:		IDE Base Port address
+;		DS:		RAMVARS segment
+;	Returns:
+;		DL:		Drive number (if DPT found)
+;		DS:DI:	Ptr to DPT
+;		CF:		Set if wanted DPT found
+;				Cleared if DPT not found
+;	Corrupts registers:
+;		SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FindDPT_ToDSDIForIdeMasterAtPortDX:
+	mov		si, FindDPT_IterateToMasterAtPortCallback
+	jmp		SHORT IterateAllDPTs
+
+ALIGN JUMP_ALIGN
+FindDPT_ToDSDIForIdeSlaveAtPortDX:
+	mov		si, FindDPT_IterateToSlaveAtPortCallback
+	jmp		SHORT IterateAllDPTs
+
+;--------------------------------------------------------------------
+; Iteration callback for finding DPT using
+; IDE base port for Master or Slave drive.
+;
+; FindDPT_IterateToSlaveAtPortCallback
+; FindDPT_IterateToMasterAtPortCallback
+;	Parameters:
+;		CH:		Drive number
+;		DX:		IDE Base Port address
 ;		DS:DI:	Ptr to DPT to examine
 ;	Returns:
+;		DL:		Drive number if correct DPT
 ;		CF:		Set if wanted DPT found
 ;				Cleared if wrong DPT
@@ -140,18 +97,25 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-FindDPT_IterateToDriveNumberCallback:
-	cmp		dl, [di+DPT.bDrvNum]			; Wanted DPT found?
-	je		SHORT FindDPT_RightDriveNumber	;  If so, return
-FindDPT_ReturnWrongDPT:
-	clc										; Clear CF since wrong DPT
+FindDPT_IterateToSlaveAtPortCallback:
+	test	BYTE [di+DPT.wFlags], FLG_DPT_SLAVE	; Clears CF
+	jnz		SHORT CompareBasePortAddress
+	ret		; Wrong DPT
+
+ALIGN JUMP_ALIGN
+FindDPT_IterateToMasterAtPortCallback:
+	test	BYTE [di+DPT.wFlags], FLG_DPT_SLAVE
+	jnz		SHORT ReturnWrongDPT				; Return if slave drive
+
+CompareBasePortAddress:
+	push	bx
+	eMOVZX	bx, BYTE [di+DPT.bIdevarsOffset]	; CS:BX now points to IDEVARS
+	cmp		dx, [cs:bx+IDEVARS.wPort]			; Wanted port?
+	pop		bx
+	jne		SHORT ReturnWrongDPT
+	mov		dl, ch								; Return drive number in DL
+	stc											; Set CF since wanted DPT
 	ret
-ALIGN JUMP_ALIGN
-FindDPT_RightDriveNumber:
-	push	bx
-	eMOVZX	bx, BYTE [di+DPT.bIdeOff]		; CS:BX now points to IDEVARS
-	mov		bx, [cs:bx+IDEVARS.wPort]		; Load IDE Base Port address...
-	mov		[RAMVARS.wIdeBase], bx			; ...and store it to RAMVARS
-	pop		bx
-	stc
+ReturnWrongDPT:
+	clc											; Clear CF since wrong DPT
 	ret
 
@@ -160,5 +124,5 @@
 ; Iterates all Disk Parameter Tables.
 ;
-; FindDPT_IterateAllDPTs
+; IterateAllDPTs
 ;	Parameters:
 ;		BX,DX:	Parameters to callback function
@@ -170,26 +134,24 @@
 ;				Cleared if DPT not found
 ;	Corrupts registers:
-;		Nothing, unless corrupted by callback function
+;		Nothing unless corrupted by callback function
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-FindDPT_IterateAllDPTs:
-	push	ax
+IterateAllDPTs:
 	push	cx
+	mov		cx, [RAMVARS.wDrvCntAndFirst]
+	jcxz	.AllDptsIterated			; Return if no drives
 	call	FindDPT_PointToFirstDPT		; Point DS:DI to first DPT
-	eMOVZX	cx, BYTE [RAMVARS.bDrvCnt]	; Load number of drives
-	xor		ax, ax						; Zero AX for DPT size and clear CF
-	jcxz	.Return						; Return if no drives
 ALIGN JUMP_ALIGN
 .LoopWhileDPTsLeft:
 	call	si							; Is wanted DPT?
-	jc		SHORT .Return				;  If so, return
-	mov		al, [di+DPT.bSize]			; Load DPT size to AX
-	add		di, ax						; Point to next DPT
-	loop	.LoopWhileDPTsLeft			; Check next DPT
+	jc		SHORT .AllDptsIterated		;  If so, return
+	inc		ch							; Increment drive number
+	add		di, BYTE LARGEST_DPT_SIZE	; Point to next DPT
+	dec		cl							; Decrement drives left
+	jnz		SHORT .LoopWhileDPTsLeft
 	clc									; Clear CF since DPT not found
 ALIGN JUMP_ALIGN
-.Return:
+.AllDptsIterated:
 	pop		cx
-	pop		ax
 	ret
 
@@ -209,8 +171,3 @@
 FindDPT_PointToFirstDPT:
 	mov		di, RAMVARS_size
-	test	BYTE [cs:ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
-	jz		SHORT .Return							; RAMVARS used (top of interrupt vectors)
-	add		di, BYTE FULLRAMVARS_size-RAMVARS_size	; FULLRAMVARS used (top of base memory)
-ALIGN JUMP_ALIGN
-.Return:
 	ret
Index: trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm	(revision 150)
@@ -40,6 +40,6 @@
 	eSHL_IM	ax, 6						; Segment to first stolen kB (*=40h)
 	mov		ds, ax
-	mov		WORD [FULLRAMVARS.wSign], W_SIGN_FULLRAMVARS
-	; Fall to .InitializeRamvarsFromDS
+	mov		WORD [RAMVARS.wSignature], RAMVARS_SIGNATURE
+	; Fall to .InitializeRamvars
 
 ;--------------------------------------------------------------------
@@ -59,4 +59,5 @@
 	pop		es
 	call	Memory_ZeroESDIwithSizeInCX
+	mov		WORD [RAMVARS.wSignature], RAMVARS_SIGNATURE
 	; Fall to .InitializeDriveTranslationAndReturn
 
@@ -92,5 +93,5 @@
 	test	BYTE [cs:ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
 	jnz		SHORT .GetStolenSegmentToDS
-	mov		di, SEGMENT_RAMVARS_TOP_OF_INTERRUPT_VECTORS
+	mov		di, LITE_MODE_RAMVARS_SEGMENT
 	mov		ds, di
 	ret
@@ -105,5 +106,5 @@
 	mov		ds, di					; EBDA segment to DS
 	add		di, BYTE 64				; DI to next stolen kB
-	cmp		WORD [FULLRAMVARS.wSign], W_SIGN_FULLRAMVARS
+	cmp		WORD [RAMVARS.wSignature], RAMVARS_SIGNATURE
 	jne		SHORT .LoopStolenKBs	; Loop until sign found (always found eventually)
 	ret
@@ -167,23 +168,4 @@
 
 ;--------------------------------------------------------------------
-; RamVars_IncrementHardDiskCount
-;	Parameters:
-;		DL:		Drive number for new drive
-;		DS:		RAMVARS segment
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-RamVars_IncrementHardDiskCount:
-	inc		BYTE [RAMVARS.bDrvCnt]		; Increment drive count to RAMVARS
-	cmp		BYTE [RAMVARS.bFirstDrv], 0	; First drive set?
-	ja		SHORT .Return				;  If so, return
-	mov		[RAMVARS.bFirstDrv], dl		; Store first drive number
-.Return:
-	ret
-
-
-;--------------------------------------------------------------------
 ; RamVars_GetHardDiskCountFromBDAtoCX
 ;	Parameters:
Index: trunk/XTIDE_Universal_BIOS/makefile
===================================================================
--- trunk/XTIDE_Universal_BIOS/makefile	(revision 149)
+++ trunk/XTIDE_Universal_BIOS/makefile	(revision 150)
@@ -39,4 +39,7 @@
 HEADERS += Src/Handlers/Int13h/
 HEADERS += Src/Handlers/Int13h/Common/
+HEADERS += Src/Device/
+HEADERS += Src/Device/IDE/
+HEADERS += Src/Device/Serial/
 HEADERS += Src/Initialization/
 HEADERS += Src/Libraries/
