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)
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
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
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)
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
48 #define ATA_FUNCTION_ATA_COMMAND 0x100
49 #define ATA_FUNCTION_ATA_IDENTIFY 0x101
52 #define ATA_FUNCTION_ATAPI_COMMAND 0x200
55 #define ATA_FLAGS_DATA_IN (1 << 1)
56 #define ATA_FLAGS_DATA_OUT (1 << 2)
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)
63 // 3.1.1 NCS = CAP[12:08] -> Align
64 #define AHCI_Global_Port_CAP_NCS(x) (((x) & 0xF00) >> 8)
66 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
68 #define DebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
73 (*PAHCI_COMPLETION_ROUTINE
) (
74 __in PVOID AdapterExtension
,
75 __in PVOID PortExtension
,
79 //////////////////////////////////////////////////////////////
80 // ---- Support Structures --- //
81 //////////////////////////////////////////////////////////////
84 typedef union _AHCI_INTERRUPT_STATUS
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)
97 ULONG PRCS
:1; //PhyRdy Change Status
98 ULONG IPMS
:1; //Incorrect Port Multiplier Status
99 ULONG OFS
:1; //Overflow Status
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
110 } AHCI_INTERRUPT_STATUS
;
112 typedef struct _AHCI_FIS_DMA_SETUP
114 ULONG ULONG0_1
; // FIS_TYPE_DMA_SETUP
117 // Data transfer direction, 1 - device to host
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.
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
;
129 typedef struct _AHCI_PIO_SETUP_FIS
144 UCHAR SectorNumb_Exp
;
150 UCHAR SectorCount_Exp
;
154 USHORT TransferCount
;
156 } AHCI_PIO_SETUP_FIS
;
158 typedef struct _AHCI_D2H_REGISTER_FIS
178 UCHAR SectorCount_Exp
;
182 } AHCI_D2H_REGISTER_FIS
;
184 typedef struct _AHCI_SET_DEVICE_BITS_FIS
201 } AHCI_SET_DEVICE_BITS_FIS
;
203 typedef struct _AHCI_QUEUE
205 PVOID Buffer
[MAXIMUM_QUEUE_BUFFER_SIZE
]; // because Storahci hold Srb queue of 255 size
208 } AHCI_QUEUE
, *PAHCI_QUEUE
;
210 //////////////////////////////////////////////////////////////
211 // --------------------------- //
212 //////////////////////////////////////////////////////////////
214 typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
218 ULONG CFL
:5; // Command FIS Length
219 ULONG A
:1; // IsATAPI
221 ULONG P
:1; // Prefetchable
225 ULONG C
:1; //Clear Busy upon R_OK
226 ULONG DW0_Reserved
:1;
227 ULONG PMP
:4; //Port Multiplier Port
229 ULONG PRDTL
:16; //Physical Region Descriptor Table Length
233 } AHCI_COMMAND_HEADER_DESCRIPTION
;
235 typedef struct _AHCI_PRDT
244 } AHCI_PRDT
, *PAHCI_PRDT
;
246 // 4.2.3 Command Table
247 typedef struct _AHCI_COMMAND_TABLE
249 // (16 * 32) + 64 + 16 + 48 = 648
250 // 128 byte aligned :D
254 AHCI_PRDT PRDT
[MAXIMUM_AHCI_PRDT_ENTRIES
];
255 } AHCI_COMMAND_TABLE
, *PAHCI_COMMAND_TABLE
;
257 // 4.2.2 Command Header
258 typedef struct _AHCI_COMMAND_HEADER
260 AHCI_COMMAND_HEADER_DESCRIPTION DI
; // DW 0
263 ULONG CTBA_U0
; // DW 3
264 ULONG Reserved
[4]; // DW 4-7
265 } AHCI_COMMAND_HEADER
, *PAHCI_COMMAND_HEADER
;
268 typedef struct _AHCI_RECEIVED_FIS
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
;
281 // Holds Port Information
282 typedef struct _AHCI_PORT
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
;
305 typedef struct _AHCI_MEMORY_REGISTERS
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
];
323 } AHCI_MEMORY_REGISTERS
, *PAHCI_MEMORY_REGISTERS
;
325 // Holds information for each attached attached port to a given adapter.
326 typedef struct _AHCI_PORT_EXTENSION
329 ULONG QueueSlots
; // slots which we have already assigned task (Slot)
330 ULONG CommandIssuedSlots
; // slots which has been programmed
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
;
343 // Holds Adapter Information
344 typedef struct _AHCI_ADAPTER_EXTENSION
346 ULONG SystemIoBusNumber
;
348 ULONG AhciBaseAddress
;
349 PULONG IS
;// Interrupt Status, In case of MSIM == `1`
350 ULONG PortImplemented
;// bit-mapping of ports which are implemented
360 ULONG LastInterruptPort
;
361 ULONG CurrentCommandSlot
;
363 PVOID NonCachedExtension
; // holds virtual address to noncached buffer allocated for Port Extension
372 // Message per port or shared port?
373 ULONG MessagePerPort
: 1;
375 ULONG Reserved
: 30; // not in use -- maintain 4 byte alignment
378 PAHCI_MEMORY_REGISTERS ABAR_Address
;
379 AHCI_PORT_EXTENSION PortExtension
[MAXIMUM_AHCI_PORT_COUNT
];
380 } AHCI_ADAPTER_EXTENSION
, *PAHCI_ADAPTER_EXTENSION
;
382 typedef struct _LOCAL_SCATTER_GATHER_LIST
384 ULONG NumberOfElements
;
386 STOR_SCATTER_GATHER_ELEMENT List
[MAXIMUM_AHCI_PRDT_ENTRIES
];
387 } LOCAL_SCATTER_GATHER_LIST
, *PLOCAL_SCATTER_GATHER_LIST
;
389 typedef struct _AHCI_SRB_EXTENSION
391 AHCI_COMMAND_TABLE CommandTable
;
406 UCHAR SectorCountLow
;
407 UCHAR SectorCountHigh
;
410 LOCAL_SCATTER_GATHER_LIST Sgl
;
411 PAHCI_COMPLETION_ROUTINE CompletionRoutine
;
412 } AHCI_SRB_EXTENSION
, *PAHCI_SRB_EXTENSION
;
414 //////////////////////////////////////////////////////////////
416 //////////////////////////////////////////////////////////////
420 __in PAHCI_ADAPTER_EXTENSION AdapterExtension
427 __in ULONG BufferSize
433 __in PAHCI_ADAPTER_EXTENSION AdapterExtension
,
438 DeviceInquiryRequest (
439 __in PAHCI_ADAPTER_EXTENSION AdapterExtension
,
440 __in PSCSI_REQUEST_BLOCK Srb
,
447 __inout PAHCI_QUEUE Queue
,
454 __inout PAHCI_QUEUE Queue
460 __in PSCSI_REQUEST_BLOCK Srb