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