[PCIIDEX] Improve and fix the driver

- Fix IRP handling, add missing IRP handlers
- Specify the device name for DO
- The legacy IRQ descriptor is edge-triggered
- Improve pool tagging
- Place the PNP code in a pageable section

CORE-17256
This commit is contained in:
Dmitry Borisov 2023-01-08 18:07:14 +06:00 committed by Stanislav Motylkov
parent 293fc8dc34
commit c0c57e2324
9 changed files with 1876 additions and 1229 deletions

View file

@ -4,9 +4,9 @@ spec2def(pciidex.sys pciidex.spec ADD_IMPORTLIB)
list(APPEND SOURCE
fdo.c
miniport.c
misc.c
pciidex.c
pdo.c
power.c
pciidex.h)
add_library(pciidex MODULE
@ -16,5 +16,5 @@ add_library(pciidex MODULE
add_pch(pciidex pciidex.h SOURCE)
set_module_type(pciidex kernelmodedriver)
add_importlibs(pciidex ntoskrnl)
add_importlibs(pciidex ntoskrnl hal)
add_cd_file(TARGET pciidex DESTINATION reactos/system32/drivers NO_CAB FOR all)

View file

@ -1,9 +1,9 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: PCI IDE bus driver extension
* FILE: drivers/storage/pciidex/fdo.c
* PURPOSE: IRP_MJ_PNP operations for FDOs
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
* PROJECT: PCI IDE bus driver extension
* LICENSE: See COPYING in the top level directory
* PURPOSE: IRP_MJ_PNP operations for FDOs
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
*/
#include "pciidex.h"
@ -11,481 +11,497 @@
#define NDEBUG
#include <debug.h>
#include <initguid.h>
#include <wdmguid.h>
static NTSTATUS
GetBusInterface(
IN PFDO_DEVICE_EXTENSION DeviceExtension)
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoParseResources(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PCM_RESOURCE_LIST ResourcesTranslated)
{
PBUS_INTERFACE_STANDARD BusInterface = NULL;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
PIRP Irp;
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PCM_PARTIAL_RESOURCE_DESCRIPTOR BusMasterDescriptor = NULL;
PVOID IoBase;
ULONG i;
if (DeviceExtension->BusInterface)
{
DPRINT("We already have the bus interface\n");
goto cleanup;
}
PAGED_CODE();
BusInterface = ExAllocatePool(PagedPool, sizeof(BUS_INTERFACE_STANDARD));
if (!BusInterface)
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
if (!ResourcesTranslated)
return STATUS_INVALID_PARAMETER;
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_PNP,
DeviceExtension->LowerDevice,
NULL,
0,
NULL,
&Event,
&IoStatus);
if (!Irp)
{
DPRINT("IoBuildSynchronousFsdRequest() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
for (i = 0; i < ResourcesTranslated->List[0].PartialResourceList.Count; ++i)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
Descriptor = &ResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
switch (Descriptor->Type)
{
case CmResourceTypePort:
case CmResourceTypeMemory:
{
switch (Descriptor->u.Port.Length)
{
/* Bus master port base */
case 16:
{
if (!BusMasterDescriptor)
BusMasterDescriptor = Descriptor;
break;
}
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MajorFunction = IRP_MJ_PNP;
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD;
Stack->Parameters.QueryInterface.Version = 1;
Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
default:
break;
}
}
Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (!NT_SUCCESS(Status))
goto cleanup;
default:
break;
}
}
DeviceExtension->BusInterface = BusInterface;
BusInterface = NULL;
Status = STATUS_SUCCESS;
if (!BusMasterDescriptor)
return STATUS_DEVICE_CONFIGURATION_ERROR;
cleanup:
if (BusInterface) ExFreePool(BusInterface);
return Status;
if ((BusMasterDescriptor->Type == CmResourceTypePort) &&
(BusMasterDescriptor->Flags & CM_RESOURCE_PORT_IO))
{
IoBase = (PVOID)(ULONG_PTR)BusMasterDescriptor->u.Port.Start.QuadPart;
}
else
{
IoBase = MmMapIoSpace(BusMasterDescriptor->u.Memory.Start, 16, MmNonCached);
if (!IoBase)
return STATUS_INSUFFICIENT_RESOURCES;
FdoExtension->IoBaseMapped = TRUE;
}
FdoExtension->BusMasterPortBase = IoBase;
return STATUS_SUCCESS;
}
static NTSTATUS
ReleaseBusInterface(
IN PFDO_DEVICE_EXTENSION DeviceExtension)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if (DeviceExtension->BusInterface)
{
(*DeviceExtension->BusInterface->InterfaceDereference)(
DeviceExtension->BusInterface->Context);
DeviceExtension->BusInterface = NULL;
Status = STATUS_SUCCESS;
}
return Status;
}
NTSTATUS NTAPI
PciIdeXAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo)
{
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT Fdo;
ULONG BytesRead;
PCI_COMMON_CONFIG PciConfig;
NTSTATUS Status;
DPRINT("PciIdeXAddDevice(%p %p)\n", DriverObject, Pdo);
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
ASSERT(DriverExtension);
Status = IoCreateDevice(
DriverObject,
sizeof(FDO_DEVICE_EXTENSION) + DriverExtension->MiniControllerExtensionSize,
NULL,
FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
return Status;
}
DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
DeviceExtension->Common.IsFDO = TRUE;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
return Status;
}
Status = GetBusInterface(DeviceExtension);
if (!NT_SUCCESS(Status))
{
DPRINT("GetBusInterface() failed with status 0x%08lx\n", Status);
IoDetachDevice(DeviceExtension->LowerDevice);
return Status;
}
BytesRead = (*DeviceExtension->BusInterface->GetBusData)(
DeviceExtension->BusInterface->Context,
PCI_WHICHSPACE_CONFIG,
&PciConfig,
0,
PCI_COMMON_HDR_LENGTH);
if (BytesRead != PCI_COMMON_HDR_LENGTH)
{
DPRINT("BusInterface->GetBusData() failed()\n");
ReleaseBusInterface(DeviceExtension);
IoDetachDevice(DeviceExtension->LowerDevice);
return STATUS_IO_DEVICE_ERROR;
}
DeviceExtension->VendorId = PciConfig.VendorID;
DeviceExtension->DeviceId = PciConfig.DeviceID;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
static NTSTATUS NTAPI
PciIdeXUdmaModesSupported(
IN IDENTIFY_DATA IdentifyData,
OUT PULONG BestXferMode,
OUT PULONG CurrentXferMode)
{
ULONG Best = PIO_MODE0;
ULONG Current = PIO_MODE0;
DPRINT("PciIdeXUdmaModesSupported(%lu, %p %p)\n",
IdentifyData, BestXferMode, CurrentXferMode);
/* FIXME: if current mode is a PIO mode, how to get it?
* At the moment, PIO_MODE0 is always returned...
*/
if (IdentifyData.TranslationFieldsValid & 0x2)
{
/* PIO modes and some DMA modes are supported */
if (IdentifyData.AdvancedPIOModes & 0x10)
Best = PIO_MODE4;
else if (IdentifyData.AdvancedPIOModes & 0x8)
Best = PIO_MODE3;
else if (IdentifyData.AdvancedPIOModes & 0x4)
Best = PIO_MODE2;
else if (IdentifyData.AdvancedPIOModes & 0x2)
Best = PIO_MODE1;
else if (IdentifyData.AdvancedPIOModes & 0x1)
Best = PIO_MODE0;
if (IdentifyData.SingleWordDMASupport & 0x4)
Best = SWDMA_MODE2;
else if (IdentifyData.SingleWordDMASupport & 0x2)
Best = SWDMA_MODE1;
else if (IdentifyData.SingleWordDMASupport & 0x1)
Best = SWDMA_MODE0;
if (IdentifyData.SingleWordDMAActive & 0x4)
Current = SWDMA_MODE2;
else if (IdentifyData.SingleWordDMAActive & 0x2)
Current = SWDMA_MODE1;
else if (IdentifyData.SingleWordDMAActive & 0x1)
Current = SWDMA_MODE0;
if (IdentifyData.MultiWordDMASupport & 0x4)
Best = MWDMA_MODE2;
else if (IdentifyData.MultiWordDMASupport & 0x2)
Best = MWDMA_MODE1;
else if (IdentifyData.MultiWordDMASupport & 0x1)
Best = MWDMA_MODE0;
if (IdentifyData.MultiWordDMAActive & 0x4)
Current = MWDMA_MODE2;
else if (IdentifyData.MultiWordDMAActive & 0x2)
Current = MWDMA_MODE1;
else if (IdentifyData.MultiWordDMAActive & 0x1)
Current = MWDMA_MODE0;
}
if (IdentifyData.TranslationFieldsValid & 0x4)
{
/* UDMA modes are supported */
if (IdentifyData.UltraDMAActive & 0x10)
Current = UDMA_MODE4;
else if (IdentifyData.UltraDMAActive & 0x8)
Current = UDMA_MODE3;
else if (IdentifyData.UltraDMAActive & 0x4)
Current = UDMA_MODE2;
else if (IdentifyData.UltraDMAActive & 0x2)
Current = UDMA_MODE1;
else if (IdentifyData.UltraDMAActive & 0x1)
Current = UDMA_MODE0;
if (IdentifyData.UltraDMASupport & 0x10)
Best = UDMA_MODE4;
else if (IdentifyData.UltraDMASupport & 0x8)
Best = UDMA_MODE3;
else if (IdentifyData.UltraDMASupport & 0x4)
Best = UDMA_MODE2;
else if (IdentifyData.UltraDMASupport & 0x2)
Best = UDMA_MODE1;
else if (IdentifyData.UltraDMASupport & 0x1)
Best = UDMA_MODE0;
}
*BestXferMode = Best;
*CurrentXferMode = Current;
return TRUE;
}
static NTSTATUS
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PIRP Irp)
{
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
PCM_RESOURCE_LIST ResourceList;
NTSTATUS Status;
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject, Irp);
PAGED_CODE();
DriverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, DeviceObject->DriverObject);
ASSERT(DriverExtension);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension);
ASSERT(DeviceExtension->Common.IsFDO);
if (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp)))
{
return STATUS_UNSUCCESSFUL;
}
Status = Irp->IoStatus.Status;
if (!NT_SUCCESS(Status))
{
return Status;
}
DeviceExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
DeviceExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
Status = DriverExtension->HwGetControllerProperties(
DeviceExtension->MiniControllerExtension,
&DeviceExtension->Properties);
if (!NT_SUCCESS(Status))
return Status;
IoStack = IoGetCurrentIrpStackLocation(Irp);
DriverExtension->HwUdmaModesSupported = DeviceExtension->Properties.PciIdeUdmaModesSupported;
if (!DriverExtension->HwUdmaModesSupported)
/* This method is optional, so provide our own one */
DriverExtension->HwUdmaModesSupported = PciIdeXUdmaModesSupported;
Status = PciIdeXFdoParseResources(FdoExtension,
IoStack->Parameters.StartDevice.AllocatedResourcesTranslated);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to parse resources 0x%lx\n", Status);
return Status;
}
/* Get bus master port base, if any */
ResourceList = IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources;
if (ResourceList
&& ResourceList->Count == 1
&& ResourceList->List[0].PartialResourceList.Count == 1
&& ResourceList->List[0].PartialResourceList.Version == 1
&& ResourceList->List[0].PartialResourceList.Revision == 1
&& ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type == CmResourceTypePort
&& ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length == 16)
{
DeviceExtension->BusMasterPortBase = ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start;
}
return STATUS_SUCCESS;
Status = PciIdeXStartMiniport(FdoExtension);
if (!NT_SUCCESS(Status))
{
DPRINT1("Miniport initialization failed 0x%lx\n", Status);
return Status;
}
return STATUS_SUCCESS;
}
static NTSTATUS
static
CODE_SEG("PAGE")
VOID
PciIdeXFdoFreeResources(
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
{
PAGED_CODE();
if (FdoExtension->IoBaseMapped)
{
MmUnmapIoSpace(FdoExtension->BusMasterPortBase, 16);
FdoExtension->IoBaseMapped = FALSE;
}
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoStopDevice(
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
{
PAGED_CODE();
PciIdeXFdoFreeResources(FdoExtension);
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoRemoveDevice(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PIRP Irp)
{
PPDO_DEVICE_EXTENSION PdoExtension;
NTSTATUS Status;
ULONG i;
PAGED_CODE();
PciIdeXFdoFreeResources(FdoExtension);
ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
for (i = 0; i < MAX_IDE_CHANNEL; ++i)
{
PdoExtension = FdoExtension->Channels[i];
if (PdoExtension)
{
IoDeleteDevice(PdoExtension->Common.Self);
FdoExtension->Channels[i] = NULL;
break;
}
}
ExReleaseFastMutex(&FdoExtension->DeviceSyncMutex);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(FdoExtension->Ldo, Irp);
IoDetachDevice(FdoExtension->Ldo);
IoDeleteDevice(FdoExtension->Common.Self);
return Status;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoQueryPnpDeviceState(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PIRP Irp)
{
PAGED_CODE();
if (FdoExtension->Common.PageFiles ||
FdoExtension->Common.HibernateFiles ||
FdoExtension->Common.DumpFiles)
{
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
PPDO_DEVICE_EXTENSION
PciIdeXPdoCreateDevice(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ ULONG ChannelNumber)
{
NTSTATUS Status;
UNICODE_STRING DeviceName;
WCHAR DeviceNameBuffer[sizeof("\\Device\\Ide\\PciIde999Channel9-FFF")];
PDEVICE_OBJECT Pdo;
PPDO_DEVICE_EXTENSION PdoExtension;
ULONG Alignment;
static ULONG DeviceNumber = 0;
PAGED_CODE();
Status = RtlStringCbPrintfW(DeviceNameBuffer,
sizeof(DeviceNameBuffer),
L"\\Device\\Ide\\PciIde%uChannel%u-%x",
FdoExtension->ControllerNumber,
ChannelNumber,
DeviceNumber++);
ASSERT(NT_SUCCESS(Status));
RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
Status = IoCreateDevice(FdoExtension->Common.Self->DriverObject,
sizeof(*PdoExtension),
&DeviceName,
FILE_DEVICE_CONTROLLER,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Pdo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create PDO 0x%lx\n", Status);
return NULL;
}
DPRINT("Created device object %p '%wZ'\n", Pdo, &DeviceName);
/* DMA buffers alignment */
Alignment = FdoExtension->Properties.AlignmentRequirement;
Alignment = max(Alignment, FdoExtension->Common.Self->AlignmentRequirement);
Alignment = max(Alignment, FILE_WORD_ALIGNMENT);
Pdo->AlignmentRequirement = Alignment;
PdoExtension = Pdo->DeviceExtension;
RtlZeroMemory(PdoExtension, sizeof(*PdoExtension));
PdoExtension->Common.Self = Pdo;
PdoExtension->Channel = ChannelNumber;
PdoExtension->ParentController = FdoExtension;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
return PdoExtension;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS* pDeviceRelations)
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PIRP Irp)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations = NULL;
PDEVICE_OBJECT Pdo;
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
ULONG i, j;
ULONG PDOs = 0;
IDE_CHANNEL_STATE ChannelState;
NTSTATUS Status;
PPDO_DEVICE_EXTENSION PdoExtension;
IDE_CHANNEL_STATE ChannelState;
PDEVICE_RELATIONS DeviceRelations;
ULONG i;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension);
ASSERT(DeviceExtension->Common.IsFDO);
PAGED_CODE();
for (i = 0; i < MAX_IDE_CHANNEL; i++)
{
if (DeviceExtension->Pdo[i])
{
PDOs++;
continue;
}
ChannelState = DeviceExtension->Properties.PciIdeChannelEnabled(
DeviceExtension->MiniControllerExtension, i);
if (ChannelState == ChannelDisabled)
{
DPRINT("Channel %lu is disabled\n", i);
continue;
}
DeviceRelations = ExAllocatePoolWithTag(PagedPool,
FIELD_OFFSET(DEVICE_RELATIONS,
Objects[MAX_IDE_CHANNEL]),
TAG_PCIIDEX);
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
/* Need to create a PDO */
Status = IoCreateDevice(
DeviceObject->DriverObject,
sizeof(PDO_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&Pdo);
if (!NT_SUCCESS(Status))
/* FIXME: handle error */
continue;
DeviceRelations->Count = 0;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
PdoDeviceExtension->Common.IsFDO = FALSE;
PdoDeviceExtension->Channel = i;
PdoDeviceExtension->ControllerFdo = DeviceObject;
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
DeviceExtension->Pdo[i] = Pdo;
PDOs++;
}
for (i = 0; i < MAX_IDE_CHANNEL; ++i)
{
PdoExtension = FdoExtension->Channels[i];
if (PDOs == 0)
{
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
PagedPool,
sizeof(DEVICE_RELATIONS));
}
else
{
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
PagedPool,
sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (PDOs - 1));
}
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
/* Ignore disabled channels */
ChannelState = PciIdeXChannelState(FdoExtension, i);
if (ChannelState == ChannelDisabled)
{
if (PdoExtension)
{
PdoExtension->ReportedMissing = TRUE;
}
DeviceRelations->Count = PDOs;
for (i = 0, j = 0; i < MAX_IDE_CHANNEL; i++)
{
if (DeviceExtension->Pdo[i])
{
ObReferenceObject(DeviceExtension->Pdo[i]);
DeviceRelations->Objects[j++] = DeviceExtension->Pdo[i];
}
}
DPRINT("Channel %lu is disabled\n", i);
continue;
}
*pDeviceRelations = DeviceRelations;
return STATUS_SUCCESS;
/* Need to create a PDO */
if (!PdoExtension)
{
PdoExtension = PciIdeXPdoCreateDevice(FdoExtension, i);
FdoExtension->Channels[i] = PdoExtension;
}
if (PdoExtension && !PdoExtension->ReportedMissing)
{
DeviceRelations->Objects[DeviceRelations->Count++] = PdoExtension->Common.Self;
ObReferenceObject(PdoExtension->Common.Self);
}
}
ExReleaseFastMutex(&FdoExtension->DeviceSyncMutex);
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
PciIdeXFdoPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoQueryDeviceUsageNotification(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PIRP Irp)
{
PFDO_DEVICE_EXTENSION FdoExtension;
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = Irp->IoStatus.Information;
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
volatile LONG* Counter;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
PAGED_CODE();
switch (MinorFunction)
{
case IRP_MN_START_DEVICE: /* 0x00 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
if (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp)))
{
return STATUS_UNSUCCESSFUL;
}
Status = Irp->IoStatus.Status;
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Call lower driver */
FdoExtension = DeviceObject->DeviceExtension;
Status = STATUS_UNSUCCESSFUL;
IoStack = IoGetCurrentIrpStackLocation(Irp);
switch (IoStack->Parameters.UsageNotification.Type)
{
case DeviceUsageTypePaging:
Counter = &FdoExtension->Common.PageFiles;
break;
if (IoForwardIrpSynchronously(FdoExtension->LowerDevice, Irp))
{
Status = Irp->IoStatus.Status;
if (NT_SUCCESS(Status))
{
Status = PciIdeXFdoStartDevice(DeviceObject, Irp);
}
}
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
Status = STATUS_UNSUCCESSFUL;
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
{
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations = NULL;
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
Status = PciIdeXFdoQueryBusRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
default:
{
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
break;
}
case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
Information |= PNP_DEVICE_NOT_DISABLEABLE;
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
{
DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
default:
{
DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
case DeviceUsageTypeHibernation:
Counter = &FdoExtension->Common.HibernateFiles;
break;
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
case DeviceUsageTypeDumpFile:
Counter = &FdoExtension->Common.DumpFiles;
break;
default:
return Status;
}
IoAdjustPagingPathCount(Counter, IoStack->Parameters.UsageNotification.InPath);
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoQueryInterface(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PIO_STACK_LOCATION IoStack)
{
PAGED_CODE();
if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType,
&GUID_TRANSLATOR_INTERFACE_STANDARD))
{
CM_RESOURCE_TYPE ResourceType;
ULONG BusNumber;
ResourceType = (ULONG_PTR)IoStack->Parameters.QueryInterface.InterfaceSpecificData;
/* In native mode the IDE controller does not use any legacy interrupt resources */
if (FdoExtension->InNativeMode ||
ResourceType != CmResourceTypeInterrupt ||
IoStack->Parameters.QueryInterface.Size < sizeof(TRANSLATOR_INTERFACE))
{
return STATUS_NOT_SUPPORTED;
}
return HalGetInterruptTranslator(PCIBus,
0,
InterfaceTypeUndefined,
sizeof(TRANSLATOR_INTERFACE),
IoStack->Parameters.QueryInterface.Version,
(PTRANSLATOR_INTERFACE)IoStack->
Parameters.QueryInterface.Interface,
&BusNumber);
}
return STATUS_NOT_SUPPORTED;
}
CODE_SEG("PAGE")
NTSTATUS
PciIdeXFdoDispatchPnp(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_Inout_ PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
switch (IoStack->MinorFunction)
{
case IRP_MN_START_DEVICE:
{
Status = PciIdeXFdoStartDevice(FdoExtension, Irp);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
case IRP_MN_STOP_DEVICE:
{
Status = PciIdeXFdoStopDevice(FdoExtension);
break;
}
case IRP_MN_REMOVE_DEVICE:
return PciIdeXFdoRemoveDevice(FdoExtension, Irp);
case IRP_MN_QUERY_PNP_DEVICE_STATE:
{
Status = PciIdeXFdoQueryPnpDeviceState(FdoExtension, Irp);
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
{
if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
break;
Status = PciIdeXFdoQueryBusRelations(FdoExtension, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
Irp->IoStatus.Status = Status;
break;
}
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
{
Status = PciIdeXFdoQueryDeviceUsageNotification(FdoExtension, Irp);
break;
}
case IRP_MN_QUERY_INTERFACE:
{
Status = PciIdeXFdoQueryInterface(FdoExtension, IoStack);
if (Status == STATUS_NOT_SUPPORTED)
break;
Irp->IoStatus.Status = Status;
break;
}
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
default:
break;
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(FdoExtension->Ldo, Irp);
}

View file

@ -1,9 +1,8 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: PCI IDE bus driver extension
* FILE: drivers/storage/pciidex/miniport.c
* PURPOSE: Miniport functions
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
* PROJECT: PCI IDE bus driver extension
* LICENSE: See COPYING in the top level directory
* PURPOSE: Miniport functions
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
*/
#include "pciidex.h"
@ -14,83 +13,51 @@
/** @brief Global debugging level. Valid values are between 0 (Error) and 3 (Trace). */
ULONG PciIdeDebug = 0;
static DRIVER_DISPATCH PciIdeXForwardOrIgnore;
static NTSTATUS NTAPI
PciIdeXForwardOrIgnore(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
CODE_SEG("PAGE")
NTSTATUS
PciIdeXStartMiniport(
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
{
if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return ForwardIrpAndForget(DeviceObject, Irp);
else
{
ULONG MajorFunction = IoGetCurrentIrpStackLocation(Irp)->MajorFunction;
NTSTATUS Status;
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
NTSTATUS Status;
if (MajorFunction == IRP_MJ_CREATE ||
MajorFunction == IRP_MJ_CLEANUP ||
MajorFunction == IRP_MJ_CLOSE)
{
Status = STATUS_SUCCESS;
}
else
{
DPRINT1("PDO stub for major function 0x%lx\n", MajorFunction);
Status = STATUS_NOT_SUPPORTED;
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
PAGED_CODE();
if (FdoExtension->MiniportStarted)
return STATUS_SUCCESS;
DPRINT("Starting miniport\n");
DriverExtension = IoGetDriverObjectExtension(FdoExtension->DriverObject,
FdoExtension->DriverObject);
ASSERT(DriverExtension);
FdoExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
FdoExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
Status = DriverExtension->HwGetControllerProperties(FdoExtension->MiniControllerExtension,
&FdoExtension->Properties);
if (!NT_SUCCESS(Status))
return Status;
FdoExtension->MiniportStarted = TRUE;
return STATUS_SUCCESS;
}
_Dispatch_type_(IRP_MJ_POWER)
static DRIVER_DISPATCH PciIdeXPowerDispatch;
static NTSTATUS NTAPI
PciIdeXPowerDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
CODE_SEG("PAGE")
IDE_CHANNEL_STATE
PciIdeXChannelState(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ ULONG Channel)
{
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
PDEVICE_OBJECT LowerDevice;
PCIIDE_CHANNEL_ENABLED MiniportChannelEnabled;
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
{
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(LowerDevice, Irp);
}
else
{
switch (IoStack->MinorFunction)
{
case IRP_MN_SET_POWER:
case IRP_MN_QUERY_POWER:
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
}
Status = Irp->IoStatus.Status;
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
}
PAGED_CODE();
_Dispatch_type_(IRP_MJ_PNP)
static DRIVER_DISPATCH PciIdeXPnpDispatch;
static NTSTATUS NTAPI
PciIdeXPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return PciIdeXFdoPnpDispatch(DeviceObject, Irp);
else
return PciIdeXPdoPnpDispatch(DeviceObject, Irp);
MiniportChannelEnabled = FdoExtension->Properties.PciIdeChannelEnabled;
if (MiniportChannelEnabled)
return MiniportChannelEnabled(FdoExtension->MiniControllerExtension, Channel);
return ChannelStateUnknown;
}
/**
@ -119,122 +86,88 @@ PciIdeXDebugPrint(
va_end(ap);
}
NTSTATUS NTAPI
PciIdeXInitialize(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PCONTROLLER_PROPERTIES HwGetControllerProperties,
IN ULONG ExtensionSize)
{
ULONG i;
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
NTSTATUS Status;
DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
DriverObject, RegistryPath, HwGetControllerProperties, ExtensionSize);
Status = IoAllocateDriverObjectExtension(
DriverObject,
DriverObject,
sizeof(PCIIDEX_DRIVER_EXTENSION),
(PVOID*)&DriverExtension);
if (!NT_SUCCESS(Status))
return Status;
RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
DriverExtension->MiniControllerExtensionSize = ExtensionSize;
DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = PciIdeXForwardOrIgnore;
DriverObject->MajorFunction[IRP_MJ_POWER] = PciIdeXPowerDispatch;
DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXPnpDispatch;
return STATUS_SUCCESS;
}
/* May be called at IRQL <= DISPATCH_LEVEL */
NTSTATUS NTAPI
NTSTATUS
NTAPI
PciIdeXGetBusData(
IN PVOID DeviceExtension,
IN PVOID Buffer,
IN ULONG ConfigDataOffset,
IN ULONG BufferLength)
_In_ PVOID DeviceExtension,
_Out_writes_bytes_all_(BufferLength) PVOID Buffer,
_In_ ULONG ConfigDataOffset,
_In_ ULONG BufferLength)
{
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
ULONG BytesRead;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFDO_DEVICE_EXTENSION FdoExtension;
ULONG BytesRead;
DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
if (FdoDeviceExtension->BusInterface)
{
BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
FdoDeviceExtension->BusInterface->Context,
PCI_WHICHSPACE_CONFIG,
Buffer,
ConfigDataOffset,
BufferLength);
if (BytesRead == BufferLength)
Status = STATUS_SUCCESS;
}
FdoExtension = CONTAINING_RECORD(DeviceExtension,
FDO_DEVICE_EXTENSION,
MiniControllerExtension);
return Status;
BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
PCI_WHICHSPACE_CONFIG,
Buffer,
ConfigDataOffset,
BufferLength);
if (BytesRead != BufferLength)
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
/* May be called at IRQL <= DISPATCH_LEVEL */
NTSTATUS NTAPI
NTSTATUS
NTAPI
PciIdeXSetBusData(
IN PVOID DeviceExtension,
IN PVOID Buffer,
IN PVOID DataMask,
IN ULONG ConfigDataOffset,
IN ULONG BufferLength)
_In_ PVOID DeviceExtension,
_In_reads_bytes_(BufferLength) PVOID Buffer,
_In_reads_bytes_(BufferLength) PVOID DataMask,
_In_ ULONG ConfigDataOffset,
_In_ ULONG BufferLength)
{
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PUCHAR CurrentBuffer = NULL;
ULONG i, BytesWritten;
NTSTATUS Status;
PFDO_DEVICE_EXTENSION FdoExtension;
ULONG i, BytesWritten;
PUCHAR CurrentBuffer;
KIRQL OldIrql;
NTSTATUS Status;
DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
CurrentBuffer = ExAllocatePool(NonPagedPool, BufferLength);
if (!CurrentBuffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
return Status;
}
CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferLength, TAG_PCIIDEX);
if (!CurrentBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
if (!NT_SUCCESS(Status))
goto cleanup;
FdoExtension = CONTAINING_RECORD(DeviceExtension,
FDO_DEVICE_EXTENSION,
MiniControllerExtension);
for (i = 0; i < BufferLength; i++)
CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) | (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
KeAcquireSpinLock(&FdoExtension->BusDataLock, &OldIrql);
FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
if (!FdoDeviceExtension->BusInterface)
{
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
if (!NT_SUCCESS(Status))
goto Cleanup;
BytesWritten = (*FdoDeviceExtension->BusInterface->SetBusData)(
FdoDeviceExtension->BusInterface->Context,
PCI_WHICHSPACE_CONFIG,
CurrentBuffer,
ConfigDataOffset,
BufferLength);
if (BytesWritten == BufferLength)
Status = STATUS_SUCCESS;
else
Status = STATUS_UNSUCCESSFUL;
for (i = 0; i < BufferLength; i++)
{
CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) |
(((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
}
cleanup:
ExFreePool(CurrentBuffer);
return Status;
BytesWritten = (*FdoExtension->BusInterface.SetBusData)(FdoExtension->BusInterface.Context,
PCI_WHICHSPACE_CONFIG,
CurrentBuffer,
ConfigDataOffset,
BufferLength);
if (BytesWritten != BufferLength)
Status = STATUS_UNSUCCESSFUL;
else
Status = STATUS_SUCCESS;
Cleanup:
KeReleaseSpinLock(&FdoExtension->BusDataLock, OldIrql);
ExFreePoolWithTag(CurrentBuffer, TAG_PCIIDEX);
return Status;
}

View file

@ -1,73 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: PCI IDE bus driver extension
* FILE: drivers/storage/pciidex/misc.c
* PURPOSE: Miscellaneous operations
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
#include "pciidex.h"
#define NDEBUG
#include <debug.h>
NTSTATUS NTAPI
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice;
ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
ASSERT(LowerDevice);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(LowerDevice, Irp);
}
NTSTATUS
DuplicateUnicodeString(
IN ULONG Flags,
IN PCUNICODE_STRING SourceString,
OUT PUNICODE_STRING DestinationString)
{
if (SourceString == NULL || DestinationString == NULL
|| SourceString->Length > SourceString->MaximumLength
|| (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL)
|| Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4)
{
return STATUS_INVALID_PARAMETER;
}
if ((SourceString->Length == 0)
&& (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
{
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
DestinationString->Buffer = NULL;
}
else
{
USHORT DestMaxLength = SourceString->Length;
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
DestMaxLength += sizeof(UNICODE_NULL);
DestinationString->Buffer = ExAllocatePool(PagedPool, DestMaxLength);
if (DestinationString->Buffer == NULL)
return STATUS_NO_MEMORY;
RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
DestinationString->Length = SourceString->Length;
DestinationString->MaximumLength = DestMaxLength;
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0;
}
return STATUS_SUCCESS;
}

View file

@ -1,9 +1,8 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: PCI IDE bus driver extension
* FILE: drivers/storage/pciidex/pciidex.c
* PURPOSE: Main file
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
* PROJECT: PCI IDE bus driver extension
* LICENSE: See COPYING in the top level directory
* PURPOSE: Main file
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
*/
#include "pciidex.h"
@ -11,10 +10,330 @@
#define NDEBUG
#include <debug.h>
NTSTATUS NTAPI
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
ULONG PciIdeControllerNumber = 0;
CODE_SEG("PAGE")
NTSTATUS
NTAPI
PciIdeXDispatchWmi(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
return STATUS_SUCCESS;
NTSTATUS Status;
PAGED_CODE();
if (IS_FDO(DeviceObject->DeviceExtension))
{
PFDO_DEVICE_EXTENSION FdoExtension = DeviceObject->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(FdoExtension->Ldo, Irp);
}
else
{
Status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return Status;
}
CODE_SEG("PAGE")
VOID
NTAPI
PciIdeXUnload(
_In_ PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
PAGED_CODE();
NOTHING;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXQueryInterface(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ const GUID* Guid,
_Out_ PVOID Interface,
_In_ ULONG Size)
{
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
PIRP Irp;
PIO_STACK_LOCATION Stack;
NTSTATUS Status;
PAGED_CODE();
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
FdoExtension->Ldo,
NULL,
0,
NULL,
&Event,
&IoStatus);
if (!Irp)
return STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
Stack->Parameters.QueryInterface.InterfaceType = Guid;
Stack->Parameters.QueryInterface.Version = 1;
Stack->Parameters.QueryInterface.Size = Size;
Stack->Parameters.QueryInterface.Interface = Interface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
Status = IoCallDriver(FdoExtension->Ldo, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
return Status;
}
static
CODE_SEG("PAGE")
NTSTATUS
PciIdeXGetConfigurationInfo(
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
{
UCHAR Buffer[RTL_SIZEOF_THROUGH_FIELD(PCI_COMMON_HEADER, BaseClass)];
PPCI_COMMON_HEADER PciConfig = (PPCI_COMMON_HEADER)Buffer;
ULONG BytesRead;
PAGED_CODE();
BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
PCI_WHICHSPACE_CONFIG,
Buffer,
0,
sizeof(Buffer));
if (BytesRead != sizeof(Buffer))
return STATUS_IO_DEVICE_ERROR;
FdoExtension->VendorId = PciConfig->VendorID;
FdoExtension->DeviceId = PciConfig->DeviceID;
if (PciConfig->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR)
{
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);
}
else if (PciConfig->SubClass == PCI_SUBCLASS_MSC_RAID_CTLR)
{
FdoExtension->InNativeMode = TRUE;
}
}
DPRINT("Controller %04x:%04x, Interface byte 0x%02x, Native mode %d\n",
FdoExtension->VendorId,
FdoExtension->DeviceId,
PciConfig->ProgIf,
FdoExtension->InNativeMode);
return STATUS_SUCCESS;
}
CODE_SEG("PAGE")
NTSTATUS
NTAPI
PciIdeXAddDevice(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PDEVICE_OBJECT PhysicalDeviceObject)
{
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
PFDO_DEVICE_EXTENSION FdoExtension;
ULONG DeviceExtensionSize;
PDEVICE_OBJECT Fdo;
UNICODE_STRING DeviceName;
WCHAR DeviceNameBuffer[sizeof("\\Device\\Ide\\PciIde999")];
NTSTATUS Status;
PAGED_CODE();
Status = RtlStringCbPrintfW(DeviceNameBuffer,
sizeof(DeviceNameBuffer),
L"\\Device\\Ide\\PciIde%u",
PciIdeControllerNumber);
ASSERT(NT_SUCCESS(Status));
RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
DPRINT("%s(%p, %p) '%wZ'\n", __FUNCTION__, DriverObject, PhysicalDeviceObject, &DeviceName);
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
ASSERT(DriverExtension);
Status = RtlULongAdd(DriverExtension->MiniControllerExtensionSize,
sizeof(FDO_DEVICE_EXTENSION),
&DeviceExtensionSize);
if (!NT_SUCCESS(Status))
{
DPRINT1("Invalid miniport extension size %lx\n",
DriverExtension->MiniControllerExtensionSize);
return Status;
}
Status = IoCreateDevice(DriverObject,
DeviceExtensionSize,
&DeviceName,
FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create FDO 0x%lx\n", Status);
return Status;
}
FdoExtension = Fdo->DeviceExtension;
RtlZeroMemory(FdoExtension, sizeof(FDO_DEVICE_EXTENSION));
FdoExtension->Common.IsFDO = TRUE;
FdoExtension->Common.Self = Fdo;
FdoExtension->DriverObject = DriverObject;
FdoExtension->ControllerNumber = PciIdeControllerNumber++;
KeInitializeSpinLock(&FdoExtension->BusDataLock);
ExInitializeFastMutex(&FdoExtension->DeviceSyncMutex);
Status = IoAttachDeviceToDeviceStackSafe(Fdo, PhysicalDeviceObject, &FdoExtension->Ldo);
if (!NT_SUCCESS(Status))
{
DPRINT("Failed to attach FDO 0x%lx\n", Status);
goto Failure;
}
/* DMA buffers alignment */
Fdo->AlignmentRequirement = max(FdoExtension->Ldo->AlignmentRequirement, FILE_WORD_ALIGNMENT);
Status = PciIdeXQueryInterface(FdoExtension,
&GUID_BUS_INTERFACE_STANDARD,
&FdoExtension->BusInterface,
sizeof(BUS_INTERFACE_STANDARD));
if (!NT_SUCCESS(Status))
{
DPRINT1("No bus interface 0x%lx\n", Status);
goto Failure;
}
Status = PciIdeXGetConfigurationInfo(FdoExtension);
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to retrieve the configuration info %lx\n", Status);
goto Failure;
}
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
Failure:
if (FdoExtension->Ldo)
IoDetachDevice(FdoExtension->Ldo);
IoDeleteDevice(Fdo);
return Status;
}
static
CODE_SEG("PAGE")
VOID
PciIdeXCreateIdeDirectory(VOID)
{
HANDLE Handle;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING DirectoryName = RTL_CONSTANT_STRING(L"\\Device\\Ide");
PAGED_CODE();
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwCreateDirectoryObject(&Handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
/* We don't need a handle for a permanent object */
ZwClose(Handle);
}
/*
* Ignore directory creation failures (don't report them as a driver initialization error)
* as the directory may have already been created by another driver.
* We will handle fatal errors later via IoCreateDevice() call.
*/
}
CODE_SEG("PAGE")
NTSTATUS
NTAPI
PciIdeXInitialize(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath,
_In_ PCONTROLLER_PROPERTIES HwGetControllerProperties,
_In_ ULONG ExtensionSize)
{
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
NTSTATUS Status;
PAGED_CODE();
DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
DriverObject, RegistryPath, HwGetControllerProperties, ExtensionSize);
Status = IoAllocateDriverObjectExtension(DriverObject,
DriverObject,
sizeof(PCIIDEX_DRIVER_EXTENSION),
(PVOID*)&DriverExtension);
if (!NT_SUCCESS(Status))
return Status;
RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
DriverExtension->MiniControllerExtensionSize = ExtensionSize;
DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = PciIdeXDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PciIdeXDispatchWmi;
DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
DriverObject->DriverUnload = PciIdeXUnload;
/* Create a directory to hold the driver's device objects */
PciIdeXCreateIdeDirectory();
return STATUS_SUCCESS;
}
CODE_SEG("PAGE") /* This function is too small to be placed into INIT section */
NTSTATUS
NTAPI
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);
PAGED_CODE();
return STATUS_SUCCESS;
}

View file

@ -1,74 +1,146 @@
/*
* PROJECT: PCI IDE bus driver extension
* LICENSE: See COPYING in the top level directory
* PURPOSE: Common header file
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
*/
#ifndef _PCIIDEX_PCH_
#define _PCIIDEX_PCH_
#include <ntifs.h>
#include <ntddk.h>
#include <ntstrsafe.h>
#include <ntintsafe.h>
#include <initguid.h>
#include <wdmguid.h>
#include <ide.h>
#define TAG_PCIIDEX 'XedI'
#define IS_FDO(p) (((PCOMMON_DEVICE_EXTENSION)(p))->IsFDO)
#define IS_PRIMARY_CHANNEL(PdoExtension) (PdoExtension->Channel == 0)
/*
* Legacy ranges and interrupts
*/
#define PCIIDE_LEGACY_RESOURCE_COUNT 3
#define PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH 8
#define PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH 1
#define PCIIDE_LEGACY_PRIMARY_COMMAND_BASE 0x1F0
#define PCIIDE_LEGACY_PRIMARY_CONTROL_BASE 0x3F6
#define PCIIDE_LEGACY_PRIMARY_IRQ 14
#define PCIIDE_LEGACY_SECONDARY_COMMAND_BASE 0x170
#define PCIIDE_LEGACY_SECONDARY_CONTROL_BASE 0x376
#define PCIIDE_LEGACY_SECONDARY_IRQ 15
/*
* Programming Interface Register
*/
#define PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE 0x01
#define PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE_CAPABLE 0x02
#define PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE 0x04
#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
{
PCONTROLLER_PROPERTIES HwGetControllerProperties;
ULONG MiniControllerExtensionSize;
PCIIDE_UDMA_MODES_SUPPORTED HwUdmaModesSupported;
PCONTROLLER_PROPERTIES HwGetControllerProperties;
ULONG MiniControllerExtensionSize;
} PCIIDEX_DRIVER_EXTENSION, *PPCIIDEX_DRIVER_EXTENSION;
typedef struct _COMMON_DEVICE_EXTENSION
{
BOOLEAN IsFDO;
BOOLEAN IsFDO;
PDEVICE_OBJECT Self;
_Write_guarded_by_(_Global_interlock_)
volatile LONG PageFiles;
_Write_guarded_by_(_Global_interlock_)
volatile LONG HibernateFiles;
_Write_guarded_by_(_Global_interlock_)
volatile LONG DumpFiles;
} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
typedef struct _FDO_DEVICE_EXTENSION
{
COMMON_DEVICE_EXTENSION Common;
COMMON_DEVICE_EXTENSION Common;
PDEVICE_OBJECT Ldo;
PBUS_INTERFACE_STANDARD BusInterface;
IDE_CONTROLLER_PROPERTIES Properties;
PHYSICAL_ADDRESS BusMasterPortBase;
PDEVICE_OBJECT LowerDevice;
PDEVICE_OBJECT Pdo[MAX_IDE_CHANNEL];
USHORT VendorId;
USHORT DeviceId;
PUCHAR MiniControllerExtension[0];
ULONG ControllerNumber;
BOOLEAN InNativeMode;
BOOLEAN IoBaseMapped;
BOOLEAN MiniportStarted;
FAST_MUTEX DeviceSyncMutex;
_Guarded_by_(DeviceSyncMutex)
PPDO_DEVICE_EXTENSION Channels[MAX_IDE_CHANNEL];
USHORT VendorId;
USHORT DeviceId;
PDRIVER_OBJECT DriverObject;
PUCHAR BusMasterPortBase;
KSPIN_LOCK BusDataLock;
BUS_INTERFACE_STANDARD BusInterface;
IDE_CONTROLLER_PROPERTIES Properties;
/* Must be the last entry */
PUCHAR MiniControllerExtension[0];
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
typedef struct _PDO_DEVICE_EXTENSION
{
COMMON_DEVICE_EXTENSION Common;
ULONG Channel;
PDEVICE_OBJECT ControllerFdo;
COMMON_DEVICE_EXTENSION Common;
ULONG Channel;
PFDO_DEVICE_EXTENSION ParentController;
BOOLEAN ReportedMissing;
PUCHAR IoBase;
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
/* fdo.c */
CODE_SEG("PAGE")
DRIVER_INITIALIZE DriverEntry;
CODE_SEG("PAGE")
DRIVER_UNLOAD PciIdeXUnload;
CODE_SEG("PAGE")
DRIVER_ADD_DEVICE PciIdeXAddDevice;
NTSTATUS NTAPI
PciIdeXAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo);
NTSTATUS NTAPI
PciIdeXFdoPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
_Dispatch_type_(IRP_MJ_PNP)
CODE_SEG("PAGE")
DRIVER_DISPATCH_PAGED PciIdeXDispatchPnp;
/* misc.c */
_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
CODE_SEG("PAGE")
DRIVER_DISPATCH_PAGED PciIdeXDispatchWmi;
NTSTATUS NTAPI
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
_Dispatch_type_(IRP_MJ_POWER)
DRIVER_DISPATCH_RAISED PciIdeXDispatchPower;
CODE_SEG("PAGE")
NTSTATUS
DuplicateUnicodeString(
IN ULONG Flags,
IN PCUNICODE_STRING SourceString,
OUT PUNICODE_STRING DestinationString);
PciIdeXFdoDispatchPnp(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_Inout_ PIRP Irp);
/* pdo.c */
CODE_SEG("PAGE")
NTSTATUS
PciIdeXStartMiniport(
_In_ PFDO_DEVICE_EXTENSION FdoExtension);
NTSTATUS NTAPI
PciIdeXPdoPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
CODE_SEG("PAGE")
IDE_CHANNEL_STATE
PciIdeXChannelState(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ ULONG Channel);
#endif /* _PCIIDEX_PCH_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,66 @@
/*
* PROJECT: PCI IDE bus driver extension
* LICENSE: See COPYING in the top level directory
* PURPOSE: Power support functions
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
*/
#include "pciidex.h"
#define NDEBUG
#include <debug.h>
static
NTSTATUS
PciIdeXPdoDispatchPower(
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
_In_ PIRP Irp)
{
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
UNREFERENCED_PARAMETER(PdoExtension);
IoStack = IoGetCurrentIrpStackLocation(Irp);
switch (IoStack->MinorFunction)
{
case IRP_MN_SET_POWER:
case IRP_MN_QUERY_POWER:
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
break;
default:
Status = Irp->IoStatus.Status;
break;
}
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
static
NTSTATUS
PciIdeXFdoDispatchPower(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ PIRP Irp)
{
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(FdoExtension->Ldo, Irp);
}
NTSTATUS
NTAPI
PciIdeXDispatchPower(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
PVOID DeviceExtension = DeviceObject->DeviceExtension;
if (IS_FDO(DeviceExtension))
return PciIdeXFdoDispatchPower(DeviceExtension, Irp);
else
return PciIdeXPdoDispatchPower(DeviceExtension, Irp);
}

View file

@ -246,6 +246,7 @@ typedef NTSTATUS
_In_ PVOID DeviceExtension,
_In_ PIDE_CONTROLLER_PROPERTIES ControllerProperties);
CODE_SEG("PAGE")
NTSTATUS NTAPI
PciIdeXInitialize(
_In_ PDRIVER_OBJECT DriverObject,