[PCIIDEX] Add AHCI support

WIP

CORE-17256
This commit is contained in:
Dmitry Borisov 2024-03-03 19:02:29 +06:00
parent b0c9c12a4a
commit c04df3f2c9
13 changed files with 739 additions and 28 deletions

View file

@ -1,4 +1,5 @@
add_subdirectory(pciahci)
add_subdirectory(pciide)
add_subdirectory(pciidex)
add_subdirectory(uniata)

View file

@ -0,0 +1,14 @@
add_library(pciahci MODULE pciahci.c pciahci.rc)
set_module_type(pciahci kernelmodedriver)
if(MSVC)
target_link_options(pciahci PRIVATE /SECTION:.rsrc,!D)
else()
add_custom_command(
TARGET pciahci POST_BUILD
COMMAND native-pefixup --section:.rsrc,!D $<TARGET_FILE:pciahci>
VERBATIM)
endif()
add_importlibs(pciahci pciidex ntoskrnl)
add_cd_file(TARGET pciahci DESTINATION reactos/system32/drivers NO_CAB FOR all)
add_registry_inf(pciahci_reg.inf)

View file

@ -0,0 +1,121 @@
/*
* PROJECT: ReactOS AHCI Port Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Common file
* COPYRIGHT: Copyright 2024 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES *******************************************************************/
#include "pciahci.h"
/* GLOBALS ********************************************************************/
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ******************************************************************/
IDE_CHANNEL_STATE
NTAPI
PciAhciPortEnabled(
_In_ PVOID DeviceExtension,
_In_ ULONG Channel)
{
PAHCI_DEVICE_EXTENSION AhciExtension = DeviceExtension;
if (AhciExtension->Hba->PortsImplemented & (1 << Channel))
{
DPRINT1("AHCI Port %lu is enabled\n", Channel);
return ChannelEnabled;
}
return ChannelDisabled;
}
BOOLEAN
NTAPI
PciAhciSyncAccessRequired(
_In_ PVOID DeviceExtension)
{
return FALSE;
}
NTSTATUS
NTAPI
PciAhciTransferModeSelect(
_In_ PVOID DeviceExtension,
_In_ PPCIIDE_TRANSFER_MODE_SELECT XferMode)
{
return STATUS_SUCCESS;
}
ULONG
NTAPI
PciAhciUseDma(
_In_ PVOID DeviceExtension,
_In_ PUCHAR CdbCommand,
_In_ PUCHAR Slave)
{
/* Nothing should prevent us to use DMA */
return 1;
}
NTSTATUS
NTAPI
PciAhciGetControllerProperties(
_In_ PVOID DeviceExtension,
_Out_ PIDE_CONTROLLER_PROPERTIES ControllerProperties)
{
PAHCI_DEVICE_EXTENSION AhciExtension = DeviceExtension;
ULONG i;
if (ControllerProperties->Size != sizeof(*ControllerProperties))
return STATUS_REVISION_MISMATCH;
ControllerProperties->PciIdeChannelEnabled = PciAhciPortEnabled;
ControllerProperties->PciIdeSyncAccessRequired = PciAhciSyncAccessRequired;
ControllerProperties->PciIdeTransferModeSelect = PciAhciTransferModeSelect;
ControllerProperties->IgnoreActiveBitForAtaDevice = FALSE;
ControllerProperties->AlwaysClearBusMasterInterrupt = TRUE;
ControllerProperties->PciIdeUseDma = PciAhciUseDma;
ControllerProperties->AlignmentRequirement = 1;
ControllerProperties->DefaultPIO = 0;
ControllerProperties->SupportedTransferMode[0][0] =
ControllerProperties->SupportedTransferMode[0][1] =
ControllerProperties->SupportedTransferMode[1][0] =
ControllerProperties->SupportedTransferMode[1][1] = 0x7FFFFFFF;
AhciExtension->Hba->GlobalControl |= AHCI_GHC_AE;
for (i = 0; i < MAX_AHCI_DEVICES; ++i)
{
PAHCI_PORT_REGISTERS Port;
if (!(AhciExtension->Hba->PortsImplemented & (1 << i)))
continue;
Port = &AhciExtension->Hba->Port[i];
Port->SataError = Port->SataError;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath)
{
NTSTATUS Status;
Status = PciIdeXInitialize(DriverObject,
RegistryPath,
PciAhciGetControllerProperties,
sizeof(AHCI_DEVICE_EXTENSION));
return Status;
}

View file

@ -0,0 +1,11 @@
/*
* PROJECT: ReactOS AHCI Port Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Common header file
* COPYRIGHT: Copyright 2024 Dmitry Borisov (di.sean@protonmail.com)
*/
#include <ntddk.h>
#include <ide.h>
#include <reactos/drivers/ntddata.h>

View file

@ -0,0 +1,5 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "PCI AHCI bus driver"
#define REACTOS_STR_INTERNAL_NAME "pciahci"
#define REACTOS_STR_ORIGINAL_FILENAME "pciahci.sys"
#include <reactos/version.rc>

View file

@ -0,0 +1,8 @@
; PCI AHCI Driver
[AddReg]
HKLM,"SYSTEM\CurrentControlSet\Services\pciahci","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\pciahci","Group",0x00000000,"System Bus Extender"
HKLM,"SYSTEM\CurrentControlSet\Services\pciahci","ImagePath",0x00020000,"system32\drivers\pciahci.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\pciahci","Start",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\pciahci","Type",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\pciahci","Tag",0x00010001,0x00000010

View file

@ -14,7 +14,7 @@ add_library(pciidex MODULE
pciidex.rc
${CMAKE_CURRENT_BINARY_DIR}/pciidex.def)
add_pch(pciidex pciidex.h SOURCE)
# add_pch(pciidex pciidex.h SOURCE)
set_module_type(pciidex kernelmodedriver)
add_importlibs(pciidex ntoskrnl hal)
add_cd_file(TARGET pciidex DESTINATION reactos/system32/drivers NO_CAB FOR all)

View file

@ -19,6 +19,8 @@ PciIdeXFdoParseResources(
_In_ PCM_RESOURCE_LIST ResourcesTranslated)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR BusMasterDescriptor = NULL;
PCM_PARTIAL_RESOURCE_DESCRIPTOR AbarDescriptor = NULL;
PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL;
PVOID IoBase;
ULONG i;
@ -34,6 +36,13 @@ PciIdeXFdoParseResources(
Descriptor = &ResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
switch (Descriptor->Type)
{
case CmResourceTypeInterrupt:
{
if (!InterruptDescriptor)
InterruptDescriptor = Descriptor;
break;
}
case CmResourceTypePort:
case CmResourceTypeMemory:
{
@ -50,6 +59,13 @@ PciIdeXFdoParseResources(
default:
break;
}
/* AHCI Base Address (BAR5) */
if ((i == 5) && (FdoExtension->Flags & FDO_AHCI))
{
if (Descriptor->Type == CmResourceTypeMemory)
AbarDescriptor = Descriptor;
}
}
default:
@ -57,6 +73,34 @@ PciIdeXFdoParseResources(
}
}
if (FdoExtension->Flags & FDO_AHCI)
{
if (!AbarDescriptor || !InterruptDescriptor)
return STATUS_DEVICE_CONFIGURATION_ERROR;
DPRINT("ABAR 0x%I64x 0x%lx\n",
AbarDescriptor->u.Port.Start.QuadPart, AbarDescriptor->u.Port.Length);
FdoExtension->Abar = MmMapIoSpace(AbarDescriptor->u.Memory.Start,
AbarDescriptor->u.Port.Length,
MmNonCached);
if (!FdoExtension->Abar)
return STATUS_INSUFFICIENT_RESOURCES;
FdoExtension->IoLength = AbarDescriptor->u.Port.Length;
FdoExtension->Flags |= FDO_IO_BASE_MAPPED;
FdoExtension->InterruptVector = InterruptDescriptor->u.Interrupt.Vector;
FdoExtension->InterruptLevel = InterruptDescriptor->u.Interrupt.Level;
FdoExtension->InterruptMode =
(InterruptDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
FdoExtension->InterruptShared =
(InterruptDescriptor->ShareDisposition == CmResourceShareShared);
FdoExtension->InterruptAffinity = InterruptDescriptor->u.Interrupt.Affinity;
return STATUS_SUCCESS;
}
if (!BusMasterDescriptor)
return STATUS_DEVICE_CONFIGURATION_ERROR;
@ -71,7 +115,8 @@ PciIdeXFdoParseResources(
if (!IoBase)
return STATUS_INSUFFICIENT_RESOURCES;
FdoExtension->IoBaseMapped = TRUE;
FdoExtension->IoLength = 16;
FdoExtension->Flags |= FDO_IO_BASE_MAPPED;
}
FdoExtension->BusMasterPortBase = IoBase;
@ -128,10 +173,10 @@ PciIdeXFdoFreeResources(
{
PAGED_CODE();
if (FdoExtension->IoBaseMapped)
if (FdoExtension->Flags & FDO_IO_BASE_MAPPED)
{
MmUnmapIoSpace(FdoExtension->BusMasterPortBase, 16);
FdoExtension->IoBaseMapped = FALSE;
MmUnmapIoSpace(FdoExtension->BusMasterPortBase, FdoExtension->IoLength);
FdoExtension->Flags &= ~FDO_IO_BASE_MAPPED;
}
}
@ -165,7 +210,7 @@ PciIdeXFdoRemoveDevice(
ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
for (i = 0; i < MAX_IDE_CHANNEL; ++i)
for (i = 0; i < FdoExtension->MaxDevices; ++i)
{
PdoExtension = FdoExtension->Channels[i];
@ -285,7 +330,7 @@ PciIdeXFdoQueryBusRelations(
DeviceRelations = ExAllocatePoolWithTag(PagedPool,
FIELD_OFFSET(DEVICE_RELATIONS,
Objects[MAX_IDE_CHANNEL]),
Objects[FdoExtension->MaxDevices]),
TAG_PCIIDEX);
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
@ -294,7 +339,7 @@ PciIdeXFdoQueryBusRelations(
ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
for (i = 0; i < MAX_IDE_CHANNEL; ++i)
for (i = 0; i < FdoExtension->MaxDevices; ++i)
{
PdoExtension = FdoExtension->Channels[i];
@ -397,7 +442,7 @@ PciIdeXFdoQueryInterface(
ResourceType = (ULONG_PTR)IoStack->Parameters.QueryInterface.InterfaceSpecificData;
/* In native mode the IDE controller does not use any legacy interrupt resources */
if (FdoExtension->InNativeMode ||
if ((FdoExtension->Flags & FDO_IN_NATIVE_MODE) ||
ResourceType != CmResourceTypeInterrupt ||
IoStack->Parameters.QueryInterface.Size < sizeof(TRANSLATOR_INTERFACE))
{

View file

@ -32,6 +32,20 @@ PciIdeXStartMiniport(
FdoExtension->DriverObject);
ASSERT(DriverExtension);
if (FdoExtension->Flags & FDO_AHCI)
{
PAHCI_DEVICE_EXTENSION DeviceExtension =
(PAHCI_DEVICE_EXTENSION)FdoExtension->MiniControllerExtension;
DeviceExtension->Hba = FdoExtension->Abar;
FdoExtension->MaxDevices = MAX_AHCI_DEVICES;
}
else
{
FdoExtension->MaxDevices = MAX_IDE_CHANNEL;
}
FdoExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
FdoExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
Status = DriverExtension->HwGetControllerProperties(FdoExtension->MiniControllerExtension,

View file

@ -127,16 +127,27 @@ PciIdeXGetConfigurationInfo(
if (PciConfig->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR)
{
if (PciConfig->ProgIf & PCIIDE_PROGIF_DMA_CAPABLE)
{
FdoExtension->Flags |= FDO_DMA_CAPABLE;
}
if (PciConfig->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR)
{
/* Both IDE channels in native mode */
FdoExtension->InNativeMode =
(PciConfig->ProgIf & PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE) &&
(PciConfig->ProgIf & PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE);
if ((PciConfig->ProgIf & PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE) &&
(PciConfig->ProgIf & PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE))
{
FdoExtension->Flags |= FDO_IN_NATIVE_MODE;
}
}
else if (PciConfig->SubClass == PCI_SUBCLASS_MSC_AHCI_CTLR)
{
FdoExtension->Flags |= FDO_AHCI | FDO_IN_NATIVE_MODE;
}
else if (PciConfig->SubClass == PCI_SUBCLASS_MSC_RAID_CTLR)
{
FdoExtension->InNativeMode = TRUE;
FdoExtension->Flags |= FDO_IN_NATIVE_MODE;
}
}
@ -144,7 +155,7 @@ PciIdeXGetConfigurationInfo(
FdoExtension->VendorId,
FdoExtension->DeviceId,
PciConfig->ProgIf,
FdoExtension->InNativeMode);
!!(FdoExtension->Flags & FDO_IN_NATIVE_MODE));
return STATUS_SUCCESS;
}
@ -239,6 +250,12 @@ PciIdeXAddDevice(
goto Failure;
}
if (FdoExtension->Flags & FDO_AHCI)
{
DPRINT1("AHCI support not implemented yet\n");
goto Failure;
}
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;

View file

@ -16,6 +16,8 @@
#include <wdmguid.h>
#include <ide.h>
#include <reactos/drivers/ntddata.h>
#define TAG_PCIIDEX 'XedI'
#define IS_FDO(p) (((PCOMMON_DEVICE_EXTENSION)(p))->IsFDO)
@ -44,8 +46,6 @@
#define PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE_CAPABLE 0x08
#define PCIIDE_PROGIF_DMA_CAPABLE 0x80
#define BM_SECONDARY_CHANNEL_OFFSET 8
typedef struct _PDO_DEVICE_EXTENSION PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
typedef struct _PCIIDEX_DRIVER_EXTENSION
@ -75,18 +75,35 @@ typedef struct _FDO_DEVICE_EXTENSION
PDEVICE_OBJECT Ldo;
ULONG ControllerNumber;
BOOLEAN InNativeMode;
BOOLEAN IoBaseMapped;
ULONG Flags;
#define FDO_IN_NATIVE_MODE 0x00000001
#define FDO_AHCI 0x00000002
#define FDO_DMA_CAPABLE 0x00000004
#define FDO_IO_BASE_MAPPED 0x00000008
BOOLEAN MiniportStarted;
FAST_MUTEX DeviceSyncMutex;
_Guarded_by_(DeviceSyncMutex)
PPDO_DEVICE_EXTENSION Channels[MAX_IDE_CHANNEL];
PPDO_DEVICE_EXTENSION Channels[MAX_AHCI_DEVICES];
USHORT VendorId;
USHORT DeviceId;
PDRIVER_OBJECT DriverObject;
PUCHAR BusMasterPortBase;
union
{
PUCHAR BusMasterPortBase;
PVOID Abar;
};
ULONG IoLength;
ULONG MaxDevices;
PKINTERRUPT InterruptObject;
KINTERRUPT_MODE InterruptMode;
KAFFINITY InterruptAffinity;
ULONG InterruptVector;
KIRQL InterruptLevel;
BOOLEAN InterruptShared;
KSPIN_LOCK BusDataLock;
BUS_INTERFACE_STANDARD BusInterface;
@ -103,7 +120,17 @@ typedef struct _PDO_DEVICE_EXTENSION
ULONG Channel;
PFDO_DEVICE_EXTENSION ParentController;
BOOLEAN ReportedMissing;
PUCHAR IoBase;
ULONG Flags;
#define PDO_PIO_ONLY 0x00000001
#define PDO_DRIVE0_DMA_CAPABLE 0x00000002
#define PDO_DRIVE1_DMA_CAPABLE 0x00000004
PVOID PrdTable;
ULONG PrdTablePhysicalAddress;
ULONG MapRegisterCount;
PDMA_ADAPTER AdapterObject;
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
CODE_SEG("PAGE")

View file

@ -11,6 +11,153 @@
#define NDEBUG
#include <debug.h>
static
CODE_SEG("PAGE")
VOID
PciIdeXPdoFreeDmaResources(
_In_ PPDO_DEVICE_EXTENSION PdoExtension)
{
PDMA_OPERATIONS DmaOperations;
PDMA_ADAPTER AdapterObject;
PAGED_CODE();
PdoExtension->Flags &= ~(PDO_PIO_ONLY | PDO_DRIVE0_DMA_CAPABLE | PDO_DRIVE1_DMA_CAPABLE);
AdapterObject = PdoExtension->AdapterObject;
if (!AdapterObject)
return;
DmaOperations = AdapterObject->DmaOperations;
if (PdoExtension->PrdTable)
{
PHYSICAL_ADDRESS PrdTablePhysicalAddress;
PrdTablePhysicalAddress.QuadPart = PdoExtension->PrdTablePhysicalAddress;
DmaOperations->FreeCommonBuffer(AdapterObject,
PdoExtension->MapRegisterCount * sizeof(PRD_TABLE_ENTRY),
PrdTablePhysicalAddress,
PdoExtension->PrdTable,
FALSE);
PdoExtension->PrdTable = NULL;
}
DmaOperations->PutDmaAdapter(AdapterObject);
PdoExtension->AdapterObject = NULL;
}
static
CODE_SEG("PAGE")
BOOLEAN
PciIdeXPdoGetDmaAdapter(
_In_ PPDO_DEVICE_EXTENSION PdoExtension)
{
DEVICE_DESCRIPTION DeviceDescription = { 0 };
PAGED_CODE();
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
DeviceDescription.Master = TRUE;
DeviceDescription.ScatterGather = TRUE;
DeviceDescription.Dma32BitAddresses = TRUE;
DeviceDescription.InterfaceType = PCIBus;
DeviceDescription.MaximumLength = ATA_MAX_TRANSFER_LENGTH;
PdoExtension->AdapterObject = IoGetDmaAdapter(PdoExtension->ParentController->Ldo,
&DeviceDescription,
&PdoExtension->MapRegisterCount);
if (!PdoExtension->AdapterObject)
return FALSE;
return TRUE;
}
static
CODE_SEG("PAGE")
BOOLEAN
PciIdeXPdoAllocatePrdTable(
_In_ PPDO_DEVICE_EXTENSION PdoExtension)
{
PHYSICAL_ADDRESS LogicalAddress;
PAGED_CODE();
PdoExtension->PrdTable = PdoExtension->AdapterObject->DmaOperations->
AllocateCommonBuffer(PdoExtension->AdapterObject,
PdoExtension->MapRegisterCount * sizeof(PRD_TABLE_ENTRY),
&LogicalAddress,
FALSE);
if (!PdoExtension->PrdTable)
return FALSE;
/* 32-bit DMA */
ASSERT(LogicalAddress.HighPart == 0);
PdoExtension->PrdTablePhysicalAddress = LogicalAddress.LowPart;
return TRUE;
}
static
CODE_SEG("PAGE")
VOID
PciIdeXPdoAllocateDmaResources(
_In_ PPDO_DEVICE_EXTENSION PdoExtension)
{
BOOLEAN Success;
UCHAR DmaStatus;
PAGED_CODE();
PdoExtension->IoBase = PdoExtension->ParentController->BusMasterPortBase;
if (!IS_PRIMARY_CHANNEL(PdoExtension))
{
PdoExtension->IoBase += DMA_SECONDARY_CHANNEL_OFFSET;
}
DmaStatus = READ_PORT_UCHAR(PdoExtension->IoBase + DMA_STATUS);
DPRINT("I/O Base %p, status 0x%02x\n", PdoExtension->IoBase, DmaStatus);
/* The status bits 3:4 must return 0 on reads */
if (DmaStatus & (DMA_STATUS_RESERVED1 | DMA_STATUS_RESERVED2))
{
DPRINT1("Unexpected DMA status 0x%02x\n", DmaStatus);
goto DisableDma;
}
/* The status bits 5:6 are set by the miniport driver or BIOS firmware at boot */
if (DmaStatus & DMA_STATUS_DRIVE0_DMA_CAPABLE)
PdoExtension->Flags |= PDO_DRIVE0_DMA_CAPABLE;
if (DmaStatus & DMA_STATUS_DRIVE1_DMA_CAPABLE)
PdoExtension->Flags |= PDO_DRIVE1_DMA_CAPABLE;
Success = PciIdeXPdoGetDmaAdapter(PdoExtension);
if (!Success)
{
DPRINT1("Unable to get DMA adapter\n");
goto DisableDma;
}
Success = PciIdeXPdoAllocatePrdTable(PdoExtension);
if (!Success)
{
DPRINT1("Unable to allocate PRD table\n");
PciIdeXPdoFreeDmaResources(PdoExtension);
goto DisableDma;
}
return;
DisableDma:
/* Failed to setup DMA, falling back to PIO mode */
PdoExtension->Flags |= PDO_PIO_ONLY;
}
static
CODE_SEG("PAGE")
NTSTATUS
@ -18,16 +165,14 @@ PciIdeXPdoStartDevice(
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
_In_ PCM_RESOURCE_LIST ResourceList)
{
PUCHAR IoBase;
PFDO_DEVICE_EXTENSION FdoExtension = PdoExtension->ParentController;
PAGED_CODE();
IoBase = PdoExtension->ParentController->BusMasterPortBase;
if (!IS_PRIMARY_CHANNEL(PdoExtension))
if (FdoExtension->Flags & FDO_DMA_CAPABLE)
{
IoBase += BM_SECONDARY_CHANNEL_OFFSET;
PciIdeXPdoAllocateDmaResources(PdoExtension);
}
DPRINT("Bus Master Base %p\n", IoBase);
return STATUS_SUCCESS;
}
@ -40,6 +185,8 @@ PciIdeXPdoStopDevice(
{
PAGED_CODE();
PciIdeXPdoFreeDmaResources(PdoExtension);
return STATUS_SUCCESS;
}
@ -55,11 +202,13 @@ PciIdeXPdoRemoveDevice(
PAGED_CODE();
PciIdeXPdoFreeDmaResources(PdoExtension);
if (FinalRemove && PdoExtension->ReportedMissing)
{
ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
for (i = 0; i < MAX_IDE_CHANNEL; ++i)
for (i = 0; i < FdoExtension->MaxDevices; ++i)
{
if (FdoExtension->Channels[i] == PdoExtension)
{
@ -266,7 +415,7 @@ PciIdeXPdoQueryResources(
PAGED_CODE();
FdoExtension = PdoExtension->ParentController;
if (FdoExtension->InNativeMode)
if (FdoExtension->Flags & FDO_IN_NATIVE_MODE)
return Irp->IoStatus.Status;
ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel);
@ -346,7 +495,7 @@ PciIdeXPdoQueryResourceRequirements(
PAGED_CODE();
FdoExtension = PdoExtension->ParentController;
if (FdoExtension->InNativeMode)
if (FdoExtension->Flags & FDO_IN_NATIVE_MODE)
return Irp->IoStatus.Status;
ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel);
@ -748,6 +897,103 @@ PciIdeXPdoQueryDeviceUsageNotification(
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXQueryAhciPortInterface(
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
_In_ PIRP Irp,
_In_ PIO_STACK_LOCATION IoStack)
{
PFDO_DEVICE_EXTENSION FdoExtension = PdoExtension->ParentController;
PAHCI_PORT_INTERFACE AhciPortInterface;
PAHCI_HOST_BUS_ADAPTER Hba;
PAGED_CODE();
if (!(FdoExtension->Flags & FDO_AHCI))
return Irp->IoStatus.Status;
if (IoStack->Parameters.QueryInterface.Size < sizeof(*AhciPortInterface))
return Irp->IoStatus.Status;
Hba = FdoExtension->Abar;
AhciPortInterface = (PAHCI_PORT_INTERFACE)IoStack->Parameters.QueryInterface.Interface;
AhciPortInterface->Port = &Hba->Port[PdoExtension->Channel];
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXQueryPciIdeInterface(
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
_In_ PIRP Irp,
_In_ PIO_STACK_LOCATION IoStack)
{
PFDO_DEVICE_EXTENSION FdoExtension = PdoExtension->ParentController;
PPCIIDE_INTERFACE PciIdeInterface;
PAGED_CODE();
if (FdoExtension->Flags & FDO_AHCI)
return Irp->IoStatus.Status;
if (IoStack->Parameters.QueryInterface.Size < sizeof(*PciIdeInterface))
return Irp->IoStatus.Status;
PciIdeInterface = (PPCIIDE_INTERFACE)IoStack->Parameters.QueryInterface.Interface;
PciIdeInterface->IoBase = PdoExtension->IoBase;
if (PdoExtension->Flags & PDO_PIO_ONLY)
{
PciIdeInterface->PrdTable = NULL;
}
else
{
PciIdeInterface->PrdTable = PdoExtension->PrdTable;
PciIdeInterface->PrdTablePhysicalAddress = PdoExtension->PrdTablePhysicalAddress;
PciIdeInterface->MaximumTransferLength = PdoExtension->MapRegisterCount << PAGE_SHIFT;
PciIdeInterface->AdapterObject = PdoExtension->AdapterObject;
PciIdeInterface->DeviceObject = PdoExtension->Common.Self;
}
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXPdoQueryInterface(
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType,
&GUID_AHCI_PORT_INTERFACE))
{
Status = PciIdeXQueryAhciPortInterface(PdoExtension, Irp, IoStack);
}
else if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType,
&GUID_PCIIDE_INTERFACE))
{
Status = PciIdeXQueryPciIdeInterface(PdoExtension, Irp, IoStack);
}
else
{
Status = Irp->IoStatus.Status;
}
return Status;
}
static
CODE_SEG("PAGE")
NTSTATUS
@ -823,6 +1069,10 @@ PciIdeXPdoDispatchPnp(
Status = PciIdeXPdoQueryDeviceUsageNotification(PdoExtension, Irp);
break;
case IRP_MN_QUERY_INTERFACE:
Status = PciIdeXPdoQueryInterface(PdoExtension, Irp);
break;
default:
Status = Irp->IoStatus.Status;
break;

View file

@ -0,0 +1,198 @@
/*
* PROJECT: ReactOS Storage Stack
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: ATA driver definitions
* COPYRIGHT: Copyright 2024 Dmitry Borisov (di.sean@protonmail.com)
*/
#pragma once
/*
* 256 sectors of 512 bytes (128 kB).
* This ensures that the sector count register will not overflow
* in LBA-28 and CHS modes.
*/
#define ATA_MAX_TRANSFER_LENGTH 0x20000
/* Offset from base address */
#define DMA_SECONDARY_CHANNEL_OFFSET 8
/*
* IDE Bus Master I/O Registers
*/
#define DMA_COMMAND 0
#define DMA_STATUS 2
#define DMA_PRDT_PHYSICAL_ADDRESS 4
/*
* IDE Bus Master Command Register
*/
#define DMA_COMMAND_STOP 0x00
#define DMA_COMMAND_START 0x01
#define DMA_COMMAND_READ_FROM_SYSTEM_MEMORY 0x00
#define DMA_COMMAND_WRITE_TO_SYSTEM_MEMORY 0x08
/*
* IDE Bus Master Status Register
*/
#define DMA_STATUS_ACTIVE 0x01
#define DMA_STATUS_ERROR 0x02
#define DMA_STATUS_INTERRUPT 0x04
#define DMA_STATUS_RESERVED1 0x08
#define DMA_STATUS_RESERVED2 0x10
#define DMA_STATUS_DRIVE0_DMA_CAPABLE 0x20
#define DMA_STATUS_DRIVE1_DMA_CAPABLE 0x40
#define DMA_STATUS_SIMPLEX 0x80
/* 64 kB boundary */
#define PRD_LIMIT 0x10000
#include <pshpack1.h>
/*
* Physical Region Descriptor Table Entry
*/
typedef struct _PRD_TABLE_ENTRY
{
ULONG Address;
ULONG Length;
#define PRD_LENGTH_MASK 0xFFFF
#define PRD_END_OF_TABLE 0x80000000
} PRD_TABLE_ENTRY, *PPRD_TABLE_ENTRY;
/*
* Physical Region Descriptor Table
*/
typedef struct _PRD_TABLE
{
PRD_TABLE_ENTRY Entry[ANYSIZE_ARRAY];
} PRD_TABLE, *PPRD_TABLE;
#include <poppack.h>
typedef struct _PCIIDE_INTERFACE
{
USHORT Size;
USHORT Version;
PVOID Context;
PINTERFACE_REFERENCE InterfaceReference;
PINTERFACE_DEREFERENCE InterfaceDereference;
PUCHAR IoBase;
PVOID PrdTable;
ULONG PrdTablePhysicalAddress;
ULONG MaximumTransferLength;
PDMA_ADAPTER AdapterObject;
PDEVICE_OBJECT DeviceObject;
} PCIIDE_INTERFACE, *PPCIIDE_INTERFACE;
DEFINE_GUID(GUID_PCIIDE_INTERFACE,
0xD677FBCF, 0xABED, 0x47C8, 0x80, 0xA3, 0xE4, 0x34, 0x7E, 0xA4, 0x96, 0x47);
#define MAX_AHCI_DEVICES 32
#define AHCI_COMMAND_LIST_SIZE 0x400
#define AHCI_RECEIVED_FIS_SIZE 0x400
#include <pshpack1.h>
typedef struct _AHCI_PORT_REGISTERS
{
volatile ULONG CommandListBaseLow;
volatile ULONG CommandListBaseHigh;
volatile ULONG FisBaseLow;
volatile ULONG FisBaseHigh;
volatile ULONG InterruptStatus;
volatile ULONG InterruptEnable;
volatile ULONG CmdStatus;
volatile ULONG Reserved;
volatile ULONG TaskFileData;
volatile ULONG Signature;
volatile ULONG SataStatus;
volatile ULONG SataControl;
volatile ULONG SataError;
volatile ULONG SataActive;
volatile ULONG CommandIssue;
volatile ULONG SataNotification;
volatile ULONG FisSwitchingControl;
volatile ULONG Reserved2[11];
volatile ULONG Reserved3[4];
} AHCI_PORT_REGISTERS, *PAHCI_PORT_REGISTERS;
typedef struct _AHCI_HOST_BUS_ADAPTER
{
volatile ULONG Capabilities;
volatile ULONG GlobalControl;
#define AHCI_GHC_AE 0x80000000
volatile ULONG InterruptStatus;
volatile ULONG PortsImplemented;
volatile ULONG AhciVersion;
volatile ULONG CoalescingControl;
volatile ULONG CoalescingPorts;
volatile ULONG EnclosureManagementLocation;
volatile ULONG EnclosureManagementControl;
volatile ULONG CapabilitiesEx;
volatile ULONG BiosControl;
volatile ULONG Reserved[29 + 24];
AHCI_PORT_REGISTERS Port[MAX_AHCI_DEVICES];
} AHCI_HOST_BUS_ADAPTER, *PAHCI_HOST_BUS_ADAPTER;
typedef struct _AHCI_RECEIVED_FIS
{
UCHAR DmaSetup[0x1C];
ULONG Reserved;
UCHAR PioSetup[0x14];
ULONG Reserved2[3];
UCHAR DeviceToHost[0x14];
ULONG Reserved3;
UCHAR DeviceBits[0x08];
UCHAR UnknownFis[0x40];
UCHAR Reserved4[0x60];
} AHCI_RECEIVED_FIS, *PAHCI_RECEIVED_FIS;
typedef struct _AHCI_COMMAND_LIST_ENTRY
{
ULONG Control;
ULONG PrdByteCount;
ULONG CommandTableBaseLow;
ULONG CommandTableBaseHigh;
ULONG Reserved[4];
} AHCI_COMMAND_LIST_ENTRY, *PAHCI_COMMAND_LIST_ENTRY;
typedef struct _AHCI_PRD
{
ULONG DataBaseLow;
ULONG DataBaseHigh;
ULONG Reserved;
ULONG ByteCount;
} AHCI_PRD, *PAHCI_PRD;
#include <poppack.h>
typedef struct _AHCI_DEVICE_EXTENSION
{
PAHCI_HOST_BUS_ADAPTER Hba;
} AHCI_DEVICE_EXTENSION, *PAHCI_DEVICE_EXTENSION;
typedef struct _AHCI_PORT_INTERFACE
{
USHORT Size;
USHORT Version;
PVOID Context;
PINTERFACE_REFERENCE InterfaceReference;
PINTERFACE_DEREFERENCE InterfaceDereference;
PAHCI_PORT_REGISTERS Port;
} AHCI_PORT_INTERFACE, *PAHCI_PORT_INTERFACE;
DEFINE_GUID(GUID_AHCI_PORT_INTERFACE,
0xD677FBCF, 0xABED, 0x47C8, 0x80, 0xA3, 0xE4, 0x34, 0x7E, 0xA4, 0x96, 0x46);