reactos/drivers/bus/acpi/acpienum.c

180 lines
5.1 KiB
C

/*
* PROJECT: ReactOS ACPI bus driver
* FILE: acpi/ospm/acpienum.c
* PURPOSE: ACPI namespace enumerator
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 01-05-2001 CSH Created
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
#define HAS_CHILDREN(d) ((d)->children.next != &((d)->children))
#define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children))
#define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node))
extern struct acpi_device *acpi_root;
NTSTATUS
Bus_PlugInDevice (
struct acpi_device *Device,
PFDO_DEVICE_DATA FdoData
)
{
PDEVICE_OBJECT pdo;
PPDO_DEVICE_DATA pdoData;
NTSTATUS status;
ULONG index;
WCHAR temp[256];
PLIST_ENTRY entry;
PAGED_CODE ();
//Don't enumerate the root device
if (Device->handle == ACPI_ROOT_OBJECT)
return STATUS_SUCCESS;
/* Check we didnt add this already */
for (entry = FdoData->ListOfPDOs.Flink;
entry != &FdoData->ListOfPDOs; entry = entry->Flink)
{
struct acpi_device *CurrentDevice;
pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
//dont duplicate devices
if (pdoData->AcpiHandle == Device->handle)
return STATUS_SUCCESS;
//check everything but fixed feature devices
if (pdoData->AcpiHandle)
acpi_bus_get_device(pdoData->AcpiHandle, &CurrentDevice);
else
continue;
//check if the HID matches
if (!strcmp(Device->pnp.hardware_id, CurrentDevice->pnp.hardware_id))
{
//check if UID exists for both and matches
if (Device->flags.unique_id && CurrentDevice->flags.unique_id &&
!strcmp(Device->pnp.unique_id, CurrentDevice->pnp.unique_id))
{
/* We have a UID on both but they're the same so we have to ignore it */
DPRINT1("Detected duplicate device: %hs %hs\n", Device->pnp.hardware_id, Device->pnp.unique_id);
return STATUS_SUCCESS;
}
else if (!Device->flags.unique_id && !CurrentDevice->flags.unique_id)
{
/* No UID so we can only legally have 1 of these devices */
DPRINT1("Detected duplicate device: %hs\n", Device->pnp.hardware_id);
return STATUS_SUCCESS;
}
}
}
DPRINT("Exposing PDO\n"
"======AcpiHandle: %p\n"
"======HardwareId: %s\n",
Device->handle,
Device->pnp.hardware_id);
//
// Create the PDO
//
DPRINT("FdoData->NextLowerDriver = 0x%p\n", FdoData->NextLowerDriver);
status = IoCreateDevice(FdoData->Common.Self->DriverObject,
sizeof(PDO_DEVICE_DATA),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&pdo);
if (!NT_SUCCESS (status)) {
return status;
}
pdoData = (PPDO_DEVICE_DATA) pdo->DeviceExtension;
pdoData->AcpiHandle = Device->handle;
//
// Copy the hardware IDs
//
index = 0;
index += swprintf(&temp[index],
L"ACPI\\%hs",
Device->pnp.hardware_id);
temp[index++] = UNICODE_NULL;
index += swprintf(&temp[index],
L"*%hs",
Device->pnp.hardware_id);
temp[index++] = UNICODE_NULL;
temp[index++] = UNICODE_NULL;
pdoData->HardwareIDs = ExAllocatePoolWithTag(NonPagedPool, index*sizeof(WCHAR), 'DpcA');
if (!pdoData->HardwareIDs) {
IoDeleteDevice(pdo);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory (pdoData->HardwareIDs, temp, index*sizeof(WCHAR));
Bus_InitializePdo (pdo, FdoData);
//
// Device Relation changes if a new pdo is created. So let
// the PNP system now about that. This forces it to send bunch of pnp
// queries and cause the function driver to be loaded.
//
//IoInvalidateDeviceRelations (FdoData->UnderlyingPDO, BusRelations);
return status;
}
/* looks alot like acpi_bus_walk doesnt it */
NTSTATUS
ACPIEnumerateDevices(PFDO_DEVICE_DATA DeviceExtension)
{
ULONG Count = 0;
struct acpi_device *Device = acpi_root;
while(Device)
{
if (Device->status.present && Device->status.enabled &&
Device->flags.hardware_id)
{
Bus_PlugInDevice(Device, DeviceExtension);
Count++;
}
if (HAS_CHILDREN(Device)) {
Device = NODE_TO_DEVICE(Device->children.next);
continue;
}
if (HAS_SIBLINGS(Device)) {
Device = NODE_TO_DEVICE(Device->node.next);
continue;
}
while ((Device = Device->parent)) {
if (HAS_SIBLINGS(Device)) {
Device = NODE_TO_DEVICE(Device->node.next);
break;
}
}
}
DPRINT("acpi device count: %d\n", Count);
return STATUS_SUCCESS;
}
/* EOF */