You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1932 lines
48 KiB
1932 lines
48 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ixpnpdrv.c
|
|
|
|
Abstract:
|
|
|
|
Implements functionality necessary for the
|
|
HAL to become a PnP-style device driver
|
|
after system initialization. This is done
|
|
so that the HAL can enumerate the ACPI driver
|
|
in the way that the PnP stuff expects.
|
|
|
|
Author:
|
|
|
|
Jake Oshins (jakeo) 27-Jan-1997
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "halp.h"
|
|
#include "acpitabl.h"
|
|
#include "exboosts.h"
|
|
#include "wchar.h"
|
|
#include "xxacpi.h"
|
|
|
|
//
|
|
// Cause the GUID to be defined.
|
|
//
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma const_seg("PAGECONST")
|
|
#endif // ALLOC_DATA_PRAGMA
|
|
#include "initguid.h"
|
|
#include "wdmguid.h"
|
|
#include "halpnpp.h"
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma const_seg()
|
|
#endif // ALLOC_DATA_PRAGMA
|
|
|
|
#if DBG
|
|
ULONG HalDebug = 0;
|
|
#endif
|
|
|
|
|
|
extern WCHAR HalHardwareIdString[];
|
|
#if defined(NT_UP) && defined(APIC_HAL)
|
|
extern WCHAR MpHalHardwareIdString[];
|
|
#endif
|
|
|
|
typedef enum {
|
|
Hal = 0x80,
|
|
AcpiDriver,
|
|
WdDriver
|
|
} PDO_TYPE;
|
|
|
|
typedef enum {
|
|
PdoExtensionType = 0xc0,
|
|
FdoExtensionType
|
|
} EXTENSION_TYPE;
|
|
|
|
typedef struct _PDO_EXTENSION *PPDO_EXTENSION;
|
|
typedef struct _FDO_EXTENSION *PFDO_EXTENSION;
|
|
|
|
typedef struct _PDO_EXTENSION{
|
|
EXTENSION_TYPE ExtensionType;
|
|
PPDO_EXTENSION Next;
|
|
PDEVICE_OBJECT PhysicalDeviceObject;
|
|
PFDO_EXTENSION ParentFdoExtension;
|
|
PDO_TYPE PdoType;
|
|
//
|
|
// Only valid if PdoType == WdDriver
|
|
//
|
|
PWATCHDOG_TIMER_RESOURCE_TABLE WdTable;
|
|
} PDO_EXTENSION, *PPDO_EXTENSION;
|
|
|
|
#define ASSERT_PDO_EXTENSION(x) ASSERT((x)->ExtensionType == PdoExtensionType );
|
|
|
|
typedef struct _FDO_EXTENSION{
|
|
EXTENSION_TYPE ExtensionType;
|
|
PPDO_EXTENSION ChildPdoList;
|
|
PDEVICE_OBJECT PhysicalDeviceObject; // PDO passed into AddDevice()
|
|
PDEVICE_OBJECT FunctionalDeviceObject;
|
|
PDEVICE_OBJECT AttachedDeviceObject;
|
|
} FDO_EXTENSION, *PFDO_EXTENSION;
|
|
|
|
#define ASSERT_FDO_EXTENSION(x) ASSERT((x)->ExtensionType == FdoExtensionType );
|
|
|
|
INT_ROUTE_INTERFACE_STANDARD PciIrqRoutingInterface = {0};
|
|
|
|
NTSTATUS
|
|
HalpDriverEntry (
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpDispatchWmi(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryDeviceRelations(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN DEVICE_RELATION_TYPE RelationType,
|
|
OUT PDEVICE_RELATIONS *DeviceRelations
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryIdPdo(
|
|
IN PDEVICE_OBJECT PdoExtension,
|
|
IN BUS_QUERY_ID_TYPE IdType,
|
|
IN OUT PWSTR *BusQueryId
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryIdFdo(
|
|
IN PDEVICE_OBJECT PdoExtension,
|
|
IN BUS_QUERY_ID_TYPE IdType,
|
|
IN OUT PWSTR *BusQueryId
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryCapabilities(
|
|
IN PDEVICE_OBJECT PdoExtension,
|
|
IN PDEVICE_CAPABILITIES Capabilities
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryResources(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PCM_RESOURCE_LIST *Resources
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryResourceRequirements(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryInterface(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN LPCGUID InterfaceType,
|
|
IN USHORT Version,
|
|
IN PVOID InterfaceSpecificData,
|
|
IN ULONG InterfaceBufferSize,
|
|
IN OUT PINTERFACE Interface,
|
|
IN OUT PULONG_PTR Length
|
|
);
|
|
|
|
#if defined(_WIN64)
|
|
|
|
//
|
|
// Define the PNP interface functions.
|
|
//
|
|
|
|
VOID
|
|
HalPnpInterfaceReference(
|
|
PVOID Context
|
|
);
|
|
|
|
VOID
|
|
HalPnpInterfaceDereference(
|
|
PVOID Context
|
|
);
|
|
|
|
struct _DMA_ADAPTER *
|
|
HalPnpGetDmaAdapter(
|
|
IN PVOID Context,
|
|
IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
|
|
OUT PULONG NumberOfMapRegisters
|
|
);
|
|
|
|
#endif // _WIN64
|
|
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResourcesRoot(
|
|
IN PVOID Context,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|
IN ULONG AlternativesCount, OPTIONAL
|
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResourceRequirementsRoot(
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
);
|
|
|
|
VOID
|
|
HalpMaskAcpiInterrupt(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpUnmaskAcpiInterrupt(
|
|
VOID
|
|
);
|
|
|
|
// from xxacpi.c
|
|
NTSTATUS
|
|
HalpQueryAcpiResourceRequirements(
|
|
IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpOpenRegistryKey(
|
|
OUT PHANDLE Handle,
|
|
IN HANDLE BaseHandle OPTIONAL,
|
|
IN PUNICODE_STRING KeyName,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN BOOLEAN Create
|
|
);
|
|
|
|
PVOID
|
|
HalpGetAcpiTable(
|
|
IN ULONG Signature
|
|
);
|
|
|
|
#ifdef ACPI_CMOS_ACTIVATE
|
|
VOID
|
|
HalpCmosNullReference(
|
|
PVOID Context
|
|
);
|
|
|
|
VOID
|
|
HalpCmosNullDereference(
|
|
PVOID Context
|
|
);
|
|
#endif // ACPI_CMOS_ACTIVATE
|
|
|
|
#define HAL_DRIVER_NAME L"\\Driver\\ACPI_HAL"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, HaliInitPnpDriver)
|
|
#pragma alloc_text(PAGE, HalpOpenRegistryKey)
|
|
#pragma alloc_text(PAGE, HalpDriverEntry)
|
|
#pragma alloc_text(PAGE, HalpAddDevice)
|
|
#pragma alloc_text(PAGE, HalpDispatchPnp)
|
|
#pragma alloc_text(PAGELK, HalpDispatchPower)
|
|
#pragma alloc_text(PAGE, HalpDispatchWmi)
|
|
#pragma alloc_text(PAGE, HalpQueryDeviceRelations)
|
|
#pragma alloc_text(PAGE, HalpQueryIdPdo)
|
|
#pragma alloc_text(PAGE, HalpQueryIdFdo)
|
|
#pragma alloc_text(PAGE, HalpQueryCapabilities)
|
|
#pragma alloc_text(PAGE, HalpQueryResources)
|
|
#pragma alloc_text(PAGE, HalpQueryResourceRequirements)
|
|
#pragma alloc_text(PAGE, HalpQueryInterface)
|
|
#endif
|
|
|
|
PDRIVER_OBJECT HalpDriverObject;
|
|
|
|
|
|
NTSTATUS
|
|
HaliInitPnpDriver(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine starts the process of making the HAL into
|
|
a "driver," which is necessary because we need to
|
|
enumerate a Plug and Play PDO for the ACPI driver.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--*/
|
|
{
|
|
|
|
UNICODE_STRING DriverName;
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
RtlInitUnicodeString( &DriverName, HAL_DRIVER_NAME );
|
|
|
|
Status = IoCreateDriver( &DriverName, HalpDriverEntry );
|
|
|
|
ASSERT( NT_SUCCESS( Status ));
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpOpenRegistryKey(
|
|
OUT PHANDLE Handle,
|
|
IN HANDLE BaseHandle OPTIONAL,
|
|
IN PUNICODE_STRING KeyName,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN BOOLEAN Create
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens or creates a VOLATILE registry key using the name passed in based
|
|
at the BaseHandle node.
|
|
|
|
Arguments:
|
|
|
|
Handle - Pointer to the handle which will contain the registry key that
|
|
was opened.
|
|
|
|
BaseHandle - Handle to the base path from which the key must be opened.
|
|
|
|
KeyName - Name of the Key that must be opened/created.
|
|
|
|
DesiredAccess - Specifies the desired access that the caller needs to
|
|
the key.
|
|
|
|
Create - Determines if the key is to be created if it does not exist.
|
|
|
|
Return Value:
|
|
|
|
The function value is the final status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
ULONG disposition;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Initialize the object for the key.
|
|
//
|
|
|
|
InitializeObjectAttributes( &objectAttributes,
|
|
KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
BaseHandle,
|
|
(PSECURITY_DESCRIPTOR) NULL );
|
|
|
|
//
|
|
// Create the key or open it, as appropriate based on the caller's
|
|
// wishes.
|
|
//
|
|
|
|
if (Create) {
|
|
return ZwCreateKey( Handle,
|
|
DesiredAccess,
|
|
&objectAttributes,
|
|
0,
|
|
(PUNICODE_STRING) NULL,
|
|
REG_OPTION_VOLATILE,
|
|
&disposition );
|
|
} else {
|
|
return ZwOpenKey( Handle,
|
|
DesiredAccess,
|
|
&objectAttributes );
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpDriverEntry (
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the callback function when we call IoCreateDriver to create a
|
|
PnP Driver Object. In this function, we need to remember the DriverObject.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the driver object created by the system.
|
|
|
|
RegistryPath - is NULL.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PDEVICE_OBJECT detectedDeviceObject = NULL;
|
|
ANSI_STRING AKeyName;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// File the pointer to our driver object away
|
|
//
|
|
HalpDriverObject = DriverObject;
|
|
|
|
//
|
|
// Fill in the driver object
|
|
//
|
|
DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)HalpAddDevice;
|
|
DriverObject->MajorFunction[ IRP_MJ_PNP ] = HalpDispatchPnp;
|
|
DriverObject->MajorFunction[ IRP_MJ_POWER ] = HalpDispatchPower;
|
|
DriverObject->MajorFunction[ IRP_MJ_SYSTEM_CONTROL ] = HalpDispatchWmi;
|
|
|
|
status = IoReportDetectedDevice(DriverObject,
|
|
InterfaceTypeUndefined,
|
|
-1,
|
|
-1,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
&detectedDeviceObject);
|
|
|
|
ASSERT(detectedDeviceObject);
|
|
if (!(NT_SUCCESS(status))) {
|
|
return status;
|
|
}
|
|
|
|
HalpAddDevice(DriverObject,
|
|
detectedDeviceObject);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles AddDevice for an madeup PDO device.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to our pseudo driver object.
|
|
|
|
DeviceObject - Pointer to the device object for which this requestapplies.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_OBJECT functionalDeviceObject;
|
|
PDEVICE_OBJECT acpiChildDeviceObject;
|
|
PDEVICE_OBJECT wdChildDeviceObject;
|
|
PDEVICE_OBJECT AttachedDevice;
|
|
NTSTATUS status;
|
|
PFDO_EXTENSION FdoExtension;
|
|
PPDO_EXTENSION AcpiPdoExtension;
|
|
PPDO_EXTENSION WdPdoExtension;
|
|
PWATCHDOG_TIMER_RESOURCE_TABLE WdTable;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// We've been given the PhysicalDeviceObject. Create the
|
|
// FunctionalDeviceObject. Our FDO will be nameless.
|
|
//
|
|
|
|
status = IoCreateDevice(
|
|
DriverObject, // our driver object
|
|
sizeof(FDO_EXTENSION), // size of our extension
|
|
NULL, // our name
|
|
FILE_DEVICE_BUS_EXTENDER, // device type
|
|
0, // device characteristics
|
|
FALSE, // not exclusive
|
|
&functionalDeviceObject // store new device object here
|
|
);
|
|
|
|
if( !NT_SUCCESS( status )){
|
|
|
|
DbgBreakPoint();
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Fill in the FDO extension
|
|
//
|
|
FdoExtension = (PFDO_EXTENSION)functionalDeviceObject->DeviceExtension;
|
|
FdoExtension->ExtensionType = FdoExtensionType;
|
|
FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
|
FdoExtension->FunctionalDeviceObject = functionalDeviceObject;
|
|
|
|
functionalDeviceObject->Flags &= ~(DO_DEVICE_INITIALIZING);
|
|
|
|
//
|
|
// Now attach to the PDO we were given.
|
|
//
|
|
|
|
AttachedDevice = IoAttachDeviceToDeviceStack(functionalDeviceObject,
|
|
PhysicalDeviceObject );
|
|
if(AttachedDevice == NULL){
|
|
|
|
//
|
|
// Couldn't attach. Delete the FDO.
|
|
//
|
|
|
|
IoDeleteDevice( functionalDeviceObject );
|
|
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
|
|
}
|
|
|
|
FdoExtension->AttachedDeviceObject = AttachedDevice;
|
|
|
|
//
|
|
// Next, create a PDO for the ACPI driver.
|
|
//
|
|
status = IoCreateDevice(
|
|
DriverObject, // our driver object
|
|
sizeof(PDO_EXTENSION), // size of our extension
|
|
NULL, // our name
|
|
FILE_DEVICE_BUS_EXTENDER, // device type
|
|
FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics
|
|
FALSE, // not exclusive
|
|
&acpiChildDeviceObject // store new device object here
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
HalPrint(("Could not create ACPI device object status=0x%08x",status));
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Fill in the PDO extension
|
|
//
|
|
AcpiPdoExtension = (PPDO_EXTENSION)acpiChildDeviceObject->DeviceExtension;
|
|
AcpiPdoExtension->ExtensionType = PdoExtensionType;
|
|
AcpiPdoExtension->Next = NULL;
|
|
AcpiPdoExtension->PhysicalDeviceObject = acpiChildDeviceObject;
|
|
AcpiPdoExtension->ParentFdoExtension = FdoExtension;
|
|
AcpiPdoExtension->PdoType = AcpiDriver;
|
|
|
|
//
|
|
// Look for the watchdog timer ACPI table
|
|
// and if it is found then eject a PDO to handle the device
|
|
//
|
|
WdTable = (PWATCHDOG_TIMER_RESOURCE_TABLE) HalpGetAcpiTable( WDTT_SIGNATURE );
|
|
if (WdTable) {
|
|
|
|
//
|
|
// Next, create a PDO for the WD driver.
|
|
//
|
|
status = IoCreateDevice(
|
|
DriverObject, // our driver object
|
|
sizeof(PDO_EXTENSION), // size of our extension
|
|
NULL, // our name
|
|
FILE_DEVICE_BUS_EXTENDER, // device type
|
|
FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics
|
|
FALSE, // not exclusive
|
|
&wdChildDeviceObject // store new device object here
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
HalPrint(("Could not create WD device object status=0x%08x",status));
|
|
IoDeleteDevice( acpiChildDeviceObject );
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Fill in the PDO extension
|
|
//
|
|
WdPdoExtension = (PPDO_EXTENSION)wdChildDeviceObject->DeviceExtension;
|
|
WdPdoExtension->ExtensionType = PdoExtensionType;
|
|
WdPdoExtension->Next = NULL;
|
|
WdPdoExtension->PhysicalDeviceObject = wdChildDeviceObject;
|
|
WdPdoExtension->ParentFdoExtension = FdoExtension;
|
|
WdPdoExtension->PdoType = WdDriver;
|
|
WdPdoExtension->WdTable = WdTable;
|
|
|
|
//
|
|
// Link in the device extension
|
|
//
|
|
AcpiPdoExtension->Next = WdPdoExtension;
|
|
|
|
wdChildDeviceObject->Flags &= ~(DO_DEVICE_INITIALIZING);
|
|
}
|
|
|
|
acpiChildDeviceObject->Flags &= ~(DO_DEVICE_INITIALIZING);
|
|
|
|
//
|
|
// Record this as a child of the HAL
|
|
//
|
|
FdoExtension->ChildPdoList = AcpiPdoExtension;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpPassIrpFromFdoToPdo(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Given an FDO, pass the IRP to the next device object in the
|
|
device stack. This is the PDO if there are no lower level
|
|
filters.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - the Fdo
|
|
Irp - the request
|
|
|
|
Return Value:
|
|
|
|
Returns the result from calling the next level.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION irpSp; // our stack location
|
|
PIO_STACK_LOCATION nextIrpSp; // next guy's
|
|
PFDO_EXTENSION fdoExtension;
|
|
|
|
//
|
|
// Get the pointer to the device extension.
|
|
//
|
|
|
|
fdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
//
|
|
// Call the PDO driver with the request.
|
|
//
|
|
|
|
return IoCallDriver(fdoExtension->AttachedDeviceObject ,Irp);
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles all IRP_MJ_PNP IRPs for madeup PDO device.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object for which this IRP applies.
|
|
|
|
Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpSp;
|
|
NTSTATUS status;
|
|
ULONG length;
|
|
DEVICE_RELATION_TYPE relationType;
|
|
EXTENSION_TYPE extensionType;
|
|
BOOLEAN passDown;
|
|
#if DBG
|
|
PUCHAR objectTypeString;
|
|
#endif //DBG
|
|
|
|
PAGED_CODE();
|
|
|
|
extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
|
|
|
|
//
|
|
// Get a pointer to our stack location and take appropriate action based
|
|
// on the minor function.
|
|
//
|
|
|
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
status = Irp->IoStatus.Status;
|
|
switch (extensionType) {
|
|
|
|
case PdoExtensionType:
|
|
|
|
#if DBG
|
|
objectTypeString = "PDO";
|
|
#endif //DBG
|
|
|
|
switch (irpSp->MinorFunction) {
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
HalPrint(("HAL: (%s) Start_Device Irp received\n",
|
|
objectTypeString));
|
|
|
|
//
|
|
// If we get a start device request for a PDO, we simply
|
|
// return success.
|
|
//
|
|
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
|
|
HalPrint(("(%s) Query_Stop_Device Irp received",
|
|
objectTypeString));
|
|
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
|
|
HalPrint(("(%s) Cancel_Stop_Device Irp received",
|
|
objectTypeString));
|
|
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
|
|
HalPrint(("HAL: (%s) Stop_Device Irp received\n",
|
|
objectTypeString));
|
|
|
|
//
|
|
// If we get a stop device request for a PDO, we simply
|
|
// return success.
|
|
//
|
|
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
|
|
HalPrint(("HAL: (%s) Query_Resources Irp received\n",
|
|
objectTypeString));
|
|
|
|
status = HalpQueryResources(DeviceObject,
|
|
(PCM_RESOURCE_LIST*)&Irp->IoStatus.Information);
|
|
|
|
break;
|
|
|
|
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
|
|
|
HalPrint(("HAL: (%s) Query_Resource_Requirements Irp received\n",
|
|
objectTypeString));
|
|
|
|
status = HalpQueryResourceRequirements(DeviceObject,
|
|
(PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->IoStatus.Information);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
|
|
HalPrint(("(%s) Query_Remove_device Irp for %x",
|
|
objectTypeString,
|
|
DeviceObject));
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
|
|
HalPrint(("(%s) Cancel_Remove_device Irp for %x",
|
|
objectTypeString,
|
|
DeviceObject));
|
|
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
|
|
HalPrint(("HAL: (%s) Remove_device Irp for PDO %x\n",
|
|
objectTypeString,
|
|
DeviceObject));
|
|
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
|
|
HalPrint(("HAL: (%s) Query_Device_Relations Irp received\n",
|
|
objectTypeString));
|
|
|
|
relationType = irpSp->Parameters.QueryDeviceRelations.Type;
|
|
status = HalpQueryDeviceRelations(DeviceObject,
|
|
relationType,
|
|
(PDEVICE_RELATIONS*)&Irp->IoStatus.Information);
|
|
break;
|
|
|
|
|
|
case IRP_MN_QUERY_ID:
|
|
|
|
HalPrint(("HAL: (%s) Query_Id Irp received\n",
|
|
objectTypeString));
|
|
|
|
status = HalpQueryIdPdo(DeviceObject,
|
|
irpSp->Parameters.QueryId.IdType,
|
|
(PWSTR*)&Irp->IoStatus.Information);
|
|
|
|
break;
|
|
|
|
case IRP_MN_QUERY_INTERFACE:
|
|
|
|
HalPrint(("HAL: (%s) Query_Interface Irp received\n",
|
|
objectTypeString));
|
|
|
|
status = HalpQueryInterface(
|
|
DeviceObject,
|
|
irpSp->Parameters.QueryInterface.InterfaceType,
|
|
irpSp->Parameters.QueryInterface.Version,
|
|
irpSp->Parameters.QueryInterface.InterfaceSpecificData,
|
|
irpSp->Parameters.QueryInterface.Size,
|
|
irpSp->Parameters.QueryInterface.Interface,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
|
|
HalPrint(("HAL: (%s) Query_Capabilities Irp received\n",
|
|
objectTypeString));
|
|
|
|
status = HalpQueryCapabilities(DeviceObject,
|
|
irpSp->Parameters.DeviceCapabilities.Capabilities);
|
|
|
|
break;
|
|
|
|
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
|
|
HalPrint(("HAL: DEVICE_USAGE Irp received\n"));
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
|
|
HalPrint(("HAL: (%s) Unsupported Irp (%d) received\n",
|
|
objectTypeString,
|
|
irpSp->MinorFunction));
|
|
status = STATUS_NOT_SUPPORTED ;
|
|
break;
|
|
}
|
|
|
|
break; // end PDO cases
|
|
|
|
case FdoExtensionType:
|
|
|
|
#if DBG
|
|
objectTypeString = "FDO";
|
|
#endif //DBG
|
|
passDown = TRUE;
|
|
|
|
//
|
|
// In case we don't touch this IRP, save the current status.
|
|
//
|
|
|
|
switch (irpSp->MinorFunction) {
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
|
|
HalPrint(("HAL: (%s) Query_Device_Relations Irp received\n",
|
|
objectTypeString));
|
|
|
|
relationType = irpSp->Parameters.QueryDeviceRelations.Type;
|
|
status = HalpQueryDeviceRelations(DeviceObject,
|
|
relationType,
|
|
(PDEVICE_RELATIONS*)&Irp->IoStatus.Information);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_INTERFACE:
|
|
|
|
HalPrint(("HAL: (%s) Query_Interface Irp received\n",
|
|
objectTypeString));
|
|
|
|
status = HalpQueryInterface(
|
|
DeviceObject,
|
|
irpSp->Parameters.QueryInterface.InterfaceType,
|
|
irpSp->Parameters.QueryInterface.Version,
|
|
irpSp->Parameters.QueryInterface.InterfaceSpecificData,
|
|
irpSp->Parameters.QueryInterface.Size,
|
|
irpSp->Parameters.QueryInterface.Interface,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
|
|
break;
|
|
|
|
case IRP_MN_QUERY_ID:
|
|
|
|
HalPrint(("HAL: (%s) Query_Id Irp received\n",
|
|
objectTypeString));
|
|
|
|
status = HalpQueryIdFdo(DeviceObject,
|
|
irpSp->Parameters.QueryId.IdType,
|
|
(PWSTR*)&Irp->IoStatus.Information);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Ignore any PNP Irps unknown by the FDO but allow them
|
|
// down to the PDO.
|
|
//
|
|
|
|
status = STATUS_NOT_SUPPORTED ;
|
|
break;
|
|
}
|
|
|
|
if (passDown && (NT_SUCCESS(status) || (status == STATUS_NOT_SUPPORTED))) {
|
|
|
|
//
|
|
// Pass FDO IRPs down to the PDO.
|
|
//
|
|
// Set Irp status first.
|
|
//
|
|
if (status != STATUS_NOT_SUPPORTED) {
|
|
|
|
Irp->IoStatus.Status = status;
|
|
}
|
|
|
|
HalPrint(("HAL: (%s) Passing down Irp (%x)\n",
|
|
objectTypeString, irpSp->MinorFunction));
|
|
return HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
|
|
}
|
|
|
|
break; // end FDO cases
|
|
|
|
default:
|
|
|
|
HalPrint(( "HAL: Received IRP for unknown Device Object\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST ;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Complete the Irp and return.
|
|
//
|
|
|
|
if (status != STATUS_NOT_SUPPORTED) {
|
|
|
|
Irp->IoStatus.Status = status;
|
|
|
|
} else {
|
|
|
|
status = Irp->IoStatus.Status ;
|
|
}
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles all IRP_MJ_POWER IRPs for madeup PDO device.
|
|
Note: We don't actually handle any Power IRPs at this level so
|
|
all we do is return the status from the incoming IRP.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object for which this IRP applies.
|
|
|
|
Irp - Pointer to the IRP_MJ_POWER IRP to dispatch.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
EXTENSION_TYPE extensionType;
|
|
PIO_STACK_LOCATION irpSp;
|
|
|
|
HalPrint(("Hal: Power IRP for DevObj: %x\n", DeviceObject));
|
|
|
|
|
|
extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
|
|
|
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
//
|
|
// Simply store the appropriate status and complete the request.
|
|
//
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
if (extensionType == FdoExtensionType) {
|
|
|
|
switch (irpSp->MinorFunction) {
|
|
case IRP_MN_SET_POWER:
|
|
|
|
if (irpSp->Parameters.Power.Type == SystemPowerState) {
|
|
|
|
switch (irpSp->Parameters.Power.State.SystemState) {
|
|
case PowerSystemSleeping1:
|
|
case PowerSystemSleeping2:
|
|
case PowerSystemSleeping3:
|
|
case PowerSystemHibernate:
|
|
|
|
//
|
|
// Allocate structures used for starting up
|
|
// processors while resuming from sleep.
|
|
//
|
|
|
|
HalpBuildResumeStructures();
|
|
|
|
HalpMaskAcpiInterrupt();
|
|
|
|
break;
|
|
|
|
case PowerSystemWorking:
|
|
|
|
HalpUnmaskAcpiInterrupt();
|
|
|
|
//
|
|
// Free structures used for starting up
|
|
// processors while resuming from sleep.
|
|
//
|
|
|
|
HalpFreeResumeStructures();
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fall through.
|
|
//
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
Irp->IoStatus.Status = Status = STATUS_SUCCESS;
|
|
|
|
//
|
|
// Fall through.
|
|
//
|
|
|
|
default:
|
|
|
|
Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (irpSp->MinorFunction) {
|
|
case IRP_MN_SET_POWER:
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
Irp->IoStatus.Status = Status = STATUS_SUCCESS;
|
|
|
|
//
|
|
// Fall through.
|
|
//
|
|
|
|
default:
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpDispatchWmi(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
EXTENSION_TYPE extensionType;
|
|
|
|
extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType;
|
|
|
|
if (extensionType == FdoExtensionType) {
|
|
Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp);
|
|
} else {
|
|
Status = Irp->IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpQueryDeviceRelations(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN DEVICE_RELATION_TYPE RelationType,
|
|
OUT PDEVICE_RELATIONS *DeviceRelations
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine builds a DEVICE_RELATIONS structure that
|
|
tells the PnP manager how many children we have.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - FDO of ACPI_HAL
|
|
|
|
RelationType - we only respond to BusRelations
|
|
|
|
DeviceRelations - pointer to the structure
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PFDO_EXTENSION FdoExtension;
|
|
PDEVICE_RELATIONS relations = NULL;
|
|
ULONG relationsCount = 0;
|
|
EXTENSION_TYPE extensionType;
|
|
ULONG i;
|
|
PPDO_EXTENSION Next;
|
|
NTSTATUS Status = STATUS_NOT_SUPPORTED;
|
|
|
|
PAGED_CODE();
|
|
|
|
FdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension;
|
|
extensionType = FdoExtension->ExtensionType;
|
|
|
|
switch(RelationType) {
|
|
|
|
case BusRelations:
|
|
if (extensionType == FdoExtensionType) {
|
|
Next = FdoExtension->ChildPdoList;
|
|
while (Next) {
|
|
relationsCount += 1;
|
|
Next = Next->Next;
|
|
}
|
|
|
|
relations = ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
sizeof(DEVICE_RELATIONS) * relationsCount,
|
|
HAL_POOL_TAG
|
|
);
|
|
if (relations == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
relations->Count = relationsCount;
|
|
|
|
i = 0;
|
|
Next = FdoExtension->ChildPdoList;
|
|
while (Next) {
|
|
relations->Objects[i] = Next->PhysicalDeviceObject;
|
|
ObReferenceObject( relations->Objects[i] );
|
|
i += 1;
|
|
Next = Next->Next;
|
|
}
|
|
|
|
*DeviceRelations = relations;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case TargetDeviceRelation:
|
|
if (extensionType == PdoExtensionType) {
|
|
relations = ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
sizeof(DEVICE_RELATIONS),
|
|
HAL_POOL_TAG
|
|
);
|
|
if (relations == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
relations->Count = 1;
|
|
relations->Objects[0] = DeviceObject;
|
|
|
|
ObReferenceObject( relations->Objects[0] );
|
|
*DeviceRelations = relations;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpQueryIdPdo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN BUS_QUERY_ID_TYPE IdType,
|
|
IN OUT PWSTR *BusQueryId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine identifies each of the children that were
|
|
enumerated in HalpQueryDeviceRelations.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - PDO of the child
|
|
|
|
IdType - the type of ID to be returned, currently ignored
|
|
|
|
BusQueryId - pointer to the wide string being returned
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
|
|
PWSTR idString;
|
|
PWCHAR sourceString;
|
|
ULONG stringLen;
|
|
static WCHAR AcpiHardwareIdString[] = L"ACPI_HAL\\PNP0C08\0*PNP0C08";
|
|
static WCHAR AcpiCompatibleString[] = L"*PNP0C08";
|
|
static WCHAR AcpiInstanceIdString[] = L"0";
|
|
static WCHAR WdHardwareIdString[] = L"ACPI_HAL\\PNP0C18\0*PNP0C18";
|
|
static WCHAR WdCompatibleString[] = L"*PNP0C18";
|
|
|
|
PAGED_CODE();
|
|
|
|
switch (IdType) {
|
|
case BusQueryDeviceID:
|
|
case BusQueryHardwareIDs:
|
|
|
|
switch (PdoExtension->PdoType) {
|
|
case AcpiDriver:
|
|
sourceString = AcpiHardwareIdString;
|
|
stringLen = sizeof(AcpiHardwareIdString);
|
|
break;
|
|
|
|
case WdDriver:
|
|
HalPrint(("ID query for WD timer device"));
|
|
sourceString = WdHardwareIdString;
|
|
stringLen = sizeof(WdHardwareIdString);
|
|
break;
|
|
|
|
default:
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
break;
|
|
|
|
case BusQueryCompatibleIDs:
|
|
return STATUS_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case BusQueryInstanceID:
|
|
sourceString = AcpiInstanceIdString;
|
|
stringLen = sizeof(AcpiInstanceIdString);
|
|
break;
|
|
|
|
default:
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
idString = ExAllocatePoolWithTag(PagedPool,
|
|
stringLen + sizeof(UNICODE_NULL),
|
|
HAL_POOL_TAG);
|
|
|
|
if (!idString) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory(idString,
|
|
sourceString, stringLen);
|
|
|
|
*(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL;
|
|
|
|
*BusQueryId = idString;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
NTSTATUS
|
|
HalpQueryIdFdo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN BUS_QUERY_ID_TYPE IdType,
|
|
IN OUT PWSTR *BusQueryId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine identifies each of the children that were
|
|
enumerated in HalpQueryDeviceRelations.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - PDO of the child
|
|
|
|
IdType - the type of ID to be returned.
|
|
|
|
BusQueryId - pointer to the wide string being returned
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
|
|
PWSTR idString;
|
|
PWCHAR sourceString = NULL;
|
|
ULONG stringLen;
|
|
UNICODE_STRING String;
|
|
WCHAR Buffer[16];
|
|
NTSTATUS Status;
|
|
PWCHAR widechar;
|
|
static WCHAR HalInstanceIdString[] = L"0";
|
|
|
|
PAGED_CODE();
|
|
|
|
switch (IdType) {
|
|
case BusQueryDeviceID:
|
|
case BusQueryHardwareIDs:
|
|
|
|
//
|
|
// For the UP version of the APIC HAL, we want to detect if there is more
|
|
// than one processor installed. If so, we want to return the ID of
|
|
// the MP HAL rather than the UP HAL. This will induce PNP to reconfigure
|
|
// our devnode and setup the MP HAL for the next boot.
|
|
//
|
|
|
|
sourceString = HalHardwareIdString;
|
|
#if defined(NT_UP) && defined(APIC_HAL)
|
|
if (HalpMpInfoTable.ProcessorCount > 1) {
|
|
sourceString = MpHalHardwareIdString;
|
|
}
|
|
#endif
|
|
widechar = sourceString;
|
|
while (*widechar != UNICODE_NULL) {
|
|
widechar++;
|
|
}
|
|
stringLen = (ULONG)((PUCHAR)widechar - ((PUCHAR)sourceString) + 2);
|
|
|
|
break;
|
|
|
|
case BusQueryInstanceID:
|
|
|
|
sourceString = HalInstanceIdString;
|
|
stringLen = sizeof(HalInstanceIdString);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
if (sourceString) {
|
|
|
|
//
|
|
// Note that hardware IDs and compatible IDs must be terminated by
|
|
// 2 NULLs.
|
|
//
|
|
|
|
idString = ExAllocatePoolWithTag(PagedPool,
|
|
stringLen + sizeof(UNICODE_NULL),
|
|
HAL_POOL_TAG);
|
|
|
|
if (!idString) {
|
|
HalPrint(( "HalpQueryIdFdo: couldn't allocate pool\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory(idString,
|
|
sourceString, stringLen);
|
|
|
|
*(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL;
|
|
|
|
*BusQueryId = idString;
|
|
|
|
return STATUS_SUCCESS;
|
|
} else {
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpQueryCapabilities(
|
|
IN PDEVICE_OBJECT PdoExtension,
|
|
IN PDEVICE_CAPABILITIES Capabilities
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine fills in the DEVICE_CAPABILITIES structure for
|
|
a device.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - PDO of the child
|
|
|
|
Capabilities - pointer to the structure to be filled in.
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(Capabilities->Version == 1);
|
|
if (Capabilities->Version != 1) {
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
Capabilities->LockSupported = FALSE;
|
|
Capabilities->EjectSupported = FALSE;
|
|
Capabilities->Removable = FALSE;
|
|
Capabilities->DockDevice = FALSE;
|
|
Capabilities->UniqueID = TRUE;
|
|
Capabilities->SilentInstall = TRUE;
|
|
Capabilities->RawDeviceOK = FALSE;
|
|
Capabilities->Address = 0xffffffff;
|
|
Capabilities->UINumber = 0xffffffff;
|
|
Capabilities->D1Latency = 0;
|
|
Capabilities->D2Latency = 0;
|
|
Capabilities->D3Latency = 0;
|
|
|
|
//
|
|
// Default S->D mapping
|
|
//
|
|
Capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
|
|
Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
|
|
Capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
HalpQueryResources(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PCM_RESOURCE_LIST *Resources
|
|
)
|
|
{
|
|
PIO_RESOURCE_REQUIREMENTS_LIST requirements;
|
|
PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
|
|
PIO_RESOURCE_DESCRIPTOR descriptor;
|
|
PCM_RESOURCE_LIST cmResList;
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (PdoExtension->PdoType == AcpiDriver) {
|
|
|
|
//
|
|
// The whole point behind creating a boot config for the
|
|
// ACPI PDO is that the PnP Manager will not terminate
|
|
// its algorithm that tries to reserve boot configs for
|
|
// all of ACPI's children. So it is not necessary that
|
|
// ACPI have a complicated list of resources in its boot
|
|
// config. We'll be happy with just the IRQ.
|
|
//
|
|
// N.B. At the time of this writing, it should also be
|
|
// true that the IRQ is the only resource that the ACPI
|
|
// claims anyhow.
|
|
//
|
|
|
|
status = HalpQueryAcpiResourceRequirements(&requirements);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
cmResList = ExAllocatePoolWithTag(PagedPool,
|
|
sizeof(CM_RESOURCE_LIST),
|
|
HAL_POOL_TAG);
|
|
|
|
if (!cmResList) {
|
|
ExFreePool(requirements);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(cmResList, sizeof(CM_RESOURCE_LIST));
|
|
|
|
cmResList->Count = 1;
|
|
cmResList->List[0].InterfaceType = PNPBus;
|
|
cmResList->List[0].BusNumber = -1;
|
|
cmResList->List[0].PartialResourceList.Version = 1;
|
|
cmResList->List[0].PartialResourceList.Revision = 1;
|
|
cmResList->List[0].PartialResourceList.Count = 1;
|
|
cmResList->List[0].PartialResourceList.PartialDescriptors[0].Type =
|
|
CmResourceTypeInterrupt;
|
|
|
|
ASSERT(requirements->AlternativeLists == 1);
|
|
|
|
for (i = 0; i < requirements->List[0].Count; i++) {
|
|
|
|
descriptor = &requirements->List[0].Descriptors[i];
|
|
|
|
if (descriptor->Type == CmResourceTypeInterrupt) {
|
|
|
|
cmResList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition =
|
|
descriptor->ShareDisposition;
|
|
cmResList->List[0].PartialResourceList.PartialDescriptors[0].Flags =
|
|
descriptor->Flags;
|
|
|
|
ASSERT(descriptor->u.Interrupt.MinimumVector ==
|
|
descriptor->u.Interrupt.MaximumVector);
|
|
|
|
cmResList->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Level =
|
|
descriptor->u.Interrupt.MinimumVector;
|
|
|
|
cmResList->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector =
|
|
descriptor->u.Interrupt.MinimumVector;
|
|
|
|
cmResList->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = -1;
|
|
|
|
*Resources = cmResList;
|
|
|
|
ExFreePool(requirements);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
ExFreePool(requirements);
|
|
ExFreePool(cmResList);
|
|
return STATUS_NOT_FOUND;
|
|
|
|
|
|
} else if (PdoExtension->PdoType == WdDriver) {
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} else {
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
HalpQueryResourceRequirements(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles IRP_MN_QUERY_RESOURCE_REQUIREMENTS.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - PDO of the child
|
|
|
|
Requirements - pointer to be filled in with the devices
|
|
resource requirements.
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
|
|
PAGED_CODE();
|
|
if (PdoExtension->PdoType == AcpiDriver) {
|
|
|
|
return HalpQueryAcpiResourceRequirements(Requirements);
|
|
|
|
} else if (PdoExtension->PdoType == WdDriver) {
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpQueryInterface(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN LPCGUID InterfaceType,
|
|
IN USHORT Version,
|
|
IN PVOID InterfaceSpecificData,
|
|
IN ULONG InterfaceBufferSize,
|
|
IN OUT PINTERFACE Interface,
|
|
IN OUT PULONG_PTR Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine fills in the interface structure for
|
|
a device.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - PDO of the child
|
|
|
|
InterfaceType - Pointer to the interface type GUID.
|
|
|
|
Version - Supplies the requested interface version.
|
|
|
|
InterfaceSpecificData - This is context that means something based on the
|
|
interface.
|
|
|
|
InterfaceBufferSize - Supplies the length of the buffer for the interface
|
|
structure.
|
|
|
|
Interface - Supplies a pointer where the interface informaiton should
|
|
be returned.
|
|
|
|
Length - This value is updated on return to actual number of bytes modified.
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
#if defined(_WIN64)
|
|
|
|
PPDO_EXTENSION PdoExtension;
|
|
|
|
PdoExtension = DeviceObject->DeviceExtension;
|
|
if (PdoExtension->ExtensionType != PdoExtensionType) {
|
|
PdoExtension = NULL;
|
|
}
|
|
|
|
if (PdoExtension != NULL &&
|
|
IsEqualGUID(&GUID_BUS_INTERFACE_STANDARD, InterfaceType)) {
|
|
|
|
PBUS_INTERFACE_STANDARD standard = (PBUS_INTERFACE_STANDARD)Interface;
|
|
|
|
//
|
|
// ASSERT we know about all of the fields in the structure.
|
|
//
|
|
|
|
ASSERT(sizeof(BUS_INTERFACE_STANDARD) == FIELD_OFFSET(BUS_INTERFACE_STANDARD, GetBusData) + sizeof(PGET_SET_DEVICE_DATA));
|
|
|
|
*Length = sizeof(BUS_INTERFACE_STANDARD);
|
|
|
|
if (InterfaceBufferSize < sizeof(BUS_INTERFACE_STANDARD)) {
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
//
|
|
// The only version this code knows about is 1.
|
|
//
|
|
|
|
standard->Size = sizeof(BUS_INTERFACE_STANDARD);
|
|
standard->Version = HAL_BUS_INTERFACE_STD_VERSION;
|
|
standard->Context = DeviceObject;
|
|
|
|
standard->InterfaceReference = HalPnpInterfaceReference;
|
|
standard->InterfaceDereference = HalPnpInterfaceDereference;
|
|
standard->TranslateBusAddress = NULL; // BUGBUG
|
|
standard->GetDmaAdapter = HalPnpGetDmaAdapter;
|
|
standard->SetBusData = NULL;
|
|
standard->GetBusData = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} else
|
|
|
|
#endif // _WIN64
|
|
|
|
if (IsEqualGUID(InterfaceType, (PVOID)&GUID_TRANSLATOR_INTERFACE_STANDARD)) {
|
|
|
|
PTRANSLATOR_INTERFACE translator = (PTRANSLATOR_INTERFACE)Interface;
|
|
|
|
//
|
|
// Common initialization.
|
|
//
|
|
|
|
if (InterfaceBufferSize < sizeof(TRANSLATOR_INTERFACE)) {
|
|
*Length = sizeof(TRANSLATOR_INTERFACE);
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
switch ((CM_RESOURCE_TYPE)PtrToUlong(InterfaceSpecificData)) {
|
|
|
|
case CmResourceTypeInterrupt:
|
|
|
|
translator->Size = sizeof(TRANSLATOR_INTERFACE);
|
|
translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
|
|
translator->Context = DeviceObject;
|
|
translator->InterfaceReference = HalTranslatorReference;
|
|
translator->InterfaceDereference = HalTranslatorDereference;
|
|
translator->TranslateResources = HalIrqTranslateResourcesRoot;
|
|
translator->TranslateResourceRequirements =
|
|
HalIrqTranslateResourceRequirementsRoot;
|
|
|
|
*Length = sizeof(TRANSLATOR_INTERFACE);
|
|
|
|
break;
|
|
|
|
default:
|
|
return STATUS_NOT_SUPPORTED ;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#ifdef ACPI_CMOS_ACTIVATE
|
|
else if (IsEqualGUID(InterfaceType, (PVOID) &GUID_ACPI_CMOS_INTERFACE_STANDARD)) {
|
|
|
|
PACPI_CMOS_INTERFACE_STANDARD CmosInterface = (PACPI_CMOS_INTERFACE_STANDARD)Interface;
|
|
|
|
//
|
|
// Common initialization.
|
|
//
|
|
|
|
if (InterfaceBufferSize < sizeof(ACPI_CMOS_INTERFACE_STANDARD)) {
|
|
|
|
*Length = sizeof(ACPI_CMOS_INTERFACE_STANDARD);
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
switch ((CM_RESOURCE_TYPE)InterfaceSpecificData) {
|
|
|
|
case CmResourceTypeNull:
|
|
|
|
// standard header
|
|
CmosInterface->Size = sizeof(ACPI_CMOS_INTERFACE_STANDARD);
|
|
CmosInterface->Version = 1;
|
|
CmosInterface->InterfaceReference = HalpCmosNullReference;
|
|
CmosInterface->InterfaceDereference = HalpCmosNullReference;
|
|
|
|
// cmos interface specific
|
|
CmosInterface->ReadCmos = HalpcGetCmosDataByType;
|
|
CmosInterface->WriteCmos = HalpcSetCmosDataByType;
|
|
|
|
*Length = sizeof(ACPI_CMOS_INTERFACE_STANDARD);
|
|
|
|
break;
|
|
|
|
default:
|
|
return STATUS_NOT_SUPPORTED ;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#endif // ACPI_CMOS_ACTIVATE
|
|
|
|
|
|
//
|
|
// If we got here, we don't handle this interface type.
|
|
//
|
|
|
|
return STATUS_NOT_SUPPORTED ;
|
|
}
|
|
|
|
#if defined(_WIN64)
|
|
|
|
|
|
VOID
|
|
HalPnpInterfaceReference(
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function increments the reference count on the interface context.
|
|
|
|
Arguments:
|
|
|
|
Context - Supplies a pointer to the interface context. This is actually
|
|
the PDO for the root bus.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
|
|
PAGED_CODE();
|
|
|
|
ASSERT_PDO_EXTENSION( PdoExtension );
|
|
}
|
|
|
|
VOID
|
|
HalPnpInterfaceDereference(
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function decrements the reference count on the interface context.
|
|
|
|
Arguments:
|
|
|
|
Context - Supplies a pointer to the interface context. This is actually
|
|
the PDO for the root bus.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT_PDO_EXTENSION( PdoExtension );
|
|
}
|
|
|
|
PDMA_ADAPTER
|
|
HalPnpGetDmaAdapter(
|
|
IN PVOID Context,
|
|
IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
|
|
OUT PULONG NumberOfMapRegisters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function writes the PCI configuration space.
|
|
|
|
Arguments:
|
|
|
|
Context - Supplies a pointer to the interface context. This is actually
|
|
the PDO for the root bus.
|
|
|
|
DeviceDescriptor - Supplies the device descriptor used to allocate the dma
|
|
adapter object.
|
|
|
|
NubmerOfMapRegisters - Returns the maximum number of map registers a device
|
|
can allocate at one time.
|
|
|
|
Return Value:
|
|
|
|
Returns a DMA adapter or NULL.
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension;
|
|
PAGED_CODE();
|
|
|
|
ASSERT_PDO_EXTENSION( PdoExtension );
|
|
|
|
return (PDMA_ADAPTER) HalGetAdapter( DeviceDescriptor, NumberOfMapRegisters );
|
|
}
|
|
|
|
#endif // _WIN64
|
|
|
|
#ifdef ACPI_CMOS_ACTIVATE
|
|
|
|
//
|
|
// This section implements a CMOS access method
|
|
//
|
|
VOID
|
|
HalpCmosNullReference(
|
|
PVOID Context
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HalpCmosNullDereference(
|
|
PVOID Context
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
#endif
|