mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 07:08:19 +00:00
403 lines
12 KiB
C
403 lines
12 KiB
C
/*
|
|
* PROJECT: ReactOS Generic CPU Driver
|
|
* LICENSE: GNU GPLv2 only as published by the Free Software Foundation
|
|
* FILE: drivers/processor/processr/pnp.c
|
|
* PURPOSE: Plug N Play routines
|
|
* PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include "processr.h"
|
|
|
|
#include <stdio.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
static
|
|
NTSTATUS
|
|
GetDeviceId(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
BUS_QUERY_ID_TYPE IdType,
|
|
PWSTR *DeviceId)
|
|
{
|
|
PIO_STACK_LOCATION IrpStack;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
PDEVICE_OBJECT TargetObject;
|
|
KEVENT Event;
|
|
PIRP Irp;
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
/* Initialize the event */
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
TargetObject = IoGetAttachedDeviceReference(DeviceObject);
|
|
|
|
/* Build the IRP */
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
|
|
TargetObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&Event,
|
|
&IoStatus);
|
|
if (Irp == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
/* PNP IRPs all begin life as STATUS_NOT_SUPPORTED */
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
/* Get the top of stack */
|
|
IrpStack = IoGetNextIrpStackLocation(Irp);
|
|
|
|
/* Set the top of stack */
|
|
RtlZeroMemory(IrpStack, sizeof(IO_STACK_LOCATION));
|
|
IrpStack->MajorFunction = IRP_MJ_PNP;
|
|
IrpStack->MinorFunction = IRP_MN_QUERY_ID;
|
|
IrpStack->Parameters.QueryId.IdType = IdType;
|
|
|
|
/* Call the driver */
|
|
Status = IoCallDriver(TargetObject, Irp);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&Event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
|
|
Status = IoStatus.Status;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*DeviceId = (PWSTR)IoStatus.Information;
|
|
}
|
|
|
|
done:
|
|
/* Dereference the target device object */
|
|
ObDereferenceObject(TargetObject);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
static
|
|
VOID
|
|
ProcessorSetFriendlyName(
|
|
PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
KEY_VALUE_PARTIAL_INFORMATION *Buffer = NULL;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING HardwareKeyName, ValueName, EnumKeyName;
|
|
HANDLE KeyHandle = NULL;
|
|
ULONG DataLength = 0;
|
|
ULONG BufferLength = 0;
|
|
NTSTATUS Status;
|
|
PWSTR KeyNameBuffer = NULL;
|
|
PWSTR DeviceId = NULL;
|
|
PWSTR InstanceId = NULL;
|
|
PWSTR pszPrefix = L"\\Registry\\Machine\\System\\CurrentcontrolSet\\Enum";
|
|
|
|
RtlInitUnicodeString(&HardwareKeyName,
|
|
L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&HardwareKeyName,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
NULL);
|
|
Status = ZwOpenKey(&KeyHandle,
|
|
KEY_READ,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString(&ValueName,
|
|
L"ProcessorNameString");
|
|
Status = ZwQueryValueKey(KeyHandle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
NULL,
|
|
0,
|
|
&DataLength);
|
|
if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_SUCCESS)
|
|
{
|
|
DPRINT1("ZwQueryValueKey() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Buffer = ExAllocatePool(PagedPool,
|
|
DataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION));
|
|
if (Buffer == NULL)
|
|
{
|
|
DPRINT1("ExAllocatePool() failed\n");
|
|
goto done;
|
|
}
|
|
|
|
Status = ZwQueryValueKey(KeyHandle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
Buffer,
|
|
DataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION),
|
|
&DataLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ZwQueryValueKey() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
DPRINT("ProcessorNameString: %S\n", (PWSTR)&Buffer->Data[0]);
|
|
|
|
ZwClose(KeyHandle);
|
|
KeyHandle = NULL;
|
|
|
|
Status = GetDeviceId(DeviceObject,
|
|
BusQueryDeviceID,
|
|
&DeviceId);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("GetDeviceId() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
DPRINT("DeviceId: %S\n", DeviceId);
|
|
|
|
Status = GetDeviceId(DeviceObject,
|
|
BusQueryInstanceID,
|
|
&InstanceId);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("GetDeviceId() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
DPRINT("InstanceId: %S\n", InstanceId);
|
|
|
|
BufferLength = wcslen(pszPrefix) + 1 + wcslen(DeviceId) + 1 + wcslen(InstanceId) + 1;
|
|
|
|
KeyNameBuffer = ExAllocatePool(PagedPool, BufferLength * sizeof(WCHAR));
|
|
if (KeyNameBuffer == NULL)
|
|
{
|
|
DPRINT1("ExAllocatePool() failed\n");
|
|
goto done;
|
|
}
|
|
|
|
swprintf(KeyNameBuffer, L"%s\\%s\\%s", pszPrefix, DeviceId, InstanceId);
|
|
|
|
RtlInitUnicodeString(&EnumKeyName, KeyNameBuffer);
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&EnumKeyName,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
NULL);
|
|
Status = ZwOpenKey(&KeyHandle,
|
|
KEY_WRITE,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitUnicodeString(&ValueName,
|
|
L"FriendlyName");
|
|
Status = ZwSetValueKey(KeyHandle,
|
|
&ValueName,
|
|
0,
|
|
REG_SZ,
|
|
(PVOID)&Buffer->Data[0],
|
|
Buffer->DataLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ZwSetValueKey() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
if (KeyHandle != NULL)
|
|
ZwClose(KeyHandle);
|
|
|
|
if (KeyNameBuffer != NULL)
|
|
ExFreePool(KeyNameBuffer);
|
|
|
|
if (InstanceId != NULL)
|
|
ExFreePool(InstanceId);
|
|
|
|
if (DeviceId != NULL)
|
|
ExFreePool(DeviceId);
|
|
|
|
if (Buffer != NULL)
|
|
ExFreePool(Buffer);
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
ProcessorStartDevice(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PCM_RESOURCE_LIST ResourceList,
|
|
IN PCM_RESOURCE_LIST ResourceListTranslated)
|
|
{
|
|
DPRINT("ProcessorStartDevice()\n");
|
|
|
|
ProcessorSetFriendlyName(DeviceObject);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
ProcessorPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp;
|
|
ULONG_PTR Information = 0;
|
|
NTSTATUS Status = STATUS_NOT_SUPPORTED;
|
|
|
|
DPRINT("ProcessorPnp()\n");
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
switch (IrpSp->MinorFunction)
|
|
{
|
|
case IRP_MN_START_DEVICE:
|
|
DPRINT(" IRP_MN_START_DEVICE received\n");
|
|
|
|
/* Call lower driver */
|
|
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = ProcessorStartDevice(DeviceObject,
|
|
IrpSp->Parameters.StartDevice.AllocatedResources,
|
|
IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
DPRINT(" IRP_MN_QUERY_REMOVE_DEVICE\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
DPRINT(" IRP_MN_REMOVE_DEVICE received\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
DPRINT(" IRP_MN_CANCEL_REMOVE_DEVICE\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
DPRINT(" IRP_MN_STOP_DEVICE received\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
DPRINT(" IRP_MN_QUERY_STOP_DEVICE received\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
DPRINT(" IRP_MN_CANCEL_STOP_DEVICE\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
DPRINT(" IRP_MN_QUERY_DEVICE_RELATIONS\n");
|
|
|
|
switch (IrpSp->Parameters.QueryDeviceRelations.Type)
|
|
{
|
|
case BusRelations:
|
|
DPRINT(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
break;
|
|
|
|
case RemovalRelations:
|
|
DPRINT(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
default:
|
|
DPRINT(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
|
|
IrpSp->Parameters.QueryDeviceRelations.Type);
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
|
DPRINT(" IRP_MN_SURPRISE_REMOVAL received\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* (optional) 0xd */
|
|
DPRINT(" IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
default:
|
|
DPRINT(" Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
}
|
|
|
|
Irp->IoStatus.Information = Information;
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
ProcessorAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo)
|
|
{
|
|
PDEVICE_EXTENSION DeviceExtension = NULL;
|
|
PDEVICE_OBJECT Fdo = NULL;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("ProcessorAddDevice()\n");
|
|
|
|
ASSERT(DriverObject);
|
|
ASSERT(Pdo);
|
|
|
|
/* Create functional device object */
|
|
Status = IoCreateDevice(DriverObject,
|
|
sizeof(DEVICE_EXTENSION),
|
|
NULL,
|
|
FILE_DEVICE_UNKNOWN,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
FALSE,
|
|
&Fdo);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
DeviceExtension = (PDEVICE_EXTENSION)Fdo->DeviceExtension;
|
|
RtlZeroMemory(DeviceExtension, sizeof(DEVICE_EXTENSION));
|
|
|
|
DeviceExtension->DeviceObject = Fdo;
|
|
|
|
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
|
|
IoDeleteDevice(Fdo);
|
|
return Status;
|
|
}
|
|
|
|
Fdo->Flags |= DO_DIRECT_IO;
|
|
Fdo->Flags |= DO_POWER_PAGABLE;
|
|
|
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/* EOF */
|