[USBOHCI_NEW][USBUHCI_NEW] Avoid unnecessary/incorrect status defines.
[reactos.git] / drivers / storage / storahci / storahci.h
index 97144ad..8c5277d 100644 (file)
@@ -9,9 +9,14 @@
 #include <ata.h>
 #include <storport.h>
 
+#define NDEBUG
+#include <debug.h>
+
 #define DEBUG 1
+#if defined(_MSC_VER)
 #pragma warning(disable:4214) // bit field types other than int
 #pragma warning(disable:4201) // nameless struct/union
+#endif
 
 #define MAXIMUM_AHCI_PORT_COUNT             32
 #define MAXIMUM_AHCI_PRDT_ENTRIES           32
 #define MAXIMUM_QUEUE_BUFFER_SIZE           255
 #define MAXIMUM_TRANSFER_LENGTH             (128*1024) // 128 KB
 
+#define DEVICE_ATA_BLOCK_SIZE               512
+
 // device type (DeviceParams)
 #define AHCI_DEVICE_TYPE_ATA                1
 #define AHCI_DEVICE_TYPE_ATAPI              2
 #define AHCI_DEVICE_TYPE_NODEVICE           3
 
 // section 3.1.2
-#define AHCI_Global_HBA_CONTROL_HR          (1 << 0)
-#define AHCI_Global_HBA_CONTROL_IE          (1 << 1)
-#define AHCI_Global_HBA_CONTROL_MRSM        (1 << 2)
-#define AHCI_Global_HBA_CONTROL_AE          (1 << 31)
 #define AHCI_Global_HBA_CAP_S64A            (1 << 31)
 
+// FIS Types : http://wiki.osdev.org/AHCI
+#define FIS_TYPE_REG_H2D        0x27 // Register FIS - host to device
+#define FIS_TYPE_REG_D2H        0x34 // Register FIS - device to host
+#define FIS_TYPE_DMA_ACT        0x39 // DMA activate FIS - device to host
+#define FIS_TYPE_DMA_SETUP      0x41 // DMA setup FIS - bidirectional
+#define FIS_TYPE_BIST           0x58 // BIST activate FIS - bidirectional
+#define FIS_TYPE_PIO_SETUP      0x5F // PIO setup FIS - device to host
+#define FIS_TYPE_DEV_BITS       0xA1 // Set device bits FIS - device to host
+
 #define AHCI_ATA_CFIS_FisType               0
 #define AHCI_ATA_CFIS_PMPort_C              1
 #define AHCI_ATA_CFIS_CommandReg            2
@@ -49,6 +61,7 @@
 // ATA Functions
 #define ATA_FUNCTION_ATA_COMMAND            0x100
 #define ATA_FUNCTION_ATA_IDENTIFY           0x101
+#define ATA_FUNCTION_ATA_READ               0x102
 
 // ATAPI Functions
 #define ATA_FUNCTION_ATAPI_COMMAND          0x200
@@ -56,6 +69,8 @@
 // ATA Flags
 #define ATA_FLAGS_DATA_IN                   (1 << 1)
 #define ATA_FLAGS_DATA_OUT                  (1 << 2)
+#define ATA_FLAGS_48BIT_COMMAND             (1 << 3)
+#define ATA_FLAGS_USE_DMA                   (1 << 4)
 
 #define IsAtaCommand(AtaFunction)           (AtaFunction & ATA_FUNCTION_ATA_COMMAND)
 #define IsAtapiCommand(AtaFunction)         (AtaFunction & ATA_FUNCTION_ATAPI_COMMAND)
 #define IsAdapterCAPS64(CAP)                (CAP & AHCI_Global_HBA_CAP_S64A)
 
 // 3.1.1 NCS = CAP[12:08] -> Align
-#define AHCI_Global_Port_CAP_NCS(x)            (((x) & 0xF00) >> 8)
+#define AHCI_Global_Port_CAP_NCS(x)         (((x) & 0xF00) >> 8)
 
 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
-#if DEBUG
-    #define DebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
-#endif
+//#define AhciDebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
+#define AhciDebugPrint(format, ...) DbgPrint("(%s:%d) " format, __RELFILE__, __LINE__, ##__VA_ARGS__)
 
 typedef
 VOID
 (*PAHCI_COMPLETION_ROUTINE) (
-    __in PVOID AdapterExtension,
     __in PVOID PortExtension,
     __in PVOID Srb
     );
@@ -225,7 +238,7 @@ typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
         ULONG R : 1;         // Reset
         ULONG B : 1;         // BIST
         ULONG C : 1;         //Clear Busy upon R_OK
-        ULONG DW0_Reserved : 1;
+        ULONG RSV : 1;
         ULONG PMP : 4;       //Port Multiplier Port
 
         ULONG PRDTL : 16;    //Physical Region Descriptor Table Length
@@ -234,6 +247,20 @@ typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
     ULONG Status;
 } AHCI_COMMAND_HEADER_DESCRIPTION;
 
+typedef union _AHCI_GHC
+{
+    struct
+    {
+        ULONG HR : 1;
+        ULONG IE : 1;
+        ULONG MRSM : 1;
+        ULONG RSV0 : 28;
+        ULONG AE : 1;
+    };
+
+    ULONG Status;
+} AHCI_GHC;
+
 // section 3.3.7
 typedef union _AHCI_PORT_CMD
 {
@@ -295,6 +322,25 @@ typedef union _AHCI_SERIAL_ATA_STATUS
     ULONG Status;
 }  AHCI_SERIAL_ATA_STATUS;
 
+typedef union _AHCI_TASK_FILE_DATA
+{
+    struct
+    {
+        struct _STS
+        {
+            UCHAR ERR : 1;
+            UCHAR CS1 : 2;
+            UCHAR DRQ : 1;
+            UCHAR CS2 : 3;
+            UCHAR BSY : 1;
+        } STS;
+        UCHAR ERR;
+        USHORT RSV;
+    };
+
+    ULONG Status;
+} AHCI_TASK_FILE_DATA;
+
 typedef struct _AHCI_PRDT
 {
     ULONG DBA;
@@ -321,10 +367,10 @@ typedef struct _AHCI_COMMAND_TABLE
 typedef struct _AHCI_COMMAND_HEADER
 {
     AHCI_COMMAND_HEADER_DESCRIPTION DI;   // DW 0
-    ULONG PRDBC;                // DW 1
-    ULONG CTBA0;                // DW 2
-    ULONG CTBA_U0;              // DW 3
-    ULONG Reserved[4];          // DW 4-7
+    ULONG PRDBC;                          // DW 1
+    ULONG CTBA;                           // DW 2
+    ULONG CTBA_U;                         // DW 3
+    ULONG Reserved[4];                    // DW 4-7
 } AHCI_COMMAND_HEADER, *PAHCI_COMMAND_HEADER;
 
 // Received FIS
@@ -365,27 +411,33 @@ typedef struct _AHCI_PORT
     ULONG   Vendor[4];                          // 0x70 ~ 0x7F, vendor specific
 } AHCI_PORT, *PAHCI_PORT;
 
-#ifdef DEBUG
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLB) == 0x00);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLBU) == 0x04);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, FB) == 0x08);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBU) == 0x0C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, IS) == 0x10);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, IE) == 0x14);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CMD) == 0x18);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV0) == 0x1C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, TFD) == 0x20);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SIG) == 0x24);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SSTS) == 0x28);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SCTL) == 0x2C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SERR) == 0x30);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SACT) == 0x34);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CI) == 0x38);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SNTF) == 0x3C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBS) == 0x40);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV1) == 0x44);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, Vendor) == 0x70);
-#endif
+typedef union _AHCI_INTERRUPT_ENABLE
+{
+    struct
+    {
+        ULONG DHRE :1;
+        ULONG PSE :1;
+        ULONG DSE :1;
+        ULONG SDBE :1;
+        ULONG UFE :1;
+        ULONG DPE :1;
+        ULONG PCE :1;
+        ULONG DMPE :1;
+        ULONG DW5_Reserved :14;
+        ULONG PRCE :1;
+        ULONG IPME :1;
+        ULONG OFE :1;
+        ULONG DW5_Reserved2 :1;
+        ULONG INFE :1;
+        ULONG IFE :1;
+        ULONG HBDE :1;
+        ULONG HBFE :1;
+        ULONG TFEE :1;
+        ULONG CPDE :1;
+    };
+
+    ULONG Status;
+} AHCI_INTERRUPT_ENABLE;
 
 typedef struct _AHCI_MEMORY_REGISTERS
 {
@@ -406,31 +458,33 @@ typedef struct _AHCI_MEMORY_REGISTERS
     AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT];
 } AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS;
 
-#ifdef DEBUG
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP) == 0x00);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, GHC) == 0x04);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, IS) == 0x08);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PI) == 0x0C);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VS) == 0x10);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_CTL) == 0x14);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_PTS) == 0x18);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_LOC) == 0x1C);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_CTL) == 0x20);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP2) == 0x24);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, BOHC) == 0x28);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, Reserved) == 0x2C);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VendorSpecific) == 0xA0);
-#endif
-
 // Holds information for each attached attached port to a given adapter.
 typedef struct _AHCI_PORT_EXTENSION
 {
     ULONG PortNumber;
     ULONG QueueSlots;                                   // slots which we have already assigned task (Slot)
     ULONG CommandIssuedSlots;                           // slots which has been programmed
-    BOOLEAN IsActive;
+    ULONG MaxPortQueueDepth;
+
+    struct
+    {
+        UCHAR RemovableDevice;
+        UCHAR Lba48BitMode;
+        UCHAR AccessType;
+        UCHAR DeviceType;
+        UCHAR IsActive;
+        LARGE_INTEGER MaxLba;
+        ULONG BytesPerLogicalSector;
+        ULONG BytesPerPhysicalSector;
+        UCHAR VendorId[41];
+        UCHAR RevisionID[9];
+        UCHAR SerialNumber[21];
+    } DeviceParams;
+
+    STOR_DPC CommandCompletion;
     PAHCI_PORT Port;                                    // AHCI Port Infomation
     AHCI_QUEUE SrbQueue;                                // pending Srbs
+    AHCI_QUEUE CompletionQueue;
     PSCSI_REQUEST_BLOCK Slot[MAXIMUM_AHCI_PORT_NCS];    // Srbs which has been alloted a port
     PAHCI_RECEIVED_FIS ReceivedFIS;
     PAHCI_COMMAND_HEADER CommandList;
@@ -462,11 +516,6 @@ typedef struct _AHCI_ADAPTER_EXTENSION
 
     PVOID NonCachedExtension; // holds virtual address to noncached buffer allocated for Port Extension
 
-    struct
-    {
-        UCHAR DeviceType;
-    } DeviceParams;
-
     struct
     {
         // Message per port or shared port?
@@ -508,13 +557,25 @@ typedef struct _AHCI_SRB_EXTENSION
 
     ULONG SlotIndex;
     LOCAL_SCATTER_GATHER_LIST Sgl;
+    PLOCAL_SCATTER_GATHER_LIST pSgl;
     PAHCI_COMPLETION_ROUTINE CompletionRoutine;
+
+    // for alignment purpose -- 128 byte alignment
+    // do not try to access (R/W) this field
+    UCHAR Reserved[128];
 } AHCI_SRB_EXTENSION, *PAHCI_SRB_EXTENSION;
 
 //////////////////////////////////////////////////////////////
 //                       Declarations                       //
 //////////////////////////////////////////////////////////////
 
+VOID
+AhciProcessIO (
+    __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+    __in UCHAR PathId,
+    __in PSCSI_REQUEST_BLOCK Srb
+    );
+
 BOOLEAN
 AhciAdapterReset (
     __in PAHCI_ADAPTER_EXTENSION AdapterExtension
@@ -534,6 +595,24 @@ IsPortValid (
     __in ULONG pathId
     );
 
+UCHAR DeviceRequestSense (
+    __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+    __in PSCSI_REQUEST_BLOCK Srb,
+    __in PCDB Cdb
+    );
+
+UCHAR DeviceRequestReadWrite (
+    __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+    __in PSCSI_REQUEST_BLOCK Srb,
+    __in PCDB Cdb
+    );
+
+UCHAR DeviceRequestCapacity (
+    __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+    __in PSCSI_REQUEST_BLOCK Srb,
+    __in PCDB Cdb
+    );
+
 UCHAR
 DeviceInquiryRequest (
     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
@@ -541,6 +620,18 @@ DeviceInquiryRequest (
     __in PCDB Cdb
     );
 
+UCHAR DeviceRequestComplete (
+    __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+    __in PSCSI_REQUEST_BLOCK Srb,
+    __in PCDB Cdb
+    );
+
+UCHAR DeviceReportLuns (
+    __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+    __in PSCSI_REQUEST_BLOCK Srb,
+    __in PCDB Cdb
+    );
+
 __inline
 BOOLEAN
 AddQueue (
@@ -559,3 +650,68 @@ PAHCI_SRB_EXTENSION
 GetSrbExtension(
     __in PSCSI_REQUEST_BLOCK Srb
     );
+
+__inline
+ULONG64
+AhciGetLba (
+    __in PCDB Cdb,
+    __in ULONG CdbLength
+    );
+
+//////////////////////////////////////////////////////////////
+//                       Assertions                         //
+//////////////////////////////////////////////////////////////
+
+// I assert every silly mistake I can do while coding
+// because god never help me debugging the code
+// but these asserts do :')
+
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP)            == 0x00);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, GHC)            == 0x04);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, IS)             == 0x08);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PI)             == 0x0C);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VS)             == 0x10);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_CTL)        == 0x14);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_PTS)        == 0x18);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_LOC)         == 0x1C);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_CTL)         == 0x20);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP2)           == 0x24);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, BOHC)           == 0x28);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, Reserved)       == 0x2C);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VendorSpecific) == 0xA0);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PortList)       == 0x100);
+
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLB)    == 0x00);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLBU)   == 0x04);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, FB)     == 0x08);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBU)    == 0x0C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, IS)     == 0x10);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, IE)     == 0x14);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CMD)    == 0x18);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV0)   == 0x1C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, TFD)    == 0x20);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SIG)    == 0x24);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SSTS)   == 0x28);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SCTL)   == 0x2C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SERR)   == 0x30);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SACT)   == 0x34);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CI)     == 0x38);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SNTF)   == 0x3C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBS)    == 0x40);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV1)   == 0x44);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, Vendor) == 0x70);
+
+C_ASSERT((sizeof(AHCI_COMMAND_TABLE) % 128) == 0);
+
+C_ASSERT(sizeof(AHCI_GHC)                        == sizeof(ULONG));
+C_ASSERT(sizeof(AHCI_PORT_CMD)                   == sizeof(ULONG));
+C_ASSERT(sizeof(AHCI_TASK_FILE_DATA)             == sizeof(ULONG));
+C_ASSERT(sizeof(AHCI_INTERRUPT_ENABLE)           == sizeof(ULONG));
+C_ASSERT(sizeof(AHCI_SERIAL_ATA_STATUS)          == sizeof(ULONG));
+C_ASSERT(sizeof(AHCI_SERIAL_ATA_CONTROL)         == sizeof(ULONG));
+C_ASSERT(sizeof(AHCI_COMMAND_HEADER_DESCRIPTION) == sizeof(ULONG));
+
+C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, CFIS) == 0x00);
+C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, ACMD) == 0x40);
+C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, RSV0) == 0x50);
+C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, PRDT) == 0x80);