mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[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:
parent
293fc8dc34
commit
c0c57e2324
9 changed files with 1876 additions and 1229 deletions
|
@ -4,9 +4,9 @@ spec2def(pciidex.sys pciidex.spec ADD_IMPORTLIB)
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
fdo.c
|
fdo.c
|
||||||
miniport.c
|
miniport.c
|
||||||
misc.c
|
|
||||||
pciidex.c
|
pciidex.c
|
||||||
pdo.c
|
pdo.c
|
||||||
|
power.c
|
||||||
pciidex.h)
|
pciidex.h)
|
||||||
|
|
||||||
add_library(pciidex MODULE
|
add_library(pciidex MODULE
|
||||||
|
@ -16,5 +16,5 @@ add_library(pciidex MODULE
|
||||||
|
|
||||||
add_pch(pciidex pciidex.h SOURCE)
|
add_pch(pciidex pciidex.h SOURCE)
|
||||||
set_module_type(pciidex kernelmodedriver)
|
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)
|
add_cd_file(TARGET pciidex DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: PCI IDE bus driver extension
|
||||||
* PROJECT: PCI IDE bus driver extension
|
* LICENSE: See COPYING in the top level directory
|
||||||
* FILE: drivers/storage/pciidex/fdo.c
|
* PURPOSE: IRP_MJ_PNP operations for FDOs
|
||||||
* PURPOSE: IRP_MJ_PNP operations for FDOs
|
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
|
||||||
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
* Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pciidex.h"
|
#include "pciidex.h"
|
||||||
|
@ -11,481 +11,497 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <initguid.h>
|
static
|
||||||
#include <wdmguid.h>
|
CODE_SEG("PAGE")
|
||||||
|
NTSTATUS
|
||||||
static NTSTATUS
|
PciIdeXFdoParseResources(
|
||||||
GetBusInterface(
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
|
||||||
IN PFDO_DEVICE_EXTENSION DeviceExtension)
|
_In_ PCM_RESOURCE_LIST ResourcesTranslated)
|
||||||
{
|
{
|
||||||
PBUS_INTERFACE_STANDARD BusInterface = NULL;
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR BusMasterDescriptor = NULL;
|
||||||
KEVENT Event;
|
PVOID IoBase;
|
||||||
IO_STATUS_BLOCK IoStatus;
|
ULONG i;
|
||||||
PIRP Irp;
|
|
||||||
PIO_STACK_LOCATION Stack;
|
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
if (DeviceExtension->BusInterface)
|
PAGED_CODE();
|
||||||
{
|
|
||||||
DPRINT("We already have the bus interface\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
BusInterface = ExAllocatePool(PagedPool, sizeof(BUS_INTERFACE_STANDARD));
|
if (!ResourcesTranslated)
|
||||||
if (!BusInterface)
|
return STATUS_INVALID_PARAMETER;
|
||||||
{
|
|
||||||
DPRINT("ExAllocatePool() failed\n");
|
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
for (i = 0; i < ResourcesTranslated->List[0].PartialResourceList.Count; ++i)
|
||||||
Irp = IoBuildSynchronousFsdRequest(
|
{
|
||||||
IRP_MJ_PNP,
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
||||||
DeviceExtension->LowerDevice,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
&Event,
|
|
||||||
&IoStatus);
|
|
||||||
if (!Irp)
|
|
||||||
{
|
|
||||||
DPRINT("IoBuildSynchronousFsdRequest() failed\n");
|
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
Descriptor = &ResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
|
||||||
Irp->IoStatus.Information = 0;
|
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);
|
default:
|
||||||
Stack->MajorFunction = IRP_MJ_PNP;
|
break;
|
||||||
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;
|
|
||||||
|
|
||||||
Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
|
default:
|
||||||
if (Status == STATUS_PENDING)
|
break;
|
||||||
{
|
}
|
||||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
}
|
||||||
Status = IoStatus.Status;
|
|
||||||
}
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
DeviceExtension->BusInterface = BusInterface;
|
if (!BusMasterDescriptor)
|
||||||
BusInterface = NULL;
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
cleanup:
|
if ((BusMasterDescriptor->Type == CmResourceTypePort) &&
|
||||||
if (BusInterface) ExFreePool(BusInterface);
|
(BusMasterDescriptor->Flags & CM_RESOURCE_PORT_IO))
|
||||||
return Status;
|
{
|
||||||
|
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
|
static
|
||||||
ReleaseBusInterface(
|
CODE_SEG("PAGE")
|
||||||
IN PFDO_DEVICE_EXTENSION DeviceExtension)
|
NTSTATUS
|
||||||
{
|
|
||||||
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
|
|
||||||
PciIdeXFdoStartDevice(
|
PciIdeXFdoStartDevice(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
|
||||||
IN PIRP Irp)
|
_In_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
|
NTSTATUS Status;
|
||||||
PFDO_DEVICE_EXTENSION DeviceExtension;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PCM_RESOURCE_LIST ResourceList;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject, Irp);
|
PAGED_CODE();
|
||||||
|
|
||||||
DriverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, DeviceObject->DriverObject);
|
if (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp)))
|
||||||
ASSERT(DriverExtension);
|
{
|
||||||
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
return STATUS_UNSUCCESSFUL;
|
||||||
ASSERT(DeviceExtension);
|
}
|
||||||
ASSERT(DeviceExtension->Common.IsFDO);
|
Status = Irp->IoStatus.Status;
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
DeviceExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
DeviceExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
|
|
||||||
Status = DriverExtension->HwGetControllerProperties(
|
|
||||||
DeviceExtension->MiniControllerExtension,
|
|
||||||
&DeviceExtension->Properties);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
DriverExtension->HwUdmaModesSupported = DeviceExtension->Properties.PciIdeUdmaModesSupported;
|
Status = PciIdeXFdoParseResources(FdoExtension,
|
||||||
if (!DriverExtension->HwUdmaModesSupported)
|
IoStack->Parameters.StartDevice.AllocatedResourcesTranslated);
|
||||||
/* This method is optional, so provide our own one */
|
if (!NT_SUCCESS(Status))
|
||||||
DriverExtension->HwUdmaModesSupported = PciIdeXUdmaModesSupported;
|
{
|
||||||
|
DPRINT1("Failed to parse resources 0x%lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get bus master port base, if any */
|
Status = PciIdeXStartMiniport(FdoExtension);
|
||||||
ResourceList = IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources;
|
if (!NT_SUCCESS(Status))
|
||||||
if (ResourceList
|
{
|
||||||
&& ResourceList->Count == 1
|
DPRINT1("Miniport initialization failed 0x%lx\n", Status);
|
||||||
&& ResourceList->List[0].PartialResourceList.Count == 1
|
return Status;
|
||||||
&& ResourceList->List[0].PartialResourceList.Version == 1
|
}
|
||||||
&& ResourceList->List[0].PartialResourceList.Revision == 1
|
|
||||||
&& ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type == CmResourceTypePort
|
return STATUS_SUCCESS;
|
||||||
&& ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length == 16)
|
|
||||||
{
|
|
||||||
DeviceExtension->BusMasterPortBase = ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start;
|
|
||||||
}
|
|
||||||
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(
|
PciIdeXFdoQueryBusRelations(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
|
||||||
OUT PDEVICE_RELATIONS* pDeviceRelations)
|
_In_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PFDO_DEVICE_EXTENSION DeviceExtension;
|
PPDO_DEVICE_EXTENSION PdoExtension;
|
||||||
PDEVICE_RELATIONS DeviceRelations = NULL;
|
IDE_CHANNEL_STATE ChannelState;
|
||||||
PDEVICE_OBJECT Pdo;
|
PDEVICE_RELATIONS DeviceRelations;
|
||||||
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
|
ULONG i;
|
||||||
ULONG i, j;
|
|
||||||
ULONG PDOs = 0;
|
|
||||||
IDE_CHANNEL_STATE ChannelState;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
PAGED_CODE();
|
||||||
ASSERT(DeviceExtension);
|
|
||||||
ASSERT(DeviceExtension->Common.IsFDO);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_IDE_CHANNEL; i++)
|
DeviceRelations = ExAllocatePoolWithTag(PagedPool,
|
||||||
{
|
FIELD_OFFSET(DEVICE_RELATIONS,
|
||||||
if (DeviceExtension->Pdo[i])
|
Objects[MAX_IDE_CHANNEL]),
|
||||||
{
|
TAG_PCIIDEX);
|
||||||
PDOs++;
|
if (!DeviceRelations)
|
||||||
continue;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
|
||||||
ChannelState = DeviceExtension->Properties.PciIdeChannelEnabled(
|
|
||||||
DeviceExtension->MiniControllerExtension, i);
|
|
||||||
if (ChannelState == ChannelDisabled)
|
|
||||||
{
|
|
||||||
DPRINT("Channel %lu is disabled\n", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Need to create a PDO */
|
DeviceRelations->Count = 0;
|
||||||
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;
|
|
||||||
|
|
||||||
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
|
ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
|
||||||
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;
|
|
||||||
|
|
||||||
DeviceExtension->Pdo[i] = Pdo;
|
for (i = 0; i < MAX_IDE_CHANNEL; ++i)
|
||||||
PDOs++;
|
{
|
||||||
}
|
PdoExtension = FdoExtension->Channels[i];
|
||||||
|
|
||||||
if (PDOs == 0)
|
/* Ignore disabled channels */
|
||||||
{
|
ChannelState = PciIdeXChannelState(FdoExtension, i);
|
||||||
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
|
if (ChannelState == ChannelDisabled)
|
||||||
PagedPool,
|
{
|
||||||
sizeof(DEVICE_RELATIONS));
|
if (PdoExtension)
|
||||||
}
|
{
|
||||||
else
|
PdoExtension->ReportedMissing = TRUE;
|
||||||
{
|
}
|
||||||
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
|
|
||||||
PagedPool,
|
|
||||||
sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (PDOs - 1));
|
|
||||||
}
|
|
||||||
if (!DeviceRelations)
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
|
||||||
DeviceRelations->Count = PDOs;
|
DPRINT("Channel %lu is disabled\n", i);
|
||||||
for (i = 0, j = 0; i < MAX_IDE_CHANNEL; i++)
|
continue;
|
||||||
{
|
}
|
||||||
if (DeviceExtension->Pdo[i])
|
|
||||||
{
|
|
||||||
ObReferenceObject(DeviceExtension->Pdo[i]);
|
|
||||||
DeviceRelations->Objects[j++] = DeviceExtension->Pdo[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*pDeviceRelations = DeviceRelations;
|
/* Need to create a PDO */
|
||||||
return STATUS_SUCCESS;
|
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
|
static
|
||||||
PciIdeXFdoPnpDispatch(
|
CODE_SEG("PAGE")
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
NTSTATUS
|
||||||
IN PIRP Irp)
|
PciIdeXFdoQueryDeviceUsageNotification(
|
||||||
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
|
||||||
|
_In_ PIRP Irp)
|
||||||
{
|
{
|
||||||
PFDO_DEVICE_EXTENSION FdoExtension;
|
PIO_STACK_LOCATION IoStack;
|
||||||
ULONG MinorFunction;
|
NTSTATUS Status;
|
||||||
PIO_STACK_LOCATION Stack;
|
volatile LONG* Counter;
|
||||||
ULONG_PTR Information = Irp->IoStatus.Information;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
PAGED_CODE();
|
||||||
MinorFunction = Stack->MinorFunction;
|
|
||||||
|
|
||||||
switch (MinorFunction)
|
if (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp)))
|
||||||
{
|
{
|
||||||
case IRP_MN_START_DEVICE: /* 0x00 */
|
return STATUS_UNSUCCESSFUL;
|
||||||
{
|
}
|
||||||
DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
|
Status = Irp->IoStatus.Status;
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
/* Call lower driver */
|
{
|
||||||
FdoExtension = DeviceObject->DeviceExtension;
|
return Status;
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
}
|
||||||
|
|
||||||
if (IoForwardIrpSynchronously(FdoExtension->LowerDevice, Irp))
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
{
|
switch (IoStack->Parameters.UsageNotification.Type)
|
||||||
Status = Irp->IoStatus.Status;
|
{
|
||||||
if (NT_SUCCESS(Status))
|
case DeviceUsageTypePaging:
|
||||||
{
|
Counter = &FdoExtension->Common.PageFiles;
|
||||||
Status = PciIdeXFdoStartDevice(DeviceObject, Irp);
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = Information;
|
case DeviceUsageTypeHibernation:
|
||||||
Irp->IoStatus.Status = Status;
|
Counter = &FdoExtension->Common.HibernateFiles;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
break;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: PCI IDE bus driver extension
|
||||||
* PROJECT: PCI IDE bus driver extension
|
* LICENSE: See COPYING in the top level directory
|
||||||
* FILE: drivers/storage/pciidex/miniport.c
|
* PURPOSE: Miniport functions
|
||||||
* PURPOSE: Miniport functions
|
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
|
||||||
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pciidex.h"
|
#include "pciidex.h"
|
||||||
|
@ -14,83 +13,51 @@
|
||||||
/** @brief Global debugging level. Valid values are between 0 (Error) and 3 (Trace). */
|
/** @brief Global debugging level. Valid values are between 0 (Error) and 3 (Trace). */
|
||||||
ULONG PciIdeDebug = 0;
|
ULONG PciIdeDebug = 0;
|
||||||
|
|
||||||
static DRIVER_DISPATCH PciIdeXForwardOrIgnore;
|
CODE_SEG("PAGE")
|
||||||
static NTSTATUS NTAPI
|
NTSTATUS
|
||||||
PciIdeXForwardOrIgnore(
|
PciIdeXStartMiniport(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
{
|
||||||
if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
|
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
|
||||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
NTSTATUS Status;
|
||||||
else
|
|
||||||
{
|
|
||||||
ULONG MajorFunction = IoGetCurrentIrpStackLocation(Irp)->MajorFunction;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
if (MajorFunction == IRP_MJ_CREATE ||
|
PAGED_CODE();
|
||||||
MajorFunction == IRP_MJ_CLEANUP ||
|
|
||||||
MajorFunction == IRP_MJ_CLOSE)
|
if (FdoExtension->MiniportStarted)
|
||||||
{
|
return STATUS_SUCCESS;
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
DPRINT("Starting miniport\n");
|
||||||
else
|
|
||||||
{
|
DriverExtension = IoGetDriverObjectExtension(FdoExtension->DriverObject,
|
||||||
DPRINT1("PDO stub for major function 0x%lx\n", MajorFunction);
|
FdoExtension->DriverObject);
|
||||||
Status = STATUS_NOT_SUPPORTED;
|
ASSERT(DriverExtension);
|
||||||
}
|
|
||||||
Irp->IoStatus.Information = 0;
|
FdoExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
|
||||||
Irp->IoStatus.Status = Status;
|
FdoExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
Status = DriverExtension->HwGetControllerProperties(FdoExtension->MiniControllerExtension,
|
||||||
return Status;
|
&FdoExtension->Properties);
|
||||||
}
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
FdoExtension->MiniportStarted = TRUE;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Dispatch_type_(IRP_MJ_POWER)
|
CODE_SEG("PAGE")
|
||||||
static DRIVER_DISPATCH PciIdeXPowerDispatch;
|
IDE_CHANNEL_STATE
|
||||||
static NTSTATUS NTAPI
|
PciIdeXChannelState(
|
||||||
PciIdeXPowerDispatch(
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
_In_ ULONG Channel)
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
PCIIDE_CHANNEL_ENABLED MiniportChannelEnabled;
|
||||||
PIO_STACK_LOCATION IoStack;
|
|
||||||
PDEVICE_OBJECT LowerDevice;
|
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
PAGED_CODE();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_Dispatch_type_(IRP_MJ_PNP)
|
MiniportChannelEnabled = FdoExtension->Properties.PciIdeChannelEnabled;
|
||||||
static DRIVER_DISPATCH PciIdeXPnpDispatch;
|
if (MiniportChannelEnabled)
|
||||||
static NTSTATUS NTAPI
|
return MiniportChannelEnabled(FdoExtension->MiniControllerExtension, Channel);
|
||||||
PciIdeXPnpDispatch(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
return ChannelStateUnknown;
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
|
||||||
if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
|
|
||||||
return PciIdeXFdoPnpDispatch(DeviceObject, Irp);
|
|
||||||
else
|
|
||||||
return PciIdeXPdoPnpDispatch(DeviceObject, Irp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,122 +86,88 @@ PciIdeXDebugPrint(
|
||||||
va_end(ap);
|
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 */
|
/* May be called at IRQL <= DISPATCH_LEVEL */
|
||||||
NTSTATUS NTAPI
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
PciIdeXGetBusData(
|
PciIdeXGetBusData(
|
||||||
IN PVOID DeviceExtension,
|
_In_ PVOID DeviceExtension,
|
||||||
IN PVOID Buffer,
|
_Out_writes_bytes_all_(BufferLength) PVOID Buffer,
|
||||||
IN ULONG ConfigDataOffset,
|
_In_ ULONG ConfigDataOffset,
|
||||||
IN ULONG BufferLength)
|
_In_ ULONG BufferLength)
|
||||||
{
|
{
|
||||||
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
|
PFDO_DEVICE_EXTENSION FdoExtension;
|
||||||
ULONG BytesRead;
|
ULONG BytesRead;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
|
DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
|
||||||
DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
|
DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
|
||||||
|
|
||||||
FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
|
FdoExtension = CONTAINING_RECORD(DeviceExtension,
|
||||||
if (FdoDeviceExtension->BusInterface)
|
FDO_DEVICE_EXTENSION,
|
||||||
{
|
MiniControllerExtension);
|
||||||
BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
|
|
||||||
FdoDeviceExtension->BusInterface->Context,
|
|
||||||
PCI_WHICHSPACE_CONFIG,
|
|
||||||
Buffer,
|
|
||||||
ConfigDataOffset,
|
|
||||||
BufferLength);
|
|
||||||
if (BytesRead == BufferLength)
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
/* May be called at IRQL <= DISPATCH_LEVEL */
|
||||||
NTSTATUS NTAPI
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
PciIdeXSetBusData(
|
PciIdeXSetBusData(
|
||||||
IN PVOID DeviceExtension,
|
_In_ PVOID DeviceExtension,
|
||||||
IN PVOID Buffer,
|
_In_reads_bytes_(BufferLength) PVOID Buffer,
|
||||||
IN PVOID DataMask,
|
_In_reads_bytes_(BufferLength) PVOID DataMask,
|
||||||
IN ULONG ConfigDataOffset,
|
_In_ ULONG ConfigDataOffset,
|
||||||
IN ULONG BufferLength)
|
_In_ ULONG BufferLength)
|
||||||
{
|
{
|
||||||
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
|
PFDO_DEVICE_EXTENSION FdoExtension;
|
||||||
PUCHAR CurrentBuffer = NULL;
|
ULONG i, BytesWritten;
|
||||||
ULONG i, BytesWritten;
|
PUCHAR CurrentBuffer;
|
||||||
NTSTATUS Status;
|
KIRQL OldIrql;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
|
DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
|
||||||
DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
|
DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
|
||||||
|
|
||||||
CurrentBuffer = ExAllocatePool(NonPagedPool, BufferLength);
|
CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferLength, TAG_PCIIDEX);
|
||||||
if (!CurrentBuffer)
|
if (!CurrentBuffer)
|
||||||
{
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
|
FdoExtension = CONTAINING_RECORD(DeviceExtension,
|
||||||
if (!NT_SUCCESS(Status))
|
FDO_DEVICE_EXTENSION,
|
||||||
goto cleanup;
|
MiniControllerExtension);
|
||||||
|
|
||||||
for (i = 0; i < BufferLength; i++)
|
KeAcquireSpinLock(&FdoExtension->BusDataLock, &OldIrql);
|
||||||
CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) | (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
|
|
||||||
|
|
||||||
FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
|
Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
|
||||||
if (!FdoDeviceExtension->BusInterface)
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
goto Cleanup;
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
BytesWritten = (*FdoDeviceExtension->BusInterface->SetBusData)(
|
for (i = 0; i < BufferLength; i++)
|
||||||
FdoDeviceExtension->BusInterface->Context,
|
{
|
||||||
PCI_WHICHSPACE_CONFIG,
|
CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) |
|
||||||
CurrentBuffer,
|
(((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
|
||||||
ConfigDataOffset,
|
}
|
||||||
BufferLength);
|
|
||||||
if (BytesWritten == BufferLength)
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
else
|
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
cleanup:
|
BytesWritten = (*FdoExtension->BusInterface.SetBusData)(FdoExtension->BusInterface.Context,
|
||||||
ExFreePool(CurrentBuffer);
|
PCI_WHICHSPACE_CONFIG,
|
||||||
return Status;
|
CurrentBuffer,
|
||||||
|
ConfigDataOffset,
|
||||||
|
BufferLength);
|
||||||
|
if (BytesWritten != BufferLength)
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
else
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
KeReleaseSpinLock(&FdoExtension->BusDataLock, OldIrql);
|
||||||
|
|
||||||
|
ExFreePoolWithTag(CurrentBuffer, TAG_PCIIDEX);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,9 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: PCI IDE bus driver extension
|
||||||
* PROJECT: PCI IDE bus driver extension
|
* LICENSE: See COPYING in the top level directory
|
||||||
* FILE: drivers/storage/pciidex/pciidex.c
|
* PURPOSE: Main file
|
||||||
* PURPOSE: Main file
|
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
|
||||||
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pciidex.h"
|
#include "pciidex.h"
|
||||||
|
@ -11,10 +10,330 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
ULONG PciIdeControllerNumber = 0;
|
||||||
DriverEntry(
|
|
||||||
IN PDRIVER_OBJECT DriverObject,
|
CODE_SEG("PAGE")
|
||||||
IN PUNICODE_STRING RegistryPath)
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_
|
#ifndef _PCIIDEX_PCH_
|
||||||
#define _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>
|
#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
|
typedef struct _PCIIDEX_DRIVER_EXTENSION
|
||||||
{
|
{
|
||||||
PCONTROLLER_PROPERTIES HwGetControllerProperties;
|
PCONTROLLER_PROPERTIES HwGetControllerProperties;
|
||||||
ULONG MiniControllerExtensionSize;
|
ULONG MiniControllerExtensionSize;
|
||||||
PCIIDE_UDMA_MODES_SUPPORTED HwUdmaModesSupported;
|
|
||||||
} PCIIDEX_DRIVER_EXTENSION, *PPCIIDEX_DRIVER_EXTENSION;
|
} PCIIDEX_DRIVER_EXTENSION, *PPCIIDEX_DRIVER_EXTENSION;
|
||||||
|
|
||||||
typedef struct _COMMON_DEVICE_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;
|
} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
|
||||||
|
|
||||||
typedef struct _FDO_DEVICE_EXTENSION
|
typedef struct _FDO_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
COMMON_DEVICE_EXTENSION Common;
|
COMMON_DEVICE_EXTENSION Common;
|
||||||
|
PDEVICE_OBJECT Ldo;
|
||||||
|
|
||||||
PBUS_INTERFACE_STANDARD BusInterface;
|
ULONG ControllerNumber;
|
||||||
IDE_CONTROLLER_PROPERTIES Properties;
|
BOOLEAN InNativeMode;
|
||||||
PHYSICAL_ADDRESS BusMasterPortBase;
|
BOOLEAN IoBaseMapped;
|
||||||
PDEVICE_OBJECT LowerDevice;
|
BOOLEAN MiniportStarted;
|
||||||
PDEVICE_OBJECT Pdo[MAX_IDE_CHANNEL];
|
|
||||||
USHORT VendorId;
|
FAST_MUTEX DeviceSyncMutex;
|
||||||
USHORT DeviceId;
|
_Guarded_by_(DeviceSyncMutex)
|
||||||
PUCHAR MiniControllerExtension[0];
|
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;
|
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
typedef struct _PDO_DEVICE_EXTENSION
|
typedef struct _PDO_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
COMMON_DEVICE_EXTENSION Common;
|
COMMON_DEVICE_EXTENSION Common;
|
||||||
|
ULONG Channel;
|
||||||
ULONG Channel;
|
PFDO_DEVICE_EXTENSION ParentController;
|
||||||
PDEVICE_OBJECT ControllerFdo;
|
BOOLEAN ReportedMissing;
|
||||||
|
PUCHAR IoBase;
|
||||||
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
} 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;
|
DRIVER_ADD_DEVICE PciIdeXAddDevice;
|
||||||
NTSTATUS NTAPI
|
|
||||||
PciIdeXAddDevice(
|
|
||||||
IN PDRIVER_OBJECT DriverObject,
|
|
||||||
IN PDEVICE_OBJECT Pdo);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
_Dispatch_type_(IRP_MJ_PNP)
|
||||||
PciIdeXFdoPnpDispatch(
|
CODE_SEG("PAGE")
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
DRIVER_DISPATCH_PAGED PciIdeXDispatchPnp;
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
/* misc.c */
|
_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
|
||||||
|
CODE_SEG("PAGE")
|
||||||
|
DRIVER_DISPATCH_PAGED PciIdeXDispatchWmi;
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
_Dispatch_type_(IRP_MJ_POWER)
|
||||||
ForwardIrpAndForget(
|
DRIVER_DISPATCH_RAISED PciIdeXDispatchPower;
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
|
CODE_SEG("PAGE")
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
DuplicateUnicodeString(
|
PciIdeXFdoDispatchPnp(
|
||||||
IN ULONG Flags,
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
|
||||||
IN PCUNICODE_STRING SourceString,
|
_Inout_ PIRP Irp);
|
||||||
OUT PUNICODE_STRING DestinationString);
|
|
||||||
|
|
||||||
/* pdo.c */
|
CODE_SEG("PAGE")
|
||||||
|
NTSTATUS
|
||||||
|
PciIdeXStartMiniport(
|
||||||
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension);
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
CODE_SEG("PAGE")
|
||||||
PciIdeXPdoPnpDispatch(
|
IDE_CHANNEL_STATE
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
PciIdeXChannelState(
|
||||||
IN PIRP Irp);
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
|
||||||
|
_In_ ULONG Channel);
|
||||||
|
|
||||||
#endif /* _PCIIDEX_PCH_ */
|
#endif /* _PCIIDEX_PCH_ */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
66
drivers/storage/ide/pciidex/power.c
Normal file
66
drivers/storage/ide/pciidex/power.c
Normal 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);
|
||||||
|
}
|
|
@ -246,6 +246,7 @@ typedef NTSTATUS
|
||||||
_In_ PVOID DeviceExtension,
|
_In_ PVOID DeviceExtension,
|
||||||
_In_ PIDE_CONTROLLER_PROPERTIES ControllerProperties);
|
_In_ PIDE_CONTROLLER_PROPERTIES ControllerProperties);
|
||||||
|
|
||||||
|
CODE_SEG("PAGE")
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
PciIdeXInitialize(
|
PciIdeXInitialize(
|
||||||
_In_ PDRIVER_OBJECT DriverObject,
|
_In_ PDRIVER_OBJECT DriverObject,
|
||||||
|
|
Loading…
Reference in a new issue