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 NDEBUG
13 #include <debug.h>
14 
15 #define DEBUG 1
16 #if defined(_MSC_VER)
17 #pragma warning(disable:4214) // bit field types other than int
18 #pragma warning(disable:4201) // nameless struct/union
19 #endif
20 
21 #define MAXIMUM_AHCI_PORT_COUNT             32
22 #define MAXIMUM_AHCI_PRDT_ENTRIES           32
23 #define MAXIMUM_AHCI_PORT_NCS               30
24 #define MAXIMUM_QUEUE_BUFFER_SIZE           255
25 #define MAXIMUM_TRANSFER_LENGTH             (128*1024) // 128 KB
26 
27 #define DEVICE_ATA_BLOCK_SIZE               512
28 
29 // device type (DeviceParams)
30 #define AHCI_DEVICE_TYPE_ATA                1
31 #define AHCI_DEVICE_TYPE_ATAPI              2
32 #define AHCI_DEVICE_TYPE_NODEVICE           3
33 
34 // section 3.1.2
35 #define AHCI_Global_HBA_CAP_S64A            (1 << 31)
36 
37 // FIS Types : http://wiki.osdev.org/AHCI
38 #define FIS_TYPE_REG_H2D        0x27 // Register FIS - host to device
39 #define FIS_TYPE_REG_D2H        0x34 // Register FIS - device to host
40 #define FIS_TYPE_DMA_ACT        0x39 // DMA activate FIS - device to host
41 #define FIS_TYPE_DMA_SETUP      0x41 // DMA setup FIS - bidirectional
42 #define FIS_TYPE_BIST           0x58 // BIST activate FIS - bidirectional
43 #define FIS_TYPE_PIO_SETUP      0x5F // PIO setup FIS - device to host
44 #define FIS_TYPE_DEV_BITS       0xA1 // Set device bits FIS - device to host
45 
46 #define AHCI_ATA_CFIS_FisType               0
47 #define AHCI_ATA_CFIS_PMPort_C              1
48 #define AHCI_ATA_CFIS_CommandReg            2
49 #define AHCI_ATA_CFIS_FeaturesLow           3
50 #define AHCI_ATA_CFIS_LBA0                  4
51 #define AHCI_ATA_CFIS_LBA1                  5
52 #define AHCI_ATA_CFIS_LBA2                  6
53 #define AHCI_ATA_CFIS_Device                7
54 #define AHCI_ATA_CFIS_LBA3                  8
55 #define AHCI_ATA_CFIS_LBA4                  9
56 #define AHCI_ATA_CFIS_LBA5                  10
57 #define AHCI_ATA_CFIS_FeaturesHigh          11
58 #define AHCI_ATA_CFIS_SectorCountLow        12
59 #define AHCI_ATA_CFIS_SectorCountHigh       13
60 
61 // ATA Functions
62 #define ATA_FUNCTION_ATA_COMMAND            0x100
63 #define ATA_FUNCTION_ATA_IDENTIFY           0x101
64 #define ATA_FUNCTION_ATA_READ               0x102
65 
66 // ATAPI Functions
67 #define ATA_FUNCTION_ATAPI_COMMAND          0x200
68 
69 // ATA Flags
70 #define ATA_FLAGS_DATA_IN                   (1 << 1)
71 #define ATA_FLAGS_DATA_OUT                  (1 << 2)
72 #define ATA_FLAGS_48BIT_COMMAND             (1 << 3)
73 #define ATA_FLAGS_USE_DMA                   (1 << 4)
74 
75 #define IsAtaCommand(AtaFunction)           (AtaFunction & ATA_FUNCTION_ATA_COMMAND)
76 #define IsAtapiCommand(AtaFunction)         (AtaFunction & ATA_FUNCTION_ATAPI_COMMAND)
77 #define IsDataTransferNeeded(SrbExtension)  (SrbExtension->Flags & (ATA_FLAGS_DATA_IN | ATA_FLAGS_DATA_OUT))
78 #define IsAdapterCAPS64(CAP)                (CAP & AHCI_Global_HBA_CAP_S64A)
79 
80 // 3.1.1 NCS = CAP[12:08] -> Align
81 #define AHCI_Global_Port_CAP_NCS(x)         (((x) & 0xF00) >> 8)
82 
83 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
84 //#define AhciDebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
85 #define AhciDebugPrint(format, ...) DbgPrint("(%s:%d) " format, __RELFILE__, __LINE__, ##__VA_ARGS__)
86 
87 typedef
88 VOID
89 (*PAHCI_COMPLETION_ROUTINE) (
90     __in PVOID PortExtension,
91     __in PVOID Srb
92     );
93 
94 //////////////////////////////////////////////////////////////
95 //              ---- Support Structures ---                 //
96 //////////////////////////////////////////////////////////////
97 
98 // section 3.3.5
99 typedef union _AHCI_INTERRUPT_STATUS
100 {
101     struct
102     {
103         ULONG DHRS:1;       //Device to Host Register FIS Interrupt
104         ULONG PSS :1;       //PIO Setup FIS Interrupt
105         ULONG DSS :1;       //DMA Setup FIS Interrupt
106         ULONG SDBS :1;      //Set Device Bits Interrupt
107         ULONG UFS :1;       //Unknown FIS Interrupt
108         ULONG DPS :1;       //Descriptor Processed
109         ULONG PCS :1;       //Port Connect Change Status
110         ULONG DMPS :1;      //Device Mechanical Presence Status (DMPS)
111         ULONG Reserved :14;
112         ULONG PRCS :1;      //PhyRdy Change Status
113         ULONG IPMS :1;      //Incorrect Port Multiplier Status
114         ULONG OFS :1;       //Overflow Status
115         ULONG Reserved2 :1;
116         ULONG INFS :1;      //Interface Non-fatal Error Status
117         ULONG IFS :1;       //Interface Fatal Error Status
118         ULONG HBDS :1;      //Host Bus Data Error Status
119         ULONG HBFS :1;      //Host Bus Fatal Error Status
120         ULONG TFES :1;      //Task File Error Status
121         ULONG CPDS :1;      //Cold Port Detect Status
122     };
123 
124     ULONG Status;
125 } AHCI_INTERRUPT_STATUS;
126 
127 typedef struct _AHCI_FIS_DMA_SETUP
128 {
129     ULONG ULONG0_1;         // FIS_TYPE_DMA_SETUP
130                             // Port multiplier
131                             // Reserved
132                             // Data transfer direction, 1 - device to host
133                             // Interrupt bit
134                             // Auto-activate. Specifies if DMA Activate FIS is needed
135     UCHAR Reserved[2];      // Reserved
136     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.
137     ULONG DmaBufferHigh;
138     ULONG Reserved2;        // More reserved
139     ULONG DmaBufferOffset;  // Byte offset into buffer. First 2 bits must be 0
140     ULONG TranferCount;     // Number of bytes to transfer. Bit 0 must be 0
141     ULONG Reserved3;        // Reserved
142 } AHCI_FIS_DMA_SETUP;
143 
144 typedef struct _AHCI_PIO_SETUP_FIS
145 {
146     UCHAR FisType;
147     UCHAR Reserved1 :5;
148     UCHAR D :1;
149     UCHAR I :1;
150     UCHAR Reserved2 :1;
151     UCHAR Status;
152     UCHAR Error;
153 
154     UCHAR SectorNumber;
155     UCHAR CylLow;
156     UCHAR CylHigh;
157     UCHAR Dev_Head;
158 
159     UCHAR SectorNumb_Exp;
160     UCHAR CylLow_Exp;
161     UCHAR CylHigh_Exp;
162     UCHAR Reserved3;
163 
164     UCHAR SectorCount;
165     UCHAR SectorCount_Exp;
166     UCHAR Reserved4;
167     UCHAR E_Status;
168 
169     USHORT TransferCount;
170     UCHAR Reserved5[2];
171 } AHCI_PIO_SETUP_FIS;
172 
173 typedef struct _AHCI_D2H_REGISTER_FIS
174 {
175     UCHAR FisType;
176     UCHAR Reserved1 :6;
177     UCHAR I:1;
178     UCHAR Reserved2 :1;
179     UCHAR Status;
180     UCHAR Error;
181 
182     UCHAR SectorNumber;
183     UCHAR CylLow;
184     UCHAR CylHigh;
185     UCHAR Dev_Head;
186 
187     UCHAR SectorNum_Exp;
188     UCHAR CylLow_Exp;
189     UCHAR CylHigh_Exp;
190     UCHAR Reserved;
191 
192     UCHAR SectorCount;
193     UCHAR SectorCount_Exp;
194     UCHAR Reserved3[2];
195 
196     UCHAR Reserved4[4];
197 } AHCI_D2H_REGISTER_FIS;
198 
199 typedef struct _AHCI_SET_DEVICE_BITS_FIS
200 {
201     UCHAR FisType;
202 
203     UCHAR PMPort: 4;
204     UCHAR Reserved1 :2;
205     UCHAR I :1;
206     UCHAR N :1;
207 
208     UCHAR Status_Lo :3;
209     UCHAR Reserved2 :1;
210     UCHAR Status_Hi :3;
211     UCHAR Reserved3 :1;
212 
213     UCHAR Error;
214 
215     UCHAR Reserved5[4];
216 } AHCI_SET_DEVICE_BITS_FIS;
217 
218 typedef struct _AHCI_QUEUE
219 {
220     PVOID Buffer[MAXIMUM_QUEUE_BUFFER_SIZE];  // because Storahci hold Srb queue of 255 size
221     ULONG Head;
222     ULONG Tail;
223 } AHCI_QUEUE, *PAHCI_QUEUE;
224 
225 //////////////////////////////////////////////////////////////
226 //              ---------------------------                 //
227 //////////////////////////////////////////////////////////////
228 
229 typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
230 {
231     struct
232     {
233         ULONG CFL : 5;       // Command FIS Length
234         ULONG A : 1;         // IsATAPI
235         ULONG W : 1;         // Write
236         ULONG P : 1;         // Prefetchable
237 
238         ULONG R : 1;         // Reset
239         ULONG B : 1;         // BIST
240         ULONG C : 1;         //Clear Busy upon R_OK
241         ULONG RSV : 1;
242         ULONG PMP : 4;       //Port Multiplier Port
243 
244         ULONG PRDTL : 16;    //Physical Region Descriptor Table Length
245     };
246 
247     ULONG Status;
248 } AHCI_COMMAND_HEADER_DESCRIPTION;
249 
250 typedef union _AHCI_GHC
251 {
252     struct
253     {
254         ULONG HR : 1;
255         ULONG IE : 1;
256         ULONG MRSM : 1;
257         ULONG RSV0 : 28;
258         ULONG AE : 1;
259     };
260 
261     ULONG Status;
262 } AHCI_GHC;
263 
264 // section 3.3.7
265 typedef union _AHCI_PORT_CMD
266 {
267     struct
268     {
269         ULONG ST : 1;
270         ULONG SUD : 1;
271         ULONG POD : 1;
272         ULONG CLO : 1;
273         ULONG FRE : 1;
274         ULONG RSV0 : 3;
275         ULONG CCS : 5;
276         ULONG MPSS : 1;
277         ULONG FR : 1;
278         ULONG CR : 1;
279         ULONG CPS : 1;
280         ULONG PMA : 1;
281         ULONG HPCP : 1;
282         ULONG MPSP : 1;
283         ULONG CPD : 1;
284         ULONG ESP : 1;
285         ULONG FBSCP : 1;
286         ULONG APSTE : 1;
287         ULONG ATAPI : 1;
288         ULONG DLAE : 1;
289         ULONG ALPE : 1;
290         ULONG ASP : 1;
291         ULONG ICC : 4;
292     };
293 
294     ULONG Status;
295 } AHCI_PORT_CMD;
296 
297 typedef union _AHCI_SERIAL_ATA_CONTROL
298 {
299     struct
300     {
301         ULONG DET :4;
302         ULONG SPD :4;
303         ULONG IPM :4;
304         ULONG SPM :4;
305         ULONG PMP :4;
306         ULONG DW11_Reserved :12;
307     };
308 
309     ULONG Status;
310 }  AHCI_SERIAL_ATA_CONTROL;
311 
312 typedef union _AHCI_SERIAL_ATA_STATUS
313 {
314     struct
315     {
316         ULONG DET :4;
317         ULONG SPD :4;
318         ULONG IPM :4;
319         ULONG RSV0 :20;
320     };
321 
322     ULONG Status;
323 }  AHCI_SERIAL_ATA_STATUS;
324 
325 typedef union _AHCI_TASK_FILE_DATA
326 {
327     struct
328     {
329         struct _STS
330         {
331             UCHAR ERR : 1;
332             UCHAR CS1 : 2;
333             UCHAR DRQ : 1;
334             UCHAR CS2 : 3;
335             UCHAR BSY : 1;
336         } STS;
337         UCHAR ERR;
338         USHORT RSV;
339     };
340 
341     ULONG Status;
342 } AHCI_TASK_FILE_DATA;
343 
344 typedef struct _AHCI_PRDT
345 {
346     ULONG DBA;
347     ULONG DBAU;
348     ULONG RSV0;
349 
350     ULONG DBC : 22;
351     ULONG RSV1 : 9;
352     ULONG I : 1;
353 } AHCI_PRDT, *PAHCI_PRDT;
354 
355 // 4.2.3 Command Table
356 typedef struct _AHCI_COMMAND_TABLE
357 {
358     // (16 * 32) + 64 + 16 + 48 = 648
359     // 128 byte aligned :D
360     UCHAR CFIS[64];
361     UCHAR ACMD[16];
362     UCHAR RSV0[48];
363     AHCI_PRDT PRDT[MAXIMUM_AHCI_PRDT_ENTRIES];
364 } AHCI_COMMAND_TABLE, *PAHCI_COMMAND_TABLE;
365 
366 // 4.2.2 Command Header
367 typedef struct _AHCI_COMMAND_HEADER
368 {
369     AHCI_COMMAND_HEADER_DESCRIPTION DI;   // DW 0
370     ULONG PRDBC;                          // DW 1
371     ULONG CTBA;                           // DW 2
372     ULONG CTBA_U;                         // DW 3
373     ULONG Reserved[4];                    // DW 4-7
374 } AHCI_COMMAND_HEADER, *PAHCI_COMMAND_HEADER;
375 
376 // Received FIS
377 typedef struct _AHCI_RECEIVED_FIS
378 {
379     struct _AHCI_FIS_DMA_SETUP          DmaSetupFIS;      // 0x00 -- DMA Setup FIS
380     ULONG                               pad0;             // 4 BYTE padding
381     struct _AHCI_PIO_SETUP_FIS          PioSetupFIS;      // 0x20 -- PIO Setup FIS
382     ULONG                               pad1[3];          // 12 BYTE padding
383     struct _AHCI_D2H_REGISTER_FIS       RegisterFIS;      // 0x40 -- Register – Device to Host FIS
384     ULONG                               pad2;             // 4 BYTE padding
385     struct _AHCI_SET_DEVICE_BITS_FIS    SetDeviceFIS;     // 0x58 -- Set Device Bit FIS
386     ULONG                               UnknowFIS[16];    // 0x60 -- Unknown FIS
387     ULONG                               Reserved[24];     // 0xA0 -- Reserved
388 } AHCI_RECEIVED_FIS, *PAHCI_RECEIVED_FIS;
389 
390 // Holds Port Information
391 typedef struct _AHCI_PORT
392 {
393     ULONG   CLB;                                // 0x00, command list base address, 1K-byte aligned
394     ULONG   CLBU;                               // 0x04, command list base address upper 32 bits
395     ULONG   FB;                                 // 0x08, FIS base address, 256-byte aligned
396     ULONG   FBU;                                // 0x0C, FIS base address upper 32 bits
397     ULONG   IS;                                 // 0x10, interrupt status
398     ULONG   IE;                                 // 0x14, interrupt enable
399     ULONG   CMD;                                // 0x18, command and status
400     ULONG   RSV0;                               // 0x1C, Reserved
401     ULONG   TFD;                                // 0x20, task file data
402     ULONG   SIG;                                // 0x24, signature
403     ULONG   SSTS;                               // 0x28, SATA status (SCR0:SStatus)
404     ULONG   SCTL;                               // 0x2C, SATA control (SCR2:SControl)
405     ULONG   SERR;                               // 0x30, SATA error (SCR1:SError)
406     ULONG   SACT;                               // 0x34, SATA active (SCR3:SActive)
407     ULONG   CI;                                 // 0x38, command issue
408     ULONG   SNTF;                               // 0x3C, SATA notification (SCR4:SNotification)
409     ULONG   FBS;                                // 0x40, FIS-based switch control
410     ULONG   RSV1[11];                           // 0x44 ~ 0x6F, Reserved
411     ULONG   Vendor[4];                          // 0x70 ~ 0x7F, vendor specific
412 } AHCI_PORT, *PAHCI_PORT;
413 
414 typedef union _AHCI_INTERRUPT_ENABLE
415 {
416     struct
417     {
418         ULONG DHRE :1;
419         ULONG PSE :1;
420         ULONG DSE :1;
421         ULONG SDBE :1;
422         ULONG UFE :1;
423         ULONG DPE :1;
424         ULONG PCE :1;
425         ULONG DMPE :1;
426         ULONG DW5_Reserved :14;
427         ULONG PRCE :1;
428         ULONG IPME :1;
429         ULONG OFE :1;
430         ULONG DW5_Reserved2 :1;
431         ULONG INFE :1;
432         ULONG IFE :1;
433         ULONG HBDE :1;
434         ULONG HBFE :1;
435         ULONG TFEE :1;
436         ULONG CPDE :1;
437     };
438 
439     ULONG Status;
440 } AHCI_INTERRUPT_ENABLE;
441 
442 typedef struct _AHCI_MEMORY_REGISTERS
443 {
444     // 0x00 - 0x2B, Generic Host Control
445     ULONG CAP;                                  // 0x00, Host capability
446     ULONG GHC;                                  // 0x04, Global host control
447     ULONG IS;                                   // 0x08, Interrupt status
448     ULONG PI;                                   // 0x0C, Port implemented
449     ULONG VS;                                   // 0x10, Version
450     ULONG CCC_CTL;                              // 0x14, Command completion coalescing control
451     ULONG CCC_PTS;                              // 0x18, Command completion coalescing ports
452     ULONG EM_LOC;                               // 0x1C, Enclosure management location
453     ULONG EM_CTL;                               // 0x20, Enclosure management control
454     ULONG CAP2;                                 // 0x24, Host capabilities extended
455     ULONG BOHC;                                 // 0x28, BIOS/OS handoff control and status
456     ULONG Reserved[0x1d];                       // 0x2C - 0x9F, Reserved
457     ULONG VendorSpecific[0x18];                 // 0xA0 - 0xFF, Vendor specific registers
458     AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT];
459 } AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS;
460 
461 // Holds information for each attached attached port to a given adapter.
462 typedef struct _AHCI_PORT_EXTENSION
463 {
464     ULONG PortNumber;
465     ULONG QueueSlots;                                   // slots which we have already assigned task (Slot)
466     ULONG CommandIssuedSlots;                           // slots which has been programmed
467     ULONG MaxPortQueueDepth;
468 
469     struct
470     {
471         UCHAR RemovableDevice;
472         UCHAR Lba48BitMode;
473         UCHAR AccessType;
474         UCHAR DeviceType;
475         UCHAR IsActive;
476         LARGE_INTEGER MaxLba;
477         ULONG BytesPerLogicalSector;
478         ULONG BytesPerPhysicalSector;
479         UCHAR VendorId[41];
480         UCHAR RevisionID[9];
481         UCHAR SerialNumber[21];
482     } DeviceParams;
483 
484     STOR_DPC CommandCompletion;
485     PAHCI_PORT Port;                                    // AHCI Port Infomation
486     AHCI_QUEUE SrbQueue;                                // pending Srbs
487     AHCI_QUEUE CompletionQueue;
488     PSCSI_REQUEST_BLOCK Slot[MAXIMUM_AHCI_PORT_NCS];    // Srbs which has been alloted a port
489     PAHCI_RECEIVED_FIS ReceivedFIS;
490     PAHCI_COMMAND_HEADER CommandList;
491     STOR_DEVICE_POWER_STATE DevicePowerState;           // Device Power State
492     PIDENTIFY_DEVICE_DATA IdentifyDeviceData;
493     STOR_PHYSICAL_ADDRESS IdentifyDeviceDataPhysicalAddress;
494     struct _AHCI_ADAPTER_EXTENSION* AdapterExtension;   // Port's Adapter Information
495 } AHCI_PORT_EXTENSION, *PAHCI_PORT_EXTENSION;
496 
497 // Holds Adapter Information
498 typedef struct _AHCI_ADAPTER_EXTENSION
499 {
500     ULONG   SystemIoBusNumber;
501     ULONG   SlotNumber;
502     ULONG   AhciBaseAddress;
503     PULONG  IS;// Interrupt Status, In case of MSIM == `1`
504     ULONG   PortImplemented;// bit-mapping of ports which are implemented
505     ULONG   PortCount;
506 
507     USHORT  VendorID;
508     USHORT  DeviceID;
509     USHORT  RevisionID;
510 
511     ULONG   Version;
512     ULONG   CAP;
513     ULONG   CAP2;
514     ULONG   LastInterruptPort;
515     ULONG   CurrentCommandSlot;
516 
517     PVOID NonCachedExtension; // holds virtual address to noncached buffer allocated for Port Extension
518 
519     struct
520     {
521         // Message per port or shared port?
522         ULONG MessagePerPort : 1;
523         ULONG Removed : 1;
524         ULONG Reserved : 30; // not in use -- maintain 4 byte alignment
525     } StateFlags;
526 
527     PAHCI_MEMORY_REGISTERS ABAR_Address;
528     AHCI_PORT_EXTENSION PortExtension[MAXIMUM_AHCI_PORT_COUNT];
529 } AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;
530 
531 typedef struct _LOCAL_SCATTER_GATHER_LIST
532 {
533     ULONG                       NumberOfElements;
534     ULONG_PTR                   Reserved;
535     STOR_SCATTER_GATHER_ELEMENT List[MAXIMUM_AHCI_PRDT_ENTRIES];
536 } LOCAL_SCATTER_GATHER_LIST, *PLOCAL_SCATTER_GATHER_LIST;
537 
538 typedef struct _AHCI_SRB_EXTENSION
539 {
540     AHCI_COMMAND_TABLE CommandTable;
541     ULONG AtaFunction;
542     ULONG Flags;
543 
544     UCHAR CommandReg;
545     UCHAR FeaturesLow;
546     UCHAR LBA0;
547     UCHAR LBA1;
548     UCHAR LBA2;
549     UCHAR Device;
550     UCHAR LBA3;
551     UCHAR LBA4;
552     UCHAR LBA5;
553     UCHAR FeaturesHigh;
554 
555     UCHAR SectorCountLow;
556     UCHAR SectorCountHigh;
557 
558     ULONG SlotIndex;
559     LOCAL_SCATTER_GATHER_LIST Sgl;
560     PLOCAL_SCATTER_GATHER_LIST pSgl;
561     PAHCI_COMPLETION_ROUTINE CompletionRoutine;
562 
563     // for alignment purpose -- 128 byte alignment
564     // do not try to access (R/W) this field
565     UCHAR Reserved[128];
566 } AHCI_SRB_EXTENSION, *PAHCI_SRB_EXTENSION;
567 
568 //////////////////////////////////////////////////////////////
569 //                       Declarations                       //
570 //////////////////////////////////////////////////////////////
571 
572 VOID
573 AhciProcessIO (
574     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
575     __in UCHAR PathId,
576     __in PSCSI_REQUEST_BLOCK Srb
577     );
578 
579 BOOLEAN
580 AhciAdapterReset (
581     __in PAHCI_ADAPTER_EXTENSION AdapterExtension
582     );
583 
584 FORCEINLINE
585 VOID
586 AhciZeroMemory (
587     __out PCHAR Buffer,
588     __in ULONG BufferSize
589     );
590 
591 FORCEINLINE
592 BOOLEAN
593 IsPortValid (
594     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
595     __in ULONG pathId
596     );
597 
598 UCHAR DeviceRequestSense (
599     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
600     __in PSCSI_REQUEST_BLOCK Srb,
601     __in PCDB Cdb
602     );
603 
604 UCHAR DeviceRequestReadWrite (
605     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
606     __in PSCSI_REQUEST_BLOCK Srb,
607     __in PCDB Cdb
608     );
609 
610 UCHAR DeviceRequestCapacity (
611     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
612     __in PSCSI_REQUEST_BLOCK Srb,
613     __in PCDB Cdb
614     );
615 
616 UCHAR
617 DeviceInquiryRequest (
618     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
619     __in PSCSI_REQUEST_BLOCK Srb,
620     __in PCDB Cdb
621     );
622 
623 UCHAR DeviceRequestComplete (
624     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
625     __in PSCSI_REQUEST_BLOCK Srb,
626     __in PCDB Cdb
627     );
628 
629 UCHAR DeviceReportLuns (
630     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
631     __in PSCSI_REQUEST_BLOCK Srb,
632     __in PCDB Cdb
633     );
634 
635 FORCEINLINE
636 BOOLEAN
637 AddQueue (
638     __inout PAHCI_QUEUE Queue,
639     __in PVOID Srb
640     );
641 
642 FORCEINLINE
643 PVOID
644 RemoveQueue (
645     __inout PAHCI_QUEUE Queue
646     );
647 
648 FORCEINLINE
649 PAHCI_SRB_EXTENSION
650 GetSrbExtension(
651     __in PSCSI_REQUEST_BLOCK Srb
652     );
653 
654 FORCEINLINE
655 ULONG64
656 AhciGetLba (
657     __in PCDB Cdb,
658     __in ULONG CdbLength
659     );
660 
661 //////////////////////////////////////////////////////////////
662 //                       Assertions                         //
663 //////////////////////////////////////////////////////////////
664 
665 // I assert every silly mistake I can do while coding
666 // because god never help me debugging the code
667 // but these asserts do :')
668 
669 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP)            == 0x00);
670 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, GHC)            == 0x04);
671 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, IS)             == 0x08);
672 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PI)             == 0x0C);
673 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VS)             == 0x10);
674 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_CTL)        == 0x14);
675 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_PTS)        == 0x18);
676 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_LOC)         == 0x1C);
677 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_CTL)         == 0x20);
678 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP2)           == 0x24);
679 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, BOHC)           == 0x28);
680 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, Reserved)       == 0x2C);
681 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VendorSpecific) == 0xA0);
682 C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PortList)       == 0x100);
683 
684 C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLB)    == 0x00);
685 C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLBU)   == 0x04);
686 C_ASSERT(FIELD_OFFSET(AHCI_PORT, FB)     == 0x08);
687 C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBU)    == 0x0C);
688 C_ASSERT(FIELD_OFFSET(AHCI_PORT, IS)     == 0x10);
689 C_ASSERT(FIELD_OFFSET(AHCI_PORT, IE)     == 0x14);
690 C_ASSERT(FIELD_OFFSET(AHCI_PORT, CMD)    == 0x18);
691 C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV0)   == 0x1C);
692 C_ASSERT(FIELD_OFFSET(AHCI_PORT, TFD)    == 0x20);
693 C_ASSERT(FIELD_OFFSET(AHCI_PORT, SIG)    == 0x24);
694 C_ASSERT(FIELD_OFFSET(AHCI_PORT, SSTS)   == 0x28);
695 C_ASSERT(FIELD_OFFSET(AHCI_PORT, SCTL)   == 0x2C);
696 C_ASSERT(FIELD_OFFSET(AHCI_PORT, SERR)   == 0x30);
697 C_ASSERT(FIELD_OFFSET(AHCI_PORT, SACT)   == 0x34);
698 C_ASSERT(FIELD_OFFSET(AHCI_PORT, CI)     == 0x38);
699 C_ASSERT(FIELD_OFFSET(AHCI_PORT, SNTF)   == 0x3C);
700 C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBS)    == 0x40);
701 C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV1)   == 0x44);
702 C_ASSERT(FIELD_OFFSET(AHCI_PORT, Vendor) == 0x70);
703 
704 C_ASSERT((sizeof(AHCI_COMMAND_TABLE) % 128) == 0);
705 
706 C_ASSERT(sizeof(AHCI_GHC)                        == sizeof(ULONG));
707 C_ASSERT(sizeof(AHCI_PORT_CMD)                   == sizeof(ULONG));
708 C_ASSERT(sizeof(AHCI_TASK_FILE_DATA)             == sizeof(ULONG));
709 C_ASSERT(sizeof(AHCI_INTERRUPT_ENABLE)           == sizeof(ULONG));
710 C_ASSERT(sizeof(AHCI_SERIAL_ATA_STATUS)          == sizeof(ULONG));
711 C_ASSERT(sizeof(AHCI_SERIAL_ATA_CONTROL)         == sizeof(ULONG));
712 C_ASSERT(sizeof(AHCI_COMMAND_HEADER_DESCRIPTION) == sizeof(ULONG));
713 
714 C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, CFIS) == 0x00);
715 C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, ACMD) == 0x40);
716 C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, RSV0) == 0x50);
717 C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, PRDT) == 0x80);
718