5ba09785f1f9d71a30360be2208afa1973f5daf9
[reactos.git] / drivers / storage / storahci / storahci.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GNU GPLv2 only as published by the Free Software Foundation
4 * PURPOSE: To Implement AHCI Miniport driver targeting storport NT 5.2
5 * PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com)
6 */
7
8 #include <ntddk.h>
9 #include <ata.h>
10 #include <storport.h>
11
12 #define DEBUG 1
13
14 #define MAXIMUM_AHCI_PORT_COUNT 25
15 #define MAXIMUM_QUEUE_BUFFER_SIZE 255
16 #define MAXIMUM_TRANSFER_LENGTH (128*1024) // 128 KB
17
18 // section 3.1.2
19 #define AHCI_Global_HBA_CONTROL_HR (1 << 0)
20 #define AHCI_Global_HBA_CONTROL_IE (1 << 1)
21 #define AHCI_Global_HBA_CONTROL_MRSM (1 << 2)
22 #define AHCI_Global_HBA_CONTROL_AE (1 << 31)
23 #define AHCI_Global_HBA_CAP_S64A (1 << 31)
24
25 // ATA Functions
26 #define ATA_FUNCTION_ATA_COMMAND 0x100
27 #define ATA_FUNCTION_ATA_IDENTIFY 0x101
28
29 // ATAPI Functions
30 #define ATA_FUNCTION_ATAPI_COMMAND 0x200
31
32 // ATA Flags
33 #define ATA_FLAGS_DATA_IN (1 << 1)
34 #define ATA_FLAGS_DATA_OUT (1 << 2)
35
36 #define IsAtaCommand(AtaFunction) (AtaFunction & ATA_FUNCTION_ATA_COMMAND)
37 #define IsAtapiCommand(AtaFunction) (AtaFunction & ATA_FUNCTION_ATAPI_COMMAND)
38 #define IsDataTransferNeeded(SrbExtension) (SrbExtension->Flags & (ATA_FLAGS_DATA_IN | ATA_FLAGS_DATA_OUT))
39 #define IsAdapterCAPS64(CAP) (CAP & AHCI_Global_HBA_CAP_S64A)
40
41 // 3.1.1 NCS = CAP[12:08] -> Align
42 #define AHCI_Global_Port_CAP_NCS(x) (((x) & 0xF00) >> 8)
43
44 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
45 #if DEBUG
46 #define DebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
47 #endif
48
49 //////////////////////////////////////////////////////////////
50 // ---- Support Structures --- //
51 //////////////////////////////////////////////////////////////
52
53 // section 3.3.5
54 typedef union _AHCI_INTERRUPT_STATUS
55 {
56 struct
57 {
58 ULONG DHRS:1; //Device to Host Register FIS Interrupt
59 ULONG PSS :1; //PIO Setup FIS Interrupt
60 ULONG DSS :1; //DMA Setup FIS Interrupt
61 ULONG SDBS :1; //Set Device Bits Interrupt
62 ULONG UFS :1; //Unknown FIS Interrupt
63 ULONG DPS :1; //Descriptor Processed
64 ULONG PCS :1; //Port Connect Change Status
65 ULONG DMPS :1; //Device Mechanical Presence Status (DMPS)
66 ULONG Reserved :14;
67 ULONG PRCS :1; //PhyRdy Change Status
68 ULONG IPMS :1; //Incorrect Port Multiplier Status
69 ULONG OFS :1; //Overflow Status
70 ULONG Reserved2 :1;
71 ULONG INFS :1; //Interface Non-fatal Error Status
72 ULONG IFS :1; //Interface Fatal Error Status
73 ULONG HBDS :1; //Host Bus Data Error Status
74 ULONG HBFS :1; //Host Bus Fatal Error Status
75 ULONG TFES :1; //Task File Error Status
76 ULONG CPDS :1; //Cold Port Detect Status
77 };
78
79 ULONG Status;
80 } AHCI_INTERRUPT_STATUS;
81
82 typedef struct _AHCI_FIS_DMA_SETUP
83 {
84 ULONG ULONG0_1; // FIS_TYPE_DMA_SETUP
85 // Port multiplier
86 // Reserved
87 // Data transfer direction, 1 - device to host
88 // Interrupt bit
89 // Auto-activate. Specifies if DMA Activate FIS is needed
90 UCHAR Reserved[2]; // Reserved
91 ULONG DmaBufferLow; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory. SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
92 ULONG DmaBufferHigh;
93 ULONG Reserved2; // More reserved
94 ULONG DmaBufferOffset; // Byte offset into buffer. First 2 bits must be 0
95 ULONG TranferCount; // Number of bytes to transfer. Bit 0 must be 0
96 ULONG Reserved3; // Reserved
97 } AHCI_FIS_DMA_SETUP;
98
99 typedef struct _AHCI_PIO_SETUP_FIS
100 {
101 UCHAR FisType;
102 UCHAR Reserved1 :5;
103 UCHAR D :1;
104 UCHAR I :1;
105 UCHAR Reserved2 :1;
106 UCHAR Status;
107 UCHAR Error;
108
109 UCHAR SectorNumber;
110 UCHAR CylLow;
111 UCHAR CylHigh;
112 UCHAR Dev_Head;
113
114 UCHAR SectorNumb_Exp;
115 UCHAR CylLow_Exp;
116 UCHAR CylHigh_Exp;
117 UCHAR Reserved3;
118
119 UCHAR SectorCount;
120 UCHAR SectorCount_Exp;
121 UCHAR Reserved4;
122 UCHAR E_Status;
123
124 USHORT TransferCount;
125 UCHAR Reserved5[2];
126 } AHCI_PIO_SETUP_FIS;
127
128 typedef struct _AHCI_D2H_REGISTER_FIS
129 {
130 UCHAR FisType;
131 UCHAR Reserved1 :6;
132 UCHAR I:1;
133 UCHAR Reserved2 :1;
134 UCHAR Status;
135 UCHAR Error;
136
137 UCHAR SectorNumber;
138 UCHAR CylLow;
139 UCHAR CylHigh;
140 UCHAR Dev_Head;
141
142 UCHAR SectorNum_Exp;
143 UCHAR CylLow_Exp;
144 UCHAR CylHigh_Exp;
145 UCHAR Reserved;
146
147 UCHAR SectorCount;
148 UCHAR SectorCount_Exp;
149 UCHAR Reserved3[2];
150
151 UCHAR Reserved4[4];
152 } AHCI_D2H_REGISTER_FIS;
153
154 typedef struct _AHCI_SET_DEVICE_BITS_FIS
155 {
156 UCHAR FisType;
157
158 UCHAR PMPort: 4;
159 UCHAR Reserved1 :2;
160 UCHAR I :1;
161 UCHAR N :1;
162
163 UCHAR Status_Lo :3;
164 UCHAR Reserved2 :1;
165 UCHAR Status_Hi :3;
166 UCHAR Reserved3 :1;
167
168 UCHAR Error;
169
170 UCHAR Reserved5[4];
171 } AHCI_SET_DEVICE_BITS_FIS;
172
173 typedef struct _AHCI_QUEUE
174 {
175 PVOID Buffer[MAXIMUM_QUEUE_BUFFER_SIZE]; // because Storahci hold Srb queue of 255 size
176 ULONG Head;
177 ULONG Tail;
178 } AHCI_QUEUE, *PAHCI_QUEUE;
179
180 //////////////////////////////////////////////////////////////
181 // --------------------------- //
182 //////////////////////////////////////////////////////////////
183
184 typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
185 {
186 struct
187 {
188 ULONG CFL :5; // Command FIS Length
189 ULONG A :1; // IsATAPI
190 ULONG W :1; // Write
191 ULONG P :1; // Prefetchable
192
193 ULONG R :1; // Reset
194 ULONG B :1; // BIST
195 ULONG C :1; //Clear Busy upon R_OK
196 ULONG DW0_Reserved :1;
197 ULONG PMP :4; //Port Multiplier Port
198
199 ULONG PRDTL :16; //Physical Region Descriptor Table Length
200 };
201
202 ULONG Status;
203 } AHCI_COMMAND_HEADER_DESCRIPTION;
204
205 // 4.2.2 Command Header
206 typedef struct _AHCI_COMMAND_HEADER
207 {
208 AHCI_COMMAND_HEADER_DESCRIPTION DI; // DW 0
209 ULONG PRDBC; // DW 1
210 ULONG CTBA0; // DW 2
211 ULONG CTBA_U0; // DW 3
212 ULONG Reserved[4]; // DW 4-7
213 } AHCI_COMMAND_HEADER, *PAHCI_COMMAND_HEADER;
214
215 // Received FIS
216 typedef struct _AHCI_RECEIVED_FIS
217 {
218 struct _AHCI_FIS_DMA_SETUP DmaSetupFIS; // 0x00 -- DMA Setup FIS
219 ULONG pad0; // 4 BYTE padding
220 struct _AHCI_PIO_SETUP_FIS PioSetupFIS; // 0x20 -- PIO Setup FIS
221 ULONG pad1[3]; // 12 BYTE padding
222 struct _AHCI_D2H_REGISTER_FIS RegisterFIS; // 0x40 -- Register – Device to Host FIS
223 ULONG pad2; // 4 BYTE padding
224 struct _AHCI_SET_DEVICE_BITS_FIS SetDeviceFIS; // 0x58 -- Set Device Bit FIS
225 ULONG UnknowFIS[16]; // 0x60 -- Unknown FIS
226 ULONG Reserved[24]; // 0xA0 -- Reserved
227 } AHCI_RECEIVED_FIS, *PAHCI_RECEIVED_FIS;
228
229 // Holds Port Information
230 typedef struct _AHCI_PORT
231 {
232 ULONG CLB; // 0x00, command list base address, 1K-byte aligned
233 ULONG CLBU; // 0x04, command list base address upper 32 bits
234 ULONG FB; // 0x08, FIS base address, 256-byte aligned
235 ULONG FBU; // 0x0C, FIS base address upper 32 bits
236 ULONG IS; // 0x10, interrupt status
237 ULONG IE; // 0x14, interrupt enable
238 ULONG CMD; // 0x18, command and status
239 ULONG RSV0; // 0x1C, Reserved
240 ULONG TFD; // 0x20, task file data
241 ULONG SIG; // 0x24, signature
242 ULONG SSTS; // 0x28, SATA status (SCR0:SStatus)
243 ULONG SCTL; // 0x2C, SATA control (SCR2:SControl)
244 ULONG SERR; // 0x30, SATA error (SCR1:SError)
245 ULONG SACT; // 0x34, SATA active (SCR3:SActive)
246 ULONG CI; // 0x38, command issue
247 ULONG SNTF; // 0x3C, SATA notification (SCR4:SNotification)
248 ULONG FBS; // 0x40, FIS-based switch control
249 ULONG RSV1[11]; // 0x44 ~ 0x6F, Reserved
250 ULONG Vendor[4]; // 0x70 ~ 0x7F, vendor specific
251 } AHCI_PORT, *PAHCI_PORT;
252
253 typedef struct _AHCI_MEMORY_REGISTERS
254 {
255 // 0x00 - 0x2B, Generic Host Control
256 ULONG CAP; // 0x00, Host capability
257 ULONG GHC; // 0x04, Global host control
258 ULONG IS; // 0x08, Interrupt status
259 ULONG PI; // 0x0C, Port implemented
260 ULONG VS; // 0x10, Version
261 ULONG CCC_CTL; // 0x14, Command completion coalescing control
262 ULONG CCC_PTS; // 0x18, Command completion coalescing ports
263 ULONG EM_LOC; // 0x1C, Enclosure management location
264 ULONG EM_CTL; // 0x20, Enclosure management control
265 ULONG CAP2; // 0x24, Host capabilities extended
266 ULONG BOHC; // 0x28, BIOS/OS handoff control and status
267 ULONG Reserved[0xA0-0x2C]; // 0x2C - 0x9F, Reserved
268 ULONG VendorSpecific[0x100-0xA0]; // 0xA0 - 0xFF, Vendor specific registers
269 AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT];
270
271 } AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS;
272
273 // Holds information for each attached attached port to a given adapter.
274 typedef struct _AHCI_PORT_EXTENSION
275 {
276 ULONG PortNumber;
277 ULONG OccupiedSlots; // slots to which we have already assigned task
278 BOOLEAN IsActive;
279 PAHCI_PORT Port; // AHCI Port Infomation
280 AHCI_QUEUE SrbQueue;
281 PAHCI_RECEIVED_FIS ReceivedFIS;
282 PAHCI_COMMAND_HEADER CommandList;
283 STOR_DEVICE_POWER_STATE DevicePowerState; // Device Power State
284 struct _AHCI_ADAPTER_EXTENSION* AdapterExtension; // Port's Adapter Information
285 } AHCI_PORT_EXTENSION, *PAHCI_PORT_EXTENSION;
286
287 // Holds Adapter Information
288 typedef struct _AHCI_ADAPTER_EXTENSION
289 {
290 ULONG SystemIoBusNumber;
291 ULONG SlotNumber;
292 ULONG AhciBaseAddress;
293 PULONG IS;// Interrupt Status, In case of MSIM == `1`
294 ULONG PortImplemented;// bit-mapping of ports which are implemented
295 ULONG PortCount;
296
297 USHORT VendorID;
298 USHORT DeviceID;
299 USHORT RevisionID;
300
301 ULONG Version;
302 ULONG CAP;
303 ULONG CAP2;
304 ULONG LastInterruptPort;
305 ULONG CurrentCommandSlot;
306
307 PVOID NonCachedExtension;// holds virtual address to noncached buffer allocated for Port Extension
308
309 struct
310 {
311 // Message per port or shared port?
312 ULONG MessagePerPort : 1;
313 ULONG Removed : 1;
314 ULONG Reserved : 30; // not in use -- maintain 4 byte alignment
315 } StateFlags;
316
317 PAHCI_MEMORY_REGISTERS ABAR_Address;
318 AHCI_PORT_EXTENSION PortExtension[MAXIMUM_AHCI_PORT_COUNT];
319 } AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;
320
321 typedef struct _ATA_REGISTER
322 {
323 UCHAR CommandReg;
324 ULONG Reserved;
325 } ATA_REGISTER;
326
327 typedef struct _AHCI_SRB_EXTENSION
328 {
329 ULONG AtaFunction;
330 ULONG Flags;
331 ATA_REGISTER Task;
332 ULONG SlotIndex;
333 ULONG Reserved[4];
334 } AHCI_SRB_EXTENSION, *PAHCI_SRB_EXTENSION;
335
336 //////////////////////////////////////////////////////////////
337 // Declarations //
338 //////////////////////////////////////////////////////////////
339
340 BOOLEAN
341 AhciAdapterReset (
342 __in PAHCI_ADAPTER_EXTENSION AdapterExtension
343 );
344
345 __inline
346 VOID
347 AhciZeroMemory (
348 __out PCHAR Buffer,
349 __in ULONG BufferSize
350 );
351
352 __inline
353 BOOLEAN
354 IsPortValid (
355 __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
356 __in UCHAR pathId
357 );
358
359 ULONG
360 DeviceInquiryRequest (
361 __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
362 __in PSCSI_REQUEST_BLOCK Srb,
363 __in PCDB Cdb
364 );
365
366 __inline
367 BOOLEAN
368 AddQueue (
369 __inout PAHCI_QUEUE Queue,
370 __in PVOID Srb
371 );
372
373 __inline
374 PVOID
375 RemoveQueue (
376 __inout PAHCI_QUEUE Queue
377 );