mirror of
https://github.com/reactos/reactos.git
synced 2024-05-29 16:51:47 +00:00
[PCIIDEX] Add AHCI support
WIP CORE-17256
This commit is contained in:
parent
b0c9c12a4a
commit
c04df3f2c9
|
@ -1,4 +1,5 @@
|
|||
|
||||
add_subdirectory(pciahci)
|
||||
add_subdirectory(pciide)
|
||||
add_subdirectory(pciidex)
|
||||
add_subdirectory(uniata)
|
||||
|
|
14
drivers/storage/ide/pciahci/CMakeLists.txt
Normal file
14
drivers/storage/ide/pciahci/CMakeLists.txt
Normal 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)
|
121
drivers/storage/ide/pciahci/pciahci.c
Normal file
121
drivers/storage/ide/pciahci/pciahci.c
Normal 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;
|
||||
}
|
11
drivers/storage/ide/pciahci/pciahci.h
Normal file
11
drivers/storage/ide/pciahci/pciahci.h
Normal 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>
|
5
drivers/storage/ide/pciahci/pciahci.rc
Normal file
5
drivers/storage/ide/pciahci/pciahci.rc
Normal 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>
|
8
drivers/storage/ide/pciahci/pciahci_reg.inf
Normal file
8
drivers/storage/ide/pciahci/pciahci_reg.inf
Normal 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
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
|
|
198
sdk/include/reactos/drivers/ntddata.h
Normal file
198
sdk/include/reactos/drivers/ntddata.h
Normal 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);
|
Loading…
Reference in a new issue