mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
c0c57e2324
- 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
850 lines
24 KiB
C
850 lines
24 KiB
C
/*
|
|
* PROJECT: PCI IDE bus driver extension
|
|
* LICENSE: See COPYING in the top level directory
|
|
* PURPOSE: IRP_MJ_PNP operations for PDOs
|
|
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
|
|
* Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
|
*/
|
|
|
|
#include "pciidex.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoStartDevice(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PCM_RESOURCE_LIST ResourceList)
|
|
{
|
|
PUCHAR IoBase;
|
|
|
|
PAGED_CODE();
|
|
|
|
IoBase = PdoExtension->ParentController->BusMasterPortBase;
|
|
if (!IS_PRIMARY_CHANNEL(PdoExtension))
|
|
{
|
|
IoBase += BM_SECONDARY_CHANNEL_OFFSET;
|
|
}
|
|
DPRINT("Bus Master Base %p\n", IoBase);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoStopDevice(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoRemoveDevice(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ BOOLEAN FinalRemove)
|
|
{
|
|
PFDO_DEVICE_EXTENSION FdoExtension = PdoExtension->ParentController;
|
|
ULONG i;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (FinalRemove && PdoExtension->ReportedMissing)
|
|
{
|
|
ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
|
|
|
|
for (i = 0; i < MAX_IDE_CHANNEL; ++i)
|
|
{
|
|
if (FdoExtension->Channels[i] == PdoExtension)
|
|
{
|
|
FdoExtension->Channels[i] = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ExReleaseFastMutex(&FdoExtension->DeviceSyncMutex);
|
|
|
|
IoDeleteDevice(PdoExtension->Common.Self);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryStopRemoveDevice(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
if (PdoExtension->Common.PageFiles ||
|
|
PdoExtension->Common.HibernateFiles ||
|
|
PdoExtension->Common.DumpFiles)
|
|
{
|
|
return STATUS_DEVICE_BUSY;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryTargetDeviceRelations(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PDEVICE_RELATIONS DeviceRelations;
|
|
|
|
PAGED_CODE();
|
|
|
|
DeviceRelations = ExAllocatePoolWithTag(PagedPool,
|
|
sizeof(DEVICE_RELATIONS),
|
|
TAG_PCIIDEX);
|
|
if (!DeviceRelations)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
DeviceRelations->Count = 1;
|
|
DeviceRelations->Objects[0] = PdoExtension->Common.Self;
|
|
ObReferenceObject(PdoExtension->Common.Self);
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static IO_COMPLETION_ROUTINE PciIdeXOnRepeaterCompletion;
|
|
|
|
static
|
|
NTSTATUS
|
|
NTAPI
|
|
PciIdeXOnRepeaterCompletion(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_In_ PIRP Irp,
|
|
_In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
|
|
{
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
|
|
|
if (Irp->PendingReturned)
|
|
KeSetEvent(Context, IO_NO_INCREMENT, FALSE);
|
|
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoRepeatRequest(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp,
|
|
_In_opt_ PDEVICE_CAPABILITIES DeviceCapabilities)
|
|
{
|
|
PDEVICE_OBJECT Fdo, TopDeviceObject;
|
|
PIO_STACK_LOCATION IoStack, SubStack;
|
|
PIRP SubIrp;
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
Fdo = PdoExtension->ParentController->Common.Self;
|
|
TopDeviceObject = IoGetAttachedDeviceReference(Fdo);
|
|
|
|
SubIrp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE);
|
|
if (!SubIrp)
|
|
{
|
|
ObDereferenceObject(TopDeviceObject);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
SubStack = IoGetNextIrpStackLocation(SubIrp);
|
|
RtlCopyMemory(SubStack, IoStack, sizeof(IO_STACK_LOCATION));
|
|
|
|
if (DeviceCapabilities)
|
|
SubStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
|
|
|
|
IoSetCompletionRoutine(SubIrp,
|
|
PciIdeXOnRepeaterCompletion,
|
|
&Event,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
SubIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
Status = IoCallDriver(TopDeviceObject, SubIrp);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
|
|
ObDereferenceObject(TopDeviceObject);
|
|
|
|
Status = SubIrp->IoStatus.Status;
|
|
IoFreeIrp(SubIrp);
|
|
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryCapabilities(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
DEVICE_CAPABILITIES ParentCapabilities;
|
|
PDEVICE_CAPABILITIES DeviceCapabilities;
|
|
PIO_STACK_LOCATION IoStack;
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
/* Get the capabilities of the parent device */
|
|
RtlZeroMemory(&ParentCapabilities, sizeof(ParentCapabilities));
|
|
ParentCapabilities.Size = sizeof(ParentCapabilities);
|
|
ParentCapabilities.Version = 1;
|
|
ParentCapabilities.Address = MAXULONG;
|
|
ParentCapabilities.UINumber = MAXULONG;
|
|
Status = PciIdeXPdoRepeatRequest(PdoExtension, Irp, &ParentCapabilities);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
|
|
*DeviceCapabilities = ParentCapabilities;
|
|
|
|
/* Override some fields */
|
|
DeviceCapabilities->UniqueID = FALSE;
|
|
DeviceCapabilities->Address = PdoExtension->Channel;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryPnpDeviceState(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
if (PdoExtension->Common.PageFiles ||
|
|
PdoExtension->Common.HibernateFiles ||
|
|
PdoExtension->Common.DumpFiles)
|
|
{
|
|
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryResources(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PFDO_DEVICE_EXTENSION FdoExtension;
|
|
IDE_CHANNEL_STATE ChannelState;
|
|
PCM_RESOURCE_LIST ResourceList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
|
ULONG CommandPortBase, ControlPortBase, InterruptVector;
|
|
ULONG ListSize;
|
|
|
|
PAGED_CODE();
|
|
|
|
FdoExtension = PdoExtension->ParentController;
|
|
if (FdoExtension->InNativeMode)
|
|
return Irp->IoStatus.Status;
|
|
|
|
ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel);
|
|
if (ChannelState == ChannelDisabled)
|
|
return Irp->IoStatus.Status;
|
|
|
|
ListSize = sizeof(CM_RESOURCE_LIST) +
|
|
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCIIDE_LEGACY_RESOURCE_COUNT - 1);
|
|
ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_PCIIDEX);
|
|
if (!ResourceList)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
/* Legacy mode resources */
|
|
ResourceList->Count = 1;
|
|
ResourceList->List[0].InterfaceType = Isa;
|
|
ResourceList->List[0].PartialResourceList.Version = 1;
|
|
ResourceList->List[0].PartialResourceList.Revision = 1;
|
|
ResourceList->List[0].PartialResourceList.Count = PCIIDE_LEGACY_RESOURCE_COUNT;
|
|
|
|
if (IS_PRIMARY_CHANNEL(PdoExtension))
|
|
{
|
|
CommandPortBase = PCIIDE_LEGACY_PRIMARY_COMMAND_BASE;
|
|
ControlPortBase = PCIIDE_LEGACY_PRIMARY_CONTROL_BASE;
|
|
InterruptVector = PCIIDE_LEGACY_PRIMARY_IRQ;
|
|
}
|
|
else
|
|
{
|
|
CommandPortBase = PCIIDE_LEGACY_SECONDARY_COMMAND_BASE;
|
|
ControlPortBase = PCIIDE_LEGACY_SECONDARY_CONTROL_BASE;
|
|
InterruptVector = PCIIDE_LEGACY_SECONDARY_IRQ;
|
|
}
|
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
|
|
|
|
/* Command port base */
|
|
Descriptor->Type = CmResourceTypePort;
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
Descriptor->u.Port.Length = PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH;
|
|
Descriptor->u.Port.Start.LowPart = CommandPortBase;
|
|
++Descriptor;
|
|
|
|
/* Control port base */
|
|
Descriptor->Type = CmResourceTypePort;
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
Descriptor->u.Port.Length = PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH;
|
|
Descriptor->u.Port.Start.LowPart = ControlPortBase;
|
|
++Descriptor;
|
|
|
|
/* Interrupt */
|
|
Descriptor->Type = CmResourceTypeInterrupt;
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
|
Descriptor->u.Interrupt.Level = InterruptVector;
|
|
Descriptor->u.Interrupt.Vector = InterruptVector;
|
|
Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1;
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryResourceRequirements(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PFDO_DEVICE_EXTENSION FdoExtension;
|
|
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
|
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
|
IDE_CHANNEL_STATE ChannelState;
|
|
ULONG CommandPortBase, ControlPortBase, InterruptVector;
|
|
ULONG ListSize;
|
|
|
|
PAGED_CODE();
|
|
|
|
FdoExtension = PdoExtension->ParentController;
|
|
if (FdoExtension->InNativeMode)
|
|
return Irp->IoStatus.Status;
|
|
|
|
ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel);
|
|
if (ChannelState == ChannelDisabled)
|
|
return Irp->IoStatus.Status;
|
|
|
|
ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * (PCIIDE_LEGACY_RESOURCE_COUNT - 1);
|
|
RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_PCIIDEX);
|
|
if (!RequirementsList)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
/* Legacy mode resources */
|
|
RequirementsList->InterfaceType = Isa;
|
|
RequirementsList->ListSize = ListSize;
|
|
RequirementsList->AlternativeLists = 1;
|
|
RequirementsList->List[0].Version = 1;
|
|
RequirementsList->List[0].Revision = 1;
|
|
RequirementsList->List[0].Count = PCIIDE_LEGACY_RESOURCE_COUNT;
|
|
|
|
if (IS_PRIMARY_CHANNEL(PdoExtension))
|
|
{
|
|
CommandPortBase = PCIIDE_LEGACY_PRIMARY_COMMAND_BASE;
|
|
ControlPortBase = PCIIDE_LEGACY_PRIMARY_CONTROL_BASE;
|
|
InterruptVector = PCIIDE_LEGACY_PRIMARY_IRQ;
|
|
}
|
|
else
|
|
{
|
|
CommandPortBase = PCIIDE_LEGACY_SECONDARY_COMMAND_BASE;
|
|
ControlPortBase = PCIIDE_LEGACY_SECONDARY_CONTROL_BASE;
|
|
InterruptVector = PCIIDE_LEGACY_SECONDARY_IRQ;
|
|
}
|
|
|
|
Descriptor = &RequirementsList->List[0].Descriptors[0];
|
|
|
|
/* Command port base */
|
|
Descriptor->Type = CmResourceTypePort;
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
Descriptor->u.Port.Length = PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH;
|
|
Descriptor->u.Port.Alignment = 1;
|
|
Descriptor->u.Port.MinimumAddress.LowPart = CommandPortBase;
|
|
Descriptor->u.Port.MaximumAddress.LowPart = CommandPortBase +
|
|
PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH - 1;
|
|
++Descriptor;
|
|
|
|
/* Control port base */
|
|
Descriptor->Type = CmResourceTypePort;
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
Descriptor->u.Port.Length = PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH;
|
|
Descriptor->u.Port.Alignment = 1;
|
|
Descriptor->u.Port.MinimumAddress.LowPart = ControlPortBase;
|
|
Descriptor->u.Port.MaximumAddress.LowPart = ControlPortBase +
|
|
PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH - 1;
|
|
++Descriptor;
|
|
|
|
/* Interrupt */
|
|
Descriptor->Type = CmResourceTypeInterrupt;
|
|
Descriptor->ShareDisposition = CmResourceShareShared;
|
|
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
|
Descriptor->u.Interrupt.MinimumVector = InterruptVector;
|
|
Descriptor->u.Interrupt.MaximumVector = InterruptVector;
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
PCWSTR
|
|
PciIdeXGetControllerVendorId(
|
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
switch (FdoExtension->VendorId)
|
|
{
|
|
case 0x0E11:
|
|
return L"Compaq";
|
|
case 0x1039:
|
|
return L"SiS";
|
|
case 0x1050:
|
|
return L"WinBond";
|
|
case 0x1095:
|
|
return L"CMD";
|
|
case 0x10B9:
|
|
return L"ALi";
|
|
case 0x8086:
|
|
return L"Intel";
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Only certain controllers have a non-numeric identifier */
|
|
return NULL;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
PCWSTR
|
|
PciIdeXGetControllerDeviceId(
|
|
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
/* Intel */
|
|
if (FdoExtension->VendorId == 0x8086)
|
|
{
|
|
switch (FdoExtension->DeviceId)
|
|
{
|
|
case 0x1230:
|
|
return L"PIIX";
|
|
case 0x7010:
|
|
return L"PIIX3";
|
|
case 0x7111:
|
|
return L"PIIX4";
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryId(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
NTSTATUS Status;
|
|
PWCHAR Buffer, End;
|
|
size_t CharCount, Remaining;
|
|
static const WCHAR IdeCompatibleId[] = L"*PNP0600";
|
|
|
|
PAGED_CODE();
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
switch (IoStack->Parameters.QueryId.IdType)
|
|
{
|
|
case BusQueryDeviceID:
|
|
{
|
|
static const WCHAR PciIdeDeviceId[] = L"PCIIDE\\IDEChannel";
|
|
|
|
Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(PciIdeDeviceId), TAG_PCIIDEX);
|
|
if (!Buffer)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCopyMemory(Buffer, PciIdeDeviceId, sizeof(PciIdeDeviceId));
|
|
|
|
DPRINT("Device ID: '%S'\n", Buffer);
|
|
break;
|
|
}
|
|
|
|
case BusQueryHardwareIDs:
|
|
{
|
|
PFDO_DEVICE_EXTENSION FdoExtension;
|
|
PCWSTR VendorString;
|
|
PWCHAR IdStart;
|
|
|
|
DBG_UNREFERENCED_LOCAL_VARIABLE(IdStart);
|
|
|
|
/* Maximum string length */
|
|
CharCount = sizeof("WinBond-1234") +
|
|
sizeof("Secondary_IDE_Channel") +
|
|
sizeof(IdeCompatibleId) +
|
|
sizeof(ANSI_NULL); /* multi-string */
|
|
|
|
Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
CharCount * sizeof(WCHAR),
|
|
TAG_PCIIDEX);
|
|
if (!Buffer)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
FdoExtension = PdoExtension->ParentController;
|
|
VendorString = PciIdeXGetControllerVendorId(FdoExtension);
|
|
|
|
DPRINT("HardwareIDs:\n");
|
|
|
|
/* ID 1 */
|
|
if (VendorString)
|
|
{
|
|
PCWSTR DeviceString = PciIdeXGetControllerDeviceId(FdoExtension);
|
|
|
|
if (DeviceString)
|
|
{
|
|
Status = RtlStringCchPrintfExW(Buffer,
|
|
CharCount,
|
|
&End,
|
|
&Remaining,
|
|
0,
|
|
L"%ls-%ls",
|
|
VendorString,
|
|
DeviceString);
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringCchPrintfExW(Buffer,
|
|
CharCount,
|
|
&End,
|
|
&Remaining,
|
|
0,
|
|
L"%ls-%04x",
|
|
VendorString,
|
|
FdoExtension->DeviceId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringCchPrintfExW(Buffer,
|
|
CharCount,
|
|
&End,
|
|
&Remaining,
|
|
0,
|
|
L"%04x-%04x",
|
|
FdoExtension->VendorId,
|
|
FdoExtension->DeviceId);
|
|
}
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
DPRINT(" '%S'\n", Buffer);
|
|
|
|
++End;
|
|
--Remaining;
|
|
|
|
/* ID 2 */
|
|
IdStart = End;
|
|
Status = RtlStringCchPrintfExW(End,
|
|
Remaining,
|
|
&End,
|
|
&Remaining,
|
|
0,
|
|
L"%ls",
|
|
IS_PRIMARY_CHANNEL(PdoExtension) ?
|
|
L"Primary_IDE_Channel" :
|
|
L"Secondary_IDE_Channel");
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
DPRINT(" '%S'\n", IdStart);
|
|
|
|
++End;
|
|
--Remaining;
|
|
|
|
/* ID 3 */
|
|
IdStart = End;
|
|
Status = RtlStringCchPrintfExW(End,
|
|
Remaining,
|
|
&End,
|
|
&Remaining,
|
|
0,
|
|
L"%ls",
|
|
IdeCompatibleId);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
DPRINT(" '%S'\n", IdStart);
|
|
|
|
*++End = UNICODE_NULL; /* multi-string */
|
|
break;
|
|
}
|
|
|
|
case BusQueryCompatibleIDs:
|
|
{
|
|
Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
sizeof(IdeCompatibleId) + sizeof(UNICODE_NULL),
|
|
TAG_PCIIDEX);
|
|
if (!Buffer)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCopyMemory(Buffer, IdeCompatibleId, sizeof(IdeCompatibleId));
|
|
|
|
Buffer[sizeof(IdeCompatibleId) / sizeof(WCHAR)] = UNICODE_NULL; /* multi-string */
|
|
|
|
DPRINT("Compatible ID: '%S'\n", Buffer);
|
|
break;
|
|
}
|
|
|
|
case BusQueryInstanceID:
|
|
{
|
|
CharCount = sizeof("0");
|
|
|
|
Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
CharCount * sizeof(WCHAR),
|
|
TAG_PCIIDEX);
|
|
if (!Buffer)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
Status = RtlStringCchPrintfExW(Buffer,
|
|
CharCount,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
L"%lu",
|
|
PdoExtension->Channel);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
DPRINT("Instance ID: '%S'\n", Buffer);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryDeviceText(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PWCHAR Buffer;
|
|
ULONG Size;
|
|
|
|
PAGED_CODE();
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
switch (IoStack->Parameters.QueryDeviceText.DeviceTextType)
|
|
{
|
|
case DeviceTextLocationInformation:
|
|
{
|
|
static const WCHAR PrimaryChannelText[] = L"Primary channel";
|
|
static const WCHAR SecondaryChannelText[] = L"Secondary channel";
|
|
|
|
if (IS_PRIMARY_CHANNEL(PdoExtension))
|
|
Size = sizeof(PrimaryChannelText);
|
|
else
|
|
Size = sizeof(SecondaryChannelText);
|
|
|
|
Buffer = ExAllocatePoolWithTag(PagedPool, Size, TAG_PCIIDEX);
|
|
if (!Buffer)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCopyMemory(Buffer,
|
|
IS_PRIMARY_CHANNEL(PdoExtension) ?
|
|
PrimaryChannelText : SecondaryChannelText,
|
|
Size);
|
|
|
|
DPRINT("Device ID: '%S'\n", Buffer);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoQueryDeviceUsageNotification(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
NTSTATUS Status;
|
|
volatile LONG* Counter;
|
|
|
|
PAGED_CODE();
|
|
|
|
Status = PciIdeXPdoRepeatRequest(PdoExtension, Irp, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
switch (IoStack->Parameters.UsageNotification.Type)
|
|
{
|
|
case DeviceUsageTypePaging:
|
|
Counter = &PdoExtension->Common.PageFiles;
|
|
break;
|
|
|
|
case DeviceUsageTypeHibernation:
|
|
Counter = &PdoExtension->Common.HibernateFiles;
|
|
break;
|
|
|
|
case DeviceUsageTypeDumpFile:
|
|
Counter = &PdoExtension->Common.DumpFiles;
|
|
break;
|
|
|
|
default:
|
|
return Status;
|
|
}
|
|
|
|
IoAdjustPagingPathCount(Counter, IoStack->Parameters.UsageNotification.InPath);
|
|
IoInvalidateDeviceState(PdoExtension->Common.Self);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
PciIdeXPdoDispatchPnp(
|
|
_In_ PPDO_DEVICE_EXTENSION PdoExtension,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
NTSTATUS Status;
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
PAGED_CODE();
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
switch (IoStack->MinorFunction)
|
|
{
|
|
case IRP_MN_START_DEVICE:
|
|
Status = PciIdeXPdoStartDevice(PdoExtension,
|
|
IoStack->Parameters.StartDevice.AllocatedResources);
|
|
break;
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
Status = PciIdeXPdoStopDevice(PdoExtension);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
Status = PciIdeXPdoQueryStopRemoveDevice(PdoExtension);
|
|
break;
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
Status = PciIdeXPdoRemoveDevice(PdoExtension,
|
|
IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
|
|
Status = PciIdeXPdoQueryTargetDeviceRelations(PdoExtension, Irp);
|
|
else
|
|
Status = Irp->IoStatus.Status;
|
|
break;
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
Status = PciIdeXPdoQueryCapabilities(PdoExtension, Irp);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
|
Status = PciIdeXPdoQueryPnpDeviceState(PdoExtension, Irp);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
Status = PciIdeXPdoQueryResources(PdoExtension, Irp);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
|
Status = PciIdeXPdoQueryResourceRequirements(PdoExtension, Irp);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_ID:
|
|
Status = PciIdeXPdoQueryId(PdoExtension, Irp);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
|
Status = PciIdeXPdoQueryDeviceText(PdoExtension, Irp);
|
|
break;
|
|
|
|
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
|
|
Status = PciIdeXPdoQueryDeviceUsageNotification(PdoExtension, Irp);
|
|
break;
|
|
|
|
default:
|
|
Status = Irp->IoStatus.Status;
|
|
break;
|
|
}
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
NTAPI
|
|
PciIdeXDispatchPnp(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
if (IS_FDO(DeviceObject->DeviceExtension))
|
|
return PciIdeXFdoDispatchPnp(DeviceObject->DeviceExtension, Irp);
|
|
else
|
|
return PciIdeXPdoDispatchPnp(DeviceObject->DeviceExtension, Irp);
|
|
}
|