Leaked source code of windows server 2003
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

/*++
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