- Sync to 0.41b2
- Fixed bug with unnecessary call to AtapiEnableInterrupts() inside AtapiSendCommand() when DRQ is never asserted
- Added registry option AtapiSendDisableIntr to manage ATAPI command sending behavior. AFAIU, under VirtualBox it is unnecessary to disable interrupts around sending ATAPI commands.
- Implemented registry options for BUSY and DRQ timing adjustments.
- Added VirtualBox tuning option - VirtualBox value in registry. Sets timings and ATAPI (CD/DVD) related options to the most compatible values.
- Fixed bug with UDMA2 support on Intel ICH1/2/3/4/5 chips.
- Made some experimental changes in automatic slow-down algorithm. This code is rather old, but was not tested properly.
- Fixed bug with accessing SATA registers on Intel chips
- Many other fixes

svn path=/trunk/; revision=51736
This commit is contained in:
Rafal Harabien 2011-05-14 15:52:49 +00:00
parent ad38ca5072
commit 17dcf7d2e5
23 changed files with 3313 additions and 1036 deletions

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2005 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Module Name:
atapi.h
@ -92,14 +92,16 @@ ScsiDebugPrint(
#else // SCSI_PORT_DBG_PRINT
//#ifndef USE_DBGPRINT_LOGGER
//ULONG
//_cdecl
//DbgPrint(
// PCH Format,
// ...
// );
//#endif // USE_DBGPRINT_LOGGER
#ifndef USE_DBGPRINT_LOGGER
/*
ULONG
_cdecl
DbgPrint(
PCH Format,
...
);
*/
#endif // USE_DBGPRINT_LOGGER
#define PRINT_PREFIX
@ -243,8 +245,8 @@ typedef struct _IDE_REGISTERS_2 {
#define DFLAGS_DWORDIO_ENABLED 0x0400 // Indicates that we should use 32-bit IO
#define DFLAGS_WCACHE_ENABLED 0x0800 // Indicates that we use write cache
#define DFLAGS_RCACHE_ENABLED 0x1000 // Indicates that we use read cache
#define DFLAGS_ORIG_GEOMETRY 0x2000 //
#define DFLAGS_REINIT_DMA 0x4000 //
#define DFLAGS_ORIG_GEOMETRY 0x2000 //
#define DFLAGS_REINIT_DMA 0x4000 //
#define DFLAGS_HIDDEN 0x8000 // Hidden device, available only with special IOCTLs
// via communication virtual device
//#define DFLAGS_ 0x10000 //
@ -346,18 +348,20 @@ typedef struct _MODE_PARAMETER_HEADER_10 {
#define IDE_COMMAND_DOOR_UNLOCK 0xDF
#define IDE_COMMAND_STANDBY_IMMED 0xE0 // flush and spin down
#define IDE_COMMAND_STANDBY 0xE2 // flush and spin down and enable autopowerdown timer
#define IDE_COMMAND_READ_PM 0xE4 // SATA PM
#define IDE_COMMAND_SLEEP 0xE6 // flush, spin down and deactivate interface
#define IDE_COMMAND_FLUSH_CACHE 0xE7
#define IDE_COMMAND_WRITE_PM 0xE8 // SATA PM
#define IDE_COMMAND_IDENTIFY 0xEC
#define IDE_COMMAND_MEDIA_EJECT 0xED
#define IDE_COMMAND_FLUSH_CACHE48 0xEA
#define IDE_COMMAND_ENABLE_MEDIA_STATUS 0xEF
#define IDE_COMMAND_SET_FEATURES 0xEF /* features command,
#define IDE_COMMAND_SET_FEATURES 0xEF /* features command,
IDE_COMMAND_ENABLE_MEDIA_STATUS */
#define IDE_COMMAND_READ_NATIVE_SIZE 0xF8
#define IDE_COMMAND_SET_NATIVE_SIZE 0xF9
#define SCSIOP_ATA_PASSTHROUGH 0xCC //
#define SCSIOP_ATA_PASSTHROUGH 0xCC //
//
// IDE status definitions
@ -569,7 +573,7 @@ typedef struct _IDENTIFY_DATA {
USHORT DoubleWordIo; // 60 48
USHORT Reserved62_0:8; // 62 49
USHORT SupportDma:1;
USHORT SupportDma:1;
USHORT SupportLba:1;
USHORT DisableIordy:1;
USHORT SupportIordy:1;
@ -587,11 +591,11 @@ typedef struct _IDENTIFY_DATA {
#define IDENTIFY_CAPABILITIES_SUPPORT_QTAG 0x4000
#define IDENTIFY_CAPABILITIES_SUPPORT_IDMA 0x8000*/
USHORT DeviceStandbyMin:1; // 64 50
USHORT DeviceStandbyMin:1; // 64 50
USHORT Reserved50_1:13;
USHORT DeviceCapability1:1;
USHORT DeviceCapability0:1;
// USHORT Reserved2;
// USHORT Reserved2;
UCHAR Vendor51; // 66 51
UCHAR PioCycleTimingMode; // 67
@ -644,6 +648,7 @@ typedef struct _IDENTIFY_DATA {
USHORT SataCapabilities; // 76
#define ATA_SATA_GEN1 0x0002
#define ATA_SATA_GEN2 0x0004
#define ATA_SATA_GEN3 0x0008
#define ATA_SUPPORT_NCQ 0x0100
#define ATA_SUPPORT_IFPWRMNGTRCV 0x0200
@ -678,12 +683,12 @@ typedef struct _IDENTIFY_DATA {
USHORT Reserved_82_15:1;
USHORT Microcode:1; // 83/86
USHORT Queued:1; //
USHORT CFA:1; //
USHORT APM:1; //
USHORT Notify:1; //
USHORT Standby:1; //
USHORT Spinup:1; //
USHORT Queued:1; //
USHORT CFA:1; //
USHORT APM:1; //
USHORT Notify:1; //
USHORT Standby:1; //
USHORT Spinup:1; //
USHORT Reserver_83_7:1;
USHORT MaxSecurity:1; //
USHORT AutoAcoustic:1; //
@ -707,7 +712,7 @@ typedef struct _IDENTIFY_DATA {
USHORT UltraDMASupport : 8; // 88
USHORT UltraDMAActive : 8;
USHORT EraseTime; // 89
USHORT EnhancedEraseTime; // 90
USHORT CurentAPMLevel; // 91
@ -743,9 +748,9 @@ typedef struct _IDENTIFY_DATA {
USHORT Reserved107[10]; // 107-116
ULONG LargeSectorSize; // 117-118
USHORT Reserved117[8]; // 119-126
USHORT RemovableStatus; // 127
USHORT SecurityStatus; // 128
@ -775,7 +780,7 @@ typedef struct _IDENTIFY_DATA {
UCHAR :1;
UCHAR CmdProtocol:2; // 00 00
// USHORT GeneralConfiguration; // 00
USHORT NumberOfCylinders; // 02
USHORT Reserved1; // 04
USHORT NumberOfHeads; // 06
@ -944,29 +949,6 @@ AtapiSoftReset(
ULONG DeviceNumber
);
/*#define IdeHardReset(BaseIoAddress,result) \
{\
UCHAR statusByte;\
ULONG i;\
SelectDrive(BaseIoAddress,DeviceNumber); \
AtapiWritePort1(&BaseIoAddress->AltStatus,IDE_DC_DISABLE_INTERRUPTS | IDE_DC_RESET_CONTROLLER );\
ScsiPortStallExecution(50 * 1000);\
AtapiWritePort1(&BaseIoAddress->AltStatus,IDE_DC_REENABLE_CONTROLLER);\
// 5 seconds for reset \
for (i = 0; i < 1000 * (1+11); i++) {\
statusByte = AtapiReadPort1(&BaseIoAddress->AltStatus);\
if (statusByte != IDE_STATUS_IDLE && statusByte != IDE_STATUS_SUCCESS) {\
ScsiPortStallExecution((i<1000) ? 5 : 500);\
} else {\
break;\
}\
}\
KdPrint2((PRINT_PREFIX "IdeHardReset: Status %x\n", statusByte)); \
if (i == 1000*1000) {\
result = FALSE;\
}\
result = TRUE;\
}*/
#endif //USER_MODE
@ -1045,6 +1027,17 @@ AtapiInterrupt__(
IN UCHAR c
);
UCHAR
NTAPI
AtapiCheckInterrupt__(
IN PVOID HwDeviceExtension,
IN UCHAR c
);
#define INTERRUPT_REASON_IGNORE 0
#define INTERRUPT_REASON_OUR 1
#define INTERRUPT_REASON_UNEXPECTED 2
BOOLEAN
NTAPI
AtapiHwInitialize(
@ -1061,9 +1054,10 @@ IdeBuildSenseBuffer(
VOID
NTAPI
IdeMediaStatus(
IN BOOLEAN EnableMSN,
BOOLEAN EnableMSN,
IN PVOID HwDeviceExtension,
IN UCHAR Channel
IN ULONG lChannel,
IN ULONG DeviceNumber
);
ULONG NTAPI
@ -1325,6 +1319,14 @@ UniataAnybodyHome(
extern UCHAR AtaCommands48[256];
extern UCHAR AtaCommandFlags[256];
/*
We need LBA48 when requested LBA or BlockCount are too large.
But for LBA-based commands we have *special* limitation
*/
#define UniAta_need_lba48(command, lba, count, supp48) \
( ((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) && (supp48) && (((lba+count) >= ATA_MAX_IOLBA28) || (count > 256)) ) || \
(lba > ATA_MAX_LBA28) || (count > 255) )
#ifdef _DEBUG
#define PrintNtConsole _PrintNtConsole
#else //_DEBUG

View file

@ -78,4 +78,4 @@ CheckIfBadBlock(
IN ULONG count
);
#endif // _BADBLOCK_H_INCLUDED_
#endif // _BADBLOCK_H_INCLUDED_

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2010 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Module Name:
bm_devs.h
@ -245,11 +245,12 @@ typedef struct _BUSMASTER_CONTROLLER_INFORMATION {
#define ATA_I82801JD_AH 0x3a028086
#define ATA_I82801JD_R1 0x3a058086
#define ATA_I82801JD_S2 0x3a068086
/*
#define ATA_I82801JI_S1 0x3a208086
#define ATA_I82801JI_AH 0x3a228086
#define ATA_I82801JI_R1 0x3a258086
#define ATA_I82801JI_S2 0x3a268086
*/
#define ATA_5Series_S1 0x3b208086
#define ATA_5Series_S2 0x3b218086
#define ATA_5Series_AH1 0x3b228086
@ -554,7 +555,10 @@ typedef struct _BUSMASTER_CONTROLLER_INFORMATION {
#define ATA_VIACX700 0x83241106
#define ATA_VIASATAIDE 0x53241106
#define ATA_VIAVX800 0x83531106
#define ATA_VIASATAIDE2 0xc4091106
#define ATA_VIAVX855 0x84091106
#define ATA_VIASATAIDE3 0x90011106
#define ATA_VIAVX900 0x84101106
#define ATA_ITE_ID 0x1283
#define ATA_IT8172G 0x81721283
@ -785,20 +789,20 @@ BUSMASTER_CONTROLLER_INFORMATION const BusMasterAdapters[] = {
PCI_DEV_HW_SPEC_BM( 2923, 8086, 0x00, ATA_SA300, "Intel ICH9" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 2925, 8086, 0x00, ATA_SA300, "Intel ICH9" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a20, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a26, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH2 | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a22, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a25, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a20, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a26, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH2 | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a22, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a25, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a00, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a06, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH2 | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a02, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a05, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a00, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a06, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH2 | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3a02, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 3a05, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
/*
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH2 | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH2 | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( ????, 8086, 0x00, ATA_SA300, "Intel ICH10" , UNIATA_SATA | UNIATA_AHCI ),
*/
PCI_DEV_HW_SPEC_BM( 3b20, 8086, 0x00, ATA_SA300, "Intel 5 Series/3400" , I6CH | UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3b21, 8086, 0x00, ATA_SA300, "Intel 5 Series/3400" , I6CH2 | UNIATA_SATA ),
@ -823,16 +827,16 @@ BUSMASTER_CONTROLLER_INFORMATION const BusMasterAdapters[] = {
PCI_DEV_HW_SPEC_BM( 1c09, 8086, 0x00, ATA_SA300, "Intel Cougar Point" , I6CH2 | UNIATA_SATA ),
// PCI_DEV_HW_SPEC_BM( 3200, 8086, 0x00, ATA_SA150, "Intel 31244" , UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 3200, 8086, 0x00, ATA_UDMA5, "Intel SCH" , I1CH ),
PCI_DEV_HW_SPEC_BM( 3200, 8086, 0x00, ATA_UDMA5, "Intel SCH" , I1CH ),
/*
PCI_DEV_HW_SPEC_BM( 2360, 197b, 0x00, ATA_SA300, "JMB360" , 0 ),
PCI_DEV_HW_SPEC_BM( 2361, 197b, 0x00, ATA_SA300, "JMB361" , 0 ),
PCI_DEV_HW_SPEC_BM( 2363, 197b, 0x00, ATA_SA300, "JMB363" , 0 ),
PCI_DEV_HW_SPEC_BM( 2365, 197b, 0x00, ATA_SA300, "JMB365" , 0 ),
PCI_DEV_HW_SPEC_BM( 2366, 197b, 0x00, ATA_SA300, "JMB366" , 0 ),
PCI_DEV_HW_SPEC_BM( 2360, 197b, 0x00, ATA_SA300, "JMB360" , UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 2361, 197b, 0x00, ATA_UDMA6, "JMB361" , 0 ),
PCI_DEV_HW_SPEC_BM( 2363, 197b, 0x00, ATA_UDMA6, "JMB363" , 0 ),
PCI_DEV_HW_SPEC_BM( 2365, 197b, 0x00, ATA_UDMA6, "JMB365" , 0 ),
PCI_DEV_HW_SPEC_BM( 2366, 197b, 0x00, ATA_UDMA6, "JMB366" , 0 ),
PCI_DEV_HW_SPEC_BM( 2368, 197b, 0x00, ATA_UDMA6, "JMB368" , 0 ),
*/
/*
PCI_DEV_HW_SPEC_BM( 5040, 11ab, 0x00, ATA_SA150, "Marvell 88SX5040" , UNIATA_SATA ),
PCI_DEV_HW_SPEC_BM( 5041, 11ab, 0x00, ATA_SA150, "Marvell 88SX5041" , UNIATA_SATA ),
@ -1073,5 +1077,11 @@ Ata_is_dev_listed(
((pciData)->BaseClass == PCI_DEV_CLASS_STORAGE && \
(pciData)->SubClass == PCI_DEV_SUBCLASS_IDE)
#define Ata_is_ahci_dev(pciData) \
((pciData)->BaseClass == PCI_DEV_CLASS_STORAGE && \
(pciData)->SubClass == PCI_DEV_SUBCLASS_SATA && \
(pciData)->ProgIf == PCI_DEV_PROGIF_AHCI_1_0 && \
((pciData)->u.type0.BaseAddresses[5] & ~0x7))
#endif //__IDE_BUSMASTER_H__

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2010 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Module Name:
bsmaster.h
@ -83,6 +83,9 @@ Revision History:
#define ATA_ALTIOSIZE 0x01 /* alternate registers size */
#define ATA_BMIOSIZE 0x20
#define ATA_PC98_BANKIOSIZE 0x01
//#define ATA_MAX_LBA28 DEF_U64(0x0fffffff)
// Hitachi 1 Tb HDD didn't allow LBA28 with BCount > 1 beyond this LBA
#define ATA_MAX_IOLBA28 DEF_U64(0x0fffff80)
#define ATA_MAX_LBA28 DEF_U64(0x0fffffff)
#define ATA_DMA_ENTRIES 256 /* PAGESIZE/2/sizeof(BM_DMA_ENTRY)*/
@ -109,6 +112,8 @@ typedef struct _BUSMASTER_CTX {
#define PCI_DEV_SUBCLASS_ATA 0x05
#define PCI_DEV_SUBCLASS_SATA 0x06
#define PCI_DEV_PROGIF_AHCI_1_0 0x01
/* structure for holding DMA address data */
typedef struct BM_DMA_ENTRY {
ULONG base;
@ -180,7 +185,11 @@ typedef struct _IDE_AHCI_REGISTERS {
} CAP;
#define AHCI_CAP_NOP_MASK 0x0000001f
#define AHCI_CAP_SPM 0x00010000
#define AHCI_CAP_NCS_MASK 0x00001f00
#define AHCI_CAP_PMD 0x00008000
#define AHCI_CAP_SPM 0x00020000
#define AHCI_CAP_SAM 0x00040000
#define AHCI_CAP_SCLO 0x01000000
#define AHCI_CAP_S64A 0x80000000
// Global HBA Control
@ -231,6 +240,7 @@ typedef union _SATA_SSTATUS_REG {
#define SStatus_SPD_NoDev 0x00
#define SStatus_SPD_Gen1 0x01
#define SStatus_SPD_Gen2 0x02
#define SStatus_SPD_Gen3 0x03
ULONG IPM:4; // Interface Power Management
@ -261,6 +271,7 @@ typedef union _SATA_SCONTROL_REG {
#define SControl_SPD_NoRestrict 0x00
#define SControl_SPD_LimGen1 0x01
#define SControl_SPD_LimGen2 0x02
#define SControl_SPD_LimGen3 0x03
ULONG IPM:4; // Interface Power Management Transitions Allowed
@ -387,15 +398,37 @@ typedef union _AHCI_IS_REG {
ULONG Reg;
} AHCI_IS_REG, *PAHCI_IS_REG;
#define ATA_AHCI_P_IX_DHR 0x00000001
#define ATA_AHCI_P_IX_PS 0x00000002
#define ATA_AHCI_P_IX_DS 0x00000004
#define ATA_AHCI_P_IX_SDB 0x00000008
#define ATA_AHCI_P_IX_UF 0x00000010
#define ATA_AHCI_P_IX_DP 0x00000020
#define ATA_AHCI_P_IX_PC 0x00000040
#define ATA_AHCI_P_IX_DI 0x00000080
#define ATA_AHCI_P_IX_PRC 0x00400000
#define ATA_AHCI_P_IX_IPM 0x00800000
#define ATA_AHCI_P_IX_OF 0x01000000
#define ATA_AHCI_P_IX_INF 0x04000000
#define ATA_AHCI_P_IX_IF 0x08000000
#define ATA_AHCI_P_IX_HBD 0x10000000
#define ATA_AHCI_P_IX_HBF 0x20000000
#define ATA_AHCI_P_IX_TFE 0x40000000
#define ATA_AHCI_P_IX_CPD 0x80000000
#define AHCI_CLB_ALIGNEMENT_MASK ((ULONGLONG)(1024-1))
#define AHCI_FIS_ALIGNEMENT_MASK ((ULONGLONG)(256-1))
#define AHCI_CMD_ALIGNEMENT_MASK ((ULONGLONG)(128-1))
typedef struct _IDE_AHCI_PORT_REGISTERS {
union {
struct {
ULONG CLB; // command list base address
ULONG CLB; // command list base address, 1K-aligned
ULONG CLBU; // command list base address (upper 32bits)
};
ULONGLONG CLB64;
};
}; // 0x100 + 0x80*c + 0x0000
union {
struct {
@ -403,12 +436,12 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
ULONG FBU; // FIS base address (upper 32bits)
};
ULONGLONG FB64;
};
}; // 0x100 + 0x80*c + 0x0008
union {
ULONG IS_Reg; // interrupt status
AHCI_IS_REG IS;
};
}; // 0x100 + 0x80*c + 0x0010
union {
ULONG Reg; // interrupt enable
@ -434,7 +467,7 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
ULONG TFEE:1;// Task File Error Enable
ULONG CPDE:1;// Cold Port Detect Enable
};
} IE;
} IE; // 0x100 + 0x80*c + 0x0014
union {
ULONG Reg; // command register
@ -472,7 +505,7 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
#define SATA_CMD_ICC_Partial 0x02
#define SATA_CMD_ICC_Slumber 0x06
};
} CMD;
} CMD; // 0x100 + 0x80*c + 0x0018
ULONG Reserved;
@ -489,7 +522,7 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
UCHAR ERR; // Contains the latest copy of the task file error register.
UCHAR Reserved[2];
};
} TFD;
} TFD; // 0x100 + 0x80*c + 0x0020
union {
ULONG Reg; // signature
@ -499,24 +532,25 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
UCHAR LbaMid;
UCHAR LbaHigh;
};
} SIG;
} SIG; // 0x100 + 0x80*c + 0x0024
union {
ULONG SStatus; // SCR0
SATA_SSTATUS_REG SSTS;
};
}; // 0x100 + 0x80*c + 0x0028
union {
ULONG SControl; // SCR2
SATA_SCONTROL_REG SCTL;
};
}; // 0x100 + 0x80*c + 0x002c
union {
ULONG SError; // SCR1
SATA_SERROR_REG SERR;
};
}; // 0x100 + 0x80*c + 0x0030
union {
ULONG SACT; // SCR3
ULONG SActive; // bitmask
};
ULONG CI; // Command issue, bitmask
}; // 0x100 + 0x80*c + 0x0034
ULONG CI; // Command issue, bitmask, 0x100 + 0x80*c + 0x0038
// AHCI 1.1
union {
@ -525,7 +559,8 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
USHORT PMN; // PM Notify, bitmask
USHORT Reserved;
};
} SNTF;
} SNTF; // 0x100 + 0x80*c + 0x003c
ULONG FIS_Switching_Reserved[12];
UCHAR VendorSpec[16];
@ -534,7 +569,39 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
#define IDX_AHCI_P_CLB (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, CLB))
#define IDX_AHCI_P_FB (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, FB))
#define IDX_AHCI_P_IS (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, IS))
#define IDX_AHCI_P_IE (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, IE))
#define IDX_AHCI_P_CI (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, CI))
#define IDX_AHCI_P_TFD (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD))
#define IDX_AHCI_P_SIG (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG))
#define IDX_AHCI_P_CMD (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, CMD))
#define IDX_AHCI_P_SNTF (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SNTF))
// AHCI commands ( -> IDX_AHCI_P_CMD)
#define ATA_AHCI_P_CMD_ST 0x00000001
#define ATA_AHCI_P_CMD_SUD 0x00000002
#define ATA_AHCI_P_CMD_POD 0x00000004
#define ATA_AHCI_P_CMD_CLO 0x00000008
#define ATA_AHCI_P_CMD_FRE 0x00000010
#define ATA_AHCI_P_CMD_CCS_MASK 0x00001f00
#define ATA_AHCI_P_CMD_ISS 0x00002000
#define ATA_AHCI_P_CMD_FR 0x00004000
#define ATA_AHCI_P_CMD_CR 0x00008000
#define ATA_AHCI_P_CMD_CPS 0x00010000
#define ATA_AHCI_P_CMD_PMA 0x00020000
#define ATA_AHCI_P_CMD_HPCP 0x00040000
#define ATA_AHCI_P_CMD_ISP 0x00080000
#define ATA_AHCI_P_CMD_CPD 0x00100000
#define ATA_AHCI_P_CMD_ATAPI 0x01000000
#define ATA_AHCI_P_CMD_DLAE 0x02000000
#define ATA_AHCI_P_CMD_ALPE 0x04000000
#define ATA_AHCI_P_CMD_ASP 0x08000000
#define ATA_AHCI_P_CMD_ICC_MASK 0xf0000000
#define ATA_AHCI_P_CMD_NOOP 0x00000000
#define ATA_AHCI_P_CMD_ACTIVE 0x10000000
#define ATA_AHCI_P_CMD_PARTIAL 0x20000000
#define ATA_AHCI_P_CMD_SLUMBER 0x60000000
typedef struct _IDE_AHCI_PRD_ENTRY {
union {
@ -559,21 +626,42 @@ typedef struct _IDE_AHCI_PRD_ENTRY {
#define ATA_AHCI_DMA_ENTRIES (PAGE_SIZE/2/sizeof(IDE_AHCI_PRD_ENTRY)) /* 128 */
#define ATA_AHCI_MAX_TAGS 32
#define AHCI_FIS_TYPE_ATA_H2D 0x27
#define AHCI_FIS_TYPE_ATA_D2H 0x34
#define AHCI_FIS_COMM_PM (0x80 | AHCI_DEV_SEL_PM)
#define AHCI_DEV_SEL_1 0x00
#define AHCI_DEV_SEL_2 0x01
#define AHCI_DEV_SEL_PM 0x0f
/* 128-byte aligned */
typedef struct _IDE_AHCI_CMD {
UCHAR cfis[64];
UCHAR acmd[32];
UCHAR Reserved[32];
IDE_AHCI_PRD_ENTRY prd_tab[ATA_AHCI_DMA_ENTRIES];
IDE_AHCI_PRD_ENTRY prd_tab[ATA_AHCI_DMA_ENTRIES]; // also 128-byte aligned
} IDE_AHCI_CMD, *PIDE_AHCI_CMD;
/* cmd_flags */
#define ATA_AHCI_CMD_ATAPI 0x0020
#define ATA_AHCI_CMD_WRITE 0x0040
#define ATA_AHCI_CMD_PREFETCH 0x0080
#define ATA_AHCI_CMD_RESET 0x0100
#define ATA_AHCI_CMD_BIST 0x0200
#define ATA_AHCI_CMD_CLR_BUSY 0x0400
/* 128-byte aligned */
typedef struct _IDE_AHCI_CMD_LIST {
USHORT cmd_flags;
USHORT prd_length; /* PRD entries */
ULONG bytecount;
ULONGLONG cmd_table_phys; /* 128byte aligned */
ULONGLONG cmd_table_phys; /* points to IDE_AHCI_CMD */
ULONG Reserved[4];
} IDE_AHCI_CMD_LIST, *PIDE_AHCI_CMD_LIST;
/* 256-byte aligned */
typedef struct _IDE_AHCI_RCV_FIS {
UCHAR dsfis[28];
UCHAR Reserved1[4];
@ -586,6 +674,13 @@ typedef struct _IDE_AHCI_RCV_FIS {
UCHAR Reserved4[96];
} IDE_AHCI_RCV_FIS, *PIDE_AHCI_RCV_FIS;
/* 1K-byte aligned */
typedef struct _IDE_AHCI_CHANNEL_CTL_BLOCK {
IDE_AHCI_CMD_LIST cmd_list[ATA_AHCI_MAX_TAGS]; // 1K-size (32*32)
IDE_AHCI_RCV_FIS rcv_fis;
IDE_AHCI_CMD cmd; // for single internal comamnds w/o associated AtaReq
} IDE_AHCI_CHANNEL_CTL_BLOCK, *PIDE_AHCI_CHANNEL_CTL_BLOCK;
#define IsBusMaster(pciData) \
( ((pciData)->Command & (PCI_ENABLE_BUS_MASTER/* | PCI_ENABLE_IO_SPACE*/)) == \
@ -608,41 +703,54 @@ typedef union _ATA_REQ {
// ULONG reqId; // serial
struct {
union {
//union {
struct {
union _ATA_REQ* next_req;
union _ATA_REQ* prev_req;
struct {
union _ATA_REQ* next_req;
union _ATA_REQ* prev_req;
PSCSI_REQUEST_BLOCK Srb; // Current request on controller.
PSCSI_REQUEST_BLOCK Srb; // Current request on controller.
PUSHORT DataBuffer; // Data buffer pointer.
ULONG WordsLeft; // Data words left.
ULONG TransferLength; // Originally requested transfer length
LONGLONG lba;
ULONG WordsTransfered;// Data words already transfered.
ULONG bcount;
PUSHORT DataBuffer; // Data buffer pointer.
ULONG WordsLeft; // Data words left.
ULONG TransferLength; // Originally requested transfer length
LONGLONG lba;
ULONG WordsTransfered;// Data words already transfered.
ULONG bcount;
UCHAR retry;
UCHAR ttl;
// UCHAR tag;
UCHAR Flags;
UCHAR ReqState;
UCHAR retry;
UCHAR ttl;
// UCHAR tag;
UCHAR Flags;
UCHAR ReqState;
PSCSI_REQUEST_BLOCK OriginalSrb; // Mechanism Status Srb Data
PSCSI_REQUEST_BLOCK OriginalSrb; // Mechanism Status Srb Data
ULONG dma_entries;
union {
ULONG dma_entries;
union {
// for ATA
struct {
ULONG dma_base;
ULONGLONG ahci_base64; // for AHCI
};
ULONG dma_baseu;
} ata;
// for AHCI
struct {
ULONGLONG ahci_base64;
ULONGLONG in_lba;
PIDE_AHCI_CMD ahci_cmd_ptr;
ULONG in_bcount;
ULONG in_status;
USHORT io_cmd_flags; // out
} ahci;
};
UCHAR padding_128b[128];
};
//UCHAR padding_128b[128]; // Note: we assume, NT allocates block > 4k as PAGE-aligned
//};
struct {
union {
BM_DMA_ENTRY dma_tab[ATA_DMA_ENTRIES];
IDE_AHCI_CMD ahci_cmd; // for AHCI
IDE_AHCI_CMD ahci_cmd0; // for AHCI, 128-byte aligned
};
};
};
@ -660,6 +768,7 @@ typedef union _ATA_REQ {
#define REQ_FLAG_FORCE_DOWNRATE_LBA48 0x10
#define REQ_FLAG_DMA_DBUF 0x20
#define REQ_FLAG_DMA_DBUF_PRD 0x40
#define REQ_FLAG_LBA48 0x80
// Request states
#define REQ_STATE_NONE 0x00
@ -810,10 +919,12 @@ typedef struct _HW_CHANNEL {
PUCHAR DmaBuffer;
//
PIDE_AHCI_CMD_LIST AHCI_CL;
ULONGLONG AHCI_CL_PhAddr;
PVOID AHCI_FIS; // is not actually used by UniATA now, but is required by AHCI controller
ULONGLONG AHCI_FIS_PhAddr;
PIDE_AHCI_CHANNEL_CTL_BLOCK AhciCtlBlock0; // unaligned
PIDE_AHCI_CHANNEL_CTL_BLOCK AhciCtlBlock; // 128-byte aligned
ULONGLONG AHCI_CTL_PhAddr;
IORES BaseIoAHCI_Port;
//PVOID AHCI_FIS; // is not actually used by UniATA now, but is required by AHCI controller
//ULONGLONG AHCI_FIS_PhAddr;
// Note: in contrast to FBSD, we keep PRD and CMD item in AtaReq structure
#ifdef QUEUE_STATISTICS
@ -841,6 +952,8 @@ typedef struct _HW_CHANNEL {
#define CTRFLAGS_DSC_BSY 0x0080
#define CTRFLAGS_NO_SLAVE 0x0100
//#define CTRFLAGS_PATA 0x0200
#define CTRFLAGS_AHCI_PM 0x0400
#define CTRFLAGS_AHCI_PM2 0x0800
#define CTRFLAGS_PERMANENT (CTRFLAGS_DMA_RO | CTRFLAGS_NO_SLAVE)
@ -904,18 +1017,22 @@ typedef struct _HW_LU_EXTENSION {
// Controller-specific LUN options
union {
/* for tricky controllers, those can change Logical-to-Physical LUN mapping.
mainly for mapping SATA ports to compatible PATA registers
Treated as PHYSICAL port number, regardless of logical mapping.
*/
ULONG SATA_lun_map;
};
struct _HW_DEVICE_EXTENSION* DeviceExtension;
struct _HW_CHANNEL* chan;
ULONG Lun;
#ifdef IO_STATISTICS
LONGLONG ModeErrorCount[MAX_RETRIES];
LONGLONG RecoverCount[MAX_RETRIES];
LONGLONG IoCount;
LONGLONG BlockIoCount;
#endif//IO_STATISTICS
} HW_LU_EXTENSION, *PHW_LU_EXTENSION;
@ -1007,6 +1124,7 @@ typedef struct _HW_DEVICE_EXTENSION {
IORES BaseIoAHCI_0;
//PIDE_AHCI_PORT_REGISTERS BaseIoAHCIPort[AHCI_MAX_PORT];
ULONG AHCI_CAP;
BOOLEAN opt_AtapiDmaZeroTransfer; // default FALSE
BOOLEAN opt_AtapiDmaControlCmd; // default FALSE
@ -1201,7 +1319,7 @@ extern VOID
NTAPI
AtapiDmaReinit(
IN PHW_DEVICE_EXTENSION deviceExtension,
IN ULONG ldev,
IN PHW_LU_EXTENSION LunExt,
IN PATA_REQ AtaReq
);
@ -1209,7 +1327,7 @@ extern VOID
NTAPI
AtapiDmaInit__(
IN PHW_DEVICE_EXTENSION deviceExtension,
IN ULONG ldev
IN PHW_LU_EXTENSION LunExt
);
extern VOID
@ -1218,7 +1336,7 @@ AtapiDmaInit(
IN PVOID HwDeviceExtension,
IN ULONG DeviceNumber,
IN ULONG lChannel, // logical channel,
// is always 0 except simplex-only controllers
// is always 0 except simplex-only and multi-channel controllers
IN SCHAR apiomode,
IN SCHAR wdmamode,
IN SCHAR udmamode
@ -1376,7 +1494,7 @@ VOID
DDKFASTAPI
AtapiWritePort4(
IN PHW_CHANNEL chan,
IN ULONG_PTR port,
IN ULONGIO_PTR port,
IN ULONG data
);
@ -1384,7 +1502,7 @@ VOID
DDKFASTAPI
AtapiWritePort2(
IN PHW_CHANNEL chan,
IN ULONG_PTR port,
IN ULONGIO_PTR port,
IN USHORT data
);
@ -1392,7 +1510,7 @@ VOID
DDKFASTAPI
AtapiWritePort1(
IN PHW_CHANNEL chan,
IN ULONG_PTR port,
IN ULONGIO_PTR port,
IN UCHAR data
);
@ -1400,7 +1518,7 @@ VOID
DDKFASTAPI
AtapiWritePortEx4(
IN PHW_CHANNEL chan,
IN ULONG_PTR port,
IN ULONGIO_PTR port,
IN ULONG offs,
IN ULONG data
);
@ -1409,7 +1527,7 @@ VOID
DDKFASTAPI
AtapiWritePortEx1(
IN PHW_CHANNEL chan,
IN ULONG_PTR port,
IN ULONGIO_PTR port,
IN ULONG offs,
IN UCHAR data
);
@ -1418,28 +1536,28 @@ ULONG
DDKFASTAPI
AtapiReadPort4(
IN PHW_CHANNEL chan,
IN ULONG_PTR port
IN ULONGIO_PTR port
);
USHORT
DDKFASTAPI
AtapiReadPort2(
IN PHW_CHANNEL chan,
IN ULONG_PTR port
IN ULONGIO_PTR port
);
UCHAR
DDKFASTAPI
AtapiReadPort1(
IN PHW_CHANNEL chan,
IN ULONG_PTR port
IN ULONGIO_PTR port
);
ULONG
DDKFASTAPI
AtapiReadPortEx4(
IN PHW_CHANNEL chan,
IN ULONG_PTR port,
IN ULONGIO_PTR port,
IN ULONG offs
);
@ -1447,7 +1565,7 @@ UCHAR
DDKFASTAPI
AtapiReadPortEx1(
IN PHW_CHANNEL chan,
IN ULONG_PTR port,
IN ULONGIO_PTR port,
IN ULONG offs
);
@ -1455,7 +1573,7 @@ VOID
DDKFASTAPI
AtapiWriteBuffer4(
IN PHW_CHANNEL chan,
IN ULONG_PTR _port,
IN ULONGIO_PTR _port,
IN PVOID Buffer,
IN ULONG Count,
IN ULONG Timing
@ -1465,7 +1583,7 @@ VOID
DDKFASTAPI
AtapiWriteBuffer2(
IN PHW_CHANNEL chan,
IN ULONG_PTR _port,
IN ULONGIO_PTR _port,
IN PVOID Buffer,
IN ULONG Count,
IN ULONG Timing
@ -1475,7 +1593,7 @@ VOID
DDKFASTAPI
AtapiReadBuffer4(
IN PHW_CHANNEL chan,
IN ULONG_PTR _port,
IN ULONGIO_PTR _port,
IN PVOID Buffer,
IN ULONG Count,
IN ULONG Timing
@ -1485,7 +1603,7 @@ VOID
DDKFASTAPI
AtapiReadBuffer2(
IN PHW_CHANNEL chan,
IN ULONG_PTR _port,
IN ULONGIO_PTR _port,
IN PVOID Buffer,
IN ULONG Count,
IN ULONG Timing
@ -1496,8 +1614,8 @@ AtapiReadBuffer2(
#define GET_LDEV2(P, T, L) (T)*/
#define GET_CHANNEL(Srb) (Srb->PathId)
#define GET_LDEV(Srb) (Srb->TargetId | (Srb->PathId << 1))
#define GET_LDEV2(P, T, L) (T | ((P)<<1))
//#define GET_LDEV(Srb) (Srb->TargetId | (Srb->PathId << 1))
//#define GET_LDEV2(P, T, L) (T | ((P)<<1))
#define GET_CDEV(Srb) (Srb->TargetId)
VOID
@ -1536,10 +1654,20 @@ UniataForgetDevice(
extern ULONG SkipRaids;
extern ULONG ForceSimplex;
extern BOOLEAN g_opt_AtapiDmaRawRead;
extern BOOLEAN InDriverEntry;
extern BOOLEAN g_opt_Verbose;
extern ULONG g_opt_VirtualMachine;
#define VM_AUTO 0x00
#define VM_NONE 0x01
#define VM_VBOX 0x02
#define VM_VMWARE 0x03
#define VM_QEMU 0x04
#define VM_MAX_KNOWN VM_QEMU
extern BOOLEAN WinVer_WDM_Model;

View file

@ -87,9 +87,22 @@
/***************************************************/
/* ReactOS-specific defines */
#ifdef DDKAPI
#ifdef __REACTOS__
#define USE_REACTOS_DDK
#endif //DDKAPI
#endif //__REACTOS__
#ifdef USE_REACTOS_DDK
#define ULONGIO_PTR ULONG_PTR
#define CRNT_ILK_TYPE
#define CRNT_ILK_PTYPE
#define REGRTL_STR_PTYPE
#else
#define ULONG_PTR ULONG
#define ULONGIO_PTR ULONG
#define CRNT_ILK_TYPE (PVOID)
#define CRNT_ILK_PTYPE (PVOID*)
#define REGRTL_STR_PTYPE (PWCHAR)
#endif //USE_REACTOS_DDK
/* Are we under GNU C (mingw) ??? */
#if __GNUC__ >=3

File diff suppressed because it is too large Load diff

View file

@ -129,6 +129,10 @@ InitBadBlocks(
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2]; // Main record and zero filled end of array marker
WCHAR DevSerial[128];
#ifdef _DEBUG
UCHAR cDevSerial[128];
ULONG i;
#endif
ULONG Length;
PLIST_ENTRY link;
PSBadBlockListItem cur;
@ -145,10 +149,10 @@ InitBadBlocks(
QueryTable[0].QueryRoutine = BadBlockQueryRoutine;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = NULL; // If Name is NULL, the QueryRoutine function
// specified for this table entry is called
// for all values associated with the current
// registry key.
QueryTable[0].Name = NULL; // If Name is NULL, the QueryRoutine function
// specified for this table entry is called
// for all values associated with the current
// registry key.
QueryTable[0].EntryContext = NULL;
QueryTable[0].DefaultType = REG_NONE;
QueryTable[0].DefaultData = 0;
@ -173,8 +177,13 @@ InitBadBlocks(
Length++;
Length += EncodeVendorStr(DevSerial+Length, LunExt->IdentifyData.SerialNumber, sizeof(LunExt->IdentifyData.SerialNumber));
#ifdef _DEBUG
KdPrint(( "LunExt %#x\n", LunExt));
KdPrint(( "S/N:%S\n", DevSerial));
for(i=0; i<Length; i++) {
cDevSerial[i] = (UCHAR)(DevSerial[i]);
}
KdPrint(( "S/N:%s\n", cDevSerial));
#endif
LunExt->nBadBlocks = 0;
LunExt->arrBadBlocks = NULL;
@ -260,7 +269,7 @@ CheckIfBadBlock(
for (ULONG i = 0; i < nBadBlocks; i++)
{
if (lba + count > arrBadBlocks->m_lbaStart &&
if (lba + count > arrBadBlocks->m_lbaStart &&
lba < arrBadBlocks->m_lbaEnd) {
KdPrint(( "listed BB @ %I64x\n", lba));
return true;

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2010 Alexander A. Telyatnikov (Alter)
Copyright (c) 2002-2011 Alexander A. Telyatnikov (Alter)
Module Name:
id_dma.cpp
@ -185,28 +185,52 @@ err_1:
if(deviceExtension->HwFlags & UNIATA_AHCI) {
if(chan->AHCI_CL) {
KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: AHCI\n" ));
if(chan->AhciCtlBlock) {
KdPrint2((PRINT_PREFIX " already initialized %x\n", chan->AhciCtlBlock));
return;
}
chan->AHCI_CL = (PIDE_AHCI_CMD_LIST)MmAllocateContiguousMemory(sizeof(IDE_AHCI_CMD_LIST)*ATA_AHCI_MAX_TAGS+sizeof(IDE_AHCI_RCV_FIS), ph4gb);
if(chan->AHCI_CL) {
chan->AHCI_CL_PhAddr = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)(chan->AHCI_CL), &i, &ph_addru);
if(!chan->AHCI_CL_PhAddr || !i || ((LONG)(chan->AHCI_CL_PhAddr) == -1)) {
// Need 1K-byte alignment
chan->AhciCtlBlock0 = (PIDE_AHCI_CHANNEL_CTL_BLOCK)MmAllocateContiguousMemory(
sizeof(IDE_AHCI_CHANNEL_CTL_BLOCK)+AHCI_CLB_ALIGNEMENT_MASK,
ph4gb);
if(chan->AhciCtlBlock0) {
union {
PUCHAR AhciCtlBlock;
ULONGLONG AhciCtlBlock64;
};
AhciCtlBlock64 = 0;
AhciCtlBlock = (PUCHAR)chan->AhciCtlBlock0;
KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: CLP BASE %I64x\n", AhciCtlBlock64));
AhciCtlBlock64 += AHCI_CLB_ALIGNEMENT_MASK;
AhciCtlBlock64 &= ~AHCI_CLB_ALIGNEMENT_MASK;
KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: CLP BASE 1k-aligned %I64x\n", AhciCtlBlock64));
chan->AhciCtlBlock = (PIDE_AHCI_CHANNEL_CTL_BLOCK)AhciCtlBlock;
chan->AHCI_CTL_PhAddr = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)(chan->AhciCtlBlock), &i, &ph_addru);
KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: CLP Phys BASE %I64x\n", chan->AHCI_CTL_PhAddr));
if(!chan->AHCI_CTL_PhAddr || !i || ((LONG)(chan->AHCI_CTL_PhAddr) == -1)) {
KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No AHCI CLP BASE\n" ));
chan->AHCI_CL = NULL;
chan->AHCI_CL_PhAddr = 0;
chan->AhciCtlBlock = NULL;
chan->AHCI_CTL_PhAddr = 0;
return;
}
if(ph_addru) {
KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No AHCI CLP below 4Gb\n" ));
MmFreeContiguousMemory(chan->AHCI_CL);
chan->AHCI_CL = NULL;
chan->AHCI_CL_PhAddr = 0;
MmFreeContiguousMemory(chan->AhciCtlBlock0);
chan->AhciCtlBlock = NULL;
chan->AHCI_CTL_PhAddr = 0;
return;
}
} else {
KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: Can't alloc AHCI CLP\n"));
}
}
#endif //USE_OWN_DMA
#endif //USE_OWN_DMA
return;
} // end AtapiDmaAlloc()
@ -227,16 +251,16 @@ AtapiDmaSetup(
PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
BOOLEAN use_DB_IO = FALSE;
//BOOLEAN use_AHCI = FALSE;
BOOLEAN use_AHCI = (deviceExtension->HwFlags & UNIATA_AHCI) ? TRUE : FALSE;
ULONG orig_count = count;
ULONG max_entries = (deviceExtension->HwFlags & UNIATA_AHCI) ? ATA_AHCI_DMA_ENTRIES : ATA_DMA_ENTRIES;
ULONG max_entries = use_AHCI ? ATA_AHCI_DMA_ENTRIES : ATA_DMA_ENTRIES;
AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: mode %#x, data %x, count %x, lCh %x, dev %x\n",
deviceExtension->lun[lChannel*2+DeviceNumber].TransferMode,
chan->lun[DeviceNumber]->TransferMode,
data, count, lChannel, DeviceNumber ));
if(deviceExtension->lun[lChannel*2+DeviceNumber].TransferMode < ATA_DMA) {
if(chan->lun[DeviceNumber]->TransferMode < ATA_DMA) {
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: Not DMA mode, assume this is just preparation\n" ));
//return FALSE;
}
@ -251,14 +275,20 @@ AtapiDmaSetup(
return FALSE;
}
//KdPrint2((PRINT_PREFIX " checkpoint 3\n" ));
if((ULONG_PTR)data & deviceExtension->AlignmentMask) {
if((ULONG)data & deviceExtension->AlignmentMask) {
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: unaligned data: %#x (%#x)\n", data, deviceExtension->AlignmentMask));
return FALSE;
}
//KdPrint2((PRINT_PREFIX " checkpoint 4\n" ));
KdPrint2((PRINT_PREFIX " get Phys(PRD=%x)\n", &(AtaReq->dma_tab) ));
dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)&(AtaReq->dma_tab) /*chan->dma_tab*/, &i, &dma_baseu);
if(use_AHCI) {
KdPrint2((PRINT_PREFIX " get Phys(AHCI_CMD=%x)\n", &(AtaReq->ahci.ahci_cmd_ptr->prd_tab) ));
dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)&(AtaReq->ahci.ahci_cmd_ptr->prd_tab), &i, &dma_baseu);
AtaReq->ahci.ahci_base64 = NULL; // clear before setup
} else {
KdPrint2((PRINT_PREFIX " get Phys(PRD=%x)\n", &(AtaReq->dma_tab) ));
dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)&(AtaReq->dma_tab) /*chan->dma_tab*/, &i, &dma_baseu);
}
if(dma_baseu) {
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: SRB built-in PRD above 4Gb: %8.8x%8.8x\n", dma_baseu, dma_base));
if(!deviceExtension->Host64) {
@ -271,7 +301,7 @@ AtapiDmaSetup(
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: No BASE\n" ));
return FALSE;
}
AtaReq->dma_base = dma_base;
AtaReq->ata.dma_base = dma_base; // aliased to ahci_base64
KdPrint2((PRINT_PREFIX " get Phys(data=%x)\n", data ));
dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, Srb, data, &dma_count, &dma_baseu);
@ -283,26 +313,26 @@ retry_DB_IO:
dma_base = chan->DB_IO_PhAddr;
data = (PUCHAR)(chan->DB_IO);
} else {
AtaReq->ahci_base64 = (ULONGLONG)dma_base | ((ULONGLONG)dma_baseu << 32);
AtaReq->ahci.ahci_base64 = (ULONGLONG)dma_base | ((ULONGLONG)dma_baseu << 32);
}
} else
if(!dma_count || ((LONG)(dma_base) == -1)) {
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: No 1st block\n" ));
//AtaReq->dma_base = NULL;
AtaReq->ahci_base64 = NULL;
AtaReq->ahci.ahci_base64 = NULL;
return FALSE;
}
dma_count = min(count, (PAGE_SIZE - ((ULONG_PTR)data & PAGE_MASK)));
dma_count = min(count, (PAGE_SIZE - ((ULONG)data & PAGE_MASK)));
data += dma_count;
count -= dma_count;
i = 0;
while (count) {
if(deviceExtension->HwFlags & UNIATA_AHCI) {
AtaReq->ahci_cmd.prd_tab[i].base = dma_base;
AtaReq->ahci_cmd.prd_tab[i].baseu = dma_baseu;
AtaReq->ahci_cmd.prd_tab[i].DBC = ((dma_count-1) & 0x3fffff);
if(use_AHCI) {
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].base = dma_base;
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].baseu = dma_baseu;
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC = ((dma_count-1) & 0x3fffff);
} else {
AtaReq->dma_tab[i].base = dma_base;
AtaReq->dma_tab[i].count = (dma_count & 0xffff);
@ -311,7 +341,7 @@ retry_DB_IO:
if (i >= max_entries) {
KdPrint2((PRINT_PREFIX "too many segments in DMA table\n" ));
//AtaReq->dma_base = NULL;
AtaReq->ahci_base64 = NULL;
AtaReq->ahci.ahci_base64 = NULL;
return FALSE;
}
KdPrint2((PRINT_PREFIX " get Phys(data[n]=%x)\n", data ));
@ -329,7 +359,7 @@ retry_DB_IO:
} else
if(!dma_count || !dma_base || ((LONG)(dma_base) == -1)) {
//AtaReq->dma_base = NULL;
AtaReq->ahci_base64 = 0;
AtaReq->ahci.ahci_base64 = 0;
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: No NEXT block\n" ));
return FALSE;
}
@ -339,10 +369,10 @@ retry_DB_IO:
count -= min(count, PAGE_SIZE);
}
KdPrint2((PRINT_PREFIX " set TERM\n" ));
if(deviceExtension->HwFlags & UNIATA_AHCI) {
AtaReq->ahci_cmd.prd_tab[i].base = dma_base;
AtaReq->ahci_cmd.prd_tab[i].baseu = dma_baseu;
AtaReq->ahci_cmd.prd_tab[i].DBC = ((dma_count-1) & 0x3fffff);
if(use_AHCI) {
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].base = dma_base;
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].baseu = dma_baseu;
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC = ((dma_count-1) & 0x3fffff);
} else {
AtaReq->dma_tab[i].base = dma_base;
AtaReq->dma_tab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT;
@ -466,15 +496,15 @@ AtapiDmaStart(
(Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "read" : "write",
lChannel, DeviceNumber ));
if(!AtaReq->dma_base) {
KdPrint2((PRINT_PREFIX "AtapiDmaStart: *** !AtaReq->dma_base\n"));
if(!AtaReq->ata.dma_base) {
KdPrint2((PRINT_PREFIX "AtapiDmaStart: *** !AtaReq->ata.dma_base\n"));
return;
}
if(AtaReq->Flags & REQ_FLAG_DMA_DBUF_PRD) {
KdPrint2((PRINT_PREFIX " DBUF_PRD\n"));
ASSERT(FALSE);
if(deviceExtension->HwFlags & UNIATA_AHCI) {
RtlCopyMemory(chan->DB_PRD, &(AtaReq->ahci_cmd), sizeof(AtaReq->ahci_cmd));
RtlCopyMemory(chan->DB_PRD, AtaReq->ahci.ahci_cmd_ptr, sizeof(AtaReq->ahci_cmd0));
} else {
RtlCopyMemory(chan->DB_PRD, &(AtaReq->dma_tab), sizeof(AtaReq->dma_tab));
}
@ -495,10 +525,10 @@ AtapiDmaStart(
if(ChipType == PRNEW) {
ULONG Channel = deviceExtension->Channel + lChannel;
if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
AtapiWritePortEx1(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
AtapiReadPortEx1(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) |
AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) |
(Channel ? 0x08 : 0x02));
AtapiWritePortEx4(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x05000000 : 0x06000000) | (Srb->DataTransferLength >> 1)
);
}
@ -519,7 +549,7 @@ AtapiDmaStart(
// set pointer to Pointer Table
AtapiWritePort4(chan, IDX_BM_PRD_Table,
AtaReq->dma_base
AtaReq->ata.dma_base
);
// set transfer direction
AtapiWritePort1(chan, IDX_BM_Command,
@ -557,15 +587,20 @@ AtapiDmaDone(
KdPrint2((PRINT_PREFIX "AtapiDmaDone: dev %d\n", DeviceNumber));
if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " ACHTUNG! should not be called for AHCI!\n"));
return 0xff;
}
switch(VendorID) {
case ATA_PROMISE_ID:
if(ChipType == PRNEW) {
ULONG Channel = deviceExtension->Channel + lChannel;
if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
AtapiWritePortEx1(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
AtapiReadPortEx1(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) &
AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) &
~(Channel ? 0x08 : 0x02));
AtapiWritePortEx4(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
0
);
}
@ -604,23 +639,29 @@ VOID
NTAPI
AtapiDmaReinit(
IN PHW_DEVICE_EXTENSION deviceExtension,
IN ULONG ldev,
IN PHW_LU_EXTENSION LunExt,
IN PATA_REQ AtaReq
)
{
PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]);
SCHAR apiomode;
apiomode = (CHAR)AtaPioMode(&(LunExt->IdentifyData));
if(!(AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: !(AtaReq->Flags & REQ_FLAG_DMA_OPERATION), fall to PIO on Device %d\n", ldev & 1));
"AtapiDmaReinit: !(AtaReq->Flags & REQ_FLAG_DMA_OPERATION), fall to PIO on Device %d\n", LunExt->Lun));
goto limit_pio;
}
if(!AtaReq->dma_base) {
if(deviceExtension->HwFlags & UNIATA_AHCI) {
if(!AtaReq->ahci.ahci_base64) {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: no AHCI PRD, fall to PIO on Device %d\n", LunExt->Lun));
goto limit_pio;
}
} else
if(!AtaReq->ata.dma_base) {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: no PRD, fall to PIO on Device %d\n", ldev & 1));
"AtapiDmaReinit: no PRD, fall to PIO on Device %d\n", LunExt->Lun));
goto limit_pio;
}
@ -628,14 +669,14 @@ AtapiDmaReinit(
(AtaReq->lba >= (LONGLONG)ATA_MAX_LBA28) &&
(LunExt->TransferMode > ATA_PIO5) ) {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: FORCE_DOWNRATE on Device %d for LBA48\n", ldev & 1));
"AtapiDmaReinit: FORCE_DOWNRATE on Device %d for LBA48\n", LunExt->Lun));
goto limit_lba48;
}
if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: FORCE_DOWNRATE on Device %d\n", ldev & 1));
"AtapiDmaReinit: FORCE_DOWNRATE on Device %d\n", LunExt->Lun));
if(AtaReq->lba >= (LONGLONG)ATA_MAX_LBA28) {
limit_lba48:
LunExt->DeviceFlags |= REQ_FLAG_FORCE_DOWNRATE_LBA48;
@ -645,16 +686,16 @@ limit_pio:
(LunExt->TransferMode > ATA_PIO5) && (LunExt->TransferMode != ATA_PIO0+apiomode)
) {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: set PIO mode on Device %d (%x -> %x)\n", ldev & 1, LunExt->TransferMode, ATA_PIO0+apiomode));
AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
"AtapiDmaReinit: set PIO mode on Device %d (%x -> %x)\n", LunExt->Lun, LunExt->TransferMode, ATA_PIO0+apiomode));
AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
apiomode,
-1,
-1 );
} else
if(LunExt->LimitedTransferMode < LunExt->TransferMode) {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: set PIO mode on Device %d (%x -> %x) (2)\n", ldev & 1, LunExt->TransferMode, LunExt->LimitedTransferMode));
AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
"AtapiDmaReinit: set PIO mode on Device %d (%x -> %x) (2)\n", LunExt->Lun, LunExt->TransferMode, LunExt->LimitedTransferMode));
AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
LunExt->LimitedTransferMode-ATA_PIO0,
-1,
-1 );
@ -662,8 +703,8 @@ limit_pio:
} else {
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: set MAX mode on Device %d\n", ldev & 1));
AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
"AtapiDmaReinit: set MAX mode on Device %d\n", LunExt->Lun));
AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
apiomode,
min( retry_Wdma[AtaReq->retry],
(CHAR)AtaWmode(&(LunExt->IdentifyData)) ),
@ -672,14 +713,14 @@ limit_pio:
}
// LunExt->DeviceFlags &= ~DFLAGS_FORCE_DOWNRATE;
} else
if(/*!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_FORCE_DOWNRATE) &&*/
if(/*!(LunExt->DeviceFlags & DFLAGS_FORCE_DOWNRATE) &&*/
(LunExt->LimitedTransferMode >
LunExt->TransferMode) ||
(LunExt->DeviceFlags & DFLAGS_REINIT_DMA)) {
// restore IO mode
KdPrint2((PRINT_PREFIX
"AtapiDmaReinit: restore IO mode on Device %d\n", ldev & 1));
AtapiDmaInit__(deviceExtension, ldev);
"AtapiDmaReinit: restore IO mode on Device %d\n", LunExt->Lun));
AtapiDmaInit__(deviceExtension, LunExt);
}
} // end AtapiDmaReinit()
@ -687,14 +728,12 @@ VOID
NTAPI
AtapiDmaInit__(
IN PHW_DEVICE_EXTENSION deviceExtension,
IN ULONG ldev
IN PHW_LU_EXTENSION LunExt
)
{
PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]);
if(LunExt->IdentifyData.SupportDma) {
KdPrint2((PRINT_PREFIX
"AtapiDmaInit__: Set (U)DMA on Device %d\n", ldev & 1));
"AtapiDmaInit__: Set (U)DMA on Device %d\n", LunExt->Lun));
/* for(i=AtaUmode(&(LunExt->IdentifyData)); i>=0; i--) {
AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
(CHAR)AtaPioMode(&(LunExt->IdentifyData)),
@ -707,14 +746,14 @@ AtapiDmaInit__(
(CHAR)AtaWmode(&(LunExt->IdentifyData)),
UDMA_MODE0+(CHAR)i );
}*/
AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
(CHAR)AtaPioMode(&(LunExt->IdentifyData)),
(CHAR)AtaWmode(&(LunExt->IdentifyData)),
(CHAR)AtaUmode(&(LunExt->IdentifyData)) );
} else {
KdPrint2((PRINT_PREFIX
"AtapiDmaInit__: Set PIO on Device %d\n", ldev & 1));
AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
"AtapiDmaInit__: Set PIO on Device %d\n", LunExt->Lun));
AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
(CHAR)AtaPioMode(&(LunExt->IdentifyData)), -1, -1);
}
} // end AtapiDmaInit__()
@ -779,12 +818,12 @@ AtapiDmaInit(
ULONG Channel = deviceExtension->Channel + lChannel;
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
//LONG statusByte = 0;
ULONG dev = Channel*2 + DeviceNumber;
ULONG ldev = lChannel*2 + DeviceNumber;
ULONG dev = Channel*2 + DeviceNumber; // for non-SATA/AHCI only!
ULONG ldev = lChannel*2 + DeviceNumber; // for non-SATA/AHCI only!
ULONG slotNumber = deviceExtension->slotNumber;
ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
LONG i;
PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]);
PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
ULONG VendorID = deviceExtension->DevID & 0xffff;
//ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
@ -878,7 +917,9 @@ AtapiDmaInit(
if(LunExt->IdentifyData.SataCapabilities != 0x0000 &&
LunExt->IdentifyData.SataCapabilities != 0xffff) {
//udmamode = min(udmamode, 6);
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_SA150)) {
KdPrint2((PRINT_PREFIX "LunExt->LimitedTransferMode %x, LunExt->OrigTransferMode %x\n",
LunExt->LimitedTransferMode, LunExt->OrigTransferMode));
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode))) {
return;
}
udmamode = min(udmamode, 5);
@ -1093,18 +1134,18 @@ set_new_acard:
apiomode = 4;
for(i=udmamode; i>=0; i--) {
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
AtapiWritePortEx4(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_udmatiming[udmamode]);
AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_udmatiming[udmamode]);
return;
}
}
for(i=wdmamode; i>=0; i--) {
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
AtapiWritePortEx4(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_wdmatiming[wdmamode]);
AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_wdmatiming[wdmamode]);
return;
}
}
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
AtapiWritePortEx4(chan, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_piotiming[apiomode]);
AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_piotiming[apiomode]);
return;
}
return;
@ -1317,12 +1358,13 @@ set_new_acard:
for(i=udmamode; i>=0; i--) {
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
/* Set UDMA reference clock (33/66/133MHz). */
SetPciConfig1(0x48, reg48 | (0x0001 << dev));
if(!(ChipFlags & ICH4_FIX)) {
SetPciConfig2(0x4a, (reg4a & ~(0x3 << (dev<<2))) |
(0x01 + !(i & 0x01)) );
}
if(i >= 2) {
if(i >= 3) {
reg54 |= (0x1 << dev);
} else {
reg54 &= ~(0x1 << dev);
@ -1369,19 +1411,18 @@ set_new_acard:
GetPciConfig4(0x40, reg40);
GetPciConfig1(0x44, reg44);
mask40 = 0x000000ff;
/* Allow PIO/WDMA timing controls. */
reg40 &= ~0x00ff00ff;
reg40 |= ~0x40774077;
/* Set PIO/WDMA timings. */
if(!(DeviceNumber & 1)) {
mask40 |= 0x00003300;
new40 = ((USHORT)(intel_timings[idx]) << 8);
//mask44 = 0x00; // already done on init
//new44 = 0x00;
} else {
mask44 = 0x0f;
new44 = ((intel_timings[idx] & 0x30) >> 2) |
(intel_timings[idx] & 0x03);
}
new40 |= 0x00004077;
if (Channel) {
mask40 <<= 16;
@ -1905,6 +1946,33 @@ setup_drive_ite:
AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
}
return;
case ATA_JMICRON_ID: {
UCHAR reg40;
GetPciConfig1(0x40, reg40);
if(reg40 & 0x08) {
// 80-pin check
udmamode = min(udmamode, 2);
}
/* Nothing to do to setup mode, the controller snoop SET_FEATURE cmd. */
if(apiomode >= 4)
apiomode = 4;
for(i=udmamode; i>=0; i--) {
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
return;
}
}
for(i=wdmamode; i>=0; i--) {
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
return;
}
}
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
return;
}
return;
break; }
}
try_generic_dma:
@ -1977,8 +2045,8 @@ cyrix_timing(
case ATA_WDMA2: reg24 = 0x00002020; break;
case ATA_UDMA2: reg24 = 0x00911030; break;
}
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),(dev*8) + 0x20, reg20);
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),(dev*8) + 0x24, reg24);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(dev*8) + 0x20, reg20);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(dev*8) + 0x24, reg24);
} // cyrix_timing()
VOID
@ -2244,4 +2312,3 @@ via82c_timing(
SetPciConfig1(0x4b-dev, (FIT(active - 1, 0, 0xf) << 4) | FIT(recover - 1, 0, 0xf) );
} // end via82c_timing()

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2004-2010 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2004-2011 Alexandr A. Telyatnikov (Alter)
Module Name:
id_init.cpp
@ -63,16 +63,26 @@ UniataChipDetectChannels(
KdPrint2((PRINT_PREFIX "UniataChipDetectChannels:\n" ));
if(ChipFlags & (UNIATA_SATA | UNIATA_AHCI)) {
if(!deviceExtension->NumberChannels) {
KdPrint2((PRINT_PREFIX "uninitialized SATA/AHCI port number -> 1\n"));
deviceExtension->NumberChannels = 1;
}
if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhciPM", 1 /* DEBUG */)) {
KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1\n"));
deviceExtension->NumberLuns = 2;
//chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
} else {
KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS));
deviceExtension->NumberLuns = SATA_MAX_PM_UNITS;
//deviceExtension->NumberLuns = 1;
}
}
if(deviceExtension->MasterDev) {
KdPrint2((PRINT_PREFIX "MasterDev -> 1 chan\n"));
deviceExtension->NumberChannels = 1;
}
if(ChipFlags & (UNIATA_SATA | UNIATA_AHCI)) {
KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS));
//deviceExtension->NumberLuns = SATA_MAX_PM_UNITS;
}
switch(VendorID) {
case ATA_ACER_LABS_ID:
switch(deviceExtension->DevID) {
@ -118,7 +128,7 @@ UniataChipDetectChannels(
KdPrint2((PRINT_PREFIX "New ATI PATA 1 chan\n"));
break;
}
break;
/* FALLTHROUGH */
case ATA_SILICON_IMAGE_ID:
if(ChipFlags & SIIBUG) {
@ -151,7 +161,7 @@ UniataChipDetectChannels(
/* 2 SATA without SATA registers on first channel + 1 PATA on second */
// do nothing, generic PATA INIT
KdPrint2((PRINT_PREFIX "VIA SATA without SATA regs -> no PM\n"));
deviceExtension->NumberLuns = SATA_MAX_PM_UNITS;
deviceExtension->NumberLuns = 1;
}
break;
case ATA_ITE_ID:
@ -246,8 +256,18 @@ UniataChipDetect(
if(i != BMLIST_TERMINATOR) {
DevTypeInfo = (PBUSMASTER_CONTROLLER_INFORMATION)&BusMasterAdapters[i];
} else {
if(Ata_is_ahci_dev(pciData)) {
KdPrint2((PRINT_PREFIX " AHCI candidate"));
deviceExtension->NumberChannels = 0;
if(!UniataAhciDetect(HwDeviceExtension, pciData, ConfigInfo)) {
KdPrint2((PRINT_PREFIX " AHCI init failed - not detected\n"));
return STATUS_UNSUCCESSFUL;
}
KdPrint2((PRINT_PREFIX " unknown AHCI dev, addr %#x", deviceExtension->BaseIoAHCI_0.Addr));
}
unknown_dev:
KdPrint2((PRINT_PREFIX " unknown dev, BM addr %#x", BaseIoAddressBM));
KdPrint2((PRINT_PREFIX " unknown dev, BM addr %#I64x", BaseIoAddressBM));
DevTypeInfo = NULL;
KdPrint2((PRINT_PREFIX " MaxTransferMode %#x\n", deviceExtension->MaxTransferMode));
@ -324,6 +344,7 @@ unknown_dev:
PCI_DEV_HW_SPEC_BM( 8324, 1106, 0x00, ATA_SA150, "VIA CX700" , VIA133 | VIASATA),
PCI_DEV_HW_SPEC_BM( 8353, 1106, 0x00, ATA_SA150, "VIA VX800" , VIA133 | VIASATA),
PCI_DEV_HW_SPEC_BM( 8409, 1106, 0x00, ATA_UDMA6, "VIA VX855" , VIA133 | 0x00 ),
PCI_DEV_HW_SPEC_BM( 8410, 1106, 0x00, ATA_SA300, "VIA VX900" , VIA133 | VIASATA),
PCI_DEV_HW_SPEC_BM( ffff, ffff, 0xff, BMLIST_TERMINATOR , NULL , BMLIST_TERMINATOR )
};
@ -353,7 +374,9 @@ unknown_dev:
// New chips have own DeviceId
if(deviceExtension->DevID != ATA_VIA82C571 &&
deviceExtension->DevID != ATA_VIACX700IDE &&
deviceExtension->DevID != ATA_VIASATAIDE) {
deviceExtension->DevID != ATA_VIASATAIDE &&
deviceExtension->DevID != ATA_VIASATAIDE2 &&
deviceExtension->DevID != ATA_VIASATAIDE3) {
KdPrint2((PRINT_PREFIX "Via new\n"));
break;
}
@ -479,13 +502,24 @@ for_ugly_chips:
ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
if(ChipFlags & UNIATA_AHCI) {
deviceExtension->NumberChannels = 0;
if(!UniataAhciDetect(HwDeviceExtension, pciData, ConfigInfo)) {
KdPrint2((PRINT_PREFIX " AHCI detect failed\n"));
return STATUS_UNSUCCESSFUL;
}
} else
if(!UniataChipDetectChannels(HwDeviceExtension, pciData, DeviceNumber, ConfigInfo)) {
return STATUS_UNSUCCESSFUL;
}
// UniataAhciDetect() sets proper number of channels
if(!UniataAllocateLunExt(deviceExtension, UNIATA_ALLOCATE_NEW_LUNS)) {
return STATUS_UNSUCCESSFUL;
}
if(ChipFlags & UNIATA_AHCI) {
}
switch(VendorID) {
case ATA_ACER_LABS_ID:
if(ChipFlags & UNIATA_SATA) {
@ -594,6 +628,7 @@ for_ugly_chips:
case ATA_ATI_ID:
KdPrint2((PRINT_PREFIX "ATI\n"));
/* FALLTHROUGH */
case ATA_SILICON_IMAGE_ID: {
if(ChipFlags & SIIBUG) {
@ -718,7 +753,7 @@ for_ugly_chips:
break; }
case ATA_SIS_ID: {
//if(ChipType != SIS_SOUTH) {
//if(ChipType != SIS_SOUTH) {}
BOOLEAN SIS_182=FALSE;
if(!(ChipFlags & SIS_BASE)) {
@ -964,6 +999,7 @@ for_ugly_chips:
}
if(deviceExtension->MaxTransferMode >= ATA_SA150) {
GetPciConfig1(0x90, tmp8);
KdPrint2((PRINT_PREFIX "Intel chip config: %x\n", tmp8));
/* SATA parts can be either compat or AHCI */
if(ChipFlags & UNIATA_AHCI) {
@ -991,6 +1027,7 @@ for_ugly_chips:
chan = &deviceExtension->chan[c];
IsPata = FALSE;
if(ChipFlags & ICH5) {
KdPrint2((PRINT_PREFIX "ICH5\n"));
if ((tmp8 & 0x04) == 0) {
chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
} else if ((tmp8 & 0x02) == 0) {
@ -1006,11 +1043,13 @@ for_ugly_chips:
}
} else
if(ChipFlags & I6CH2) {
KdPrint2((PRINT_PREFIX "I6CH2\n"));
chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
} else {
KdPrint2((PRINT_PREFIX "other Intel\n"));
switch(tmp8 & 0x03) {
case 2:
if(c!=0) {
if(c!=0) {
// PATA
IsPata = TRUE;
}
@ -1029,8 +1068,8 @@ for_ugly_chips:
KdPrint2((PRINT_PREFIX "PATA part\n"));
} else {
if((ChipFlags & ICH5) && BaseMemAddress) {
KdPrint2((PRINT_PREFIX "ICH5 indexed\n"));
if(/*(ChipFlags & ICH5) &&*/ BaseMemAddress) {
KdPrint2((PRINT_PREFIX "BaseMemAddress[5] -> indexed\n"));
chan->RegTranslation[IDX_INDEXED_ADDR].Addr = BaseMemAddress + 0;
chan->RegTranslation[IDX_INDEXED_ADDR].MemIo = MemIo;
chan->RegTranslation[IDX_INDEXED_DATA].Addr = BaseMemAddress + 4;
@ -1038,7 +1077,7 @@ for_ugly_chips:
}
if((ChipFlags & ICH5) || BaseMemAddress) {
KdPrint2((PRINT_PREFIX "i indexed\n"));
KdPrint2((PRINT_PREFIX "io indexed\n"));
// Rather interesting way of register access...
ChipType = INTEL_IDX;
deviceExtension->HwFlags &= ~CHIPTYPE_MASK;
@ -1066,14 +1105,25 @@ for_ugly_chips:
deviceExtension->MaximumDmaTransferLength = 63*1024;
}
break;
}
if(ChipFlags & UNIATA_AHCI) {
if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 1)) {
KdPrint((" AHCI excluded\n"));
return STATUS_UNSUCCESSFUL;
case ATA_JMICRON_ID:
/* New JMicron PATA controllers */
GetPciConfig1(0xdf, tmp8);
if(tmp8 & 0x40) {
KdPrint((" Check JMicron AHCI\n"));
if(Ata_is_ahci_dev(pciData)) {
ChipFlags |= UNIATA_AHCI;
deviceExtension->HwFlags |= UNIATA_AHCI;
} else {
KdPrint((" JMicron PATA\n"));
}
} else {
/* set controller configuration to a combined setup we support */
SetPciConfig4(0x40, 0x80c0a131);
SetPciConfig4(0x80, 0x01200000);
//KdPrint((" JMicron Combined (not supported yet)\n"));
//return STATUS_NOT_FOUND;
}
return UniataAhciInit(HwDeviceExtension) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
break;
}
return STATUS_SUCCESS;
@ -1372,7 +1422,7 @@ NTAPI
UniAtaReadLunConfig(
IN PHW_DEVICE_EXTENSION deviceExtension,
IN ULONG channel, // physical channel
IN ULONG ldev
IN ULONG DeviceNumber
)
{
ULONG tmp32;
@ -1383,33 +1433,33 @@ UniAtaReadLunConfig(
c = channel - deviceExtension->Channel; // logical channel
chan = &deviceExtension->chan[c];
ldev &= (deviceExtension->NumberLuns-1);
LunExt = &(deviceExtension->lun[c*deviceExtension->NumberLuns+ldev]);
DeviceNumber = (DeviceNumber % deviceExtension->NumberLuns);
LunExt = chan->lun[DeviceNumber];
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, ldev, L"ReadCacheEnable", 1);
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"ReadCacheEnable", 1);
LunExt->opt_ReadCacheEnable = tmp32 ? TRUE : FALSE;
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, ldev, L"WriteCacheEnable", 1);
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"WriteCacheEnable", 1);
LunExt->opt_WriteCacheEnable = tmp32 ? TRUE : FALSE;
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, ldev, L"MaxTransferMode", chan->MaxTransferMode);
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"MaxTransferMode", chan->MaxTransferMode);
LunExt->opt_MaxTransferMode = tmp32;
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, ldev, L"PreferedTransferMode", 0xffffffff);
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"PreferedTransferMode", 0xffffffff);
LunExt->opt_PreferedTransferMode = tmp32;
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, ldev, L"ReadOnly", 0);
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"ReadOnly", 0);
if(tmp32 <= 2) {
LunExt->opt_ReadOnly = (UCHAR)tmp32;
}
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, ldev, L"GeomType", 0xffffffff);
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"GeomType", 0xffffffff);
if(tmp32 > 2) {
tmp32 = 0xffffffff;
}
LunExt->opt_GeomType = tmp32;
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, ldev, L"Hidden", 0);
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"Hidden", 0);
if(tmp32) {
LunExt->DeviceFlags |= DFLAGS_HIDDEN;
}
@ -1448,7 +1498,7 @@ AtapiReadChipConfig(
}
deviceExtension->opt_AtapiDmaZeroTransfer = FALSE;
deviceExtension->opt_AtapiDmaControlCmd = FALSE;
deviceExtension->opt_AtapiDmaRawRead = FALSE;//TRUE; // Disabling that for VirtualBox
deviceExtension->opt_AtapiDmaRawRead = g_opt_AtapiDmaRawRead;
deviceExtension->opt_AtapiDmaReadWrite = TRUE;
}
@ -1546,11 +1596,31 @@ AtapiChipInit(
KdPrint2((PRINT_PREFIX "VendorID/DeviceID/Rev %#x/%#x/%#x\n", VendorID, DeviceID, RevID));
if(deviceExtension->UnknownDev) {
KdPrint2((PRINT_PREFIX " Unknown chip, exiting\n" ));
KdPrint2((PRINT_PREFIX " Unknown chip\n" ));
//return TRUE;
VendorID = 0xffffffff;
}
if(ChipFlags & UNIATA_AHCI) {
/* if BAR(5) is IO it should point to SATA interface registers */
if(!deviceExtension->BaseIoAHCI_0.Addr) {
KdPrint2((PRINT_PREFIX " !BaseIoAHCI_0, exiting\n" ));
return FALSE;
}
if(c == CHAN_NOT_SPECIFIED) {
return UniataAhciInit(HwDeviceExtension);
} else
if(c<deviceExtension->NumberChannels) {
KdPrint2((PRINT_PREFIX " AHCI single channel init\n" ));
UniataAhciReset(HwDeviceExtension, c);
return TRUE;
} else {
KdPrint2((PRINT_PREFIX " AHCI non-existent channel\n" ));
return FALSE;
}
}
switch(VendorID) {
// case ATA_ACARD_ID:
// break;
@ -1653,7 +1723,7 @@ AtapiChipInit(
KdPrint2((PRINT_PREFIX "Intel SATA\n"));
if(ChipFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX "Skip AHCI\n"));
KdPrint2((PRINT_PREFIX "Do nothing for AHCI\n"));
break;
}
if(c == CHAN_NOT_SPECIFIED) {
@ -1736,7 +1806,7 @@ AtapiChipInit(
}
if(ChipType == INTEL_IDX) {
KdPrint2((PRINT_PREFIX "i indexed\n"));
KdPrint2((PRINT_PREFIX "io indexed\n"));
//for(c=0; c<deviceExtension->NumberChannels; c++) {
chan = &deviceExtension->chan[c];
UniataSataWritePort4(chan, IDX_SATA_SError, 0xffffffff, 0);
@ -1773,17 +1843,17 @@ AtapiChipInit(
KdPrint2((PRINT_PREFIX "BaseIoAddressSATA_0=%x\n", deviceExtension->BaseIoAddressSATA_0.Addr));
if(ChipFlags & NVQ) {
/* clear interrupt status */
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, 0x00ff00ff);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, 0x00ff00ff);
/* enable device and PHY state change interrupts */
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4, 0x000d000d);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4, 0x000d000d);
/* disable NCQ support */
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400,
AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400) & 0xfffffff9);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400,
AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400) & 0xfffffff9);
} else {
/* clear interrupt status */
AtapiWritePortEx1(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, 0xff);
AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, 0xff);
/* enable device and PHY state change interrupts */
AtapiWritePortEx1(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1, 0xdd);
AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1, 0xdd);
}
/* enable PCI interrupt */
ChangePciConfig2(offsetof(PCI_COMMON_CONFIG, Command), (a & ~0x0400));
@ -1814,16 +1884,16 @@ AtapiChipInit(
/* setup clocks */
if(c == CHAN_NOT_SPECIFIED) {
// ATA_OUTB(ctlr->r_res1, 0x11, ATA_INB(ctlr->r_res1, 0x11) | 0x0a);
AtapiWritePortEx1(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
AtapiReadPortEx1(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) | 0x0a );
AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) | 0x0a );
}
/* FALLTHROUGH */
case PROLD:
/* enable burst mode */
// ATA_OUTB(ctlr->r_res1, 0x1f, ATA_INB(ctlr->r_res1, 0x1f) | 0x01);
if(c == CHAN_NOT_SPECIFIED) {
AtapiWritePortEx1(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1f,
AtapiReadPortEx1(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1f) | 0x01 );
AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1f,
AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1f) | 0x01 );
} else {
// check 80-pin cable
chan = &deviceExtension->chan[c];
@ -1848,7 +1918,7 @@ AtapiChipInit(
case PRMIO:
if(c == CHAN_NOT_SPECIFIED) {
if(ChipFlags & PRSATA) {
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressBM_0),0x6c, 0x000000ff);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x6c, 0x000000ff);
}
} else {
chan = &deviceExtension->chan[c];
@ -1927,16 +1997,16 @@ AtapiChipInit(
unit10 = (c & 2);
if(ChipFlags & SIINOSATAIRQ) {
KdPrint2((PRINT_PREFIX "Disable broken SATA intr on c=%x\n", c));
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + (unit01 << 7) + (unit10 << 8),0);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + (unit01 << 7) + (unit10 << 8),0);
}
}
} else {
if(ChipFlags & SIINOSATAIRQ) {
KdPrint2((PRINT_PREFIX "Disable broken SATA intr on c=%x\n", c));
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + (unit01 << 7) + (unit10 << 8),0);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + (unit01 << 7) + (unit10 << 8),0);
} else {
KdPrint2((PRINT_PREFIX "Enable SATA intr on c=%x\n", c));
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16));
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16));
}
}
}
@ -1946,16 +2016,16 @@ AtapiChipInit(
// Enable 3rd and 4th channels
if (ChipFlags & SII4CH) {
KdPrint2((PRINT_PREFIX "SII4CH\n"));
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0200, 0x00000002);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0200, 0x00000002);
}
} else {
chan = &deviceExtension->chan[c];
/* dont block interrupts */
//ChangePciConfig4(0x48, (a & ~0x03c00000));
tmp32 = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48);
AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48, (1 << 22) << c);
tmp32 = AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48);
AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48, (1 << 22) << c);
// flush
tmp32 = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48);
tmp32 = AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x48);
/* Initialize FIFO PCI bus arbitration */
GetPciConfig1(offsetof(PCI_COMMON_CONFIG, CacheLineSize), tmp8);
@ -2171,7 +2241,7 @@ UniataInitMapBM(
for(c=0; c<deviceExtension->NumberChannels; c++) {
chan = &deviceExtension->chan[c];
for (i=0; i<IDX_BM_IO_SZ; i++) {
chan->RegTranslation[IDX_BM_IO+i].Addr = BaseIoAddressBM_0 ? ((ULONG_PTR)BaseIoAddressBM_0 + i) : 0;
chan->RegTranslation[IDX_BM_IO+i].Addr = BaseIoAddressBM_0 ? ((ULONGIO_PTR)BaseIoAddressBM_0 + i) : 0;
chan->RegTranslation[IDX_BM_IO+i].MemIo = MemIo;
}
if(BaseIoAddressBM_0) {
@ -2191,11 +2261,11 @@ UniataInitMapBase(
ULONG i;
for (i=0; i<IDX_IO1_SZ; i++) {
chan->RegTranslation[IDX_IO1+i].Addr = BaseIoAddress1 ? ((ULONG_PTR)BaseIoAddress1 + i) : 0;
chan->RegTranslation[IDX_IO1+i].Addr = BaseIoAddress1 ? ((ULONGIO_PTR)BaseIoAddress1 + i) : 0;
chan->RegTranslation[IDX_IO1+i].MemIo = FALSE;
}
for (i=0; i<IDX_IO2_SZ; i++) {
chan->RegTranslation[IDX_IO2+i].Addr = BaseIoAddress2 ? ((ULONG_PTR)BaseIoAddress2 + i) : 0;
chan->RegTranslation[IDX_IO2+i].Addr = BaseIoAddress2 ? ((ULONGIO_PTR)BaseIoAddress2 + i) : 0;
chan->RegTranslation[IDX_IO2+i].MemIo = FALSE;
}
UniataInitSyncBaseIO(chan);
@ -2234,6 +2304,8 @@ AtapiSetupLunPtrs(
chan->NextDpcChan = -1;
for(i=0; i<deviceExtension->NumberLuns; i++) {
chan->lun[i]->DeviceExtension = deviceExtension;
chan->lun[i]->chan = chan;
chan->lun[i]->Lun = i;
}
} // end AtapiSetupLunPtrs()

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2010 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
@ -98,7 +98,7 @@ AtapiGetIoRange(
IN ULONG length
)
{
ULONG_PTR io_start = 0;
ULONGIO_PTR io_start = 0;
KdPrint2((PRINT_PREFIX " AtapiGetIoRange:\n"));
if(ConfigInfo->NumberOfAccessRanges <= rid)
@ -208,6 +208,7 @@ UniataCheckPCISubclass(
break;
case PCI_DEV_SUBCLASS_IDE:
case PCI_DEV_SUBCLASS_ATA:
break;
case PCI_DEV_SUBCLASS_SATA:
break;
default:
@ -250,6 +251,9 @@ UniataEnumBusMasterController__(
ULONG DeviceID;
ULONG dev_id;
USHORT SubVendorID;
USHORT SubSystemID;
ULONG i;
ULONG pass=0;
@ -295,7 +299,7 @@ UniataEnumBusMasterController__(
break;
}
// no device in this slot
if(busDataRead == 2) {
if(busDataRead == 2) {
NeedPciAltInit = TRUE;
continue;
}
@ -310,10 +314,39 @@ UniataEnumBusMasterController__(
BaseClass = pciData.BaseClass;
SubClass = pciData.SubClass;
dev_id = VendorID | (DeviceID << 16);
SubVendorID = pciData.u.type0.SubVendorID;
SubSystemID = pciData.u.type0.SubSystemID;
//KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
if(BaseClass != PCI_DEV_CLASS_STORAGE)
if(VendorID == 0x80ee && DeviceID == 0xcafe) {
KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VirtualBox Guest Service\n",busNumber,slotNumber,funcNumber));
if(g_opt_VirtualMachine == VM_AUTO) {
g_opt_VirtualMachine = VM_VBOX;
}
//continue;
} else
if((VendorID == 0x15ad) ||
(SubVendorID == 0x15ad && SubSystemID == 0x1976)) {
KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VMWare\n",busNumber,slotNumber,funcNumber));
if(g_opt_VirtualMachine == VM_AUTO) {
g_opt_VirtualMachine = VM_VMWARE;
}
//g_opt_VirtualBox = TRUE;
} else
if(SubVendorID == 0x1af4 && SubSystemID == 0x1100) {
KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - QEmu\n",busNumber,slotNumber,funcNumber));
if(g_opt_VirtualMachine == VM_AUTO) {
g_opt_VirtualMachine = VM_QEMU;
}
}
if(BaseClass != PCI_DEV_CLASS_STORAGE) {
continue;
}
KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x\n",busNumber,slotNumber,funcNumber));
KdPrint2((PRINT_PREFIX "Storage Class\n"));
@ -367,7 +400,8 @@ UniataEnumBusMasterController__(
/* unknown chipsets, try generic DMA if it seems possible */
default:
KdPrint2((PRINT_PREFIX "Default device\n"));
if(Ata_is_supported_dev(&pciData))
if(Ata_is_supported_dev(&pciData) ||
Ata_is_ahci_dev(&pciData))
found = TRUE;
break;
}
@ -825,6 +859,11 @@ UniataAllocateLunExt(
}
}
if(!deviceExtension->NumberLuns) {
KdPrint2((PRINT_PREFIX "default NumberLuns=2\n"));
deviceExtension->NumberLuns = 2;
}
deviceExtension->lun = (PHW_LU_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_LU_EXTENSION) * (deviceExtension->NumberChannels+1) * deviceExtension->NumberLuns);
if (!deviceExtension->lun) {
KdPrint2((PRINT_PREFIX "!deviceExtension->lun => SP_RETURN_ERROR\n"));
@ -900,7 +939,7 @@ UniataFindBusMasterController(
ULONG dev_id;
PCI_SLOT_NUMBER slotData;
ULONG_PTR i;
ULONG i;
ULONG channel;
ULONG c = 0;
PUCHAR ioSpace;
@ -953,7 +992,7 @@ UniataFindBusMasterController(
KdPrint2((PRINT_PREFIX "AdapterInterfaceType: Isa\n"));
}
if(InDriverEntry) {
i = (ULONG_PTR)Context;
i = (ULONG)Context;
if(i & 0x80000000) {
AltInit = TRUE;
}
@ -969,7 +1008,7 @@ UniataFindBusMasterController(
}
if(i >= BMListLen) {
KdPrint2((PRINT_PREFIX "unexpected device arrival\n"));
i = (ULONG_PTR)Context;
i = (ULONG)Context;
if(FirstMasterOk) {
channel = 1;
}
@ -1104,12 +1143,16 @@ UniataFindBusMasterController(
if (found)
break;
KdPrint2((PRINT_PREFIX "Default device\n"));
if(!Ata_is_supported_dev(&pciData)) {
KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n"));
found = FALSE;
} else {
if(Ata_is_supported_dev(&pciData)) {
KdPrint2((PRINT_PREFIX "Ata_is_supported_dev\n"));
found = TRUE;
} else
if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX "AHCI candidate\n"));
found = TRUE;
} else {
KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n"));
found = FALSE;
}
deviceExtension->UnknownDev = TRUE;
break;
@ -1217,7 +1260,7 @@ UniataFindBusMasterController(
BaseIoAddressBM_0,
(*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
deviceExtension->BusMaster = TRUE;
deviceExtension->BaseIoAddressBM_0.Addr = (ULONG_PTR)BaseIoAddressBM_0;
deviceExtension->BaseIoAddressBM_0.Addr = (ULONGIO_PTR)BaseIoAddressBM_0;
if((*ConfigInfo->AccessRanges)[4].RangeInMemory) {
deviceExtension->BaseIoAddressBM_0.MemIo = TRUE;
}
@ -1233,7 +1276,7 @@ UniataFindBusMasterController(
if(deviceExtension->BusMaster && !MasterDev) {
KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE && !MasterDev\n"));
statusByte = AtapiReadPort1(&(deviceExtension->chan[0]), IDX_BM_Status);
KdPrint2((PRINT_PREFIX " statusByte = %x\n", statusByte));
KdPrint2((PRINT_PREFIX " BM statusByte = %x\n", statusByte));
if(statusByte == 0xff) {
KdPrint2((PRINT_PREFIX " invalid port ?\n"));
/*
@ -1377,7 +1420,7 @@ UniataFindBusMasterController(
KdPrint2((PRINT_PREFIX "update ConfigInfo->w2k\n"));
_ConfigInfo->w2k.Dma64BitAddresses = 0;
_ConfigInfo->w2k.ResetTargetSupported = TRUE;
_ConfigInfo->w2k.MaximumNumberOfLogicalUnits = 2;
_ConfigInfo->w2k.MaximumNumberOfLogicalUnits = (UCHAR)deviceExtension->NumberLuns;
}
// Save the Interrupe Mode for later use
@ -1454,6 +1497,9 @@ UniataFindBusMasterController(
/* do extra channel-specific setups */
AtapiReadChipConfig(HwDeviceExtension, i, channel);
//AtapiChipInit(HwDeviceExtension, i, channel);
if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " No more setup for AHCI channel\n"));
} else
if(deviceExtension->AltRegMap) {
KdPrint2((PRINT_PREFIX " Non-standard registers layout\n"));
} else {
@ -1598,7 +1644,8 @@ UniataFindBusMasterController(
chan->RegTranslation[IDX_SATA_IO].Addr,
chan->RegTranslation[IDX_SATA_IO].MemIo ? "mem" : "io"));
UniataDumpATARegs(chan);
if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
UniataDumpATARegs(chan);
#ifndef UNIATA_CORE
#ifdef UNIATA_INIT_ON_PROBE
@ -1644,6 +1691,7 @@ UniataFindBusMasterController(
//#ifdef UNIATA_INIT_ON_PROBE
// }
#endif //UNIATA_INIT_ON_PROBE
}
found = TRUE;
chan->PrimaryAddress = FALSE;
@ -1796,7 +1844,7 @@ UniataFindFakeBusMasterController(
ULONG dev_id;
PCI_SLOT_NUMBER slotData;
ULONG_PTR i;
ULONG i;
// PUCHAR ioSpace;
// UCHAR statusByte;
@ -1818,7 +1866,7 @@ UniataFindFakeBusMasterController(
*Again = FALSE;
if(InDriverEntry) {
i = (ULONG_PTR)Context;
i = (ULONG)Context;
} else {
for(i=0; i<BMListLen; i++) {
if(BMList[i].slotNumber == ConfigInfo->SlotNumber &&
@ -1910,14 +1958,7 @@ UniataFindFakeBusMasterController(
goto exit_notfound;
}
switch(SubClass) {
case PCI_DEV_SUBCLASS_IDE:
case PCI_DEV_SUBCLASS_RAID:
case PCI_DEV_SUBCLASS_ATA:
case PCI_DEV_SUBCLASS_SATA:
// ok
break;
default:
if(!UniataCheckPCISubclass(FALSE, BMList[i].RaidFlags, SubClass)) {
KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
goto exit_notfound;
}
@ -1954,12 +1995,12 @@ UniataFindFakeBusMasterController(
if (found)
break;
KdPrint2((PRINT_PREFIX "Default device\n"));
if(!Ata_is_supported_dev(&pciData)) {
KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n"));
found = FALSE;
} else {
if(Ata_is_supported_dev(&pciData)) {
KdPrint2((PRINT_PREFIX "Ata_is_supported_dev\n"));
found = TRUE;
} else {
KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n"));
found = FALSE;
}
deviceExtension->UnknownDev = TRUE;
break;
@ -2015,7 +2056,7 @@ UniataFindFakeBusMasterController(
BaseIoAddressBM_0,
(*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
deviceExtension->BusMaster = TRUE;
deviceExtension->BaseIoAddressBM_0.Addr = (ULONG_PTR)BaseIoAddressBM_0;
deviceExtension->BaseIoAddressBM_0.Addr = (ULONGIO_PTR)BaseIoAddressBM_0;
if((*ConfigInfo->AccessRanges)[4].RangeInMemory) {
deviceExtension->BaseIoAddressBM_0.MemIo = TRUE;
}
@ -2438,14 +2479,14 @@ AtapiFindController(
ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
ConfigInfo->AdapterInterfaceType,
ConfigInfo->SystemIoBusNumber,
ScsiPortConvertUlongToPhysicalAddress((ULONG_PTR)BaseIoAddress1 + 0x0E),
ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress1 + 0x0E),
ATA_ALTIOSIZE,
TRUE);
} else {
ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
ConfigInfo->AdapterInterfaceType,
ConfigInfo->SystemIoBusNumber,
ScsiPortConvertUlongToPhysicalAddress((ULONG_PTR)BaseIoAddress1 + ATA_ALTOFFSET),
ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress1 + ATA_ALTOFFSET),
ATA_ALTIOSIZE,
TRUE);
}
@ -2698,8 +2739,8 @@ UniataAnybodyHome(
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
ULONG ldev = GET_LDEV2(lChannel, deviceNumber, 0);
PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]);
//ULONG ldev = GET_LDEV2(lChannel, deviceNumber, 0);
PHW_LU_EXTENSION LunExt = chan->lun[deviceNumber];
SATA_SSTATUS_REG SStatus;
UCHAR signatureLow;
@ -2775,8 +2816,8 @@ CheckDevice(
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
ULONG ldev = GET_LDEV2(lChannel, deviceNumber, 0);
PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]);
//ULONG ldev = GET_LDEV2(lChannel, deviceNumber, 0);
PHW_LU_EXTENSION LunExt;
UCHAR signatureLow,
signatureHigh;
@ -2786,6 +2827,21 @@ CheckDevice(
KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x\n",
deviceNumber));
if(deviceNumber > chan->NumberLuns) {
return 0;
}
LunExt = chan->lun[deviceNumber];
if(ResetDev && (deviceExtension->HwFlags & UNIATA_AHCI)) {
KdPrint2((PRINT_PREFIX "CheckDevice: reset AHCI dev\n"));
if(UniataAhciSoftReset(HwDeviceExtension, chan->lChannel, deviceNumber) == (ULONG)(-1)) {
KdPrint2((PRINT_PREFIX "CheckDevice: (no dev)\n"));
UniataForgetDevice(LunExt);
return 0;
}
} else
if(ResetDev) {
KdPrint2((PRINT_PREFIX "CheckDevice: reset dev\n"));
@ -2839,26 +2895,35 @@ CheckDevice(
}
}
}
// Select the device.
SelectDrive(chan, deviceNumber);
if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
return 0;
}
if(deviceExtension->HwFlags & UNIATA_AHCI) {
RetVal = LunExt->DeviceFlags;
signatureLow = signatureHigh = 0; // make GCC happy
} else {
// Select the device.
SelectDrive(chan, deviceNumber);
statusByte = WaitOnBaseBusyLong(chan);
if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
return 0;
}
GetBaseStatus(chan, statusByte);
if(deviceExtension->HwFlags & UNIATA_SATA) {
UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, deviceNumber);
}
statusByte = WaitOnBaseBusyLong(chan);
KdPrint2((PRINT_PREFIX "CheckDevice: status %#x\n", statusByte));
if(((statusByte | IDE_STATUS_BUSY) == 0xff) ||
(statusByte & IDE_STATUS_BUSY)) {
KdPrint2((PRINT_PREFIX "CheckDevice: busy => return\n"));
UniataForgetDevice(LunExt);
return 0;
GetBaseStatus(chan, statusByte);
if(deviceExtension->HwFlags & UNIATA_SATA) {
UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, deviceNumber);
}
KdPrint2((PRINT_PREFIX "CheckDevice: status %#x\n", statusByte));
if(((statusByte | IDE_STATUS_BUSY) == 0xff) ||
(statusByte & IDE_STATUS_BUSY)) {
KdPrint2((PRINT_PREFIX "CheckDevice: busy => return\n"));
UniataForgetDevice(LunExt);
return 0;
}
signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
}
// set default costs
@ -2866,9 +2931,22 @@ CheckDevice(
LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_HDD;
LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_HDD;
signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
if(deviceExtension->HwFlags & UNIATA_AHCI) {
if(RetVal & DFLAGS_DEVICE_PRESENT) {
if(IssueIdentify(HwDeviceExtension,
deviceNumber,
lChannel,
(RetVal & DFLAGS_ATAPI_DEVICE) ? IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
FALSE)) {
// OK
KdPrint2((PRINT_PREFIX "CheckDevice: detected AHCI Device %#x\n",
deviceNumber));
} else {
RetVal &= ~DFLAGS_ATAPI_DEVICE;
LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
}
}
} else
if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
KdPrint2((PRINT_PREFIX "CheckDevice: ATAPI signature found\n"));
@ -2982,7 +3060,6 @@ FindDevices(
//ULONG deviceNumber;
ULONG i;
UCHAR statusByte;
ULONG ldev;
ULONG max_ldev;
BOOLEAN AtapiOnly = FALSE;
@ -2995,24 +3072,31 @@ FindDevices(
// Clear expecting interrupt flag and current SRB field.
chan->ExpectingInterrupt = FALSE;
// chan->CurrentSrb = NULL;
max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : IDE_MAX_LUN_PER_CHAN;
// max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : IDE_MAX_LUN_PER_CHAN;
max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : deviceExtension->NumberLuns;
KdPrint2((PRINT_PREFIX " max_ldev %d\n", max_ldev));
// Search for devices.
for (i = 0; i < max_ldev; i++) {
AtapiDisableInterrupts(deviceExtension, Channel);
//AtapiDisableInterrupts(deviceExtension, Channel);
if(Flags & UNIATA_FIND_DEV_UNHIDE) {
ldev = GET_LDEV2(Channel, i, 0);
deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_HIDDEN;
chan->lun[i]->DeviceFlags &= ~DFLAGS_HIDDEN;
}
deviceResponded |=
(CheckDevice(HwDeviceExtension, Channel, i, TRUE) != 0);
//AtapiEnableInterrupts(deviceExtension, Channel);
}
if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
AtapiEnableInterrupts(deviceExtension, Channel);
KdPrint2((PRINT_PREFIX
"FindDevices: returning %d (AHCI)\n",
deviceResponded));
return deviceResponded;
}
for (i = 0; i < max_ldev; i++) {
ldev = GET_LDEV2(Channel, i, 0);
LunExt = &(deviceExtension->lun[ldev]);
LunExt = chan->lun[i];
if (( LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) &&
!(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) &&
@ -3114,7 +3198,7 @@ FindDevices(
i));
// Don't use this device as writes could cause corruption.
LunExt->DeviceFlags &= ~DFLAGS_DEVICE_PRESENT;
UniataForgetDevice(&(deviceExtension->lun[ldev]));
UniataForgetDevice(LunExt);
continue;
}
@ -3145,8 +3229,7 @@ FindDevices(
*/
if(deviceResponded) {
for (i = 0; i < max_ldev; i++) {
ldev = GET_LDEV2(Channel, i, 0);
LunExt = &(deviceExtension->lun[ldev]);
LunExt = chan->lun[i];
KdPrint2((PRINT_PREFIX
"FindDevices: select %d dev to clear INTR\n", i));
@ -3156,8 +3239,7 @@ FindDevices(
"FindDevices: statusByte=%#x\n", statusByte));
}
for (i = 0; i < max_ldev; i++) {
ldev = GET_LDEV2(Channel, i, 0);
LunExt = &(deviceExtension->lun[ldev]);
LunExt = chan->lun[i];
if(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) {
// Make sure some device (master is preferred) is selected on exit.

View file

@ -107,13 +107,13 @@ UniataQueueRequest(
BOOLEAN reordered = FALSE;
#endif //QUEUE_STATISTICS
PHW_LU_EXTENSION LunExt = chan->lun[GET_LDEV(Srb) & 1];
PHW_LU_EXTENSION LunExt = chan->lun[GET_CDEV(Srb)];
AtaReq->Srb = Srb;
/*
#ifdef _DEBUG
if(!LunExt) {
PrintNtConsole("q: chan = %#x, dev %#x\n", chan, GET_LDEV(Srb));
PrintNtConsole("q: chan = %#x, dev %#x\n", chan, GET_CDEV(Srb));
int i;
for(i=0; i<1000; i++) {
AtapiStallExecution(5*1000);
@ -267,7 +267,7 @@ UniataRemoveRequest(
PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
//PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension;
ULONG cdev = GET_LDEV(Srb) & 1;
ULONG cdev = GET_CDEV(Srb);
PHW_LU_EXTENSION LunExt = chan->lun[cdev];
if(!LunExt)

View file

@ -42,4 +42,4 @@ UniataGetNextChannel(
IN PHW_CHANNEL chan
);
#endif //__UNIATA_COMMAND_QUEUE_SUPPORT__H__
#endif //__UNIATA_COMMAND_QUEUE_SUPPORT__H__

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,36 @@
/*++
Copyright (c) 2008-2011 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
Abstract:
This module handles SATA-related staff
Author:
Alexander A. Telyatnikov (Alter)
Environment:
kernel mode only
Notes:
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Revision History:
--*/
#ifndef __UNIATA_SATA__H__
#define __UNIATA_SATA__H__
@ -9,12 +42,16 @@ UniataSataConnect(
IN ULONG pm_port = 0 /* for port multipliers */
);
#define UNIATA_SATA_RESET_ENABLE TRUE
#define UNIATA_SATA_FAST_ENABLE FALSE
UCHAR
NTAPI
UniataSataPhyEnable(
IN PVOID HwDeviceExtension,
IN ULONG lChannel, // logical channel
IN ULONG pm_port = 0 /* for port multipliers */
IN ULONG pm_port = 0, /* for port multipliers */
IN BOOLEAN doReset = UNIATA_SATA_FAST_ENABLE
);
#define UNIATA_SATA_DO_CONNECT TRUE
@ -40,11 +77,28 @@ UniataSataEvent(
IN ULONG Action,
IN ULONG pm_port = 0 /* for port multipliers */
);
/*
#define UniataIsSATARangeAvailable(deviceExtension, lChannel) \
((deviceExtension->BaseIoAddressSATA_0.Addr || \
deviceExtension->BaseIoAHCI_0.Addr) && \
(deviceExtension->chan[lChannel].RegTranslation[IDX_SATA_SStatus].Addr))
*/
__inline
BOOLEAN
UniataIsSATARangeAvailable(
IN PHW_DEVICE_EXTENSION deviceExtension,
IN ULONG lChannel
)
{
// seems, check for deviceExtension->BaseIoAddressSATA_0.Addr and
// deviceExtension->BaseIoAHCI_0.Addr is not necessary now
if(deviceExtension->chan[lChannel].RegTranslation[IDX_SATA_SStatus].Addr ||
deviceExtension->chan[lChannel].RegTranslation[IDX_SATA_SStatus].Proc) {
return TRUE;
}
return FALSE;
} // end UniataIsSATARangeAvailable()
ULONG
NTAPI
@ -69,6 +123,14 @@ UniataAhciInit(
IN PVOID HwDeviceExtension
);
BOOLEAN
NTAPI
UniataAhciDetect(
IN PVOID HwDeviceExtension,
IN PPCI_COMMON_CONFIG pciData, // optional
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
);
UCHAR
NTAPI
UniataAhciStatus(
@ -79,7 +141,7 @@ UniataAhciStatus(
ULONG
NTAPI
UniataAhciSetupFIS(
UniataAhciSetupFIS_H2D(
IN PHW_DEVICE_EXTENSION deviceExtension,
IN ULONG DeviceNumber,
IN ULONG lChannel,
@ -91,4 +153,165 @@ UniataAhciSetupFIS(
IN ULONG flags
);
UCHAR
NTAPI
UniataAhciSendCommand(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber,
IN ULONG flags,
IN ULONG timeout
);
ULONG
NTAPI
UniataAhciSoftReset(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber
);
ULONG
NTAPI
UniataAhciWaitReady(
IN PHW_CHANNEL chan,
IN ULONG timeout
);
ULONG
NTAPI
UniataAhciHardReset(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
OUT PULONG signature
);
VOID
NTAPI
UniataAhciReset(
IN PVOID HwDeviceExtension,
IN ULONG lChannel
);
VOID
NTAPI
UniataAhciStartFR(
IN PHW_CHANNEL chan
);
VOID
NTAPI
UniataAhciStopFR(
IN PHW_CHANNEL chan
);
VOID
NTAPI
UniataAhciStart(
IN PHW_CHANNEL chan
);
VOID
NTAPI
UniataAhciCLO(
IN PHW_CHANNEL chan
);
VOID
NTAPI
UniataAhciStop(
IN PHW_CHANNEL chan
);
__inline
ULONG
UniataAhciReadChannelPort4(
IN PHW_CHANNEL chan,
IN ULONG io_port_ndx
)
{
ULONG v = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&((chan)->BaseIoAHCI_Port), io_port_ndx);
KdPrint3((PRINT_PREFIX "ReadChannelPort4 ch%d[%x] = %x\n", chan->lChannel, io_port_ndx, v));
return v;
} // end UniataAhciReadChannelPort4()
__inline
VOID
UniataAhciWriteChannelPort4(
IN PHW_CHANNEL chan,
IN ULONG io_port_ndx,
IN ULONG data
)
{
KdPrint3((PRINT_PREFIX "WriteChannelPort4 %x => ch%d[%x]\n", data, chan->lChannel, io_port_ndx));
AtapiWritePortEx4(NULL, (ULONGIO_PTR)&((chan)->BaseIoAHCI_Port), io_port_ndx, data);
} // end UniataAhciWriteChannelPort4()
#define UniataAhciReadHostPort4(deviceExtension, io_port_ndx) \
AtapiReadPortEx4(NULL, (ULONGIO_PTR)&((deviceExtension)->BaseIoAHCI_0), io_port_ndx)
#define UniataAhciWriteHostPort4(deviceExtension, io_port_ndx, data) \
AtapiWritePortEx4(NULL, (ULONGIO_PTR)&((deviceExtension)->BaseIoAHCI_0), io_port_ndx, data)
UCHAR
NTAPI
UniataAhciBeginTransaction(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber,
IN PSCSI_REQUEST_BLOCK Srb
);
UCHAR
NTAPI
UniataAhciEndTransaction(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber,
IN PSCSI_REQUEST_BLOCK Srb
);
VOID
NTAPI
UniataAhciResume(
IN PHW_CHANNEL chan
);
__inline
ULONG
UniataAhciUlongFromRFIS(
PUCHAR RCV_FIS
)
{
return ( (((ULONG)(RCV_FIS[6])) << 24) |
(((ULONG)(RCV_FIS[5])) << 16) |
(((ULONG)(RCV_FIS[4])) << 8) |
((ULONG)(RCV_FIS[12])) );
}
BOOLEAN
NTAPI
UniataAhciReadPM(
IN PHW_CHANNEL chan,
IN ULONG DeviceNumber,
IN ULONG Reg,
OUT PULONG result
);
UCHAR
NTAPI
UniataAhciWritePM(
IN PHW_CHANNEL chan,
IN ULONG DeviceNumber,
IN ULONG Reg,
IN ULONG value
);
VOID
UniataAhciSetupCmdPtr(
IN OUT PATA_REQ AtaReq
);
#endif //__UNIATA_SATA__H__

View file

@ -16,7 +16,9 @@ KeTestSpinLock,(
(
SpinLock
))
#if 0
#ifndef USE_REACTOS_DDK
CROSSNT_DECL(
LONG,
__fastcall,
@ -62,13 +64,16 @@ InterlockedCompareExchange,(
IN PVOID ExChange,
IN PVOID Comperand
))
#endif
#define CrNtInterlockedIncrement InterlockedIncrement
#define CrNtInterlockedDecrement InterlockedDecrement
#define CrNtInterlockedExchangeAdd InterlockedExchangeAdd
#else
#define CrNtInterlockedIncrement InterlockedIncrement
#define CrNtInterlockedDecrement InterlockedDecrement
#define CrNtInterlockedExchangeAdd InterlockedExchangeAdd
#define CrNtInterlockedCompareExchange InterlockedCompareExchange
#endif // !USE_REACTOS_DDK
CROSSNT_DECL_EX("HAL.DLL",
KIRQL,__stdcall,
KeRaiseIrqlToDpcLevel,(),())

View file

@ -57,7 +57,13 @@ CrNtGetProcAddress(
PCHAR pFunctionName
);
typedef BOOLEAN (__stdcall *ptrCrNtPsGetVersion)(
#ifdef __GNUC__
#define DECL_FUNC_PTR(_type, _cconv, _name) _type _cconv ( * _name)
#else
#define DECL_FUNC_PTR(_type, _cconv, _name) _type (_cconv * _name)
#endif
typedef DECL_FUNC_PTR(BOOLEAN, __stdcall, ptrCrNtPsGetVersion)(
PULONG MajorVersion OPTIONAL,
PULONG MinorVersion OPTIONAL,
PULONG BuildNumber OPTIONAL,
@ -67,7 +73,7 @@ typedef BOOLEAN (__stdcall *ptrCrNtPsGetVersion)(
extern "C"
ptrCrNtPsGetVersion CrNtPsGetVersion;
typedef NTSTATUS (__stdcall *ptrCrNtNtQuerySystemInformation)(
typedef DECL_FUNC_PTR(NTSTATUS, __stdcall, ptrCrNtNtQuerySystemInformation)(
IN SYSTEM_INFORMATION_CLASS SystemInfoClass,
OUT PVOID SystemInfoBuffer,
IN ULONG SystemInfoBufferSize,
@ -114,6 +120,8 @@ extern HANDLE g_hHal;
// NT3.51 doesn't export strlen() and strcmp()
// The same time, Release build doesn't depend no these functions since they are inlined
#ifndef USE_REACTOS_DDK
size_t __cdecl CrNtstrlen (
const char * str
);
@ -126,6 +134,8 @@ int __cdecl CrNtstrcmp (
#define strlen CrNtstrlen
#define strcmp CrNtstrcmp
#endif // !USE_REACTOS_DDK
#endif //_DEBUG
#define CROSSNT_DECL_API
@ -137,4 +147,4 @@ int __cdecl CrNtstrcmp (
}; // end extern "C"
#endif //__CROSS_VERSION_LIB_NT__H__
#endif //__CROSS_VERSION_LIB_NT__H__

View file

@ -43,4 +43,4 @@ DbgDump_SetAutoReconnect(
};
#endif //__cplusplus
#endif //__DBG_DUMP_TOOLS__H__
#endif //__DBG_DUMP_TOOLS__H__

View file

@ -1,10 +1,156 @@
#ifndef __CROSSNT_MISC__H__
#define __CROSSNT_MISC__H__
#ifdef USE_REACTOS_DDK
/* The definitions look so crappy, because the code doesn't care
whether the source is an array or an integer */
#define MOV_DD_SWP(a,b) ((a) = RtlUlongByteSwap(*(PULONG)&(b)))
#define MOV_DW_SWP(a,b) ((a) = RtlUshortByteSwap(*(PUSHORT)&(b)))
#define MOV_SWP_DW2DD(a,b) ((a) = RtlUshortByteSwap(*(PUSHORT)&(b)))
#else
typedef void
(__fastcall *ptrMOV_DD_SWP)(
void* a, // ECX
void* b // EDX
);
extern "C" ptrMOV_DD_SWP _MOV_DD_SWP;
extern "C"
void
__fastcall
_MOV_DD_SWP_i486(
void* a, // ECX
void* b // EDX
);
extern "C"
void
__fastcall
_MOV_DD_SWP_i386(
void* a, // ECX
void* b // EDX
);
#define MOV_DD_SWP(a,b) _MOV_DD_SWP(&(a),&(b))
/********************/
extern "C"
void
__fastcall
_MOV_DW_SWP(
void* a, // ECX
void* b // EDX
);
#define MOV_DW_SWP(a,b) _MOV_DW_SWP(&(a),&(b))
/********************/
typedef void
(__fastcall *ptrREVERSE_DD)(
void* a // ECX
);
extern "C" ptrREVERSE_DD _REVERSE_DD;
void
__fastcall
_REVERSE_DD_i486(
void* a // ECX
);
void
__fastcall
_REVERSE_DD_i386(
void* a // ECX
);
#define REVERSE_DD(a,b) _REVERSE_DD(&(a),&(b))
/********************/
extern "C"
void
__fastcall
_REVERSE_DW(
void* a // ECX
);
#define REVERSE_DW(a) _REVERSE_DW(&(a))
/********************/
extern "C"
void
__fastcall
_MOV_DW2DD_SWP(
void* a, // ECX
void* b // EDX
);
#define MOV_DW2DD_SWP(a,b) _MOV_DW2DD_SWP(&(a),&(b))
/********************/
extern "C"
void
__fastcall
_MOV_SWP_DW2DD(
void* a, // ECX
void* b // EDX
);
#define MOV_SWP_DW2DD(a,b) _MOV_SWP_DW2DD(&(a),&(b))
/********************/
extern "C"
void
__fastcall
_MOV_MSF(
void* a, // ECX
void* b // EDX
);
#define MOV_MSF(a,b) _MOV_MSF(&(a),&(b))
/********************/
typedef void
(__fastcall *ptrMOV_MSF_SWP)(
void* a, // ECX
void* b // EDX
);
extern "C" ptrMOV_MSF_SWP _MOV_MSF_SWP;
extern "C"
void
__fastcall
_MOV_MSF_SWP_i486(
void* a, // ECX
void* b // EDX
);
extern "C"
void
__fastcall
_MOV_MSF_SWP_i386(
void* a, // ECX
void* b // EDX
);
#define MOV_MSF_SWP(a,b) _MOV_MSF_SWP(&(a),&(b))
/********************/
extern "C"
void
__fastcall
_XCHG_DD(
void* a, // ECX
void* b // EDX
);
#define XCHG_DD(a,b) _XCHG_DD(&(a),&(b))
#endif //USE_REACTOS_DDK
#endif // __CROSSNT_MISC__H__

View file

@ -1,15 +1,19 @@
#ifndef __NTDDK_EX__H__
#define __NTDDK_EX__H__
//#ifndef USE_REACTOS_DDK
#ifdef ASSERT
#undef ASSERT
#define ASSERT(x) ((void)0)
// #define ASSERT(x) if (!(x)) { RtlAssert("#x",__FILE__,__LINE__, ""); }
#endif
#endif //ASSERT
//#endif //USE_REACTOS_DDK
#ifndef FILE_CHARACTERISTIC_PNP_DEVICE // DDK 2003
#if !defined(FILE_CHARACTERISTIC_PNP_DEVICE) || defined(USE_REACTOS_DDK) // DDK 2003
#ifndef FILE_CHARACTERISTIC_PNP_DEVICE
#define FILE_CHARACTERISTIC_PNP_DEVICE 0x00000800
#endif // !FILE_CHARACTERISTIC_PNP_DEVICE
#endif
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation,
@ -42,7 +46,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
SystemUnloadGdiDriverInformation,
SystemTimeAdjustmentInformation,
SystemSummaryMemoryInformation,
#ifndef __REACTOS__
#ifndef USE_REACTOS_DDK
SystemNextEventIdInformation,
SystemEventIdsInformation,
SystemCrashDumpInformation,
@ -50,7 +54,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
SystemMirrorMemoryInformation,
SystemPerformanceTraceInformation,
SystemObsolete0,
#endif
#endif // USE_REACTOS_DDK
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
@ -60,17 +64,17 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
SystemPrioritySeperation,
SystemPlugPlayBusInformation,
SystemDockInformation,
#ifdef __REACTOS__
#ifdef USE_REACTOS_DDK
SystemPowerInformationNative,
#elif defined IRP_MN_START_DEVICE
SystemPowerInformationInfo,
#else
SystemPowerInformation,
#endif
#endif // USE_REACTOS_DDK
SystemProcessorSpeedInformation,
SystemCurrentTimeZoneInformation,
SystemLookasideInformation,
#ifdef __REACTOS__
#ifdef USE_REACTOS_DDK
SystemTimeSlipNotification,
SystemSessionCreate,
SystemSessionDetach,
@ -124,9 +128,11 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
SystemPrefetchPathInformation,
SystemVerifierFaultsInformation,
MaxSystemInfoClass,
#endif //__REACTOS__
#endif // USE_REACTOS_DDK
} SYSTEM_INFORMATION_CLASS;
#endif // !defined(FILE_CHARACTERISTIC_PNP_DEVICE) || defined(USE_REACTOS_DDK)
NTSYSAPI
NTSTATUS

View file

@ -935,7 +935,7 @@ ScsiPortWriteRegisterBufferUlong(
SCSIPORT_API
SCSI_PHYSICAL_ADDRESS NTAPI
ScsiPortConvertUlongToPhysicalAddress(
ULONG_PTR UlongAddress
ULONG UlongAddress
);
SCSIPORT_API

View file

@ -1,3 +1,5 @@
#include "config.h"
extern "C" {
#include <ntddk.h>
@ -6,7 +8,7 @@ extern "C" {
#include "stddef.h"
#include "stdarg.h"
#include "inc/CrossNt.h"
#include "inc\CrossNt.h"
#include "atapi.h" // includes scsi.h
#include "ntdddisk.h"
@ -22,13 +24,10 @@ extern "C" {
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define TAG_UNIATA 'Uata'
#define TAG_UNIATA 'ataU'
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,TAG_UNIATA)
#endif //UNIATA_CORE
#include "badblock.h"

View file

@ -63,6 +63,7 @@ extern "C" {
#define IOCTL_SCSI_MINIPORT_UNIATA_RESETBB ((FILE_DEVICE_SCSI << 16) + 0x09a5)
#define IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE ((FILE_DEVICE_SCSI << 16) + 0x09a6)
#define IOCTL_SCSI_MINIPORT_UNIATA_REG_IO ((FILE_DEVICE_SCSI << 16) + 0x09a7)
#define IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION ((FILE_DEVICE_SCSI << 16) + 0x09a8)
typedef struct _ADDREMOVEDEV {
ULONG WaitForPhysicalLink; // us
@ -87,6 +88,15 @@ typedef struct _GETTRANSFERMODE {
ULONG Reserved;
} GETTRANSFERMODE, *PGETTRANSFERMODE;
typedef struct _GETDRVVERSION {
ULONG Length;
USHORT VersionMj;
USHORT VersionMn;
USHORT SubVerMj;
USHORT SubVerMn;
ULONG Reserved;
} GETDRVVERSION, *PGETDRVVERSION;
typedef struct _CHANINFO {
ULONG MaxTransferMode; // may differ from Controller's value due to 40-pin cable
ULONG ChannelCtrlFlags;
@ -131,9 +141,11 @@ typedef struct _ADAPTERINFO {
// with so many broken PCI IDE controllers being sold, we have
// to support them.
ULONG NumberChannels;
BOOLEAN ChanInfoValid;
CHAR Reserved[3];
UCHAR NumberLuns;
BOOLEAN LunInfoValid;
CHAR Reserved;
ULONG AdapterInterfaceType;
@ -264,6 +276,7 @@ typedef struct _UNIATA_CTL {
ADAPTERINFO AdapterInfo;
// IDENTIFY_DATA2 LunIdent;
// ATA_PASS_THROUGH_DIRECT AtaDirect;
GETDRVVERSION Version;
UNIATA_REG_IO_HDR RegIo;
};
} UNIATA_CTL, *PUNIATA_CTL;

View file

@ -1,6 +1,10 @@
#define UNIATA_VER_STR "40a5"
#define UNIATA_VER_DOT 0.40.1.5
#define UNIATA_VER_DOT_COMMA 0,40,1,5
#define UNIATA_VER_DOT_STR "0.40.1.5"
#define UNIATA_VER_YEAR 2010
#define UNIATA_VER_YEAR_STR "2010"
#define UNIATA_VER_STR "41b2"
#define UNIATA_VER_DOT 0.41.2.2
#define UNIATA_VER_MJ 0
#define UNIATA_VER_MN 41
#define UNIATA_VER_SUB_MJ 2
#define UNIATA_VER_SUB_MN 2
#define UNIATA_VER_DOT_COMMA 0,41,2,2
#define UNIATA_VER_DOT_STR "0.41.2.2"
#define UNIATA_VER_YEAR 2011
#define UNIATA_VER_YEAR_STR "2011"