ReactOS 0.4.16-dev-2633-g8dc9e50
ahci_generic.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS ATA Bus Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: AHCI controller minidriver
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "pciidex.h"
11
12/* GLOBALS ********************************************************************/
13
15static const struct
16{
20{
21 { PCI_VEN_NVIDIA, 0x0550 },
22 { PCI_VEN_NVIDIA, 0x0584 },
23};
24
25/* FUNCTIONS ******************************************************************/
26
27static
28CODE_SEG("PAGE")
31 _In_ PVOID ChannelContext)
32{
33 PCHANNEL_DATA_AHCI ChanData = ChannelContext;
34 PDMA_OPERATIONS DmaOperations = ChanData->DmaAdapter->DmaOperations;
35 ULONG i, j, SlotNumber, CommandSlots, BlockSize;
36 ULONG CommandListSize, CommandTableLength, CommandTablesPerPage;
38 ULONG_PTR BufferVa;
39 ULONG64 BufferPa;
41
42 PAGED_CODE();
43
44 /* The maximum size of the command list is 1024 bytes */
45 CommandSlots = ChanData->Controller->QueueDepth;
46 CommandListSize = FIELD_OFFSET(AHCI_COMMAND_LIST, CommandHeader[CommandSlots]);
47 BlockSize = CommandListSize + (AHCI_COMMAND_LIST_ALIGNMENT - 1);
48
49 /* Add the receive area structure (256 bytes) */
50 if (!(ChanData->ChanInfo & CHANNEL_FLAG_HAS_FBS))
51 {
52 BlockSize += sizeof(AHCI_RECEIVED_FIS);
53
54 /* The command list is 1024-byte aligned, which saves us some bytes of allocation size */
55 BlockSize += ALIGN_UP_BY(CommandListSize, AHCI_RECEIVED_FIS_ALIGNMENT) - CommandListSize;
56 }
57
58 Buffer = DmaOperations->AllocateCommonBuffer(ChanData->DmaAdapter,
59 BlockSize,
61 TRUE); // Cached
62 if (!Buffer)
64 RtlZeroMemory(Buffer, BlockSize);
65
66 ChanData->Mem.CommandListSize = BlockSize;
67 ChanData->Mem.CommandListOriginal = Buffer;
69
70 BufferVa = (ULONG_PTR)Buffer;
71 BufferPa = PhysicalAddress.QuadPart;
72
73 /* Command list */
74 BufferVa = ALIGN_UP_BY(BufferVa, AHCI_COMMAND_LIST_ALIGNMENT);
75 BufferPa = ALIGN_UP_BY(BufferPa, AHCI_COMMAND_LIST_ALIGNMENT);
76 ChanData->CommandList = (PVOID)BufferVa;
77 ChanData->Mem.CommandListPhys = BufferPa;
78 BufferVa += CommandListSize;
79 BufferPa += CommandListSize;
80
81 /* Alignment requirement */
83
84 /* Received FIS structure */
85 if (!(ChanData->ChanInfo & CHANNEL_FLAG_HAS_FBS))
86 {
87 BufferVa = ALIGN_UP_BY(BufferVa, AHCI_RECEIVED_FIS_ALIGNMENT);
88 BufferPa = ALIGN_UP_BY(BufferPa, AHCI_RECEIVED_FIS_ALIGNMENT);
89 ChanData->ReceivedFis = (PVOID)BufferVa;
90 ChanData->Mem.ReceivedFisPhys = BufferPa;
91 BufferVa += sizeof(AHCI_RECEIVED_FIS);
92 BufferPa += sizeof(AHCI_RECEIVED_FIS);
93
94 /* Alignment requirement */
96 }
97
98 if (ChanData->ChanInfo & CHANNEL_FLAG_HAS_FBS)
99 {
100 /* The FBS receive area is 4kB, allocate a page which is also 4kB-aligned */
101 BlockSize = PAGE_SIZE;
102
103 /*
104 * Some other architectures, like ia64, use a different page size,
105 * that is a multiple of 4096.
106 */
108
109 Buffer = DmaOperations->AllocateCommonBuffer(ChanData->DmaAdapter,
110 BlockSize,
112 TRUE);
113 if (!Buffer)
115 RtlZeroMemory(Buffer, BlockSize);
116
117 ChanData->Mem.ReceivedFisOriginal = Buffer;
119
120 BufferVa = (ULONG_PTR)Buffer;
121 BufferPa = PhysicalAddress.QuadPart;
122
123 ChanData->ReceivedFis = (PVOID)BufferVa;
124 ChanData->Mem.ReceivedFisPhys = BufferPa;
125
126 /* Alignment requirement */
128 }
129
130 /* 32-bit DMA */
131 if (!(ChanData->ChanInfo & CHANNEL_FLAG_64_BIT_DMA))
132 {
133 ASSERT((ULONG)(ChanData->Mem.CommandListPhys >> 32) == 0);
134 ASSERT((ULONG)(ChanData->Mem.ReceivedFisPhys >> 32) == 0);
135 }
136
137 CommandTableLength = FIELD_OFFSET(AHCI_COMMAND_TABLE, PrdTable[ChanData->MaximumPhysicalPages]);
138
139 ASSERT(ChanData->MaximumPhysicalPages != 0 &&
140 ChanData->MaximumPhysicalPages <= AHCI_MAX_PRDT_ENTRIES);
141
142 /*
143 * See ATA_MAX_TRANSFER_LENGTH, currently the MaximumPhysicalPages is restricted to
144 * a maximum of (0x20000 / PAGE_SIZE) + 1 = 33 pages.
145 * Each command table will require us 128 + 16 * 33 + (128 - 1) = 783 bytes of shared memory.
146 */
147 ASSERT(PAGE_SIZE > (CommandTableLength + (AHCI_COMMAND_TABLE_ALIGNMENT - 1)));
148
149 /* Allocate one-page chunks to avoid having a large chunk of contiguous memory */
150 CommandTablesPerPage = PAGE_SIZE / (CommandTableLength + (AHCI_COMMAND_TABLE_ALIGNMENT - 1));
151
152 /* Command tables allocation loop */
153 SlotNumber = 0;
154 i = CommandSlots;
155 while (i > 0)
156 {
157 ULONG TableCount;
158
159 TableCount = min(i, CommandTablesPerPage);
160 BlockSize = (CommandTableLength + (AHCI_COMMAND_TABLE_ALIGNMENT - 1)) * TableCount;
161
162 /* Allocate a chunk of memory */
163 Buffer = DmaOperations->AllocateCommonBuffer(ChanData->DmaAdapter,
164 BlockSize,
166 TRUE);
167 if (!Buffer)
169 RtlZeroMemory(Buffer, BlockSize);
170
173 ChanData->Mem.CommandTableSize[SlotNumber] = BlockSize;
174
175 BufferVa = (ULONG_PTR)Buffer;
176 BufferPa = PhysicalAddress.QuadPart;
177
178 /* Split the allocation into command tables */
179 for (j = 0; j < TableCount; ++j)
180 {
181 PAHCI_COMMAND_HEADER CommandHeader;
182
183 BufferVa = ALIGN_UP_BY(BufferVa, AHCI_COMMAND_TABLE_ALIGNMENT);
184 BufferPa = ALIGN_UP_BY(BufferPa, AHCI_COMMAND_TABLE_ALIGNMENT);
185
186 /* Alignment requirement */
187 ASSERT(BufferPa % AHCI_COMMAND_TABLE_ALIGNMENT == 0);
188
189 /* 32-bit DMA */
190 if (!(ChanData->ChanInfo & CHANNEL_FLAG_64_BIT_DMA))
191 {
192 ASSERT((ULONG)(BufferPa >> 32) == 0);
193 }
194
195 ChanData->CommandTable[SlotNumber] = (PAHCI_COMMAND_TABLE)BufferVa;
196
197 CommandHeader = &ChanData->CommandList->CommandHeader[SlotNumber];
198 CommandHeader->CommandTableBaseLow = (ULONG)BufferPa;
199 CommandHeader->CommandTableBaseHigh = (ULONG)(BufferPa >> 32);
200
201 ++SlotNumber;
202 BufferVa += CommandTableLength;
203 BufferPa += CommandTableLength;
204 }
205
206 i -= TableCount;
207 }
208
209 return STATUS_SUCCESS;
210}
211
212static
213CODE_SEG("PAGE")
214VOID
216 _In_ PVOID ChannelContext)
217{
218 PCHANNEL_DATA_AHCI ChanData = ChannelContext;
219 PDMA_ADAPTER DmaAdapter = ChanData->DmaAdapter;
220 PDMA_OPERATIONS DmaOperations = ChanData->DmaAdapter->DmaOperations;
221 ULONG i;
222
223 PAGED_CODE();
224
225 if (ChanData->Mem.CommandListOriginal)
226 {
227 DmaOperations->FreeCommonBuffer(DmaAdapter,
228 ChanData->Mem.CommandListSize,
230 ChanData->Mem.CommandListOriginal,
231 TRUE); // Cached
232 ChanData->Mem.CommandListOriginal = NULL;
233 }
234
235 if (ChanData->Mem.ReceivedFisOriginal)
236 {
237 DmaOperations->FreeCommonBuffer(DmaAdapter,
238 PAGE_SIZE,
240 ChanData->Mem.ReceivedFisOriginal,
241 TRUE);
242 ChanData->Mem.ReceivedFisOriginal = NULL;
243 }
244
245 for (i = 0; i < AHCI_MAX_COMMAND_SLOTS; ++i)
246 {
247 if (ChanData->Mem.CommandTableOriginal[i])
248 {
249 DmaOperations->FreeCommonBuffer(DmaAdapter,
250 ChanData->Mem.CommandTableSize[i],
251 ChanData->Mem.CommandTablePhysOriginal[i],
252 ChanData->Mem.CommandTableOriginal[i],
253 TRUE);
254 ChanData->Mem.CommandTableOriginal[i] = NULL;
255 }
256 }
257}
258
259#if DBG
260static
261CODE_SEG("PAGE")
263AtaAhciIsVbox(VOID)
264{
266 PPCI_COMMON_HEADER PciData = (PPCI_COMMON_HEADER)Buffer; // Partial PCI header
268 PCI_SLOT_NUMBER Slot;
269
270 PAGED_CODE();
271
272 Slot.u.AsULONG = 0;
273 Slot.u.bits.DeviceNumber = 4;
274 Slot.u.bits.FunctionNumber = 0;
275
277 0,
278 Slot.u.AsULONG,
279 &Buffer,
281 sizeof(Buffer));
282 return (BytesRead == sizeof(Buffer)) &&
283 (PciData->VendorID == 0x80EE) &&
284 (PciData->DeviceID == 0xCAFE);
285}
286#endif
287
288static
289CODE_SEG("PAGE")
290VOID
292 _In_ PVOID IoBase)
293{
294 ULONG i, Control;
295
296 PAGED_CODE();
297
300 return;
301
302 INFO("HBA ownership change\n");
303
305
306 /* Wait up to 2 seconds */
307 for (i = 0; i < 200000; ++i)
308 {
310
312 return;
313
315 }
316
317 WARN("Unable to acquire the OS semaphore %08lx\n", Control);
318}
319
324static
325CODE_SEG("PAGE")
328 _In_ ULONG AhciCapabilities,
329 _In_ ULONG CmdStatus)
330{
331 PAGED_CODE();
332
333 if (CmdStatus & AHCI_PXCMD_HPCP)
334 return TRUE;
335
336 if ((AhciCapabilities & AHCI_CAP_SXS) && (CmdStatus & AHCI_PXCMD_ESP))
337 return TRUE;
338
339 if ((AhciCapabilities & AHCI_CAP_SMPS) && (CmdStatus & AHCI_PXCMD_MPSP))
340 return TRUE;
341
342 return FALSE;
343}
344
345static
346CODE_SEG("PAGE")
349 _In_ PATA_CONTROLLER Controller)
350{
351 PCHANNEL_DATA_AHCI ChanData;
352 ULONG i;
353
354 PAGED_CODE();
355 ASSERT(Controller->MaxChannels != 0);
356
358 sizeof(*ChanData) * Controller->MaxChannels,
360 if (!ChanData)
362
363 Controller->ChanDataBlock = ChanData;
364
365 for (i = 0; i < AHCI_MAX_PORTS; ++i)
366 {
367 ULONG CmdStatus;
368
369 if (!(Controller->ChannelBitmap & (1 << i)))
370 continue;
371
372 Controller->Channels[i] = ChanData;
373
374 ChanData->Channel = i;
375 ChanData->Controller = Controller;
376
377 ChanData->AllocateMemory = AtaAhciAllocateMemory;
378 ChanData->FreeMemory = AtaAhciFreeMemory;
379 ChanData->EnableInterrupts = AtaAhciEnableInterrupts;
380 ChanData->PreparePrdTable = AtaAhciPreparePrdTable;
381 ChanData->PrepareIo = AtaAhciPrepareIo;
382 ChanData->StartIo = AtaAhciStartIo;
383 ChanData->SetTransferMode = SataSetTransferMode;
384 ChanData->TransferModeSupported = SATA_ALL;
385
386 ChanData->IoBase = AHCI_PORT_BASE(Controller->IoBase, i);
387
388 ChanData->EnableInterrupts(ChanData, FALSE);
389
390 /* Begin the process of stopping the command list DMA engine for later initialization */
391 CmdStatus = AHCI_PORT_READ(ChanData->IoBase, PxCmdStatus);
392 if (CmdStatus & AHCI_PXCMD_ST)
393 {
394 CmdStatus &= ~AHCI_PXCMD_ST;
395 AHCI_PORT_WRITE(ChanData->IoBase, PxCmdStatus, CmdStatus);
396 }
397
398 /* The AHCI HBA can only perform DMA I/O and PIO is not supported */
399 ChanData->ChanInfo = CHANNEL_FLAG_PIO_VIA_DMA;
400
401 if (Controller->AhciCapabilities & AHCI_CAP_S64A)
402 ChanData->ChanInfo |= CHANNEL_FLAG_64_BIT_DMA;
403
404 if (Controller->AhciCapabilities & AHCI_CAP_SNCQ)
405 ChanData->ChanInfo |= CHANNEL_FLAG_HAS_NCQ;
406
407 /* Check for the FIS-based switching feature support */
408 if ((Controller->AhciCapabilities & AHCI_CAP_SPM) &&
409 (Controller->AhciCapabilities & AHCI_CAP_FBSS) &&
410 (CmdStatus & AHCI_PXCMD_FBSCP))
411 {
412 INFO("CH %lu: FBS supported\n", ChanData->Channel);
413 ChanData->ChanInfo |= CHANNEL_FLAG_HAS_FBS;
414 }
415
416 if (AtaAhciIsPortRemovable(Controller->AhciCapabilities, CmdStatus))
417 {
418 INFO("CH %lu: Port is external\n", ChanData->Channel);
419 ChanData->ChanInfo |= CHANNEL_FLAG_IS_EXTERNAL;
420 }
421
422 ++ChanData;
423 }
424
425 return STATUS_SUCCESS;
426}
427
428static
429CODE_SEG("PAGE")
430PVOID
432 _Inout_ PATA_CONTROLLER Controller)
433{
434 PVOID Abar;
435 ULONG i, Index;
436 PCIIDEX_PAGED_DATA static const struct
437 {
440 ULONG Index;
441 } AbarLocations[] =
442 {
443 { PCI_VEN_CAVIUM, 0xA01C, 0 },
444 };
445
446 PAGED_CODE();
447
448 /* Default index */
449 Index = 5;
450
451 for (i = 0; i < RTL_NUMBER_OF(AbarLocations); ++i)
452 {
453 if ((Controller->Pci.VendorID == AbarLocations[i].VendorID) &&
454 (Controller->Pci.DeviceID == AbarLocations[i].DeviceID))
455 {
456 Index = AbarLocations[i].Index;
457 break;
458 }
459 }
460
461 if (!(Controller->AccessRange[Index].Flags & RANGE_IS_MEMORY))
462 return NULL;
463
464 Abar = AtaCtrlPciMapBar(Controller, Index, 0);
465 if (!Abar)
466 return NULL;
467
468 return Abar;
469}
470
471static
472CODE_SEG("PAGE")
475 _In_ PVOID ChannelContext,
476 _In_ BOOLEAN Attach)
477{
478 PCHANNEL_DATA_AHCI ChanData = ChannelContext;
479
480 PAGED_CODE();
481
482 if (Attach)
483 {
484 /* We do enable interrupts in the QBR handler */
485 }
486 else
487 {
489 AtaAhciStopDma(ChanData);
490 }
491
492 return STATUS_SUCCESS;
493}
494
495static
496VOID
498 _In_ PATA_CONTROLLER Controller)
499{
500 ULONG GlobalControl;
501
502 GlobalControl = AHCI_HBA_READ(Controller->IoBase, HbaGlobalControl);
503 if (!(GlobalControl & AHCI_GHC_AE))
504 {
505 /* Set AE on power up */
506 GlobalControl |= AHCI_GHC_AE;
507 AHCI_HBA_WRITE(Controller->IoBase, HbaGlobalControl, GlobalControl);
508 }
509
510 /* Clear HBA interrupts */
511 AHCI_HBA_WRITE(Controller->IoBase, HbaInterruptStatus, 0xFFFFFFFF);
512
513 /* Enable interrupts */
514 GlobalControl |= AHCI_GHC_IE;
515 AHCI_HBA_WRITE(Controller->IoBase, HbaGlobalControl, GlobalControl);
516}
517
518static
519VOID
521 _In_ PATA_CONTROLLER Controller)
522{
523 ULONG GlobalControl;
525
526 /* Failed to connect interrupt */
527 if (!Controller->InterruptObject)
528 return;
529
530 OldIrql = KeAcquireInterruptSpinLock(Controller->InterruptObject);
531
532 /* Disable interrupts */
533 GlobalControl = AHCI_HBA_READ(Controller->IoBase, HbaGlobalControl);
534 GlobalControl &= ~AHCI_GHC_IE;
535 AHCI_HBA_WRITE(Controller->IoBase, HbaGlobalControl, GlobalControl);
536
537 /* Clear HBA interrupts */
538 AHCI_HBA_WRITE(Controller->IoBase, HbaInterruptStatus, 0xFFFFFFFF);
539
540 KeReleaseInterruptSpinLock(Controller->InterruptObject, OldIrql);
541}
542
543static
544CODE_SEG("PAGE")
545VOID
547 _In_ PATA_CONTROLLER Controller)
548{
549 PAGED_CODE();
550
551 if (Controller->InterruptObject)
552 {
553 IoDisconnectInterrupt(Controller->InterruptObject);
554 Controller->InterruptObject = NULL;
555 }
556}
557
558static
559CODE_SEG("PAGE")
562 _In_ PATA_CONTROLLER Controller)
563{
564 PAGED_CODE();
565
566 if (Controller->Pci.VendorID == PCI_VEN_INTEL)
567 {
568 /* IDE or AHCI */
569 if ((Controller->Pci.DeviceID == 0x2652) || (Controller->Pci.DeviceID == 0x2653))
570 return TRUE;
571 }
572
573 /* IDE, RAID, or AHCI */
574 if ((Controller->Pci.VendorID == PCI_VEN_VIA) && (Controller->Pci.DeviceID == 0x3349))
575 return TRUE;
576
577 return FALSE;
578}
579
580static
581CODE_SEG("PAGE")
584 _In_ PATA_CONTROLLER Controller)
585{
586 ULONG i;
587
588 PAGED_CODE();
589
590 /* Some controllers share the same PCI ID between AHCI and IDE/RAID modes */
592 {
593 if (Controller->Pci.SubClass != PCI_SUBCLASS_MSC_AHCI_CTLR)
594 return FALSE;
595 }
596
597 /*
598 * Match the controller through the PCI ID.
599 * We do not want to check the PCI subclass code because of
600 * some AHCI controllers that support AHCI even in IDE emulation mode.
601 * For example, nVidia 10DE:0550 uses the same PCI ID between AHCI and IDE modes,
602 * but BAR5 will always be available and AHCI can be enabled by setting GHC.AE to 1.
603 */
604 for (i = 0; i < RTL_NUMBER_OF(AhciControllerList); ++i)
605 {
606 if ((Controller->Pci.VendorID == AhciControllerList[i].VendorID) &&
607 (Controller->Pci.DeviceID == AhciControllerList[i].DeviceID))
608 {
609 return TRUE;
610 }
611 }
612
613 /* Check for generic PCI AHCI controller */
614 if ((Controller->Pci.BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
615 (Controller->Pci.SubClass == PCI_SUBCLASS_MSC_AHCI_CTLR))
616 {
617 return TRUE;
618 }
619
620 return FALSE;
621}
622
623CODE_SEG("PAGE")
626 _Inout_ PATA_CONTROLLER Controller)
627{
628 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDesc = &Controller->InterruptDesc;
629 ULONG i, GlobalControl;
631
632 PAGED_CODE();
633
634 if (!AhciMatchController(Controller))
635 return STATUS_NO_MATCH;
636
637 if (Controller->InterruptDesc.Type != CmResourceTypeInterrupt)
638 {
639 ERR("No interrupt resource\n");
641 }
642
643 Controller->IoBase = AtaAhciGetAbar(Controller);
644 if (!Controller->IoBase)
645 return STATUS_NO_MATCH; // Try IDE/RAID
646
647 Controller->Flags = CTRL_FLAG_IS_AHCI | CTRL_FLAG_SATA_HBA_ACPI;
648 Controller->Start = AtaAhciHbaStart;
649 Controller->Stop = AtaAhciHbaStop;
650 Controller->FreeResources = AtaAhciHbaFreeResouces;
651 Controller->AttachChannel = AtaAhciAttachChannel;
652
653 /* Set AE before accessing other AHCI registers */
654 GlobalControl = AHCI_HBA_READ(Controller->IoBase, HbaGlobalControl);
655 GlobalControl |= AHCI_GHC_AE;
656 AHCI_HBA_WRITE(Controller->IoBase, HbaGlobalControl, GlobalControl);
657
658 Controller->AhciCapabilities = AHCI_HBA_READ(Controller->IoBase, HbaCapabilities);
659 Controller->ChannelBitmap = AHCI_HBA_READ(Controller->IoBase, HbaPortBitmap);
660 Controller->MaxChannels = CountSetBits(Controller->ChannelBitmap);
661 if (Controller->MaxChannels == 0)
662 {
663 ASSERT(Controller->MaxChannels == 0);
665 }
666
667 Controller->AhciVersion = AHCI_HBA_READ(Controller->IoBase, HbaAhciVersion);
668 if (Controller->AhciVersion >= AHCI_VERSION_1_2)
669 {
670 Controller->AhciCapabilitiesEx = AHCI_HBA_READ(Controller->IoBase, HbaCapabilitiesEx);
671
672 if (Controller->AhciCapabilitiesEx & AHCI_CAP2_BOH)
673 AtaAhciHbaRequestOsOwnership(Controller->IoBase);
674 }
675
676 /* Reset the HBA into a consistent state */
677 GlobalControl = AHCI_HBA_READ(Controller->IoBase, HbaGlobalControl);
678 GlobalControl |= AHCI_GHC_HR;
679 AHCI_HBA_WRITE(Controller->IoBase, HbaGlobalControl, GlobalControl);
680
681 /* HBA reset may take up to 1 second */
682 for (i = 100000; i > 0; i--)
683 {
684 GlobalControl = AHCI_HBA_READ(Controller->IoBase, HbaGlobalControl);
685 if (!(GlobalControl & AHCI_GHC_HR))
686 break;
687
689 }
690 if (i == 0)
691 {
692 ERR("HBA reset failed %08lx\n", GlobalControl);
693 return STATUS_IO_TIMEOUT;
694 }
695
696 /* Re-enable AE */
697 GlobalControl |= AHCI_GHC_AE;
698 AHCI_HBA_WRITE(Controller->IoBase, HbaGlobalControl, GlobalControl);
699
700 /* Disable interrupts */
701 GlobalControl = AHCI_HBA_READ(Controller->IoBase, HbaGlobalControl);
702 if (GlobalControl & AHCI_GHC_IE)
703 {
704 GlobalControl &= ~AHCI_GHC_IE;
705 AHCI_HBA_WRITE(Controller->IoBase, HbaGlobalControl, GlobalControl);
706 }
707
708#if DBG
709 /* On virtual machines, this will allow us to test the PMP support code */
710 if (AtaAhciIsVbox())
711 Controller->AhciCapabilities |= AHCI_CAP_SPM;
712#endif
713
714 Status = AtaAhciCreateChannelData(Controller);
715 if (!NT_SUCCESS(Status))
716 return Status;
717
718 Controller->QueueDepth = ((Controller->AhciCapabilities & AHCI_CAP_NCS) >> 8) + 1;
719
720 INFO("%04X:%04X.%02X: Ver %08lX, PI %08lX, CAP %08lX, CAP2 %08lX\n",
721 Controller->Pci.VendorID,
722 Controller->Pci.DeviceID,
723 Controller->Pci.RevisionID,
724 Controller->AhciVersion,
725 Controller->ChannelBitmap,
726 Controller->AhciCapabilities,
727 Controller->AhciCapabilitiesEx);
728
729 /* Clear HBA interrupts */
730 AHCI_HBA_WRITE(Controller->IoBase, HbaInterruptStatus, 0xFFFFFFFF);
731
732 Status = IoConnectInterrupt(&Controller->InterruptObject,
734 Controller,
735 NULL,
736 InterruptDesc->u.Interrupt.Vector,
737 InterruptDesc->u.Interrupt.Level,
738 InterruptDesc->u.Interrupt.Level,
739 (InterruptDesc->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
741 (InterruptDesc->ShareDisposition == CmResourceShareShared),
742 InterruptDesc->u.Interrupt.Affinity,
743 FALSE);
744 if (!NT_SUCCESS(Status))
745 {
746 ERR("Could not connect to interrupt %lu, status 0x%lx\n",
747 InterruptDesc->u.Interrupt.Vector, Status);
748 return Status;
749 }
750
751 return STATUS_SUCCESS;
752}
#define PAGED_CODE()
#define CODE_SEG(...)
#define ALIGN_UP_BY(size, align)
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
#define AHCI_CAP2_BOH
Definition: ahci.h:340
#define AHCI_RECEIVED_FIS_FBS_ALIGNMENT
Definition: ahci.h:23
#define AHCI_COMMAND_LIST_ALIGNMENT
Definition: ahci.h:22
struct _AHCI_COMMAND_TABLE * PAHCI_COMMAND_TABLE
#define AHCI_CAP_FBSS
Definition: ahci.h:323
#define AHCI_MAX_PORTS
Definition: ahci.h:10
#define AHCI_MAX_PRDT_ENTRIES
Definition: ahci.h:15
#define AHCI_CAP_SMPS
Definition: ahci.h:332
#define AHCI_CAP_SPM
Definition: ahci.h:324
#define AHCI_BOHC_OS_SEMAPHORE
Definition: ahci.h:348
#define AHCI_COMMAND_TABLE_ALIGNMENT
Definition: ahci.h:20
FORCEINLINE VOID AHCI_PORT_WRITE(_In_ PVOID PortIoBase, _In_ AHCI_PORT_REGISTER Register, _In_ ULONG Value)
Definition: ahci.h:557
#define AHCI_PXCMD_FBSCP
Definition: ahci.h:165
#define AHCI_CAP_SXS
Definition: ahci.h:316
#define AHCI_CAP_NCS
Definition: ahci.h:319
#define AHCI_PXCMD_ESP
Definition: ahci.h:164
struct _AHCI_RECEIVED_FIS AHCI_RECEIVED_FIS
#define AHCI_GHC_HR
Definition: ahci.h:307
#define AHCI_CAP_SNCQ
Definition: ahci.h:334
FORCEINLINE ULONG AHCI_PORT_READ(_In_ PVOID PortIoBase, _In_ AHCI_PORT_REGISTER Register)
Definition: ahci.h:548
#define AHCI_RECEIVED_FIS_ALIGNMENT
Definition: ahci.h:21
#define AHCI_PORT_BASE(HbaIoBase, PortNumber)
Definition: ahci.h:524
#define AHCI_GHC_AE
Definition: ahci.h:310
#define AHCI_CAP_S64A
Definition: ahci.h:335
#define AHCI_VERSION_1_2
Definition: ahci.h:300
FORCEINLINE ULONG AHCI_HBA_READ(_In_ PVOID HbaIoBase, _In_ AHCI_HOST_BUS_ADAPTER_REGISTER Register)
Definition: ahci.h:529
#define AHCI_PXCMD_HPCP
Definition: ahci.h:161
#define AHCI_GHC_IE
Definition: ahci.h:308
#define AHCI_BOHC_BIOS_SEMAPHORE
Definition: ahci.h:347
#define AHCI_MAX_COMMAND_SLOTS
Definition: ahci.h:13
#define AHCI_BOHC_BIOS_BUSY
Definition: ahci.h:351
#define AHCI_PXCMD_ST
Definition: ahci.h:149
#define AHCI_PXCMD_MPSP
Definition: ahci.h:162
@ PxCmdStatus
Definition: ahci.h:104
FORCEINLINE VOID AHCI_HBA_WRITE(_In_ PVOID HbaIoBase, _In_ AHCI_HOST_BUS_ADAPTER_REGISTER Register, _In_ ULONG Value)
Definition: ahci.h:538
@ HbaCapabilities
Definition: ahci.h:83
@ HbaCapabilitiesEx
Definition: ahci.h:92
@ HbaPortBitmap
Definition: ahci.h:86
@ HbaBiosHandoffControl
Definition: ahci.h:93
@ HbaGlobalControl
Definition: ahci.h:84
@ HbaAhciVersion
Definition: ahci.h:87
@ HbaInterruptStatus
Definition: ahci.h:85
static NTSTATUS AtaAhciAllocateMemory(_In_ PVOID ChannelContext)
Definition: ahci_generic.c:30
static PVOID AtaAhciGetAbar(_Inout_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:431
static NTSTATUS AtaAhciAttachChannel(_In_ PVOID ChannelContext, _In_ BOOLEAN Attach)
Definition: ahci_generic.c:474
static VOID AtaAhciHbaStop(_In_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:520
static BOOLEAN AtaAhciIsPortRemovable(_In_ ULONG AhciCapabilities, _In_ ULONG CmdStatus)
Definition: ahci_generic.c:327
static BOOLEAN AhciMatchController(_In_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:583
static PCIIDEX_PAGED_DATA const struct @1171 AhciControllerList[]
static BOOLEAN AhciControllerIsSubClassCheckNeeded(_In_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:561
static VOID AtaAhciHbaFreeResouces(_In_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:546
static NTSTATUS AtaAhciCreateChannelData(_In_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:348
USHORT VendorID
Definition: ahci_generic.c:17
static VOID AtaAhciFreeMemory(_In_ PVOID ChannelContext)
Definition: ahci_generic.c:215
static VOID AtaAhciHbaRequestOsOwnership(_In_ PVOID IoBase)
Definition: ahci_generic.c:291
USHORT DeviceID
Definition: ahci_generic.c:18
NTSTATUS AhciGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:625
static VOID AtaAhciHbaStart(_In_ PATA_CONTROLLER Controller)
Definition: ahci_generic.c:497
VOID AtaAhciStopDma(_In_ PCHANNEL_DATA_AHCI ChanData)
Definition: ahci_hw.c:1280
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define INFO
Definition: debug.h:89
#define ULONG_PTR
Definition: config.h:101
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
ULONG NTAPI HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: bus.c:73
#define C_ASSERT(e)
Definition: intsafe.h:73
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define KeStallExecutionProcessor(MicroSeconds)
Definition: precomp.h:27
#define min(a, b)
Definition: monoChain.cc:55
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:684
VOID NTAPI IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
Definition: irq.c:142
NTSTATUS NTAPI IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave)
Definition: irq.c:23
KIRQL NTAPI KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
Definition: spinlock.c:154
VOID NTAPI KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, IN KIRQL OldIrql)
Definition: spinlock.c:171
#define STATUS_NO_MATCH
Definition: ntstatus.h:873
#define STATUS_DEVICE_HARDWARE_ERROR
Definition: ntstatus.h:1169
#define PCI_VEN_INTEL
Definition: pata.h:19
#define PCI_VEN_CAVIUM
Definition: pata.h:18
#define SATA_ALL
Definition: pata.h:37
#define PCI_VEN_NVIDIA
Definition: pata.h:12
#define PCI_VEN_VIA
Definition: pata.h:15
CHANNEL_PREPARE_IO AtaAhciPrepareIo
Definition: pciidex.h:626
#define PCIIDEX_PAGED_DATA
Definition: pciidex.h:50
#define CHANNEL_FLAG_64_BIT_DMA
Definition: pciidex.h:266
CHANNEL_ENABLE_INTERRUPTS AtaAhciEnableInterrupts
Definition: pciidex.h:591
#define CTRL_FLAG_SATA_HBA_ACPI
Definition: pciidex.h:225
CHANNEL_SET_MODE_EX SataSetTransferMode
Definition: pciidex.h:633
#define CHANNEL_FLAG_IS_EXTERNAL
Definition: pciidex.h:271
#define CHANNEL_FLAG_PIO_VIA_DMA
Definition: pciidex.h:269
#define CTRL_FLAG_IS_AHCI
Definition: pciidex.h:227
#define RANGE_IS_MEMORY
Definition: pciidex.h:191
FORCEINLINE ULONG CountSetBits(_In_ ULONG x)
Definition: pciidex.h:827
CHANNEL_PREPARE_PRD_TABLE AtaAhciPreparePrdTable
Definition: pciidex.h:627
KSERVICE_ROUTINE AtaAhciHbaIsr
Definition: pciidex.h:629
#define CHANNEL_FLAG_HAS_NCQ
Definition: pciidex.h:276
CHANNEL_START_IO AtaAhciStartIo
Definition: pciidex.h:625
#define TAG_PCIIDEX
Definition: pciidex.h:32
#define CHANNEL_FLAG_HAS_FBS
Definition: pciidex.h:273
unsigned short USHORT
Definition: pedump.c:61
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: restypes.h:117
#define CmResourceTypeInterrupt
Definition: restypes.h:105
@ Latched
Definition: miniport.h:81
@ LevelSensitive
Definition: miniport.h:80
@ PCIConfiguration
Definition: miniport.h:93
#define STATUS_SUCCESS
Definition: shellext.h:65
DECLSPEC_NOINLINE_FROM_PAGED VOID AtaChanEnableInterruptsSync(_In_ PVOID ChannelContext, _In_ BOOLEAN Enable)
Definition: fdo.c:62
PVOID AtaCtrlPciMapBar(_In_ PATA_CONTROLLER Controller, _In_range_(0, PCI_TYPE0_ADDRESSES) ULONG Index, _In_ ULONG MinimumIoLength)
Definition: fdo.c:249
ULONG CommandTableBaseLow
Definition: ahci.h:483
ULONG CommandTableBaseHigh
Definition: ahci.h:484
AHCI_COMMAND_HEADER CommandHeader[ANYSIZE_ARRAY]
Definition: ahci.h:492
PAHCI_COMMAND_TABLE CommandTable[AHCI_MAX_COMMAND_SLOTS]
Definition: pciidex.h:343
PAHCI_COMMAND_LIST CommandList
Definition: pciidex.h:342
PAHCI_RECEIVED_FIS ReceivedFis
Definition: pciidex.h:341
CHANNEL_INFO_AHCI Mem
Definition: pciidex.h:347
ULONG64 CommandListPhys
Definition: pciidex.h:323
PVOID CommandListOriginal
Definition: pciidex.h:325
PHYSICAL_ADDRESS CommandListPhysOriginal
Definition: pciidex.h:330
ULONG CommandTableSize[AHCI_MAX_COMMAND_SLOTS]
Definition: pciidex.h:327
PVOID ReceivedFisOriginal
Definition: pciidex.h:324
ULONG CommandListSize
Definition: pciidex.h:328
PHYSICAL_ADDRESS ReceivedFisPhysOriginal
Definition: pciidex.h:329
PHYSICAL_ADDRESS CommandTablePhysOriginal[AHCI_MAX_COMMAND_SLOTS]
Definition: pciidex.h:331
ULONG64 ReceivedFisPhys
Definition: pciidex.h:322
PVOID CommandTableOriginal[AHCI_MAX_COMMAND_SLOTS]
Definition: pciidex.h:326
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@384::@387 Interrupt
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@384 u
PALLOCATE_COMMON_BUFFER AllocateCommonBuffer
Definition: iotypes.h:2637
PFREE_COMMON_BUFFER FreeCommonBuffer
Definition: iotypes.h:2638
struct _PCI_SLOT_NUMBER::@4410::@4411 bits
union _PCI_SLOT_NUMBER::@4410 u
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceID
Definition: wdfpdo.h:278
_In_ WDFIORESREQLIST _In_ ULONG SlotNumber
Definition: wdfresource.h:68
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
@ CmResourceShareShared
Definition: cmtypes.h:243
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098
#define PCI_CLASS_MASS_STORAGE_CTLR
Definition: iotypes.h:4106
#define PCI_SUBCLASS_MSC_AHCI_CTLR
Definition: iotypes.h:4135
struct _PCI_COMMON_HEADER * PPCI_COMMON_HEADER
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778