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