diff --git a/reactos/drivers/storage/ide/uniata/atapi.h b/reactos/drivers/storage/ide/uniata/atapi.h index 1252df9209b..9cc0e3b309e 100644 --- a/reactos/drivers/storage/ide/uniata/atapi.h +++ b/reactos/drivers/storage/ide/uniata/atapi.h @@ -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 diff --git a/reactos/drivers/storage/ide/uniata/badblock.h b/reactos/drivers/storage/ide/uniata/badblock.h index 5fa4bbb3b60..4e7183cb452 100644 --- a/reactos/drivers/storage/ide/uniata/badblock.h +++ b/reactos/drivers/storage/ide/uniata/badblock.h @@ -78,4 +78,4 @@ CheckIfBadBlock( IN ULONG count ); -#endif // _BADBLOCK_H_INCLUDED_ +#endif // _BADBLOCK_H_INCLUDED_ \ No newline at end of file diff --git a/reactos/drivers/storage/ide/uniata/bm_devs.h b/reactos/drivers/storage/ide/uniata/bm_devs.h index 672b22ae7fd..4eec3767a80 100644 --- a/reactos/drivers/storage/ide/uniata/bm_devs.h +++ b/reactos/drivers/storage/ide/uniata/bm_devs.h @@ -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__ diff --git a/reactos/drivers/storage/ide/uniata/bsmaster.h b/reactos/drivers/storage/ide/uniata/bsmaster.h index 0626b2c590b..ada2205aa1f 100644 --- a/reactos/drivers/storage/ide/uniata/bsmaster.h +++ b/reactos/drivers/storage/ide/uniata/bsmaster.h @@ -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; diff --git a/reactos/drivers/storage/ide/uniata/config.h b/reactos/drivers/storage/ide/uniata/config.h index 17768e42a20..687cd46e60d 100644 --- a/reactos/drivers/storage/ide/uniata/config.h +++ b/reactos/drivers/storage/ide/uniata/config.h @@ -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 diff --git a/reactos/drivers/storage/ide/uniata/id_ata.cpp b/reactos/drivers/storage/ide/uniata/id_ata.cpp index 07c44253e0e..92defcbc089 100644 --- a/reactos/drivers/storage/ide/uniata/id_ata.cpp +++ b/reactos/drivers/storage/ide/uniata/id_ata.cpp @@ -1,6 +1,6 @@ /*++ -Copyright (c) 2002-2010 Alexandr A. Telyatnikov (Alter) +Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter) Module Name: id_ata.cpp @@ -83,6 +83,14 @@ ULONG g_LogToDisplay = 0; ULONG g_WaitBusyInISR = 1; +ULONG g_opt_WaitBusyCount = 200; // 20000 +ULONG g_opt_WaitBusyDelay = 10; // 150 +ULONG g_opt_WaitDrqDelay = 10; // 100 +BOOLEAN g_opt_AtapiSendDisableIntr = 1; // 0 +BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0 + +ULONG g_opt_VirtualMachine = 0; // Auto + BOOLEAN InDriverEntry = TRUE; BOOLEAN g_opt_Verbose = 0; @@ -160,14 +168,6 @@ AtapiAdapterControl( #endif //UNIATA_CORE -BOOLEAN -NTAPI -AtapiCheckInterrupt__( - IN PVOID HwDeviceExtension, - IN UCHAR c - ); - - #ifndef UNIATA_CORE BOOLEAN @@ -240,7 +240,7 @@ VOID \ DDKFASTAPI \ AtapiWritePort##sz( \ IN PHW_CHANNEL chan, \ - IN ULONG_PTR _port, \ + IN ULONGIO_PTR _port, \ IN _type data \ ) \ { \ @@ -274,7 +274,7 @@ VOID \ DDKFASTAPI \ AtapiWritePortEx##sz( \ IN PHW_CHANNEL chan, \ - IN ULONG_PTR _port, \ + IN ULONGIO_PTR _port, \ IN ULONG offs, \ IN _type data \ ) \ @@ -309,7 +309,7 @@ _type \ DDKFASTAPI \ AtapiReadPort##sz( \ IN PHW_CHANNEL chan, \ - IN ULONG_PTR _port \ + IN ULONGIO_PTR _port \ ) \ { \ PIORES res; \ @@ -343,7 +343,7 @@ _type \ DDKFASTAPI \ AtapiReadPortEx##sz( \ IN PHW_CHANNEL chan, \ - IN ULONG_PTR _port, \ + IN ULONGIO_PTR _port, \ IN ULONG offs \ ) \ { \ @@ -377,7 +377,7 @@ VOID \ DDKFASTAPI \ AtapiReadBuffer##sz( \ IN PHW_CHANNEL chan, \ - IN ULONG_PTR _port, \ + IN ULONGIO_PTR _port, \ IN PVOID Buffer, \ IN ULONG Count, \ IN ULONG Timing \ @@ -422,7 +422,7 @@ VOID \ DDKFASTAPI \ AtapiWriteBuffer##sz( \ IN PHW_CHANNEL chan, \ - IN ULONG_PTR _port, \ + IN ULONGIO_PTR _port, \ IN PVOID Buffer, \ IN ULONG Count, \ IN ULONG Timing \ @@ -546,11 +546,11 @@ WaitOnBaseBusy( ) { ULONG i; - UCHAR Status; - for (i=0; i<20000; i++) { + UCHAR Status = 0xff; + for (i=0; iDeviceExtension->HwFlags & UNIATA_AHCI) { + UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber); + return; + } + GetBaseStatus(chan, statusByte2); KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2)); SelectDrive(chan, DeviceNumber); @@ -757,31 +762,52 @@ AtaCommand48( { PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; UCHAR statusByte; - ULONG ldev = lChannel*2 + DeviceNumber; ULONG i; PUCHAR plba; - KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n", - deviceExtension->DevIndex, deviceExtension->Channel, ldev, command, lba, count, feature )); + KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n", + deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature )); - //if(!(deviceExtension->HwFlags & UNIATA_SATA)) { - SelectDrive(chan, DeviceNumber); + if(deviceExtension->HwFlags & UNIATA_AHCI) { + PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); - statusByte = WaitOnBusy(chan); + KdPrint3((" (ahci)\n")); - /* ready to issue command ? */ - if (statusByte & IDE_STATUS_BUSY) { - KdPrint2((PRINT_PREFIX " Returning BUSY status\n")); - return statusByte; + RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); + + if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, + &(AHCI_CMD->cfis[0]), + command, + lba, + count, + feature, + ATA_IMMEDIATE + )) { + return 0xff; } - //} + if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) { + KdPrint2((" timeout\n")); + return 0xff; + } + return IDE_STATUS_IDLE; + } + + SelectDrive(chan, DeviceNumber); + + statusByte = WaitOnBusy(chan); + + /* ready to issue command ? */ + if (statusByte & IDE_STATUS_BUSY) { + KdPrint2((PRINT_PREFIX " Returning BUSY status\n")); + return statusByte; + } // !!! We should not check ERROR condition here // ERROR bit may be asserted durring previous operation // and not cleared after SELECT //>>>>>> NV: 2006/08/03 if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) && - CheckIfBadBlock(&(deviceExtension->lun[ldev]), lba, count)) { + CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) { KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count)); return IDE_STATUS_ERROR; //return SRB_STATUS_ERROR; @@ -789,10 +815,10 @@ AtaCommand48( //<<<<<< NV: 2006/08/03 /* only use 48bit addressing if needed because of the overhead */ - if ((lba >= ATA_MAX_LBA28 || count > 256) && - deviceExtension->lun[ldev].IdentifyData.FeaturesSupport.Address48) { + if (UniAta_need_lba48(command, lba, count, + chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) { - KdPrint2((PRINT_PREFIX " ldev %#x USE_LBA_48\n", ldev )); + KdPrint2((PRINT_PREFIX " dev %#x USE_LBA_48\n", DeviceNumber )); /* translate command into 48bit version */ if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { command = AtaCommands48[command]; @@ -815,7 +841,7 @@ AtaCommand48( AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5])); AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2])); - //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev )); + //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber )); AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) ); } else { @@ -823,18 +849,18 @@ AtaCommand48( chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48; //if(feature || - // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) { + // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) { AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature); //} AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count); AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)plba[0]); AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)plba[1]); AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]); - if(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_LBA_ENABLED) { - //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev )); + if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) { + //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber )); AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) ); } else { - //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev )); + //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber )); AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) ); } } @@ -936,10 +962,35 @@ AtaCommand( IN ULONG flags ) { - return AtaCommand48(deviceExtension, DeviceNumber, lChannel, - command, - (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24), - count, feature, flags); + if(!(deviceExtension->HwFlags & UNIATA_AHCI)) { + return AtaCommand48(deviceExtension, DeviceNumber, lChannel, + command, + (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24), + count, feature, flags); + } else { + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); + + KdPrint3(("AtaCommand(ahci)\n")); + + RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); + + if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, + &(AHCI_CMD->cfis[0]), + command, + (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24), + count, + feature, + ATA_IMMEDIATE + )) { + return 0xff; + } + if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) { + KdPrint2((" timeout\n")); + return 0xff; + } + return IDE_STATUS_IDLE; + } } // end AtaCommand() LONG @@ -1226,9 +1277,16 @@ IssueIdentify( UCHAR signatureLow, signatureHigh; BOOLEAN atapiDev = FALSE; - ULONG ldev = (lChannel * 2) + DeviceNumber; - PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]); + PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber]; + if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) { + if(chan->PmLunMap & (1 << DeviceNumber)) { + // OK + } else { + KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n")); + return FALSE; + } + } else if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) { KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n")); return FALSE; @@ -1238,13 +1296,17 @@ IssueIdentify( return FALSE; } - SelectDrive(chan, DeviceNumber); - AtapiStallExecution(10); - statusByte = WaitOnBusyLong(chan); - // Check that the status register makes sense. - GetBaseStatus(chan, statusByte2); + if(deviceExtension->HwFlags & UNIATA_AHCI) { + statusByte = WaitOnBusyLong(chan); + } else { + SelectDrive(chan, DeviceNumber); + AtapiStallExecution(10); + statusByte = WaitOnBusyLong(chan); + // Check that the status register makes sense. + GetBaseStatus(chan, statusByte2); - UniataDumpATARegs(chan); + UniataDumpATARegs(chan); + } if (Command == IDE_COMMAND_IDENTIFY) { // Mask status byte ERROR bits. @@ -1268,7 +1330,7 @@ IssueIdentify( if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) { // Device is Atapi. - KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (ldev %d)\n", ldev)); + KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber)); return FALSE; } @@ -1294,7 +1356,7 @@ IssueIdentify( if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) { - KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev)); + KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber)); // Device is Atapi. return FALSE; } @@ -1302,7 +1364,7 @@ IssueIdentify( statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX; if (statusByte != IDE_STATUS_IDLE) { // Give up on this. - KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (ldev %d)\n", ldev)); + KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber)); return FALSE; } } @@ -1318,7 +1380,7 @@ IssueIdentify( // if(deviceExtension->HwFlags & UNIATA_SATA) { if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { - j = 4; + j = 4; // skip old-style checks } else { j = 0; } @@ -1338,7 +1400,7 @@ IssueIdentify( if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) { - KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev)); + KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber)); // Device is Atapi. return FALSE; } @@ -1354,7 +1416,7 @@ IssueIdentify( if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) { // Device is Atapi. - KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev)); + KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber)); return FALSE; } } else { @@ -1468,7 +1530,7 @@ IssueIdentify( if (deviceExtension->FullIdentifyData.RemovableStatus & 1) { // Determine if this drive supports the MSN functions. KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n", - ldev, + DeviceNumber, deviceExtension->FullIdentifyData.RemovableStatus)); LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE; } @@ -1818,12 +1880,16 @@ SetDriveParameters( ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - PIDENTIFY_DATA2 identifyData = &deviceExtension->lun[(lChannel * 2) + DeviceNumber].IdentifyData; + PIDENTIFY_DATA2 identifyData; + PHW_LU_EXTENSION LunExt; // ULONG i; UCHAR statusByte; UCHAR errorByte; - if(deviceExtension->lun[(lChannel * 2) + DeviceNumber].DeviceFlags & + LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber]; + identifyData = &(LunExt->IdentifyData); + + if(LunExt->DeviceFlags & (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY)) return TRUE; @@ -1899,7 +1965,7 @@ AtapiResetController__( ULONG numberChannels = deviceExtension->NumberChannels; PHW_CHANNEL chan = NULL; ULONG i,j; - ULONG max_ldev; + ULONG MaxLuns; UCHAR statusByte; PSCSI_REQUEST_BLOCK CurSrb; ULONG ChannelCtrlFlags; @@ -1933,7 +1999,8 @@ AtapiResetController__( KdPrint2((PRINT_PREFIX "AtapiResetController: Reset channel %d\n", j)); chan = &deviceExtension->chan[j]; KdPrint2((PRINT_PREFIX " CompleteType %#x\n", CompleteType)); - max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2; + //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2; + MaxLuns = chan->NumberLuns; if(CompleteType != RESET_COMPLETE_NONE) { #ifndef UNIATA_CORE while((CurSrb = UniataGetCurRequest(chan))) { @@ -2016,130 +2083,141 @@ AtapiResetController__( CHECK_INTR_IDLE); // Reset controller - KdPrint2((PRINT_PREFIX " disable intr (0)\n")); - AtapiDisableInterrupts(deviceExtension, j); - KdPrint2((PRINT_PREFIX " done\n")); - switch(VendorID) { - case ATA_INTEL_ID: { - ULONG mask; - ULONG timeout; - if(!(ChipFlags & UNIATA_SATA)) - goto default_reset; - if(!UniataIsSATARangeAvailable(deviceExtension, j)) { - goto default_reset; - } + if(ChipFlags & UNIATA_AHCI) { + KdPrint2((PRINT_PREFIX " AHCI path\n")); + UniataAhciReset(HwDeviceExtension, j); + } else { + KdPrint2((PRINT_PREFIX " ATA path\n")); + KdPrint2((PRINT_PREFIX " disable intr (0)\n")); + AtapiDisableInterrupts(deviceExtension, j); + KdPrint2((PRINT_PREFIX " done\n")); + switch(VendorID) { + case ATA_INTEL_ID: { + ULONG mask; + ULONG timeout; + if(!(ChipFlags & UNIATA_SATA)) + goto default_reset; + if(!UniataIsSATARangeAvailable(deviceExtension, j)) { + goto default_reset; + } #if 0 - /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */ - if(ChipFlags & UNIATA_AHCI) { - mask = 0x0005 << j; - } else { - /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */ - GetPciConfig1(0x90, tmp8); - if(tmp8 & 0x04) { - mask = 0x0003; + /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */ + if(ChipFlags & UNIATA_AHCI) { + mask = 0x0005 << j; } else { - mask = 0x0001 << j; + /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */ + GetPciConfig1(0x90, tmp8); + if(tmp8 & 0x04) { + mask = 0x0003; + } else { + mask = 0x0001 << j; + } } - } #else - mask = 1 << chan->lun[0]->SATA_lun_map; - if (max_ldev > 1) { - mask |= (1 << chan->lun[1]->SATA_lun_map); - } + mask = 1 << chan->lun[0]->SATA_lun_map; + if (MaxLuns > 1) { + mask |= (1 << chan->lun[1]->SATA_lun_map); + } #endif - ChangePciConfig2(0x92, a & ~mask); - AtapiStallExecution(10); - ChangePciConfig2(0x92, a | mask); - timeout = 100; + ChangePciConfig2(0x92, a & ~mask); + AtapiStallExecution(10); + ChangePciConfig2(0x92, a | mask); + timeout = 100; - /* Wait up to 1 sec for "connect well". */ - if (ChipFlags & (I6CH | I6CH2)) - mask = mask << 8; - else - mask = mask << 4; + /* Wait up to 1 sec for "connect well". */ + if (ChipFlags & (I6CH | I6CH2)) + mask = mask << 8; + else + mask = mask << 4; - while (timeout--) { - AtapiStallExecution(10000); - GetPciConfig2(0x92, tmp16); - if ((tmp16 & mask) == mask) { + while (timeout--) { AtapiStallExecution(10000); - break; + GetPciConfig2(0x92, tmp16); + if ((tmp16 & mask) == mask) { + AtapiStallExecution(10000); + break; + } + } + break; } + case ATA_SIS_ID: + case ATA_NVIDIA_ID: { + KdPrint2((PRINT_PREFIX " SIS/nVidia\n")); + if(!(ChipFlags & UNIATA_SATA)) + goto default_reset; + break; } + case ATA_SILICON_IMAGE_ID: { + ULONG offset; + ULONG Channel = deviceExtension->Channel + j; + if(!(ChipFlags & UNIATA_SATA)) + goto default_reset; + offset = ((Channel & 1) << 7) + ((Channel & 2) << 8); + /* disable PHY state change interrupt */ + AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0); + + UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0); + + /* reset controller part for this channel */ + AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48, + AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel)); + AtapiStallExecution(1000); + AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48, + AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel)); + + + break; } + case ATA_PROMISE_ID: { + break; } + default: + if(ChipFlags & UNIATA_SATA) { + KdPrint2((PRINT_PREFIX " SATA generic reset\n")); + UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0); + } +default_reset: + KdPrint2((PRINT_PREFIX " send reset\n")); + AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS | + IDE_DC_RESET_CONTROLLER ); + KdPrint2((PRINT_PREFIX " wait a little\n")); + AtapiStallExecution(10000); + // Disable interrupts + KdPrint2((PRINT_PREFIX " disable intr\n")); + AtapiDisableInterrupts(deviceExtension, j); + AtapiStallExecution(100); + KdPrint2((PRINT_PREFIX " re-enable intr\n")); + AtapiEnableInterrupts(deviceExtension, j); + KdPrint2((PRINT_PREFIX " wait a little (2)\n")); + AtapiStallExecution(100000); + KdPrint2((PRINT_PREFIX " done\n")); + + break; + } // end switch() + + //if(!(ChipFlags & UNIATA_SATA)) {} + if(!UniataIsSATARangeAvailable(deviceExtension, j)) { + // Reset DMA engine if active + KdPrint2((PRINT_PREFIX " check DMA engine\n")); + dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel); + KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status)); + if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) || + (dma_status & BM_STATUS_INTR)) { + AtapiDmaDone(HwDeviceExtension, 0, j, NULL); } } - break; } - case ATA_SIS_ID: - case ATA_NVIDIA_ID: { - KdPrint2((PRINT_PREFIX " SIS/nVidia\n")); - if(!(ChipFlags & UNIATA_SATA)) - goto default_reset; - break; } - case ATA_SILICON_IMAGE_ID: { - ULONG offset; - ULONG Channel = deviceExtension->Channel + j; - if(!(ChipFlags & UNIATA_SATA)) - goto default_reset; - offset = ((Channel & 1) << 7) + ((Channel & 2) << 8); - /* disable PHY state change interrupt */ - AtapiWritePortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0, 0x148 + offset, 0); - - UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT); - - /* reset controller part for this channel */ - AtapiWritePortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0, 0x48, - AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0, 0x48) | (0xc0 >> Channel)); - AtapiStallExecution(1000); - AtapiWritePortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0, 0x48, - AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0, 0x48) & ~(0xc0 >> Channel)); - - - break; } - case ATA_PROMISE_ID: { - break; } - default: - if(ChipFlags & UNIATA_SATA) { - KdPrint2((PRINT_PREFIX " SATA generic reset\n")); - UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0); - } -default_reset: - KdPrint2((PRINT_PREFIX " send reset\n")); - AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS | - IDE_DC_RESET_CONTROLLER ); - KdPrint2((PRINT_PREFIX " wait a little\n")); - AtapiStallExecution(10000); - // Disable interrupts - KdPrint2((PRINT_PREFIX " disable intr\n")); - AtapiDisableInterrupts(deviceExtension, j); - AtapiStallExecution(100); - KdPrint2((PRINT_PREFIX " re-enable intr\n")); - AtapiEnableInterrupts(deviceExtension, j); - KdPrint2((PRINT_PREFIX " wait a little (2)\n")); - AtapiStallExecution(100000); - KdPrint2((PRINT_PREFIX " done\n")); - - break; - } // end switch() - - //if(!(ChipFlags & UNIATA_SATA)) { - if(!UniataIsSATARangeAvailable(deviceExtension, j)) { - // Reset DMA engine if active - KdPrint2((PRINT_PREFIX " check DMA engine\n")); - dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel); - KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status)); - if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) || - (dma_status & BM_STATUS_INTR)) { - AtapiDmaDone(HwDeviceExtension, 0, j, NULL); - } - } + } // ATA vs AHCI // all these shall be performed inside AtapiHwInitialize__() ? #if 1 KdPrint2((PRINT_PREFIX " process connected devices\n")); // Do special processing for ATAPI and IDE disk devices. - for (i = 0; i < max_ldev; i++) { + for (i = 0; i < MaxLuns; i++) { // Check if device present. - if (!(deviceExtension->lun[i + (j * 2)].DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + if(ChipFlags & UNIATA_AHCI) { + // everything is done in UniataAhciReset() + KdPrint2((PRINT_PREFIX " device have gone\n")); + continue; + } #ifdef NAVO_TEST continue; #else //NAVO_TEST @@ -2151,9 +2229,23 @@ default_reset: continue; } } else { + if(ChipFlags & UNIATA_AHCI) { + // everything is done in UniataAhciReset() + KdPrint2((PRINT_PREFIX " found some device\n")); + + if(!IssueIdentify(HwDeviceExtension, + i, j, + (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? + IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY, + FALSE)) { + KdPrint2((PRINT_PREFIX " identify failed !\n")); + UniataForgetDevice(chan->lun[i]); + } + continue; + } if(!UniataAnybodyHome(HwDeviceExtension, j, i)) { KdPrint2((PRINT_PREFIX " device have gone\n")); - UniataForgetDevice(&(deviceExtension->lun[i + (j * 2)])); + UniataForgetDevice(chan->lun[i]); } #endif //NAVO_TEST } @@ -2166,10 +2258,10 @@ default_reset: KdPrint2((PRINT_PREFIX "no drive, status %#x\n", statusByte)); - UniataForgetDevice(&(deviceExtension->lun[i + (j * 2)])); + UniataForgetDevice(chan->lun[i]); } else // Check for ATAPI disk. - if (deviceExtension->lun[i + (j * 2)].DeviceFlags & DFLAGS_ATAPI_DEVICE) { + if (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) { // Issue soft reset and issue identify. GetStatus(chan, statusByte); KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n", @@ -2216,7 +2308,7 @@ default_reset: GetBaseStatus(chan, statusByte); } // force DMA mode reinit - deviceExtension->lun[i + (j * 2)].DeviceFlags |= DFLAGS_REINIT_DMA; + chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA; } #endif //0 @@ -2229,7 +2321,7 @@ default_reset: // Call the HwInitialize routine to setup multi-block. AtapiHwInitialize__(deviceExtension, j); - } + } // for(channel) ScsiPortNotification(NextRequest, deviceExtension, NULL); return TRUE; @@ -2264,7 +2356,8 @@ MapError( UCHAR errorByte; UCHAR srbStatus = SRB_STATUS_SUCCESS; UCHAR scsiStatus; - ULONG ldev = GET_LDEV(Srb); + ULONG DeviceNumber = GET_CDEV(Srb); + PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber]; // Read the error register. @@ -2273,7 +2366,7 @@ MapError( "MapError: Error register is %#x\n", errorByte)); - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) { + if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { switch (errorByte >> 4) { case SCSI_SENSE_NO_SENSE: @@ -2411,7 +2504,7 @@ MapError( srbStatus |= SRB_STATUS_AUTOSENSE_VALID; } - deviceExtension->lun[ldev].ErrorCount++; + LunExt->ErrorCount++; } else if (errorByte & IDE_ERROR_END_OF_MEDIA) { @@ -2435,8 +2528,8 @@ MapError( srbStatus |= SRB_STATUS_AUTOSENSE_VALID; } - if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){ - deviceExtension->lun[ldev].ErrorCount++; + if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){ + LunExt->ErrorCount++; } } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) { @@ -2501,7 +2594,7 @@ MapError( srbStatus |= SRB_STATUS_AUTOSENSE_VALID; } - deviceExtension->lun[ldev].ErrorCount++; + LunExt->ErrorCount++; } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) { @@ -2531,8 +2624,8 @@ MapError( scsiStatus = SCSISTAT_CHECK_CONDITION; srbStatus = SRB_STATUS_ERROR; - if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){ - deviceExtension->lun[ldev].ErrorCount++; + if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){ + LunExt->ErrorCount++; } // Build sense buffer @@ -2551,14 +2644,14 @@ MapError( } } - if (deviceExtension->lun[ldev].ErrorCount >= MAX_ERRORS) { + if (LunExt->ErrorCount >= MAX_ERRORS) { // deviceExtension->DWordIO = FALSE; KdPrint2((PRINT_PREFIX "MapError: ErrorCount >= MAX_ERRORS\n")); - deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED; - deviceExtension->lun[ldev].MaximumBlockXfer = 0; + LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED; + LunExt->MaximumBlockXfer = 0; BrutePoint(); KdPrint2((PRINT_PREFIX @@ -2586,10 +2679,10 @@ MapError( // Reprogram to not use Multi-sector. UCHAR statusByte; - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT && - !(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE)) { + if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT && + !(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) { - statusByte = AtaCommand(deviceExtension, ldev & 0x1, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY); + statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY); // Check for errors. Reset the value to 0 (disable MultiBlock) if the // command was aborted. @@ -2603,7 +2696,7 @@ MapError( errorByte)); // Adjust the devExt. value, if necessary. - deviceExtension->lun[ldev].MaximumBlockXfer = 0; + LunExt->MaximumBlockXfer = 0; BrutePoint(); } @@ -2679,11 +2772,11 @@ AtapiHwInitialize__( AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel); FindDevices(deviceExtension, 0, lChannel); - for (i = lChannel*2; i < (lChannel+1)*2; i++) { + for (i = 0; i < chan->NumberLuns; i++) { KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i)); - LunExt = &(deviceExtension->lun[i]); + LunExt = chan->lun[i]; // skip empty slots if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { continue; @@ -2696,10 +2789,10 @@ AtapiHwInitialize__( KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n")); // Enable media status notification - IdeMediaStatus(TRUE,deviceExtension,(UCHAR)i); + IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i); // If supported, setup Multi-block transfers. - statusByte = AtaCommand(deviceExtension, i & 1, lChannel, + statusByte = AtaCommand(deviceExtension, i, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY); @@ -2714,7 +2807,7 @@ AtapiHwInitialize__( statusByte, errorByte)); - statusByte = AtaCommand(deviceExtension, i & 1, lChannel, + statusByte = AtaCommand(deviceExtension, i, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY); @@ -2741,7 +2834,7 @@ AtapiHwInitialize__( if(LunExt->opt_ReadCacheEnable) { KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n")); // If supported, setup read/write cacheing - statusByte = AtaCommand(deviceExtension, i & 1, lChannel, + statusByte = AtaCommand(deviceExtension, i, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY); @@ -2756,7 +2849,7 @@ AtapiHwInitialize__( } } else { KdPrint2((PRINT_PREFIX " Disable Read Cache\n")); - statusByte = AtaCommand(deviceExtension, i & 1, lChannel, + statusByte = AtaCommand(deviceExtension, i, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY); LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED; @@ -2764,7 +2857,7 @@ AtapiHwInitialize__( if(LunExt->opt_WriteCacheEnable) { KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n")); // If supported & allowed, setup write cacheing - statusByte = AtaCommand(deviceExtension, i & 1, lChannel, + statusByte = AtaCommand(deviceExtension, i, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY); // Check for errors. @@ -2778,7 +2871,7 @@ AtapiHwInitialize__( } } else { KdPrint2((PRINT_PREFIX " Disable Write Cache\n")); - statusByte = AtaCommand(deviceExtension, i & 1, lChannel, + statusByte = AtaCommand(deviceExtension, i, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY); LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; @@ -2831,7 +2924,7 @@ AtapiHwInitialize__( LunExt->TransferMode = (CHAR)PreferedMode; - AtapiDmaInit__(deviceExtension, i); + AtapiDmaInit__(deviceExtension, LunExt); LunExt->OrigTransferMode = LunExt->LimitedTransferMode = @@ -2893,12 +2986,15 @@ AtapiHwInitializeChanger( IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - ULONG ldev = GET_LDEV(Srb); + ULONG lChannel = GET_CHANNEL(Srb); + PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); + ULONG DeviceNumber = GET_CDEV(Srb); + PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber]; if (MechanismStatus) { - deviceExtension->lun[ldev].DiscsPresent = MechanismStatus->NumberAvailableSlots; - if (deviceExtension->lun[ldev].DiscsPresent > 1) { - deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_ATAPI_CHANGER; + LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots; + if (LunExt->DiscsPresent > 1) { + LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER; } } return; @@ -2941,7 +3037,7 @@ AtapiParseArgumentString( return 0; } - // Calculate the string length. + // Calculate the string length and lower case all characters. cptr = String; while (*cptr++) { stringLength++; @@ -3202,9 +3298,10 @@ ReturnCallback: chan = &(deviceExtension->chan[c]); - if((ULONG)InterlockedCompareExchange(&chan->CheckIntr, - CHECK_INTR_ACTIVE, - CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED) { + if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr), + CRNT_ILK_TYPE CHECK_INTR_ACTIVE, + CRNT_ILK_TYPE CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED) + { //ASSERT(!deviceExtension->simplexOnly); chan->DpcState = DPC_STATE_ISR; if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) { @@ -3256,20 +3353,27 @@ AtapiInterrupt( ULONG i_res = 0; ULONG pass; BOOLEAN checked[AHCI_MAX_PORT]; + ULONG hIS; KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID)); + if(deviceExtension->HwFlags & UNIATA_AHCI) { + hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS); + KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel)); + if(!hIS) { + return FALSE; + } + } + for(_c=0; _cNumberChannels; _c++) { checked[_c] = FALSE; } + // fc = -// atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; for(pass=0; pass<2; pass++) { for(_c=0; _cNumberChannels; _c++) { c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels; - //non_empty_chan = (deviceExtension->lun[c*2].DeviceFlags | deviceExtension->lun[c*2+1].DeviceFlags) - // & DFLAGS_DEVICE_PRESENT; if(checked[c]) continue; @@ -3293,17 +3397,19 @@ AtapiInterrupt( // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) { // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE; // } - c_state = (ULONG)InterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr), - CHECK_INTR_ACTIVE, - CHECK_INTR_DETECTED); + c_state = + (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), + CRNT_ILK_TYPE CHECK_INTR_ACTIVE, + CRNT_ILK_TYPE CHECK_INTR_DETECTED); if(c_state == CHECK_INTR_IDLE) { // c_state = deviceExtension->chan[c].CheckIntr; // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) { // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE // } - c_state = (ULONG)InterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr), - CHECK_INTR_ACTIVE, - CHECK_INTR_IDLE); + c_state = + (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), + CRNT_ILK_TYPE CHECK_INTR_ACTIVE, + CRNT_ILK_TYPE CHECK_INTR_IDLE); } } while(c_state == CHECK_INTR_CHECK); KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n")); @@ -3316,7 +3422,7 @@ AtapiInterrupt( if((c_state == CHECK_INTR_DETECTED) || (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) { - if(i_res == 2) { + if(i_res == INTERRUPT_REASON_UNEXPECTED) { KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n")); InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); return TRUE; @@ -3377,6 +3483,7 @@ AtapiInterrupt2( BOOLEAN status = FALSE; ULONG c_count = 0; ULONG i_res; + ULONG hIS; // we should never get here for ISA/MCA if(!BMList[deviceExtension->DevIndex].Isr2Enable) { @@ -3384,6 +3491,14 @@ AtapiInterrupt2( return FALSE; } + if(deviceExtension->HwFlags & UNIATA_AHCI) { + hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS); + KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel)); + if(!hIS) { + return FALSE; + } + } + for(c=0; cNumberChannels; c++) { KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c)); @@ -3392,9 +3507,10 @@ AtapiInterrupt2( continue; } - if((ULONG)CrNtInterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr), - CHECK_INTR_CHECK, - CHECK_INTR_IDLE) != CHECK_INTR_IDLE) { + if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), + CRNT_ILK_TYPE CHECK_INTR_CHECK, + CRNT_ILK_TYPE CHECK_INTR_IDLE) != CHECK_INTR_IDLE) + { KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n")); // hunt on unexpected intr (Some devices generate double interrupts, // some controllers (at least CMD649) interrupt twice with small delay. @@ -3407,7 +3523,7 @@ AtapiInterrupt2( if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) { KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n")); - if(i_res == 2) { + if(i_res == INTERRUPT_REASON_UNEXPECTED) { KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n")); InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE); return TRUE; @@ -3430,7 +3546,7 @@ AtapiInterrupt2( } KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status)); return status; - + } // end AtapiInterrupt2() RETTYPE_XXableInterrupts @@ -3447,9 +3563,10 @@ AtapiInterruptDpc( if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) { - if((ULONG)InterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr), - CHECK_INTR_ACTIVE, - CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) { + if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr), + CRNT_ILK_TYPE CHECK_INTR_ACTIVE, + CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) + { continue; } @@ -3501,9 +3618,9 @@ AtapiEnableInterrupts__( } else { // check if other channel(s) interrupted // must do nothing in simplex mode - if((ULONG)CrNtInterlockedCompareExchange(&(chan->CheckIntr), - CHECK_INTR_ACTIVE, - CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) { + if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr), + CRNT_ILK_TYPE CHECK_INTR_ACTIVE, + CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) { continue; } //ASSERT(!deviceExtension->simplexOnly); @@ -3542,16 +3659,23 @@ AtapiEnableInterrupts( ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, deviceExtension->chan[c].DisableIntr)); + PHW_CHANNEL chan; if(c >= deviceExtension->NumberChannels) { + KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c)); return; } - if(!InterlockedDecrement(&deviceExtension->chan[c].DisableIntr)) { - AtapiWritePort1(&deviceExtension->chan[c], IDX_IO2_o_Control, - IDE_DC_A_4BIT ); - deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED; + chan = &(deviceExtension->chan[c]); + KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr)); + if(!InterlockedDecrement(&chan->DisableIntr)) { + if(deviceExtension->HwFlags & UNIATA_AHCI) { + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); + } else { + AtapiWritePort1(chan, IDX_IO2_o_Control, + IDE_DC_A_4BIT ); + } + chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED; } else { - AtapiWritePort1(&deviceExtension->chan[c], IDX_IO2_o_Control, + AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ ); } return; @@ -3565,15 +3689,28 @@ AtapiDisableInterrupts( ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, deviceExtension->chan[c].DisableIntr)); - // mark channel as busy + PHW_CHANNEL chan; if(c >= deviceExtension->NumberChannels) { + KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c)); return; } - if(InterlockedIncrement(&deviceExtension->chan[c].DisableIntr)) { - AtapiWritePort1(&deviceExtension->chan[c], IDX_IO2_o_Control, - IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ ); - deviceExtension->chan[c].ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED; + chan = &(deviceExtension->chan[c]); + KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr)); + // mark channel as busy + if(InterlockedIncrement(&chan->DisableIntr)) { + if(deviceExtension->HwFlags & UNIATA_AHCI) { + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, + (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | + ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | + ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) | + ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | + ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR) + ); + } else { + AtapiWritePort1(chan, IDX_IO2_o_Control, + IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ ); + } + chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED; } return; @@ -3619,6 +3756,12 @@ AtapiCheckInterrupt__( lChannel = c; Channel = (UCHAR)(deviceExtension->Channel + lChannel); + if((ChipFlags & UNIATA_AHCI) && + UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, -1); + return OurInterrupt; + } + if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) { DmaTransfer = TRUE; KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex, @@ -3636,12 +3779,6 @@ AtapiCheckInterrupt__( goto check_unknown; } - if((ChipFlags & UNIATA_AHCI) && - UniataIsSATARangeAvailable(deviceExtension, lChannel)) { - OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, -1); - return OurInterrupt; - } - // Attention ! // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed // Such behavior was observed with Intel ICH-xxx chips @@ -3653,13 +3790,13 @@ AtapiCheckInterrupt__( switch(ChipType) { case PROLD: case PRNEW: - status = AtapiReadPortEx4(chan, (ULONG_PTR)&deviceExtension->BaseIoAddressBM_0,0x1c); + status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c); if (!DmaTransfer) break; if (!(status & ((Channel) ? 0x00004000 : 0x00000400))) { KdPrint2((PRINT_PREFIX " Promise old/new unexpected\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } break; case PRTX: @@ -3669,23 +3806,23 @@ AtapiCheckInterrupt__( break; if(!(status & 0x20)) { KdPrint2((PRINT_PREFIX " Promise tx unexpected\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } break; case PRMIO: - status = AtapiReadPortEx4(chan, (ULONG_PTR)&deviceExtension->BaseIoAddressBM_0,0x0040); + status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x0040); if(ChipFlags & PRSATA) { - pr_status = AtapiReadPortEx4(chan, (ULONG_PTR)&deviceExtension->BaseIoAddressBM_0,0x006c); - AtapiWritePortEx4(chan, (ULONG_PTR)&deviceExtension->BaseIoAddressBM_0,0x006c, pr_status & 0x000000ff); + pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c); + AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c, pr_status & 0x000000ff); } if(pr_status & (0x11 << Channel)) { // TODO: reset channel KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } if(!(status & (0x01 << Channel))) { KdPrint2((PRINT_PREFIX " Promise mio unexpected\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001); break; @@ -3702,11 +3839,11 @@ AtapiCheckInterrupt__( /* get and clear interrupt status */ if(ChipFlags & NVQ) { - pr_status = AtapiReadPortEx4(chan, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0,offs); - AtapiWritePortEx4(chan, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0,offs, (0x0fUL << shift) | 0x00f000f0); + pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs); + AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0); } else { - pr_status = AtapiReadPortEx1(chan,(ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0,offs); - AtapiWritePortEx1(chan, (ULONG_PTR)&deviceExtension->BaseIoAddressSATA_0,offs, (0x0f << shift)); + pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs); + AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift)); } KdPrint2((PRINT_PREFIX " pr_status %x\n", pr_status)); @@ -3724,9 +3861,9 @@ AtapiCheckInterrupt__( if(!(pr_status & (0x01UL << shift))) { KdPrint2((PRINT_PREFIX " nVidia unexpected\n")); if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } else { - return FALSE; + return INTERRUPT_REASON_IGNORE; } } @@ -3746,11 +3883,11 @@ AtapiCheckInterrupt__( KdPrint2((PRINT_PREFIX " Sii DS0 %x\n", reg32)); if(reg32 == 0xffffffff) { KdPrint2((PRINT_PREFIX " Sii mio unexpected\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } if(!(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_DMA_COMPLETE | BM_DS0_SII_IRQ | BM_DS0_SII_DMA_ENABLE | BM_DS0_SII_DMA_ERROR))) { KdPrint2((PRINT_PREFIX " Sii mio unexpected (2)\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } if(ChipFlags & UNIATA_SATA) { @@ -3761,7 +3898,7 @@ AtapiCheckInterrupt__( * SError bits are pending. Clear SError immediately. */ if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } } } @@ -3782,11 +3919,11 @@ AtapiCheckInterrupt__( KdPrint2((PRINT_PREFIX " 0x71 = %#x\n", reg8)); if (!(reg8 & (Channel ? 0x08 : 0x04))) { - return FALSE; + return INTERRUPT_REASON_IGNORE; } if (!DmaTransfer) { KdPrint2((PRINT_PREFIX " cmd our\n")); - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } SetPciConfig1(0x71, (Channel ? 0x08 : 0x04)); } @@ -3798,7 +3935,7 @@ AtapiCheckInterrupt__( //dma_status = GetDmaStatus(deviceExtension, lChannel); if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) { KdPrint2((PRINT_PREFIX " Acard unexpected\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR); AtapiStallExecution(1); @@ -3812,11 +3949,11 @@ AtapiCheckInterrupt__( } else if(ChipFlags & UNIATA_SATA) { if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) { if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) { - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } } } @@ -3829,7 +3966,7 @@ AtapiCheckInterrupt__( } else if(ChipFlags & UNIATA_SATA) { if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) { - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } } } @@ -3841,16 +3978,16 @@ check_unknown: KdPrint2((PRINT_PREFIX " DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status)); if(dma_status & BM_STATUS_ERR) { KdPrint2((PRINT_PREFIX " DmaTransfer + BM_STATUS_ERR -> our\n")); - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } else { KdPrint2((PRINT_PREFIX " getting status...\n")); GetStatus(chan, statusByte); KdPrint2((PRINT_PREFIX " status %#x\n", statusByte)); if(statusByte & IDE_STATUS_ERROR) { KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte)); - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } else { - return FALSE; + return INTERRUPT_REASON_IGNORE; } } } @@ -3860,7 +3997,7 @@ check_unknown: KdPrint2((PRINT_PREFIX " clear unexpected DMA intr\n")); AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL); // catch it ! - OurInterrupt = 2; + OurInterrupt = INTERRUPT_REASON_UNEXPECTED; } } skip_dma_stat_check: @@ -3868,7 +4005,7 @@ skip_dma_stat_check: AtapiStallExecution(1); } - LunExt = &(deviceExtension->lun[c*2 + chan->cur_cdev]); + LunExt = chan->lun[chan->cur_cdev]; /* if drive is busy it didn't interrupt */ /* the exception is DCS + BSY state of ATAPI devices */ KdPrint2((PRINT_PREFIX " getting status...\n")); @@ -3891,15 +4028,15 @@ skip_dma_stat_check: KdPrint2((PRINT_PREFIX " ATAPI additional check\n")); } else { KdPrint2((PRINT_PREFIX " expecting intr + BUSY (3), non ATAPI\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } if((statusByte & ~IDE_STATUS_DRQ) != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) { KdPrint3((PRINT_PREFIX " unexpected status, seems it is not our\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) { KdPrint3((PRINT_PREFIX " unexpected DRQ, seems it is not our\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } EarlyIntr = TRUE; @@ -3909,7 +4046,7 @@ skip_dma_stat_check: /* clear interrupt and get status */ GetBaseStatus(chan, statusByte); KdPrint3((PRINT_PREFIX " base status %#x (+BM_STATUS_INTR)\n", statusByte)); - return TRUE; + return INTERRUPT_REASON_OUR; } if(g_WaitBusyInISR) { @@ -3922,7 +4059,7 @@ skip_dma_stat_check: } if (statusByte & IDE_STATUS_BUSY) { KdPrint2((PRINT_PREFIX " still BUSY, seems it is not our\n")); - return FALSE; + return INTERRUPT_REASON_IGNORE; } } @@ -3974,7 +4111,7 @@ skip_dma_stat_check: //ASSERT(!chan->queue_depth || chan->cur_req); KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n")); - return TRUE; + return INTERRUPT_REASON_OUR; } // end AtapiCheckInterrupt__() @@ -4027,7 +4164,7 @@ AtapiInterrupt__( UCHAR TargetId; UCHAR Lun; UCHAR OldReqState = REQ_STATE_NONE; - ULONG ldev; + //ULONG ldev; PHW_LU_EXTENSION LunExt; lChannel = c; @@ -4042,9 +4179,9 @@ AtapiInterrupt__( } if (srb) { - PathId = srb->PathId; + PathId = srb->PathId; TargetId = srb->TargetId; - Lun = srb->Lun; + Lun = srb->Lun; } else { PathId = (UCHAR)c; TargetId = @@ -4052,9 +4189,9 @@ AtapiInterrupt__( goto enqueue_next_req; } - ldev = GET_LDEV2(PathId, TargetId, Lun); - DeviceNumber = (UCHAR)(ldev & 1); - LunExt = &(deviceExtension->lun[ldev]); + //ldev = GET_LDEV2(PathId, TargetId, Lun); + DeviceNumber = (UCHAR)(TargetId); + LunExt = chan->lun[DeviceNumber]; atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; KdPrint2((PRINT_PREFIX " dev_type %s\n", atapiDev ? "ATAPI" : "IDE")); @@ -4209,7 +4346,13 @@ ServiceInterrupt: } */ /* clear interrupt and get status */ - GetBaseStatus(chan, statusByte); + + if(deviceExtension->HwFlags & UNIATA_AHCI) { + UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb); + statusByte = (UCHAR)(AtaReq->ahci.in_status & 0xff); + } else { + GetBaseStatus(chan, statusByte); + } if(atapiDev) { KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte)); } else { @@ -4220,7 +4363,10 @@ ServiceInterrupt: KdPrint2((PRINT_PREFIX " operate like in DPC\n")); InDpc = TRUE; } - + + if(deviceExtension->HwFlags & UNIATA_AHCI) { + KdPrint3((PRINT_PREFIX " AHCI branch\n")); + } else if (!atapiDev) { // IDE if (statusByte & IDE_STATUS_BUSY) { @@ -4257,10 +4403,10 @@ try_dpc_wait: AtapiStallExecution(TimerValue); goto ServiceInterrupt; #endif //UNIATA_CORE - } else + } else if (InDpc && i == k) { // reset the controller. - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX " Resetting due to BUSY on entry - %#x.\n", statusByte)); goto IntrPrepareResetController; @@ -4277,7 +4423,7 @@ try_dpc_wait: AtapiStallExecution(10); } if (statusByte & IDE_STATUS_BUSY) { - //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) { + //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {} KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting\n")); for(k=20; k; k--) { GetStatus(chan, statusByte); @@ -4315,7 +4461,7 @@ try_dpc_wait: } } - if(AtaReq && DmaTransfer) { + if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) { switch(OldReqState) { case REQ_STATE_EARLY_INTR: case REQ_STATE_DPC_WAIT_BUSY0: @@ -4333,7 +4479,11 @@ try_dpc_wait: if ((statusByte & IDE_STATUS_ERROR) || (dma_status & BM_STATUS_ERR)) { - error = AtapiReadPort1(chan, IDX_IO1_i_Error); + if(deviceExtension->HwFlags & UNIATA_AHCI) { + error = (UCHAR)((AtaReq->ahci.in_status >> 8) && 0xff); + } else { + error = AtapiReadPort1(chan, IDX_IO1_i_Error); + } KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error)); /* if(error & IDE_STATUS_CORRECTED_ERROR) { @@ -4364,7 +4514,7 @@ continue_err: for (k = atapiDev ? 0 : 200; k; k--) { GetStatus(chan, statusByte); if (!(statusByte & IDE_STATUS_DRQ)) { - AtapiStallExecution(100); + AtapiStallExecution(50); } else { break; } @@ -4431,10 +4581,15 @@ continue_err: deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48; } else if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) { - KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n")); #ifdef IO_STATISTICS + KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n")); + KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n", + AtaReq->retry, + chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry], + chan->lun[DeviceNumber]->BlockIoCount + )); chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++; - if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->IoCount/3 || + if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 || (deviceExtension->HwFlags & UNIATA_NO80CHK) ) { #else @@ -4446,6 +4601,10 @@ continue_err: } } #ifdef IO_STATISTICS + if(AtaReq->bcount) { + // we need stats for Read/Write operations + chan->lun[DeviceNumber]->BlockIoCount++; + } chan->lun[DeviceNumber]->IoCount++; #endif //IO_STATISTICS @@ -4547,6 +4706,10 @@ IntrPrepareResetController: } KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte)); + if(deviceExtension->HwFlags & UNIATA_AHCI) { + KdPrint2((PRINT_PREFIX " AHCI path\n")); + goto ReturnEnableIntr; + } else if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) { // Write the packet. KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n")); @@ -4556,7 +4719,7 @@ IntrPrepareResetController: if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n")); - AtapiDmaStart(HwDeviceExtension, ldev & 1, lChannel, srb); + AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb); } goto ReturnEnableIntr; @@ -4578,7 +4741,7 @@ IntrPrepareResetController: KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount)); if (wordCount != AtaReq->WordsLeft) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiInterrupt: %d words requested; %d words xferred\n", AtaReq->WordsLeft, wordCount)); @@ -4587,7 +4750,7 @@ IntrPrepareResetController: // Verify this makes sense. if (wordCount > AtaReq->WordsLeft) { wordCount = AtaReq->WordsLeft; - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiInterrupt: Write underrun\n")); DataOverrun = TRUE; } @@ -4614,7 +4777,7 @@ IntrPrepareResetController: // Ensure that this is a write command. if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiInterrupt: Write interrupt\n")); statusByte = WaitOnBusy(chan); @@ -4634,7 +4797,7 @@ IntrPrepareResetController: } } else { - KdPrint3((PRINT_PREFIX + KdPrint3((PRINT_PREFIX "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n", interruptReason, srb)); @@ -4669,7 +4832,7 @@ IntrPrepareResetController: KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R wordCount %#x\n", wordCount)); if (wordCount != AtaReq->WordsLeft) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiInterrupt: %d words requested; %d words xferred\n", AtaReq->WordsLeft, wordCount)); @@ -4709,7 +4872,7 @@ IntrPrepareResetController: statusByte = WaitOnBusy(chan); if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeIntr: Read %#x words\n", wordCount)); ReadBuffer(chan, @@ -4731,7 +4894,7 @@ IntrPrepareResetController: } } else { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeIntr: Read %#x Dwords\n", wordCount/2)); ReadBuffer2(chan, @@ -4924,7 +5087,7 @@ CompleteRequest: if (status == SRB_STATUS_DATA_OVERRUN) { // Check to see if we at least get mininum number of bytes if ((srb->DataTransferLength - AtaReq->WordsLeft) > - (offsetof (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) { + (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) { status = SRB_STATUS_SUCCESS; } } @@ -5039,7 +5202,7 @@ PIO_wait_busy: if (i == 5*30) { // reset the controller. - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to BSY still up - %#x.\n", statusByte)); goto IntrPrepareResetController; @@ -5234,7 +5397,7 @@ IntrCompleteReq: KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n")); chan->RDP = FALSE; goto CompleteRDP; - } + } AtapiStallExecution(50); } } @@ -5266,7 +5429,7 @@ reenqueue_req: NULL); } else { ScsiPortNotification(NextLuRequest, - deviceExtension, + deviceExtension, PathId, TargetId, Lun); @@ -5379,7 +5542,7 @@ IdeSendSmartCommand( if (regs->bCommandReg != SMART_CMD) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendSmartCommand: bCommandReg != SMART_CMD\n")); return SRB_STATUS_INVALID_REQUEST; } @@ -5403,7 +5566,7 @@ IdeSendSmartCommand( statusByte = WaitOnBusy(chan); if (statusByte & IDE_STATUS_BUSY) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendSmartCommand: Returning BUSY status\n")); return SRB_STATUS_BUSY; } @@ -5440,7 +5603,7 @@ IdeSendSmartCommand( statusByte = WaitOnBusy(chan); if (statusByte & IDE_STATUS_BUSY) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendSmartCommand: Returning BUSY status\n")); return SRB_STATUS_BUSY; } @@ -5486,8 +5649,6 @@ UniAtaCalculateLBARegs( USHORT cylinder; ULONG tmp; - (*max_bcount) = 0; - if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) { if(LunExt->LimitedTransferMode >= ATA_DMA) { if(LunExt->DeviceExtension) { @@ -5512,6 +5673,7 @@ UniAtaCalculateLBARegs( KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n", cylinder, drvSelect, sectorNumber, (*max_bcount))); } + (*max_bcount) = 0; return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24); } // end UniAtaCalculateLBARegs() @@ -5574,8 +5736,8 @@ IdeReadWrite( PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); PHW_LU_EXTENSION LunExt; PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); - ULONG ldev = GET_LDEV(Srb); - UCHAR DeviceNumber = (UCHAR)(ldev & 1); + //ULONG ldev = GET_LDEV(Srb); + UCHAR DeviceNumber = GET_CDEV(Srb);; ULONG startingSector; ULONG max_bcount; ULONG wordCount = 0; @@ -5583,9 +5745,10 @@ IdeReadWrite( UCHAR cmd; ULONGLONG lba; BOOLEAN use_dma = FALSE; + ULONG fis_size; AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD; - LunExt = &deviceExtension->lun[ldev]; + LunExt = chan->lun[DeviceNumber]; if((CmdAction & CMD_ACTION_PREPARE) && (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) { @@ -5650,7 +5813,35 @@ IdeReadWrite( use_dma = FALSE; } } + + if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) { + UniataAhciSetupCmdPtr(AtaReq); + KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n")); + RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); + + fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, + &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]), + (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : /*IDE_COMMAND_WRITE_DMA*/ IDE_COMMAND_READ_DMA, + lba, + (USHORT)(AtaReq->bcount), + 0, + ATA_IMMEDIATE + ); + + if(!fis_size) { + KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n")); + return SRB_STATUS_ERROR; + } + + AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) | + /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/ + (fis_size / sizeof(ULONG)) | + (DeviceNumber << 12)); + KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags)); + } + AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER; + } else { // exec_only KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n")); lba = AtaReq->lba; @@ -5660,12 +5851,13 @@ IdeReadWrite( } } if(!(CmdAction & CMD_ACTION_EXEC)) { + return SRB_STATUS_PENDING; } // if this is queued request, reinit DMA and check // if DMA mode is still available - AtapiDmaReinit(deviceExtension, ldev, AtaReq); + AtapiDmaReinit(deviceExtension, LunExt, AtaReq); if (/*EnableDma &&*/ (LunExt->TransferMode >= ATA_DMA)) { use_dma = TRUE; @@ -5708,15 +5900,20 @@ IdeReadWrite( } } + // Send IO command. + KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200), + ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE))); if(use_dma) { chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION; } else { chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; } - // Send IO command. - KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200), - ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE))); + if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) { + //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); + UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb); + return SRB_STATUS_PENDING; + } if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) || use_dma) { @@ -5777,7 +5974,7 @@ IdeReadWrite( // Write next DEV_BSIZE/2*N words. if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED)) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeReadWrite: Write %#x words\n", wordCount)); WriteBuffer(chan, @@ -5787,7 +5984,7 @@ IdeReadWrite( } else { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeReadWrite: Write %#x Dwords\n", wordCount/2)); WriteBuffer2(chan, @@ -5832,7 +6029,8 @@ IdeVerify( PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); PHW_LU_EXTENSION LunExt; - ULONG ldev = GET_LDEV(Srb); + //ULONG ldev = GET_LDEV(Srb); + ULONG DeviceNumber = GET_CDEV(Srb); UCHAR statusByte; ULONG startingSector; ULONG max_bcount; @@ -5841,7 +6039,7 @@ IdeVerify( USHORT sectorCount; ULONGLONG lba; - LunExt = &deviceExtension->lun[ldev]; + LunExt = chan->lun[DeviceNumber]; // Drive has these number sectors. if(!(sectors = (ULONG)(LunExt->NumOfSectors))) { sectors = LunExt->IdentifyData.SectorsPerTrack * @@ -5895,7 +6093,7 @@ IdeVerify( lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount); - statusByte = AtaCommand48(deviceExtension, ldev & 0x01, GET_CHANNEL(Srb), + statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb), IDE_COMMAND_VERIFY, lba, sectorCount, 0, ATA_IMMEDIATE); @@ -5934,13 +6132,18 @@ AtapiSendCommand( UCHAR lChannel = GET_CHANNEL(Srb); PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]); PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); - ULONG ldev = GET_LDEV(Srb); + PHW_LU_EXTENSION LunExt; + //ULONG ldev = GET_LDEV(Srb); + ULONG DeviceNumber = GET_CDEV(Srb); ULONG i; ULONG flags; UCHAR statusByte,byteCountLow,byteCountHigh; BOOLEAN use_dma = FALSE; BOOLEAN dma_reinited = FALSE; BOOLEAN retried = FALSE; + ULONG fis_size; + + LunExt = chan->lun[DeviceNumber]; KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction)); if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER) @@ -6024,7 +6227,7 @@ AtapiSendCommand( return SRB_STATUS_BUSY; } // - if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_CHANGER_INITED) && + if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) && !AtaReq->OriginalSrb) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n")); return SRB_STATUS_BUSY; @@ -6080,7 +6283,7 @@ GetLba: if(deviceExtension->opt_AtapiDmaReadWrite) { call_dma_setup: - if(AtapiDmaSetup(HwDeviceExtension, ldev & 1, lChannel, Srb, + if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, (PUCHAR)(AtaReq->DataBuffer), Srb->DataTransferLength /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/ @@ -6114,7 +6317,7 @@ call_dma_setup: } // try setup DMA if(use_dma) { - if(!AtapiDmaSetup(HwDeviceExtension, ldev & 1, lChannel, Srb, + if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, (PUCHAR)(AtaReq->DataBuffer), Srb->DataTransferLength)) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n")); @@ -6127,14 +6330,43 @@ call_dma_setup: KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer, no DMA setup\n")); } + + if(deviceExtension->HwFlags & UNIATA_AHCI) { + UniataAhciSetupCmdPtr(AtaReq); + KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n")); + RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis)); + RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, 16); + + fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, + &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]), + IDE_COMMAND_ATAPI_PACKET /* command */, + 0 /* lba */, + (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength), + use_dma ? ATA_F_DMA : 0/* feature */, + ATA_IMMEDIATE /* flags */ + ); + + if(!fis_size) { + KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n")); + return SRB_STATUS_ERROR; + } + + AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) | + /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/ + (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) | + (fis_size / sizeof(ULONG)) | + (DeviceNumber << 12)); + KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags)); + } + } else { if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { // if this is queued request, reinit DMA and check // if DMA mode is still available KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n")); - AtapiDmaReinit(deviceExtension, ldev, AtaReq); + AtapiDmaReinit(deviceExtension, LunExt, AtaReq); if (/*EnableDma &&*/ - (deviceExtension->lun[ldev].TransferMode >= ATA_DMA)) { + (LunExt->TransferMode >= ATA_DMA)) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n")); use_dma = TRUE; } else { @@ -6159,13 +6391,13 @@ call_dma_setup: KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n")); use_dma = FALSE; AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; - //AtapiDmaReinit(deviceExtension, ldev, AtaReq); + //AtapiDmaReinit(deviceExtension, LunExt, AtaReq); } if(AtaReq->TransferLength) { if(!dma_reinited) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n")); - AtapiDmaReinit(deviceExtension, ldev, AtaReq); + AtapiDmaReinit(deviceExtension, LunExt, AtaReq); if (/*EnableDma &&*/ - (deviceExtension->lun[ldev].TransferMode >= ATA_DMA)) { + (LunExt->TransferMode >= ATA_DMA)) { use_dma = TRUE; } else { AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; @@ -6178,14 +6410,14 @@ call_dma_setup: AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION; if(!deviceExtension->opt_AtapiDmaZeroTransfer) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n")); - AtapiDmaReinit(deviceExtension, ldev, AtaReq); + AtapiDmaReinit(deviceExtension, LunExt, AtaReq); } } KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma)); if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) { KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n")); } - + KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n")); #ifndef UNIATA_CORE @@ -6195,7 +6427,7 @@ call_dma_setup: // initialize our device extension changer data. That's how we know how // many platters our target has. - if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_CHANGER_INITED) && + if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) && !AtaReq->OriginalSrb) { ULONG srbStatus; @@ -6203,7 +6435,7 @@ call_dma_setup: KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n")); // Set this flag now. If the device hangs on the mech. status // command, we will not have the chance to set it. - deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_CHANGER_INITED; + LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED; chan->MechStatusRetryCount = 3; AtaReq->OriginalSrb = Srb; @@ -6231,9 +6463,9 @@ call_dma_setup: Srb->Cdb[0], Srb->TargetId, Srb->Lun)); // Make sure command is to ATAPI device. - flags = deviceExtension->lun[ldev].DeviceFlags; + flags = LunExt->DeviceFlags; if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) { - if((Srb->Lun) > (deviceExtension->lun[ldev].DiscsPresent - 1)) { + if((Srb->Lun) > (LunExt->DiscsPresent - 1)) { // Indicate no device found at this address. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; @@ -6249,8 +6481,19 @@ call_dma_setup: return SRB_STATUS_SELECTION_TIMEOUT; } retry: + if(deviceExtension->HwFlags & UNIATA_AHCI) { + KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n")); + if(use_dma) { + chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION; + } else { + chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; + } + UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb); + return SRB_STATUS_PENDING; + } + // Select device 0 or 1. - SelectDrive(chan, ldev & 0x1); + SelectDrive(chan, DeviceNumber); // Verify that controller is ready for next command. GetStatus(chan, statusByte); @@ -6320,13 +6563,13 @@ make_reset: AtapiDisableInterrupts(deviceExtension, lChannel); - AtapiSoftReset(chan, ldev & 1); + AtapiSoftReset(chan, DeviceNumber); KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n")); // Re-initialize Atapi device. - CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), ldev & 1, TRUE); + CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE); /* - IssueIdentify(HwDeviceExtension, ldev & 1, GET_CHANNEL(Srb), + IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb), IDE_COMMAND_ATAPI_IDENTIFY, FALSE); */ // Inform the port driver that the bus has been reset. @@ -6406,37 +6649,40 @@ make_reset: KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n")); return SRB_STATUS_PENDING; - } else { + } - // This device quickly sets DRQ when ready to receive the packet. + // This device quickly sets DRQ when ready to receive the packet. - KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n", - statusByte)); + KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n", + statusByte)); - chan->ExpectingInterrupt = TRUE; - AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR; - InterlockedExchange(&(chan->CheckIntr), - CHECK_INTR_IDLE); + chan->ExpectingInterrupt = TRUE; + AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR; + InterlockedExchange(&(chan->CheckIntr), + CHECK_INTR_IDLE); - //AtapiDisableInterrupts(deviceExtension, lChannel); + if(g_opt_AtapiSendDisableIntr) { + AtapiDisableInterrupts(deviceExtension, lChannel); + } - // Write ATAPI packet command. - AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET); + // Write ATAPI packet command. + AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET); - // Wait for DRQ. - WaitOnBusy(chan); - statusByte = WaitForDrq(chan); + // Wait for DRQ. + WaitOnBusy(chan); + statusByte = WaitForDrq(chan); - // Need to read status register and clear interrupt (if any) - GetBaseStatus(chan, statusByte); + // Need to read status register and clear interrupt (if any) + GetBaseStatus(chan, statusByte); - if (!(statusByte & IDE_STATUS_DRQ)) { + if (!(statusByte & IDE_STATUS_DRQ)) { + if(g_opt_AtapiSendDisableIntr) { AtapiEnableInterrupts(deviceExtension, lChannel); - KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte)); - AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; - return SRB_STATUS_ERROR; } + KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte)); + AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; + return SRB_STATUS_ERROR; } GetStatus(chan, statusByte); @@ -6453,7 +6699,9 @@ make_reset: GetBaseStatus(chan, statusByte); - //AtapiEnableInterrupts(deviceExtension, lChannel); + if(g_opt_AtapiSendDisableIntr) { + AtapiEnableInterrupts(deviceExtension, lChannel); + } WriteBuffer(chan, (PUSHORT)Srb->Cdb, @@ -6461,7 +6709,7 @@ make_reset: 0); if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { - AtapiDmaStart(HwDeviceExtension, ldev & 1, lChannel, Srb); + AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); } KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt)); @@ -6519,7 +6767,8 @@ IdeSendCommand( ULONG status; ULONG i; PMODE_PARAMETER_HEADER modeData; - ULONG ldev; + //ULONG ldev; + ULONG DeviceNumber; PATA_REQ AtaReq; SetCheckPoint(5); //ULONG __ebp__ = 0; @@ -6552,7 +6801,8 @@ IdeSendCommand( lChannel = GET_CHANNEL(Srb); chan = &(deviceExtension->chan[lChannel]); - ldev = GET_LDEV(Srb); + //ldev = GET_LDEV(Srb); + DeviceNumber = GET_CDEV(Srb); SetCheckPoint(0x40); if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER) @@ -6589,10 +6839,9 @@ IdeSendCommand( // which support up to two devices. if ((Srb->Lun != 0) || (Srb->PathId >= deviceExtension->NumberChannels) || - (Srb->TargetId > 2) /*|| - (!deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)*/) { + (Srb->TargetId > deviceExtension->NumberLuns)) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_INQUIRY rejected\n")); // Indicate no device found at this address. status = SRB_STATUS_SELECTION_TIMEOUT; @@ -6600,15 +6849,15 @@ IdeSendCommand( } else { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_INQUIRY ok\n")); PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); - PIDENTIFY_DATA2 identifyData = &(deviceExtension->lun[ldev].IdentifyData); + PIDENTIFY_DATA2 identifyData = &(chan->lun[DeviceNumber]->IdentifyData); - if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)) { - - if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) { - KdPrint2((PRINT_PREFIX + if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + + if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n")); // Indicate no device found at this address. #ifndef NAVO_TEST @@ -6616,11 +6865,11 @@ IdeSendCommand( break; } } else { - if(!UniataAnybodyHome(HwDeviceExtension, lChannel, ldev & 1)) { - KdPrint2((PRINT_PREFIX + if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) { + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_INQUIRY device have gone\n")); // Indicate no device found at this address. - UniataForgetDevice(&(deviceExtension->lun[ldev])); + UniataForgetDevice(chan->lun[DeviceNumber]); #endif //NAVO_TEST status = SRB_STATUS_SELECTION_TIMEOUT; break; @@ -6634,15 +6883,15 @@ IdeSendCommand( inquiryData->DeviceType = DIRECT_ACCESS_DEVICE; // Set the removable bit, if applicable. - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_REMOVABLE_DRIVE) { - KdPrint2((PRINT_PREFIX + if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) { + KdPrint2((PRINT_PREFIX "RemovableMedia\n")); inquiryData->RemovableMedia = 1; } // Set the Relative Addressing (LBA) bit, if applicable. - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_LBA_ENABLED) { + if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) { inquiryData->RelativeAddressing = 1; - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "RelativeAddressing\n")); } // Set the CommandQueue bit @@ -6677,9 +6926,9 @@ IdeSendCommand( // This is used to determine if the media is write-protected. // Since IDE does not support mode sense then we will modify just the portion we need // so the higher level driver can determine if media is protected. - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { + if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { - SelectDrive(chan, ldev & 0x1); + SelectDrive(chan, DeviceNumber); AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS); statusByte = WaitOnBusy(chan); @@ -6719,13 +6968,13 @@ IdeSendCommand( case SCSIOP_TEST_UNIT_READY: - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { + if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { // Select device 0 or 1. - SelectDrive(chan, ldev & 0x1); + SelectDrive(chan, DeviceNumber); AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS); // Wait for busy. If media has not changed, return success @@ -6766,7 +7015,7 @@ IdeSendCommand( case SCSIOP_READ_CAPACITY: - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); // Claim 512 byte blocks (big-endian). @@ -6775,10 +7024,10 @@ IdeSendCommand( MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i ); // Calculate last sector. - if(!(i = (ULONG)deviceExtension->lun[ldev].NumOfSectors)) { - i = deviceExtension->lun[ldev].IdentifyData.SectorsPerTrack * - deviceExtension->lun[ldev].IdentifyData.NumberOfHeads * - deviceExtension->lun[ldev].IdentifyData.NumberOfCylinders; + if(!(i = (ULONG)chan->lun[DeviceNumber]->NumOfSectors)) { + i = chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack * + chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads * + chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders; } i--; @@ -6788,12 +7037,12 @@ IdeSendCommand( MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i ); - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n", Srb->TargetId, - deviceExtension->lun[ldev].IdentifyData.SectorsPerTrack, - deviceExtension->lun[ldev].IdentifyData.NumberOfHeads, - deviceExtension->lun[ldev].IdentifyData.NumberOfCylinders)); + chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack, + chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads, + chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders)); status = SRB_STATUS_SUCCESS; @@ -6801,7 +7050,7 @@ IdeSendCommand( case SCSIOP_VERIFY: - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); status = IdeVerify(HwDeviceExtension,Srb); @@ -6811,7 +7060,7 @@ IdeSendCommand( case SCSIOP_READ: case SCSIOP_WRITE: - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n", (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ", Srb->PathId, Srb->Lun, Srb->TargetId)); @@ -6823,7 +7072,7 @@ IdeSendCommand( case SCSIOP_START_STOP_UNIT: - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); //Determine what type of operation we should perform @@ -6834,7 +7083,7 @@ IdeSendCommand( statusByte = WaitOnBaseBusy(chan); // Eject media, // first select device 0 or 1. - SelectDrive(chan, ldev & 0x1); + SelectDrive(chan, DeviceNumber); AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT); } status = SRB_STATUS_SUCCESS; @@ -6846,7 +7095,7 @@ IdeSendCommand( statusByte = WaitOnBaseBusy(chan); - SelectDrive(chan, ldev & 0x1); + SelectDrive(chan, DeviceNumber); if (cdb->MEDIA_REMOVAL.Prevent == TRUE) { AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK); } else { @@ -6863,7 +7112,7 @@ IdeSendCommand( case SCSIOP_FLUSH_BUFFER: case SCSIOP_SYNCHRONIZE_CACHE: - SelectDrive(chan, ldev & 0x1); + SelectDrive(chan, DeviceNumber); AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE); status = SRB_STATUS_SUCCESS; // status = SRB_STATUS_PENDING; @@ -6875,10 +7124,10 @@ IdeSendCommand( // this function makes sense buffers to report the results // of the original GET_MEDIA_STATUS command - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { + if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { status = IdeBuildSenseBuffer(HwDeviceExtension,Srb); break; } @@ -6891,7 +7140,7 @@ IdeSendCommand( PIDEREGS_EX regs; BOOLEAN use_dma = FALSE; ULONG to_lim; - + regs = (PIDEREGS_EX) &(Srb->Cdb[2]); lChannel = Srb->TargetId >> 1; @@ -6901,7 +7150,7 @@ IdeSendCommand( if((regs->bOpFlags & 1) == 0) { // execute ATA command - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); @@ -6942,7 +7191,7 @@ IdeSendCommand( AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg); } AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg); - + if(use_dma) { GetBaseStatus(chan, statusByte); if(statusByte & IDE_STATUS_ERROR) { @@ -7057,7 +7306,7 @@ passthrough_err: default: - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeSendCommand: Unsupported command %#x\n", Srb->Cdb[0])); @@ -7095,12 +7344,12 @@ NTAPI IdeMediaStatus( BOOLEAN EnableMSN, IN PVOID HwDeviceExtension, - UCHAR ldev + IN ULONG lChannel, + IN ULONG DeviceNumber ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; PHW_CHANNEL chan; - UCHAR lChannel = ldev >> 1; UCHAR statusByte,errorByte; chan = &(deviceExtension->chan[lChannel]); @@ -7108,10 +7357,10 @@ IdeMediaStatus( if (EnableMSN == TRUE){ // If supported enable Media Status Notification support - if ((deviceExtension->lun[ldev].DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) { + if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) { // enable - statusByte = AtaCommand(deviceExtension, ldev & 1, lChannel, + statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY); @@ -7119,12 +7368,12 @@ IdeMediaStatus( // Read the error register. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error); - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n", statusByte, errorByte)); } else { - deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED; + chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED; KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n")); chan->ReturningMediaStatus = 0; @@ -7134,12 +7383,12 @@ IdeMediaStatus( } else { // end if EnableMSN == TRUE // disable if previously enabled - if ((deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) { + if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) { - statusByte = AtaCommand(deviceExtension, ldev & 1, lChannel, + statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY); - deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED; + chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED; } @@ -7223,19 +7472,20 @@ NTAPI UniataUserDeviceReset( PHW_DEVICE_EXTENSION deviceExtension, PHW_LU_EXTENSION LunExt, - ULONG PathId, - ULONG ldev + ULONG PathId ) { + ULONG i; AtapiDisableInterrupts(deviceExtension, PathId); if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n")); - AtapiSoftReset(&(deviceExtension->chan[PathId]), ldev & 1); + AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun); } else { KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n")); AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE); - deviceExtension->chan[PathId].lun[0]->DeviceFlags |= DFLAGS_REINIT_DMA; - deviceExtension->chan[PathId].lun[1]->DeviceFlags |= DFLAGS_REINIT_DMA; + for(i=0; iNumberLuns; i++) { + deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA; + } } LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit AtapiEnableInterrupts(deviceExtension, PathId); @@ -7316,8 +7566,10 @@ AtapiStartIo__( PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; UCHAR lChannel; PHW_CHANNEL chan; + PHW_LU_EXTENSION LunExt; ULONG status; - ULONG ldev; + //ULONG ldev; + ULONG DeviceNumber; UCHAR PathId; UCHAR TargetId; UCHAR Lun; @@ -7336,7 +7588,7 @@ AtapiStartIo__( /* KeBugCheckEx(0xc000000e, (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), - Srb->Function, + Srb->Function, TopLevel, 0x80000001); */ if(TopLevel && Srb && Srb->SrbExtension) { @@ -7347,13 +7599,15 @@ AtapiStartIo__( do { lChannel = GET_CHANNEL(Srb); - chan = &(deviceExtension->chan[lChannel]); - ldev = GET_LDEV(Srb); + //ldev = GET_LDEV(Srb); + chan = NULL; + LunExt = NULL; + DeviceNumber = GET_CDEV(Srb); //ASSERT(deviceExtension); //ASSERT(chan); - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n", Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId)); KdPrint2((PRINT_PREFIX " VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID)); @@ -7385,9 +7639,8 @@ AtapiStartIo__( commPort = TRUE; /* Pass IOCTL request down */ } else - if(GET_CDEV(Srb) >= 2 || - ldev >= deviceExtension->NumberChannels*2 || - lChannel >= deviceExtension->NumberChannels || + if(lChannel >= deviceExtension->NumberChannels || + Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns || Srb->Lun) { if(lChannel >= deviceExtension->NumberChannels) { @@ -7395,8 +7648,8 @@ AtapiStartIo__( } reject_srb: - //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) { - KdPrint3((PRINT_PREFIX + //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { + KdPrint3((PRINT_PREFIX "AtapiStartIo: SRB rejected\n")); // Indicate no device found at this address. KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); @@ -7405,17 +7658,26 @@ reject_srb: //} } - atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; + if(!commPort) { + chan = &(deviceExtension->chan[lChannel]); + LunExt = chan->lun[DeviceNumber]; + if(!LunExt) { + goto reject_srb; + } + atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; + } else { + atapiDev = FALSE; + } #ifdef _DEBUG - if(!commPort && !(chan->lun[ldev & 1])) { + if(!commPort && !LunExt) { #if 0 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n", deviceExtension, - chan, ldev & 1, + chan, DeviceNumber, deviceExtension->NumberChannels); - PrintNtConsole("lchan = %#x, ldev %#x, cdev %#x, lun0 %#x\n", - lChannel, ldev, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]); + PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n", + lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]); PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n", Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId); #endif //0 @@ -7434,7 +7696,7 @@ reject_srb: case SRB_FUNCTION_EXECUTE_SCSI: - if(!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) { // let passthrough go } else @@ -7442,8 +7704,8 @@ reject_srb: // let INQUIRY go } else { - //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) { - KdPrint2((PRINT_PREFIX + //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { + KdPrint2((PRINT_PREFIX "AtapiStartIo: EXECUTE_SCSI rejected (2)\n")); // Indicate no device found at this address. KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); @@ -7486,14 +7748,14 @@ reject_srb: } /*KeBugCheckEx(0xc000000e, (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), - Srb->Function, + Srb->Function, status, 0x80000001);*/ if(status == SRB_STATUS_BUSY) status = SRB_STATUS_PENDING; // Insert requests AFTER they have been initialized on // CMD_ACTION_PREPARE stage // we should not check TopLevel here (it is always TRUE) - //ASSERT(chan->lun[GET_LDEV(Srb) & 1]); + //ASSERT(chan->lun[GET_CDEV(Srb)]); UniataQueueRequest(chan, Srb); KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); @@ -7506,7 +7768,7 @@ reject_srb: AtaReq = (PATA_REQ)(Srb->SrbExtension); KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq)); //ASSERT(!AtaReq->Flags); - //ASSERT(chan->lun[GET_LDEV(Srb) & 1]); + //ASSERT(chan->lun[GET_CDEV(Srb)]); UniataQueueRequest(chan, Srb); // AtaReq = (PATA_REQ)(Srb->SrbExtension); //ASSERT(!AtaReq->Flags); @@ -7515,14 +7777,17 @@ reject_srb: } #ifndef NAVO_TEST - if(!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + if(!LunExt) { + goto reject_srb; + } if(Srb->Cdb[0] == SCSIOP_INQUIRY) { - if(UniataAnybodyHome(deviceExtension, chan->lChannel, ldev & 1)) { - if(!CheckDevice(HwDeviceExtension, chan->lChannel, ldev & 1, TRUE)) { + if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) { + if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) { goto reject_srb; } } - if(!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { goto reject_srb; } } else @@ -7557,7 +7822,7 @@ reject_srb: } /* KeBugCheckEx(0xc000000e, (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun), - Srb->Function, + Srb->Function, status, 0x80000002);*/ } @@ -7636,7 +7901,7 @@ reject_srb: // Note: reset is immediate command, it cannot be queued since it is usually used to // revert not- responding device to operational state KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n")); - UniataUserDeviceReset(deviceExtension, &(deviceExtension->lun[ldev]), lChannel, ldev); + UniataUserDeviceReset(deviceExtension, LunExt, lChannel); status = SRB_STATUS_SUCCESS; break; @@ -7666,9 +7931,9 @@ do_bus_reset: case SRB_FUNCTION_SHUTDOWN: KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n")); - if(!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n")); - } + } else if(atapiDev) { // FLUSH ATAPI device - do nothing KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n")); @@ -7676,35 +7941,35 @@ do_bus_reset: // FLUSH IDE/ATA device KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n")); AtapiDisableInterrupts(deviceExtension, lChannel); - status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb), + status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb), IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE); // If supported & allowed, reset write cacheing - if(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_WCACHE_ENABLED) { + if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) { // Disable write cache - status = AtaCommand(deviceExtension, ldev & 1, lChannel, + status = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY); // Check for errors. if (status & IDE_STATUS_ERROR) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Disable write cacheing on Device %d failed\n", - ldev)); + DeviceNumber)); } - deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; + LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; // Re-enable write cache - status = AtaCommand(deviceExtension, ldev & 1, lChannel, + status = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY); // Check for errors. if (status & IDE_STATUS_ERROR) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Enable write cacheing on Device %d failed\n", - ldev)); - deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; + DeviceNumber)); + LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; } else { - deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_WCACHE_ENABLED; + LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED; } } @@ -7736,10 +8001,10 @@ do_bus_reset: return FALSE; } - if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) { + if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { status = SRB_STATUS_SUCCESS; } else { - status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb), + status = AtaCommand(deviceExtension, GET_CDEV(Srb), GET_CHANNEL(Srb), IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR); if (status & IDE_STATUS_DRQ) { status = SRB_STATUS_SUCCESS; @@ -7792,7 +8057,7 @@ do_bus_reset: break; } - if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT) || + if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) || atapiDev) { status = SRB_STATUS_SELECTION_TIMEOUT; @@ -7809,12 +8074,12 @@ do_bus_reset: if (deviceExtension->NumberChannels == 1) { if (chan->PrimaryAddress) { - deviceNumber = 1 << ldev; + deviceNumber = 1 << DeviceNumber; } else { - deviceNumber = 4 << ldev; + deviceNumber = 4 << DeviceNumber; } } else { - deviceNumber = 1 << ldev; + deviceNumber = (1 << DeviceNumber) << lChannel; } versionParameters->bIDEDeviceMap = deviceNumber; @@ -7936,48 +8201,52 @@ do_bus_reset: if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) { PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer); - ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0); - PHW_LU_EXTENSION LunExt; + //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0); + ULONG DeviceNumber = AtaCtl->addr.TargetId; BOOLEAN bad_ldev; ULONG i; //chan = &(deviceExtension->chan[lChannel]); if(AtaCtl->addr.Lun || - ldev >= deviceExtension->NumberChannels*2 || + AtaCtl->addr.TargetId >= deviceExtension->NumberLuns || AtaCtl->addr.PathId >= deviceExtension->NumberChannels) { + chan = NULL; bad_ldev = TRUE; LunExt = NULL; } else { bad_ldev = FALSE; - LunExt = &(deviceExtension->lun[ldev]); lChannel = AtaCtl->addr.PathId; chan = &(deviceExtension->chan[lChannel]); + LunExt = chan->lun[DeviceNumber]; } - KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl->hdr.ControlCode, ldev)); + KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber)); /* check for valid LUN */ switch (AtaCtl->hdr.ControlCode) { case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES: case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: + // this would be BUS reset if(bad_ldev && (AtaCtl->addr.PathId >= deviceExtension->NumberChannels || AtaCtl->addr.TargetId != 0xff || AtaCtl->addr.Lun != 0 )) { if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES && - ldev < deviceExtension->NumberChannels*2) { // AtaCtl->addr.TargetId != 0xff - LunExt = &(deviceExtension->lun[ldev]); + DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff + lChannel = AtaCtl->addr.PathId; + chan = &(deviceExtension->chan[lChannel]); + LunExt = chan->lun[DeviceNumber]; // OK } else { goto handle_bad_ldev; } + } else { + lChannel = AtaCtl->addr.PathId; + chan = &(deviceExtension->chan[lChannel]); } - // this would be BUS reset - lChannel = AtaCtl->addr.PathId; - chan = &(deviceExtension->chan[lChannel]); break; case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: @@ -8034,7 +8303,7 @@ uata_ctl_queue: if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) { KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n")); if(AtaCtl->addr.TargetId != 0xff) { - deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_HIDDEN; + LunExt->DeviceFlags &= ~DFLAGS_HIDDEN; } else { } } @@ -8055,10 +8324,10 @@ uata_ctl_queue: KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId)); - deviceExtension->lun[ldev].DeviceFlags = 0; + LunExt->DeviceFlags = 0; if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) { KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n")); - deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_HIDDEN; + LunExt->DeviceFlags |= DFLAGS_HIDDEN; } for(i=0; iFindDelDev.WaitForPhysicalLink && i<30; i++) { @@ -8088,10 +8357,10 @@ uata_ctl_queue: LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit if(AtaCtl->SetMode.ApplyImmediately) { - AtapiDmaInit__(deviceExtension, ldev); + AtapiDmaInit__(deviceExtension, LunExt); } -/* deviceExtension->lun[ldev].TransferMode = - deviceExtension->lun[ldev].LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/ +/* LunExt->TransferMode = + LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/ status = SRB_STATUS_SUCCESS; break; } @@ -8106,11 +8375,24 @@ uata_ctl_queue: status = SRB_STATUS_SUCCESS; break; } + case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: { + + KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n")); + + AtaCtl->Version.Length = sizeof(GETDRVVERSION); + AtaCtl->Version.VersionMj = UNIATA_VER_MJ; + AtaCtl->Version.VersionMn = UNIATA_VER_MN; + AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ; + AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN; + + status = SRB_STATUS_SUCCESS; + break; + } case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: { KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n")); - AtaCtl->AdapterInfo.HeaderLength = offsetof(ADAPTERINFO, Chan); + AtaCtl->AdapterInfo.HeaderLength = FIELD_OFFSET(ADAPTERINFO, Chan); if(len < AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", len, @@ -8137,11 +8419,13 @@ uata_ctl_queue: AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode; AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector; AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels; + AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns; AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType; if(deviceExtension->FullDevName) { strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64); } AtaCtl->AdapterInfo.ChanInfoValid = FALSE; + AtaCtl->AdapterInfo.LunInfoValid = FALSE; RtlZeroMemory(&AtaCtl->AdapterInfo.Chan, sizeof(AtaCtl->AdapterInfo.Chan)); @@ -8149,7 +8433,7 @@ uata_ctl_queue: break; } case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: { - + KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n")); ForgetBadBlocks(LunExt); @@ -8164,7 +8448,7 @@ uata_ctl_queue: if(bad_ldev) { goto do_bus_reset; } else { - UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId, ldev); + UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId); } status = SRB_STATUS_SUCCESS; @@ -8206,7 +8490,7 @@ complete_req: if (status != SRB_STATUS_PENDING) { - KdPrint2((PRINT_PREFIX + KdPrint2((PRINT_PREFIX "AtapiStartIo: Srb %#x complete with status %#x\n", Srb, status)); @@ -8245,7 +8529,7 @@ complete_req: NULL); ScsiPortNotification(NextLuRequest, - deviceExtension, + deviceExtension, PathId, TargetId, Lun); @@ -8401,6 +8685,9 @@ DriverEntry( PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2; BOOLEAN ReEnter = FALSE; WCHAR a; +#ifndef USE_REACTOS_DDK + NTSTATUS status; +#endif PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation(); BOOLEAN PrimaryClaimed = FALSE; @@ -8419,7 +8706,21 @@ DriverEntry( if(!SavedDriverObject) { SavedDriverObject = (PDRIVER_OBJECT)DriverObject; +#ifdef USE_REACTOS_DDK KdPrint(("UniATA Init: OS should be ReactOS\n")); + MajorVersion=0x04; + MinorVersion=0x01; + BuildNumber=1; +#else + // we are here for the 1st time + // init CrossNT and get OS version + if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) { + KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status)); + //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n"); + return status; + } +#endif // USE_REACTOS_DDK + KdPrint(("UniATA Init: OS ver %x.%x (%d)\n", MajorVersion, MinorVersion, BuildNumber)); KeQuerySystemTime(&t0); do { @@ -8506,7 +8807,34 @@ DriverEntry( KdPrint2((PRINT_PREFIX "\n\nATAPI IDE enum supported BusMaster Devices\n")); if(!ReEnter) { + + g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine); + if(g_opt_VirtualMachine > VM_MAX_KNOWN) { + g_opt_VirtualMachine = 0; + } + if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) { + g_opt_VirtualMachine = VM_VBOX; + } + // Pre-scan PCI bus, also check if we are under VM UniataEnumBusMasterController(DriverObject, Argument2); + + switch(g_opt_VirtualMachine) { + case VM_VBOX: + // adjust options for VirtualBox + g_opt_WaitBusyCount = 20000; + g_opt_WaitBusyDelay = 150; + g_opt_WaitDrqDelay = 100; + g_opt_AtapiSendDisableIntr = 0; + g_opt_AtapiDmaRawRead = FALSE; + break; + } + + g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000 + g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150 + g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100 + g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0 + g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0 + } // Look for legacy ISA-bridged PCI IDE controller (onboard) @@ -8540,6 +8868,8 @@ DriverEntry( if(g_opt_Verbose) { _PrintNtConsole("Init standard Dual-channel PCI ATA controller:"); } + + for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) { for(c=0; c<2; c++) { @@ -8589,16 +8919,6 @@ DriverEntry( &hwInitializationData.comm, (PVOID)(i | (alt ? 0x80000000 : 0))); KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); - if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) { - KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n")); - hwInitializationData.comm.AdapterInterfaceType = Isa; - newStatus = ScsiPortInitialize(DriverObject, - Argument2, - &hwInitializationData.comm, - (PVOID)(i | 0x80000000)); - KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus)); - } - if (newStatus < statusToReturn) { statusToReturn = newStatus; } @@ -8661,7 +8981,7 @@ DriverEntry( /* KeBugCheckEx(0xc000000e, (i << 16) | BMList[0].ChanInitOk, - c, + c, newStatus, statusToReturn);*/ // Look for PCI IDE controller @@ -8701,6 +9021,20 @@ DriverEntry( &hwInitializationData.comm, (PVOID)i); KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); + if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) { + // Note: this is actually a BUG in scsiport.sys + // It stops scanning PCI bus when reaches empty PCI Function inside Slot + // However, this PCI Slot may have higher non-empty Functions + // UniATA will perform all staff instead of ScsiPort under NT, + // but for ReactOS it is better to patch ScsiPort. + KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n")); + hwInitializationData.comm.AdapterInterfaceType = Isa; + newStatus = ScsiPortInitialize(DriverObject, + Argument2, + &hwInitializationData.comm, + (PVOID)(i | 0x80000000)); + KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus)); + } if (newStatus < statusToReturn) statusToReturn = newStatus; @@ -9086,13 +9420,13 @@ AtapiRegCheckParameterValue( RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength); RtlAppendUnicodeToString(¶mPath, RegistryPath->Buffer); RtlAppendUnicodeToString(¶mPath, L"\\"); - RtlAppendUnicodeToString(¶mPath, PathSuffix); + RtlAppendUnicodeToString(¶mPath, REGRTL_STR_PTYPE PathSuffix); // Check for the Xxx value. RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - parameters[0].Name = Name; + parameters[0].Name = REGRTL_STR_PTYPE Name; parameters[0].EntryContext = &doRun; parameters[0].DefaultType = REG_DWORD; parameters[0].DefaultData = &zero; @@ -9232,6 +9566,7 @@ _PrintNtConsole( dbg_print_tmp_buff[511] = 0; + KdPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); HalDisplayString(dbg_print_tmp_buff); va_end(ap); diff --git a/reactos/drivers/storage/ide/uniata/id_badblock.cpp b/reactos/drivers/storage/ide/uniata/id_badblock.cpp index 2e3f7347197..0beb3dc0e1e 100644 --- a/reactos/drivers/storage/ide/uniata/id_badblock.cpp +++ b/reactos/drivers/storage/ide/uniata/id_badblock.cpp @@ -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; inBadBlocks = 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; diff --git a/reactos/drivers/storage/ide/uniata/id_dma.cpp b/reactos/drivers/storage/ide/uniata/id_dma.cpp index 64d8d0be71e..083d8557753 100644 --- a/reactos/drivers/storage/ide/uniata/id_dma.cpp +++ b/reactos/drivers/storage/ide/uniata/id_dma.cpp @@ -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() - diff --git a/reactos/drivers/storage/ide/uniata/id_init.cpp b/reactos/drivers/storage/ide/uniata/id_init.cpp index 81265998761..89b5fde8413 100644 --- a/reactos/drivers/storage/ide/uniata/id_init.cpp +++ b/reactos/drivers/storage/ide/uniata/id_init.cpp @@ -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(cNumberChannels) { + 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; cNumberChannels; 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; cNumberChannels; c++) { chan = &deviceExtension->chan[c]; for (i=0; iRegTranslation[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; iRegTranslation[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; iRegTranslation[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; iNumberLuns; i++) { chan->lun[i]->DeviceExtension = deviceExtension; + chan->lun[i]->chan = chan; + chan->lun[i]->Lun = i; } } // end AtapiSetupLunPtrs() diff --git a/reactos/drivers/storage/ide/uniata/id_probe.cpp b/reactos/drivers/storage/ide/uniata/id_probe.cpp index 00eab9bec7b..26505f5fa1f 100644 --- a/reactos/drivers/storage/ide/uniata/id_probe.cpp +++ b/reactos/drivers/storage/ide/uniata/id_probe.cpp @@ -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; iSlotNumber && @@ -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. diff --git a/reactos/drivers/storage/ide/uniata/id_queue.cpp b/reactos/drivers/storage/ide/uniata/id_queue.cpp index 4753eb321cd..451054a3838 100644 --- a/reactos/drivers/storage/ide/uniata/id_queue.cpp +++ b/reactos/drivers/storage/ide/uniata/id_queue.cpp @@ -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) diff --git a/reactos/drivers/storage/ide/uniata/id_queue.h b/reactos/drivers/storage/ide/uniata/id_queue.h index a697dec0a43..f292349456e 100644 --- a/reactos/drivers/storage/ide/uniata/id_queue.h +++ b/reactos/drivers/storage/ide/uniata/id_queue.h @@ -42,4 +42,4 @@ UniataGetNextChannel( IN PHW_CHANNEL chan ); -#endif //__UNIATA_COMMAND_QUEUE_SUPPORT__H__ +#endif //__UNIATA_COMMAND_QUEUE_SUPPORT__H__ \ No newline at end of file diff --git a/reactos/drivers/storage/ide/uniata/id_sata.cpp b/reactos/drivers/storage/ide/uniata/id_sata.cpp index 7ab242a44cc..0e45b30888d 100644 --- a/reactos/drivers/storage/ide/uniata/id_sata.cpp +++ b/reactos/drivers/storage/ide/uniata/id_sata.cpp @@ -1,6 +1,6 @@ /*++ -Copyright (c) 2008-2010 Alexandr A. Telyatnikov (Alter) +Copyright (c) 2008-2011 Alexandr A. Telyatnikov (Alter) Module Name: id_probe.cpp @@ -66,8 +66,10 @@ UniataSataConnect( for(i=0; i<100; i++) { SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, pm_port); if(SStatus.SPD == SStatus_SPD_Gen1 || - SStatus.SPD == SStatus_SPD_Gen2) { - deviceExtension->lun[lChannel*2].TransferMode = ATA_SA150 + (UCHAR)(SStatus.SPD - 1); + SStatus.SPD == SStatus_SPD_Gen2 || + SStatus.SPD == SStatus_SPD_Gen3) { + chan->lun[0]->TransferMode = ATA_SA150 + (UCHAR)(SStatus.SPD - 1); + KdPrint2((PRINT_PREFIX "SATA TransferMode %#x\n", chan->lun[0]->TransferMode)); break; } AtapiStallExecution(10000); @@ -91,7 +93,7 @@ UniataSataConnect( if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) { } */ - KdPrint2((PRINT_PREFIX "UniataSataConnect: OK, ATA status %x\n", Status)); + KdPrint2((PRINT_PREFIX "UniataSataConnect: OK, ATA status %#x\n", Status)); return IDE_STATUS_IDLE; } // end UniataSataConnect() @@ -100,7 +102,8 @@ NTAPI UniataSataPhyEnable( IN PVOID HwDeviceExtension, IN ULONG lChannel, // logical channel - IN ULONG pm_port /* for port multipliers */ + IN ULONG pm_port, /* for port multipliers */ + IN BOOLEAN doReset ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; @@ -116,9 +119,11 @@ UniataSataPhyEnable( } SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); - KdPrint2((PRINT_PREFIX "SControl %x\n", SControl.Reg)); + KdPrint2((PRINT_PREFIX "SControl %#x\n", SControl.Reg)); if(SControl.DET == SControl_DET_Idle) { - return UniataSataConnect(HwDeviceExtension, lChannel, pm_port); + if(!doReset) { + return UniataSataConnect(HwDeviceExtension, lChannel, pm_port); + } } for (retry = 0; retry < 10; retry++) { @@ -129,7 +134,7 @@ UniataSataPhyEnable( UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port); AtapiStallExecution(100); SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); - KdPrint2((PRINT_PREFIX " SControl %8.8%x\n", SControl.Reg)); + KdPrint2((PRINT_PREFIX " SControl %8.8x\n", SControl.Reg)); if(SControl.DET == SControl_DET_Init) { break; } @@ -143,7 +148,7 @@ UniataSataPhyEnable( UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port); AtapiStallExecution(100); SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); - KdPrint2((PRINT_PREFIX " SControl %8.8%x\n", SControl.Reg)); + KdPrint2((PRINT_PREFIX " SControl %8.8x\n", SControl.Reg)); if(SControl.DET == SControl_DET_Idle) { return UniataSataConnect(HwDeviceExtension, lChannel, pm_port); } @@ -176,10 +181,10 @@ UniataSataClearErr( SError.Reg = UniataSataReadPort4(chan, IDX_SATA_SError, pm_port); if(SStatus.Reg) { - KdPrint2((PRINT_PREFIX " SStatus %x\n", SStatus.Reg)); + KdPrint2((PRINT_PREFIX " SStatus %#x\n", SStatus.Reg)); } if(SError.Reg) { - KdPrint2((PRINT_PREFIX " SError %x\n", SError.Reg)); + KdPrint2((PRINT_PREFIX " SError %#x\n", SError.Reg)); /* clear error bits/interrupt */ UniataSataWritePort4(chan, IDX_SATA_SError, SError.Reg, pm_port); @@ -211,7 +216,7 @@ UniataSataEvent( { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; UCHAR Status; - ULONG ldev = lChannel*2 + (pm_port ? 1 : 0); + ULONG DeviceNumber = (pm_port ? 1 : 0); if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { return FALSE; @@ -221,16 +226,16 @@ UniataSataEvent( case UNIATA_SATA_EVENT_ATTACH: KdPrint2((PRINT_PREFIX " CONNECTED\n")); Status = UniataSataConnect(HwDeviceExtension, lChannel, pm_port); - KdPrint2((PRINT_PREFIX " Status %x\n", Status)); + KdPrint2((PRINT_PREFIX " Status %#x\n", Status)); if(Status != IDE_STATUS_IDLE) { return FALSE; } - CheckDevice(HwDeviceExtension, lChannel, pm_port ? 1 : 0 /*dev*/, FALSE); + CheckDevice(HwDeviceExtension, lChannel, DeviceNumber /*dev*/, FALSE); return TRUE; break; case UNIATA_SATA_EVENT_DETACH: KdPrint2((PRINT_PREFIX " DISCONNECTED\n")); - UniataForgetDevice(&(deviceExtension->lun[ldev])); + UniataForgetDevice(deviceExtension->chan[lChannel].lun[DeviceNumber]); return TRUE; break; } @@ -247,6 +252,8 @@ UniataSataReadPort4( if(chan && (io_port_ndx < IDX_MAX_REG) && chan->RegTranslation[io_port_ndx].Proc) { + KdPrint3((PRINT_PREFIX " UniataSataReadPort4 %#x[%d]\n", io_port_ndx, pm_port)); + PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension; PVOID HwDeviceExtension = (PVOID)deviceExtension; ULONG slotNumber = deviceExtension->slotNumber; @@ -260,6 +267,7 @@ UniataSataReadPort4( p = pm_port ? 1 : 0; if(deviceExtension->HwFlags & ICH5) { offs = 0x50+chan->lun[p]->SATA_lun_map*0x10; + KdPrint3((PRINT_PREFIX " ICH5 way, offs %#x\n", offs)); switch(io_port_ndx) { case IDX_SATA_SStatus: offs += 0; @@ -278,6 +286,7 @@ UniataSataReadPort4( return offs; } else { offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100; + KdPrint3((PRINT_PREFIX " def way, offs %#x\n", offs)); switch(io_port_ndx) { case IDX_SATA_SStatus: offs += 0; @@ -312,6 +321,8 @@ UniataSataWritePort4( if(chan && (io_port_ndx < IDX_MAX_REG) && chan->RegTranslation[io_port_ndx].Proc) { + KdPrint3((PRINT_PREFIX " UniataSataWritePort4 %#x[%d]\n", io_port_ndx, pm_port)); + PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension; PVOID HwDeviceExtension = (PVOID)deviceExtension; ULONG slotNumber = deviceExtension->slotNumber; @@ -325,6 +336,7 @@ UniataSataWritePort4( p = pm_port ? 1 : 0; if(deviceExtension->HwFlags & ICH5) { offs = 0x50+chan->lun[p]->SATA_lun_map*0x10; + KdPrint3((PRINT_PREFIX " ICH5 way, offs %#x\n", offs)); switch(io_port_ndx) { case IDX_SATA_SStatus: offs += 0; @@ -343,6 +355,7 @@ UniataSataWritePort4( return; } else { offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100; + KdPrint3((PRINT_PREFIX " def way, offs %#x\n", offs)); switch(io_port_ndx) { case IDX_SATA_SStatus: offs += 0; @@ -366,6 +379,205 @@ UniataSataWritePort4( AtapiWritePort4(chan, io_port_ndx, data); } // end UniataSataWritePort4() +BOOLEAN +NTAPI +UniataSataReadPM( + IN PHW_CHANNEL chan, + IN ULONG DeviceNumber, + IN ULONG Reg, + OUT PULONG result + ) +{ + if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { + return UniataAhciReadPM(chan, DeviceNumber, Reg, result); + } + return FALSE; +} // end UniataSataReadPM() + +UCHAR +NTAPI +UniataSataWritePM( + IN PHW_CHANNEL chan, + IN ULONG DeviceNumber, + IN ULONG Reg, + IN ULONG value + ) +{ + if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { + return UniataAhciWritePM(chan, DeviceNumber, Reg, value); + } + return 0xff; +} // end UniataSataWritePM() + +ULONG +NTAPI +UniataSataSoftReset( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + + if(deviceExtension->HwFlags & UNIATA_AHCI) { + return UniataAhciSoftReset(HwDeviceExtension, lChannel, DeviceNumber); + } + return 0xffffffff; +} // end UniataSataSoftReset() + +VOID +UniataSataIdentifyPM( + IN PHW_CHANNEL chan + ) +{ + ULONG PM_DeviceId; + ULONG PM_RevId; + ULONG PM_Ports; + UCHAR i; + ULONG signature; + PHW_LU_EXTENSION LunExt; + + KdPrint((PRINT_PREFIX "UniataSataIdentifyPM:\n")); + + chan->PmLunMap = 0; + + /* get PM vendor & product data */ + if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 0, &PM_DeviceId)) { + KdPrint2((PRINT_PREFIX " error getting PM vendor data\n")); + return; + } + /* get PM revision data */ + if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 1, &PM_RevId)) { + KdPrint2((PRINT_PREFIX " error getting PM revison data\n")); + return; + } + /* get number of HW ports on the PM */ + if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 2, &PM_Ports)) { + KdPrint2((PRINT_PREFIX " error getting PM port info\n")); + return; + } + + PM_Ports &= 0x0000000f; + + switch(PM_DeviceId) { + case 0x37261095: + /* This PM declares 6 ports, while only 5 of them are real. + * Port 5 is enclosure management bridge port, which has implementation + * problems, causing probe faults. Hide it for now. */ + KdPrint2((PRINT_PREFIX " SiI 3726 (rev=%#x) Port Multiplier with %d (5) ports\n", + PM_RevId, PM_Ports)); + PM_Ports = 5; + break; + case 0x47261095: + /* This PM declares 7 ports, while only 5 of them are real. + * Port 5 is some fake "Config Disk" with 640 sectors size, + * port 6 is enclosure management bridge port. + * Both fake ports has implementation problems, causing + * probe faults. Hide them for now. */ + KdPrint2((PRINT_PREFIX " SiI 4726 (rev=%#x) Port Multiplier with %d (5) ports\n", + PM_RevId, PM_Ports)); + PM_Ports = 5; + break; + default: + KdPrint2((PRINT_PREFIX " Port Multiplier (id=%08x rev=%#x) with %d ports\n", + PM_DeviceId, PM_RevId, PM_Ports)); + break; + } + + // reset + for(i=0; ilun[i]; + + KdPrint2((PRINT_PREFIX " Port %d\n", i)); + if(UniataSataPhyEnable(chan->DeviceExtension, chan->lChannel, i, UNIATA_SATA_RESET_ENABLE) != IDE_STATUS_IDLE) { + LunExt->DeviceFlags &= ~DFLAGS_DEVICE_PRESENT; + continue; + } + /* + * XXX: I have no idea how to properly wait for PMP port hardreset + * completion. Without this delay soft reset does not completes + * successfully. + */ + AtapiStallExecution(1000000); + + signature = UniataSataSoftReset(chan->DeviceExtension, chan->lChannel, i); + KdPrint2((PRINT_PREFIX " signature %#x\n", signature)); + + LunExt->DeviceFlags |= DFLAGS_DEVICE_PRESENT; + chan->PmLunMap |= (1 << i); + /* figure out whats there */ + switch (signature >> 16) { + case 0x0000: + LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE; + continue; + case 0xeb14: + LunExt->DeviceFlags |= DFLAGS_ATAPI_DEVICE; + continue; + } + + } + +} // end UniataSataIdentifyPM() + +#ifdef DBG +VOID +NTAPI +UniataDumpAhciRegs( + IN PHW_DEVICE_EXTENSION deviceExtension + ) +{ + ULONG j; + ULONG xReg; + + KdPrint2((PRINT_PREFIX + " AHCI Base: %#x MemIo %d Proc %d\n", + deviceExtension->BaseIoAHCI_0.Addr, + deviceExtension->BaseIoAHCI_0.MemIo, + deviceExtension->BaseIoAHCI_0.Proc)); + + for(j=0; j<=IDX_AHCI_VS; j+=sizeof(ULONG)) { + xReg = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&deviceExtension->BaseIoAHCI_0, j); + KdPrint2((PRINT_PREFIX + " AHCI_%#x (%#x) = %#x\n", + j, + (deviceExtension->BaseIoAHCI_0.Addr+j), + xReg)); + } + return; +} // end UniataDumpAhciRegs() + + +VOID +NTAPI +UniataDumpAhciPortRegs( + IN PHW_CHANNEL chan + ) +{ + ULONG j; + ULONG xReg; + + KdPrint2((PRINT_PREFIX + " AHCI port %d Base: %#x MemIo %d Proc %d\n", + chan->lChannel, + chan->BaseIoAHCI_Port.Addr, + chan->BaseIoAHCI_Port.MemIo, + chan->BaseIoAHCI_Port.Proc)); + + for(j=0; j<=IDX_AHCI_P_SNTF; j+=sizeof(ULONG)) { + xReg = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&chan->BaseIoAHCI_Port, j); + KdPrint2((PRINT_PREFIX + " AHCI%d_%#x (%#x) = %#x\n", + chan->lChannel, + j, + (chan->BaseIoAHCI_Port.Addr+j), + xReg)); + } + return; +} // end UniataDumpAhciPortRegs() +#endif //DBG + + BOOLEAN NTAPI UniataAhciInit( @@ -373,27 +585,31 @@ UniataAhciInit( ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - ULONG version; - ULONG c, i, n; + ULONG c, i; PHW_CHANNEL chan; ULONG offs; ULONG BaseMemAddress; ULONG PI; ULONG CAP; ULONG GHC; - BOOLEAN MemIo; - ULONGLONG base; + BOOLEAN MemIo = FALSE; + + KdPrint2((PRINT_PREFIX " UniataAhciInit:\n")); + +#ifdef DBG + UniataDumpAhciRegs(deviceExtension); +#endif //DBG /* reset AHCI controller */ - GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); - KdPrint2((PRINT_PREFIX " reset AHCI controller, GHC %x\n", GHC)); - AtapiWritePortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC, + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + KdPrint2((PRINT_PREFIX " reset AHCI controller, GHC %#x\n", GHC)); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, GHC | AHCI_GHC_HR); for(i=0; i<1000; i++) { AtapiStallExecution(1000); - GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); - KdPrint2((PRINT_PREFIX " AHCI GHC %x\n", GHC)); + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC)); if(!(GHC & AHCI_GHC_HR)) { break; } @@ -404,60 +620,39 @@ UniataAhciInit( } /* enable AHCI mode */ - GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); - KdPrint2((PRINT_PREFIX " enable AHCI mode, GHC %x\n", GHC)); - AtapiWritePortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC, + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + KdPrint2((PRINT_PREFIX " enable AHCI mode, GHC %#x\n", GHC)); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, GHC | AHCI_GHC_AE); - GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); - KdPrint2((PRINT_PREFIX " AHCI GHC %x\n", GHC)); + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC)); - - CAP = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_CAP); - PI = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_PI); - KdPrint2((PRINT_PREFIX " AHCI CAP %x\n", CAP)); + deviceExtension->AHCI_CAP = + CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); + PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); + KdPrint2((PRINT_PREFIX " AHCI CAP %#x\n", CAP)); if(CAP & AHCI_CAP_S64A) { KdPrint2((PRINT_PREFIX " AHCI 64bit\n")); deviceExtension->Host64 = TRUE; } + KdPrint2((PRINT_PREFIX " AHCI %d CMD slots\n", (CAP & AHCI_CAP_NCS_MASK) >> 8 )); + if(CAP & AHCI_CAP_PMD) { + KdPrint2((PRINT_PREFIX " AHCI multi-block PIO\n")); + } + if(CAP & AHCI_CAP_SAM) { + KdPrint2((PRINT_PREFIX " AHCI legasy SATA\n")); + } /* get the number of HW channels */ - PI = AtapiReadPortEx4(NULL, (ULONG)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_PI); - KdPrint2((PRINT_PREFIX " AHCI PI %x\n", PI)); - for(i=PI, n=0; i; n++, i=i>>1); - deviceExtension->NumberChannels = - max((CAP & AHCI_CAP_NOP_MASK)+1, n); - - switch(deviceExtension->DevID) { - case ATA_M88SX6111: - deviceExtension->NumberChannels = 1; - break; - case ATA_M88SX6121: - deviceExtension->NumberChannels = 2; - break; - case ATA_M88SX6141: - case ATA_M88SX6145: - deviceExtension->NumberChannels = 4; - break; - } // switch() + PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); + KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI)); /* clear interrupts */ - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS, - AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS)); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, + UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS)); /* enable AHCI interrupts */ - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC, - AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC) | AHCI_GHC_IE); - - version = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_VS); - KdPrint2((PRINT_PREFIX " AHCI version %x.%02x controller with %d ports (mask %x) detected\n", - ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f), - ((version >> 4) & 0xf0) + (version & 0x0f), - deviceExtension->NumberChannels, PI)); - - KdPrint2((PRINT_PREFIX " PM%s supported\n", - CAP & AHCI_CAP_SPM ? "" : " not")); - - deviceExtension->HwFlags |= UNIATA_SATA; - deviceExtension->HwFlags |= UNIATA_AHCI; + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, + UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC) | AHCI_GHC_IE); BaseMemAddress = deviceExtension->BaseIoAHCI_0.Addr; MemIo = deviceExtension->BaseIoAHCI_0.MemIo; @@ -466,6 +661,13 @@ UniataAhciInit( chan = &deviceExtension->chan[c]; offs = sizeof(IDE_AHCI_REGISTERS) + c*sizeof(IDE_AHCI_PORT_REGISTERS); + KdPrint2((PRINT_PREFIX " chan %d, offs %#x\n", c, offs)); + + AtapiSetupLunPtrs(chan, deviceExtension, c); + + chan->BaseIoAHCI_Port = deviceExtension->BaseIoAHCI_0; + chan->BaseIoAHCI_Port.Addr = BaseMemAddress + offs; + chan->RegTranslation[IDX_IO1_i_Status ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.STS); chan->RegTranslation[IDX_IO1_i_Status ].MemIo = MemIo; chan->RegTranslation[IDX_IO2_AltStatus] = chan->RegTranslation[IDX_IO1_i_Status]; @@ -491,21 +693,7 @@ UniataAhciInit( AtapiDmaAlloc(HwDeviceExtension, NULL, c); - base = chan->AHCI_CL_PhAddr; - if(!base) { - KdPrint2((PRINT_PREFIX " AHCI buffer allocation failed\n")); - return FALSE; - } - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_CLB, - (ULONG)(base & 0xffffffff)); - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_CLB + 4, - (ULONG)((base >> 32) & 0xffffffff)); - - base = chan->AHCI_CL_PhAddr + ATA_AHCI_MAX_TAGS; - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_FB, - (ULONG)(base & 0xffffffff)); - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_FB + 4, - (ULONG)((base >> 32) & 0xffffffff)); + UniataAhciResume(chan); chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE; } @@ -513,6 +701,139 @@ UniataAhciInit( return TRUE; } // end UniataAhciInit() +BOOLEAN +NTAPI +UniataAhciDetect( + IN PVOID HwDeviceExtension, + IN PPCI_COMMON_CONFIG pciData, // optional + IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + //ULONG slotNumber = deviceExtension->slotNumber; + ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; + ULONG version; + ULONG i, n; + ULONG PI; + ULONG CAP; + ULONG GHC; + ULONG NumberChannels; + ULONG v_Mn, v_Mj; + ULONG BaseMemAddress; + BOOLEAN MemIo; + + KdPrint2((PRINT_PREFIX " UniataAhciDetect:\n")); + + if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 1 /* DEBUG */)) { + KdPrint((" AHCI excluded\n")); + return FALSE; + } + BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber, + 5, 0, 0x10); + if(!BaseMemAddress) { + KdPrint2((PRINT_PREFIX " AHCI init failed - no IoRange\n")); + return FALSE; + } + if(BaseMemAddress && (*ConfigInfo->AccessRanges)[5].RangeInMemory) { + KdPrint2((PRINT_PREFIX "MemIo\n")); + MemIo = TRUE; + } + deviceExtension->BaseIoAHCI_0.Addr = BaseMemAddress; + deviceExtension->BaseIoAHCI_0.MemIo = MemIo; + +#ifdef DBG + UniataDumpAhciRegs(deviceExtension); +#endif //DBG + + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + if(GHC & AHCI_GHC_HR) { + KdPrint2((PRINT_PREFIX " AHCI in reset state\n")); + return FALSE; + } + + /* enable AHCI mode */ + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + KdPrint2((PRINT_PREFIX " check AHCI mode, GHC %#x\n", GHC)); + if(!(GHC & AHCI_GHC_AE)) { + KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE)\n")); + return FALSE; + } + + CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); + KdPrint2((PRINT_PREFIX " AHCI CAP %#x\n", CAP)); + if(CAP & AHCI_CAP_S64A) { + KdPrint2((PRINT_PREFIX " AHCI 64bit\n")); + //deviceExtension->Host64 = TRUE; + } + + /* get the number of HW channels */ + PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); + KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI)); + for(i=PI, n=0; i; n++, i=i>>1); + NumberChannels = + max((CAP & AHCI_CAP_NOP_MASK)+1, n); + + KdPrint2((PRINT_PREFIX " Channels %d\n", n)); + + switch(deviceExtension->DevID) { + case ATA_M88SX6111: + NumberChannels = 1; + break; + case ATA_M88SX6121: + NumberChannels = 2; + break; + case ATA_M88SX6141: + case ATA_M88SX6145: + NumberChannels = 4; + break; + } // switch() + + if(!NumberChannels) { + KdPrint2((PRINT_PREFIX " Non-AHCI - NumberChannels=0\n")); + return FALSE; + } + + version = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_VS); + v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f); + v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f); + + KdPrint2((PRINT_PREFIX " AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n", + v_Mj, v_Mn, + NumberChannels, PI)); + + if(CAP & AHCI_CAP_SPM) { + KdPrint2((PRINT_PREFIX " PM supported\n")); + 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; + } + } else { + KdPrint2((PRINT_PREFIX " PM not supported -> 1 lun/chan\n")); + deviceExtension->NumberLuns = 1; + } + + if((v_Mj != 0x01) || (v_Mn > 0x20)) { + KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n")); + if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", 1)) { + KdPrint((" AHCI revision excluded\n")); + return FALSE; + } + } + + deviceExtension->HwFlags |= UNIATA_SATA; + deviceExtension->HwFlags |= UNIATA_AHCI; + if(deviceExtension->NumberChannels < NumberChannels) { + deviceExtension->NumberChannels = NumberChannels; + } + + return TRUE; +} // end UniataAhciDetect() + UCHAR NTAPI UniataAhciStatus( @@ -529,27 +850,25 @@ UniataAhciStatus( AHCI_IS_REG IS; SATA_SSTATUS_REG SStatus; SATA_SERROR_REG SError; - ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); - ULONG_PTR base; + //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); ULONG tag=0; KdPrint(("UniataAhciStatus:\n")); - hIS = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS); - KdPrint((" hIS %x\n", hIS)); + hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS); + KdPrint((" hIS %#x\n", hIS)); hIS &= (1 << Channel); if(!hIS) { - return 0; + return INTERRUPT_REASON_IGNORE; } - base = (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); - IS.Reg = AtapiReadPort4(chan, base + IDX_AHCI_P_IS); - CI = AtapiReadPort4(chan, base + IDX_AHCI_P_CI); + IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); + CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus); SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); /* clear interrupt(s) */ - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS, hIS); - AtapiWritePort4(chan, base + IDX_AHCI_P_IS, IS.Reg); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, hIS); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg); AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg); KdPrint((" AHCI: status=%08x sstatus=%08x error=%08x CI=%08x\n", @@ -567,16 +886,16 @@ UniataAhciStatus( UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH); } if(CI & (1 << tag)) { - return 1; + return INTERRUPT_REASON_OUR; } KdPrint((" AHCI: unexpected\n")); - return 2; + return INTERRUPT_REASON_UNEXPECTED; } // end UniataAhciStatus() ULONG NTAPI -UniataAhciSetupFIS( +UniataAhciSetupFIS_H2D( IN PHW_DEVICE_EXTENSION deviceExtension, IN ULONG DeviceNumber, IN ULONG lChannel, @@ -588,68 +907,902 @@ UniataAhciSetupFIS( IN ULONG flags ) { - ULONG ldev = lChannel*2 + DeviceNumber; ULONG i; PUCHAR plba; + BOOLEAN need48; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; - KdPrint2((PRINT_PREFIX " AHCI setup FIS\n" )); + KdPrint2((PRINT_PREFIX " AHCI setup FIS ch %d, dev %d\n", lChannel, DeviceNumber)); i = 0; plba = (PUCHAR)&lba; - if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) && - CheckIfBadBlock(&(deviceExtension->lun[ldev]), lba, count)) { - KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count)); - return IDE_STATUS_ERROR; - //return SRB_STATUS_ERROR; - } + fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */ + fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */ + fis[7] = IDE_USE_LBA; + fis[15] = IDE_DC_A_4BIT; - /* translate command into 48bit version */ - if ((lba >= ATA_MAX_LBA28 || count > 256) && - deviceExtension->lun[ldev].IdentifyData.FeaturesSupport.Address48) { - if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { - command = AtaCommands48[command]; + if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) { + fis[2] = IDE_COMMAND_ATAPI_PACKET; + if(feature & ATA_F_DMA) { + fis[3] = (UCHAR)(feature & 0xff); } else { - KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); + fis[5] = (UCHAR)(count & 0xff); + fis[6] = (UCHAR)(count>>8) & 0xff; + } + } else { + + if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) && + CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) { + KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count)); + //return IDE_STATUS_ERROR; + //return SRB_STATUS_ERROR; return 0; } - } - fis[0] = 0x27; /* host to device */ - fis[1] = 0x80; /* command FIS (note PM goes here) */ - fis[2] = command; - fis[3] = (UCHAR)feature; + need48 = UniAta_need_lba48(command, lba, count, + chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48); - fis[4] = plba[0]; - fis[5] = plba[1]; - fis[6] = plba[2]; - fis[7] = IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1); - if ((lba >= ATA_MAX_LBA28 || count > 256) && - deviceExtension->lun[ldev].IdentifyData.FeaturesSupport.Address48) { - i++; - } else { + /* translate command into 48bit version */ + if(need48) { + if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { + command = AtaCommands48[command]; + } else { + KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); + return 0; + } + } + + fis[2] = command; + fis[3] = (UCHAR)feature; + + fis[4] = plba[0]; + fis[5] = plba[1]; + fis[6] = plba[2]; + if(need48) { + i++; + } else { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4333) // right shift by too large amount, data loss #endif - fis[7] |= (plba[3] >> 24) & 0x0f; + fis[7] |= IDE_DRIVE_1 | ((plba[3] >> 24) & 0x0f); #ifdef _MSC_VER #pragma warning(pop) #endif + } + + fis[8] = plba[3]; + fis[9] = plba[4]; + fis[10] = plba[5]; + fis[11] = (UCHAR)(feature>>8) & 0xff; + + fis[12] = (UCHAR)count & 0xff; + fis[13] = (UCHAR)(count>>8) & 0xff; + //fis[14] = 0x00; + } - fis[8] = plba[3]; - fis[9] = plba[4]; - fis[10] = plba[5]; - fis[11] = (UCHAR)(feature>>8) & 0xff; + KdDump(fis, 20); - fis[12] = (UCHAR)count & 0xff; - fis[13] = (UCHAR)(count>>8) & 0xff; - fis[14] = 0x00; - fis[15] = IDE_DC_A_4BIT; - - fis[16] = 0x00; - fis[17] = 0x00; - fis[18] = 0x00; - fis[19] = 0x00; return 20; -} // end UniataAhciSetupFIS() +} // end UniataAhciSetupFIS_H2D() + +UCHAR +NTAPI +UniataAhciSendCommand( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber, + IN ULONG flags, + IN ULONG timeout + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + //ULONG Channel = deviceExtension->Channel + lChannel; + //ULONG hIS; + ULONG CI = 0; + AHCI_IS_REG IS; + ULONG SError; + //SATA_SSTATUS_REG SStatus; + //SATA_SERROR_REG SError; + //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); + //ULONGIO_PTR base; + ULONG tag=0; + ULONG i; + + PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); + + KdPrint(("UniataAhciSendCommand: lChan %d\n", chan->lChannel)); + + AHCI_CL->prd_length = 0; + AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | flags | (DeviceNumber << 12); + AHCI_CL->bytecount = 0; + AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); + if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) { + KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK)); + } + + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, ATA_AHCI_P_CMD_ST); + + for (i=0; i= timeout)) { + SError = AtapiReadPort4(chan, IDX_SATA_SError); + KdPrint((" AHCI: timeout, SError %#x\n", SError)); + return 0xff; + } + + return IDE_STATUS_IDLE; + +} // end UniataAhciSendCommand() + +ULONG +NTAPI +UniataAhciSoftReset( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + //ULONG Channel = deviceExtension->Channel + lChannel; + //ULONG hIS; + //ULONG CI; + //AHCI_IS_REG IS; + //ULONG tag=0; + + KdPrint(("UniataAhciSoftReset: lChan %d\n", chan->lChannel)); + + PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); + PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); + +#ifdef DBG + UniataDumpAhciPortRegs(chan); +#endif // DBG + + /* kick controller into sane state */ + UniataAhciStop(chan); + UniataAhciCLO(chan); + UniataAhciStart(chan); + +#ifdef DBG + UniataDumpAhciPortRegs(chan); +#endif // DBG + + /* pull reset active */ + RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); + AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; + AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f; + //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT; + AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT | IDE_DC_RESET_CONTROLLER); + + if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY, 100) == 0xff) { + KdPrint2((" timeout\n")); + return (ULONG)(-1); + } + AtapiStallExecution(50); + + /* pull reset inactive */ + RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); + AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; + AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f; + //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT; + AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT); + if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) { + KdPrint2((" timeout (2)\n")); + return (ULONG)(-1); + } + + UniataAhciWaitReady(chan, 1); + + KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis)); + + return UniataAhciUlongFromRFIS(RCV_FIS); + +} // end UniataAhciSoftReset() + +ULONG +NTAPI +UniataAhciWaitReady( + IN PHW_CHANNEL chan, + IN ULONG timeout + ) +{ + ULONG TFD; + ULONG i; + + KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan->lChannel)); + + //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); + + TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); + for(i=0; ichan[lChannel]; + //ULONG Channel = deviceExtension->Channel + lChannel; + ULONG TFD; + + + KdPrint(("UniataAhciHardReset: lChan %d\n", chan->lChannel)); + + (*signature) = 0xffffffff; + + UniataAhciStop(chan); + if(UniataSataPhyEnable(HwDeviceExtension, lChannel, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE) == 0xff) { + KdPrint((" no PHY\n")); + return 0xff; + } + + /* Wait for clearing busy status. */ + TFD = UniataAhciWaitReady(chan, 15000); + if(TFD & (IDE_STATUS_DRQ | IDE_STATUS_BUSY)) { + KdPrint((" busy: TFD %#x\n", TFD)); + return TFD; + } + KdPrint((" TFD %#x\n", TFD)); + +#ifdef DBG + UniataDumpAhciPortRegs(chan); +#endif // DBG + + (*signature) = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG); + KdPrint((" sig: %#x\n", *signature)); + + UniataAhciStart(chan); + + return 0; + +} // end UniataAhciHardReset() + +VOID +NTAPI +UniataAhciReset( + IN PVOID HwDeviceExtension, + IN ULONG lChannel + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + //ULONG Channel = deviceExtension->Channel + lChannel; + //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); + ULONG CAP; + //ULONGIO_PTR base; + ULONG signature; + ULONG i; + ULONG VendorID = deviceExtension->DevID & 0xffff; + + KdPrint(("UniataAhciReset: lChan %d\n", chan->lChannel)); + + //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); + + /* Disable port interrupts */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); + + if(UniataAhciHardReset(HwDeviceExtension, lChannel, &signature)) { + + KdPrint((" No devices in all LUNs\n")); + for (i=0; iNumberLuns; i++) { + // Zero device fields to ensure that if earlier devices were found, + // but not claimed, the fields are cleared. + UniataForgetDevice(chan->lun[i]); + } + + /* enable wanted port interrupts */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, + ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC); + return; + } + + /* enable wanted port interrupts */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, + (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | + ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | + ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC) : 0) | + ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | + ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR) ); + + /* + * Only probe for PortMultiplier if HW has support. + * Ignore Marvell, which is not working, + */ + CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); + if ((CAP & AHCI_CAP_SPM) && + (VendorID != ATA_MARVELL_ID)) { + KdPrint((" check PM\n")); + signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, AHCI_DEV_SEL_PM); + /* Workaround for some ATI chips, failing to soft-reset + * when port multiplicator supported, but absent. + * XXX: We can also check PxIS.IPMS==1 here to be sure. */ + if (signature == 0xffffffff) { + KdPrint((" re-check PM\n")); + signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0); + } + } else { + signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0); + } + + KdPrint((" signature %#x\n", signature)); + chan->lun[0]->DeviceFlags &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | CTRFLAGS_AHCI_PM); + switch (signature >> 16) { + case 0x0000: + KdPrint((" ATA dev\n")); + chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT; + chan->PmLunMap = 0; + break; + case 0x9669: + KdPrint((" PM\n")); + if(deviceExtension->NumberLuns > 1) { + chan->ChannelCtrlFlags |= CTRFLAGS_AHCI_PM; + UniataSataIdentifyPM(chan); + } else { + KdPrint((" no PM supported (1 lun/chan)\n")); + } + break; + case 0xeb14: + KdPrint((" ATAPI dev\n")); + chan->lun[0]->DeviceFlags |= (DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT); + chan->PmLunMap = 0; + break; + default: /* SOS XXX */ + KdPrint((" default to ATA ???\n")); + chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT; + chan->PmLunMap = 0; + } + + return; + +} // end UniataAhciReset() + +VOID +NTAPI +UniataAhciStartFR( + IN PHW_CHANNEL chan + ) +{ + ULONG CMD; + + KdPrint2(("UniataAhciStartFR: lChan %d\n", chan->lChannel)); + + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + KdPrint2((" CMD %#x\n", CMD)); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD | ATA_AHCI_P_CMD_FRE); + + return; +} // end UniataAhciStartFR() + +VOID +NTAPI +UniataAhciStopFR( + IN PHW_CHANNEL chan + ) +{ + ULONG CMD; + ULONG i; + + KdPrint2(("UniataAhciStopFR: lChan %d\n", chan->lChannel)); + + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + KdPrint2((" CMD %#x\n", CMD)); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD & ~ATA_AHCI_P_CMD_FRE); + + for(i=0; i<1000; i++) { + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + if(!(CMD & ATA_AHCI_P_CMD_FR)) { + KdPrint2((" final CMD %#x\n", CMD)); + return; + } + AtapiStallExecution(1000); + } + KdPrint2((" CMD %#x\n", CMD)); + KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); + KdPrint2(("UniataAhciStopFR: timeout\n")); + return; +} // end UniataAhciStopFR() + +VOID +NTAPI +UniataAhciStart( + IN PHW_CHANNEL chan + ) +{ + ULONG IS, CMD; + SATA_SERROR_REG SError; + + KdPrint2(("UniataAhciStart: lChan %d\n", chan->lChannel)); + + /* clear SATA error register */ + SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); + + /* clear any interrupts pending on this channel */ + IS = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS); + + KdPrint2((" SError %#x, IS %#x\n", SError.Reg, IS)); + + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + KdPrint2((" CMD %#x\n", CMD)); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, + CMD | + ATA_AHCI_P_CMD_ST | + ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0)); + + return; +} // end UniataAhciStart() + +VOID +NTAPI +UniataAhciCLO( + IN PHW_CHANNEL chan + ) +{ + //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + //PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + ULONG CAP, CMD; + //SATA_SERROR_REG SError; + ULONG i; + + KdPrint2(("UniataAhciCLO: lChan %d\n", chan->lChannel)); + + /* issue Command List Override if supported */ + //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); + CAP = chan->DeviceExtension->AHCI_CAP; + if(!(CAP & AHCI_CAP_SCLO)) { + return; + } + KdPrint2((" send CLO\n")); + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + CMD |= ATA_AHCI_P_CMD_CLO; + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); + + for(i=0; i<1000; i++) { + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + if(!(CMD & ATA_AHCI_P_CMD_CLO)) { + KdPrint2((" final CMD %#x\n", CMD)); + return; + } + AtapiStallExecution(1000); + } + KdPrint2((" CMD %#x\n", CMD)); + KdPrint2(("UniataAhciCLO: timeout\n")); + return; +} // end UniataAhciCLO() + +VOID +NTAPI +UniataAhciStop( + IN PHW_CHANNEL chan + ) +{ + ULONG CMD; + //SATA_SERROR_REG SError; + ULONG i; + + KdPrint2(("UniataAhciStop: lChan %d\n", chan->lChannel)); + + /* issue Command List Override if supported */ + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + CMD &= ~ATA_AHCI_P_CMD_ST; + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); + + for(i=0; i<1000; i++) { + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + if(!(CMD & ATA_AHCI_P_CMD_CR)) { + KdPrint2((" final CMD %#x\n", CMD)); + return; + } + AtapiStallExecution(1000); + } + KdPrint2((" CMD %#x\n", CMD)); + KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); + KdPrint2(("UniataAhciStop: timeout\n")); + return; +} // end UniataAhciStop() + +UCHAR +NTAPI +UniataAhciBeginTransaction( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber, + IN PSCSI_REQUEST_BLOCK Srb + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + //ULONG Channel = deviceExtension->Channel + lChannel; + //ULONG hIS; + ULONG CMD; + //AHCI_IS_REG IS; + PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); + //SATA_SSTATUS_REG SStatus; + //SATA_SERROR_REG SError; + //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); + //ULONGIO_PTR base; + ULONG tag=0; + //ULONG i; + + PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); + + KdPrint2(("UniataAhciBeginTransaction: lChan %d\n", chan->lChannel)); + + if(AtaReq->dma_entries > (USHORT)0xffff) { + KdPrint2(("UniataAhciBeginTransaction too long DMA tab\n")); + return 0; + } + + AHCI_CL->prd_length = (USHORT)AtaReq->dma_entries; + AHCI_CL->cmd_flags = AtaReq->ahci.io_cmd_flags; + AHCI_CL->bytecount = 0; + AHCI_CL->cmd_table_phys = AtaReq->ahci.ahci_base64; + if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) { + KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK)); + } + + CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); + KdPrint2((" CMD %#x\n", CMD)); + CMD &= ~ATA_AHCI_P_CMD_ATAPI; + KdPrint2((" send CMD %#x\n", CMD)); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); + + /* issue command to controller */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, ATA_AHCI_P_CMD_ST); + + if(!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE)) { + // TODO: check if we send ATA_RESET and wait for ready of so. + if(AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_RESET) { + ULONG TFD; + ULONG i; + + for(i=0; i<1000000; i++) { + TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); + if(!(TFD & IDE_STATUS_BUSY)) { + break; + } + } + if(TFD & IDE_STATUS_BUSY) { + KdPrint2((" timeout\n")); + } + if(TFD & IDE_STATUS_ERROR) { + KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8))); + } + AtaReq->ahci.in_status = TFD; + + return 0x00; + } + } + + return IDE_STATUS_IDLE; + +} // end UniataAhciBeginTransaction() + +UCHAR +NTAPI +UniataAhciEndTransaction( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber, + IN PSCSI_REQUEST_BLOCK Srb + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + //ULONG Channel = deviceExtension->Channel + lChannel; + //ULONG hIS; + PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); + ULONG TFD; + PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); + + KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan->lChannel)); + + TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); + KdPrint2((" TFD %#x\n", TFD)); + + if(TFD & IDE_STATUS_ERROR) { + KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8))); + } + AtaReq->ahci.in_status = TFD; + + //if (request->flags & ATA_R_CONTROL) { + + AtaReq->ahci.in_bcount = (ULONG)(RCV_FIS[12]) | ((ULONG)(RCV_FIS[13]) << 8); + AtaReq->ahci.in_lba = (ULONG)(RCV_FIS[4]) | ((ULONGLONG)(RCV_FIS[5]) << 8) | + ((ULONGLONG)(RCV_FIS[6]) << 16); + if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) { + AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) | + ((ULONGLONG)(RCV_FIS[9]) << 32) | + ((ULONGLONG)(RCV_FIS[10]) << 40); + } else { + AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) | + ((ULONGLONG)(RCV_FIS[9]) << 32) | + ((ULONGLONG)(RCV_FIS[7] & 0x0f) << 24); + } + + //} + + return 0; + +} // end UniataAhciEndTransaction() + +VOID +NTAPI +UniataAhciResume( + IN PHW_CHANNEL chan + ) +{ + ULONGLONG base; + + KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel)); + +#ifdef DBG + UniataDumpAhciPortRegs(chan); +#endif // DBG + + /* Disable port interrupts */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); + + /* setup work areas */ + base = chan->AHCI_CTL_PhAddr; + if(!base) { + KdPrint2((PRINT_PREFIX " AHCI buffer allocation failed\n")); + return; + } + KdPrint2((PRINT_PREFIX " AHCI CLB setup\n")); + if(base & AHCI_CLB_ALIGNEMENT_MASK) { + KdPrint2((PRINT_PREFIX " AHCI CLB address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK)); + } + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB, + (ULONG)(base & 0xffffffff)); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB + 4, + (ULONG)((base >> 32) & 0xffffffff)); + + KdPrint2((PRINT_PREFIX " AHCI RCV FIS setup\n")); + base = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, rcv_fis); + if(base & AHCI_FIS_ALIGNEMENT_MASK) { + KdPrint2((PRINT_PREFIX " AHCI FIS address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK)); + } + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB, + (ULONG)(base & 0xffffffff)); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB + 4, + (ULONG)((base >> 32) & 0xffffffff)); + + /* activate the channel and power/spin up device */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, + (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | + (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM)) ? ATA_AHCI_P_CMD_ALPE : 0) | + (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM2)) ? ATA_AHCI_P_CMD_ASP : 0 )) + ); + +#ifdef DBG + UniataDumpAhciPortRegs(chan); +#endif // DBG + + UniataAhciStartFR(chan); + UniataAhciStart(chan); + +#ifdef DBG + UniataDumpAhciPortRegs(chan); +#endif // DBG + + return; +} // end UniataAhciResume() + +#if 0 +VOID +NTAPI +UniataAhciSuspend( + IN PHW_CHANNEL chan + ) +{ + ULONGLONG base; + SATA_SCONTROL_REG SControl; + + KdPrint2(("UniataAhciSuspend:\n")); + + /* Disable port interrupts */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); + + /* Reset command register. */ + UniataAhciStop(chan); + UniataAhciStopFR(chan); + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 0); + + /* Allow everything including partial and slumber modes. */ + UniataSataWritePort4(chan, IDX_SATA_SControl, 0, 0); + + /* Request slumber mode transition and give some time to get there. */ + UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, ATA_AHCI_P_CMD_SLUMBER); + AtapiStallExecution(100); + + /* Disable PHY. */ + SControl.Reg = 0; + SControl.DET = SStatus_DET_Offline; + UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, 0); + + return; +} // end UniataAhciSuspend() +#endif + +BOOLEAN +NTAPI +UniataAhciReadPM( + IN PHW_CHANNEL chan, + IN ULONG DeviceNumber, + IN ULONG Reg, + OUT PULONG result + ) +{ + //ULONG Channel = deviceExtension->Channel + lChannel; + //ULONG hIS; + //ULONG CI; + //AHCI_IS_REG IS; + //ULONG tag=0; + PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); + PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); + + KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan->lChannel, DeviceNumber)); + + if(DeviceNumber == DEVNUM_NOT_SPECIFIED) { + (*result) = UniataSataReadPort4(chan, Reg, 0); + return TRUE; + } + if(DeviceNumber < AHCI_DEV_SEL_PM) { + switch(Reg) { + case IDX_SATA_SStatus: + Reg = 0; break; + case IDX_SATA_SError: + Reg = 1; break; + case IDX_SATA_SControl: + Reg = 2; break; + default: + return FALSE; + } + } + + RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); + AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; + AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM; + AHCI_CMD->cfis[2] = IDE_COMMAND_READ_PM; + AHCI_CMD->cfis[3] = (UCHAR)Reg; + AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber); + AHCI_CMD->cfis[15] = IDE_DC_A_4BIT; + + if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 10) == 0xff) { + KdPrint2((" PM read failed\n")); + return FALSE; + } + + KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis)); + + (*result) = UniataAhciUlongFromRFIS(RCV_FIS); + return TRUE; + +} // end UniataAhciReadPM() + +UCHAR +NTAPI +UniataAhciWritePM( + IN PHW_CHANNEL chan, + IN ULONG DeviceNumber, + IN ULONG Reg, + IN ULONG value + ) +{ + //ULONG Channel = deviceExtension->Channel + lChannel; + //ULONG hIS; + //ULONG CI; + //AHCI_IS_REG IS; + //ULONG tag=0; + ULONG TFD; + PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); + //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); + + KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan->lChannel, DeviceNumber, value)); + + if(DeviceNumber == DEVNUM_NOT_SPECIFIED) { + UniataSataWritePort4(chan, Reg, value, 0); + return 0; + } + if(DeviceNumber < AHCI_DEV_SEL_PM) { + switch(Reg) { + case IDX_SATA_SStatus: + Reg = 0; break; + case IDX_SATA_SError: + Reg = 1; break; + case IDX_SATA_SControl: + Reg = 2; break; + default: + return 0xff; + } + } + + RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); + AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; + AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM; + AHCI_CMD->cfis[2] = IDE_COMMAND_WRITE_PM; + AHCI_CMD->cfis[3] = (UCHAR)Reg; + AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber); + + AHCI_CMD->cfis[12] = (UCHAR)(value & 0xff); + AHCI_CMD->cfis[4] = (UCHAR)((value >> 8) & 0xff); + AHCI_CMD->cfis[5] = (UCHAR)((value >> 16) & 0xff); + AHCI_CMD->cfis[6] = (UCHAR)((value >> 24) & 0xff); + + AHCI_CMD->cfis[15] = IDE_DC_A_4BIT; + + if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 100) == 0xff) { + KdPrint2((" PM write failed\n")); + return 0xff; + } + + TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); + + if(TFD & IDE_STATUS_ERROR) { + KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8))); + } + return (UCHAR)(TFD >> 8); + +} // end UniataAhciWritePM() + +VOID +UniataAhciSetupCmdPtr( +IN OUT PATA_REQ AtaReq + ) +{ + union { + PUCHAR prd_base; + ULONGLONG prd_base64; + }; + union { + PUCHAR prd_base0; + ULONGLONG prd_base64_0; + }; + ULONG d; + + prd_base64_0 = prd_base64 = 0; + prd_base = (PUCHAR)(&AtaReq->ahci_cmd0); + prd_base0 = prd_base; + + prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK)) & ~AHCI_CMD_ALIGNEMENT_MASK; + + d = (ULONG)(prd_base64 - prd_base64_0); + KdPrint2((PRINT_PREFIX " aligned %I64x, d=%x\n", prd_base64, d)); + + AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64; + KdPrint2((PRINT_PREFIX " ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr)); +} // end UniataAhciSetupCmdPtr() diff --git a/reactos/drivers/storage/ide/uniata/id_sata.h b/reactos/drivers/storage/ide/uniata/id_sata.h index a53fee91bdb..3ca9e0a293f 100644 --- a/reactos/drivers/storage/ide/uniata/id_sata.h +++ b/reactos/drivers/storage/ide/uniata/id_sata.h @@ -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__ diff --git a/reactos/drivers/storage/ide/uniata/inc/CrNtStubs.h b/reactos/drivers/storage/ide/uniata/inc/CrNtStubs.h index 53030f062bb..4cef3ed0e9e 100644 --- a/reactos/drivers/storage/ide/uniata/inc/CrNtStubs.h +++ b/reactos/drivers/storage/ide/uniata/inc/CrNtStubs.h @@ -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,(),()) diff --git a/reactos/drivers/storage/ide/uniata/inc/CrossNt.h b/reactos/drivers/storage/ide/uniata/inc/CrossNt.h index eeab727cae6..a0c074f2caa 100644 --- a/reactos/drivers/storage/ide/uniata/inc/CrossNt.h +++ b/reactos/drivers/storage/ide/uniata/inc/CrossNt.h @@ -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__ \ No newline at end of file diff --git a/reactos/drivers/storage/ide/uniata/inc/PostDbgMesg.h b/reactos/drivers/storage/ide/uniata/inc/PostDbgMesg.h index 5c30d729c0e..1b020610827 100644 --- a/reactos/drivers/storage/ide/uniata/inc/PostDbgMesg.h +++ b/reactos/drivers/storage/ide/uniata/inc/PostDbgMesg.h @@ -43,4 +43,4 @@ DbgDump_SetAutoReconnect( }; #endif //__cplusplus -#endif //__DBG_DUMP_TOOLS__H__ +#endif //__DBG_DUMP_TOOLS__H__ \ No newline at end of file diff --git a/reactos/drivers/storage/ide/uniata/inc/misc.h b/reactos/drivers/storage/ide/uniata/inc/misc.h index eeebfaf964e..c144d33fdda 100644 --- a/reactos/drivers/storage/ide/uniata/inc/misc.h +++ b/reactos/drivers/storage/ide/uniata/inc/misc.h @@ -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__ diff --git a/reactos/drivers/storage/ide/uniata/ntddk_ex.h b/reactos/drivers/storage/ide/uniata/ntddk_ex.h index e13ca480909..1c74fca7f21 100644 --- a/reactos/drivers/storage/ide/uniata/ntddk_ex.h +++ b/reactos/drivers/storage/ide/uniata/ntddk_ex.h @@ -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 diff --git a/reactos/drivers/storage/ide/uniata/srb.h b/reactos/drivers/storage/ide/uniata/srb.h index 9c3e46f4c6f..abc926ea6b0 100644 --- a/reactos/drivers/storage/ide/uniata/srb.h +++ b/reactos/drivers/storage/ide/uniata/srb.h @@ -935,7 +935,7 @@ ScsiPortWriteRegisterBufferUlong( SCSIPORT_API SCSI_PHYSICAL_ADDRESS NTAPI ScsiPortConvertUlongToPhysicalAddress( - ULONG_PTR UlongAddress + ULONG UlongAddress ); SCSIPORT_API diff --git a/reactos/drivers/storage/ide/uniata/stdafx.h b/reactos/drivers/storage/ide/uniata/stdafx.h index 6ee3304681e..361d5d01c7c 100644 --- a/reactos/drivers/storage/ide/uniata/stdafx.h +++ b/reactos/drivers/storage/ide/uniata/stdafx.h @@ -1,3 +1,5 @@ +#include "config.h" + extern "C" { #include @@ -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" - diff --git a/reactos/drivers/storage/ide/uniata/uata_ctl.h b/reactos/drivers/storage/ide/uniata/uata_ctl.h index 560b1d87fad..e377be310bc 100644 --- a/reactos/drivers/storage/ide/uniata/uata_ctl.h +++ b/reactos/drivers/storage/ide/uniata/uata_ctl.h @@ -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; diff --git a/reactos/drivers/storage/ide/uniata/uniata_ver.h b/reactos/drivers/storage/ide/uniata/uniata_ver.h index 381ae7b73db..d0a5d88c642 100644 --- a/reactos/drivers/storage/ide/uniata/uniata_ver.h +++ b/reactos/drivers/storage/ide/uniata/uniata_ver.h @@ -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"