1 /* 2 * PROJECT: ReactOS ACPI bus driver 3 * FILE: acpi/ospm/acpienum.c 4 * PURPOSE: ACPI namespace enumerator 5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 6 * UPDATE HISTORY: 7 * 01-05-2001 CSH Created 8 */ 9 10 #include "precomp.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 #define HAS_CHILDREN(d) ((d)->children.next != &((d)->children)) 16 #define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children)) 17 #define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node)) 18 19 extern struct acpi_device *acpi_root; 20 21 NTSTATUS 22 Bus_PlugInDevice ( 23 struct acpi_device *Device, 24 PFDO_DEVICE_DATA FdoData 25 ) 26 { 27 PDEVICE_OBJECT pdo; 28 PPDO_DEVICE_DATA pdoData; 29 NTSTATUS status; 30 ULONG index; 31 WCHAR temp[256]; 32 PLIST_ENTRY entry; 33 34 PAGED_CODE (); 35 36 //Don't enumerate the root device 37 if (Device->handle == ACPI_ROOT_OBJECT) 38 return STATUS_SUCCESS; 39 40 /* Check we didnt add this already */ 41 for (entry = FdoData->ListOfPDOs.Flink; 42 entry != &FdoData->ListOfPDOs; entry = entry->Flink) 43 { 44 struct acpi_device *CurrentDevice; 45 46 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); 47 48 //dont duplicate devices 49 if (pdoData->AcpiHandle == Device->handle) 50 return STATUS_SUCCESS; 51 52 //check everything but fixed feature devices 53 if (pdoData->AcpiHandle) 54 acpi_bus_get_device(pdoData->AcpiHandle, &CurrentDevice); 55 else 56 continue; 57 58 //check if the HID matches 59 if (!strcmp(Device->pnp.hardware_id, CurrentDevice->pnp.hardware_id)) 60 { 61 //check if UID exists for both and matches 62 if (Device->flags.unique_id && CurrentDevice->flags.unique_id && 63 !strcmp(Device->pnp.unique_id, CurrentDevice->pnp.unique_id)) 64 { 65 /* We have a UID on both but they're the same so we have to ignore it */ 66 DPRINT1("Detected duplicate device: %hs %hs\n", Device->pnp.hardware_id, Device->pnp.unique_id); 67 return STATUS_SUCCESS; 68 } 69 else if (!Device->flags.unique_id && !CurrentDevice->flags.unique_id) 70 { 71 /* No UID so we can only legally have 1 of these devices */ 72 DPRINT1("Detected duplicate device: %hs\n", Device->pnp.hardware_id); 73 return STATUS_SUCCESS; 74 } 75 } 76 } 77 78 DPRINT("Exposing PDO\n" 79 "======AcpiHandle: %p\n" 80 "======HardwareId: %s\n", 81 Device->handle, 82 Device->pnp.hardware_id); 83 84 85 // 86 // Create the PDO 87 // 88 89 DPRINT("FdoData->NextLowerDriver = 0x%p\n", FdoData->NextLowerDriver); 90 91 status = IoCreateDevice(FdoData->Common.Self->DriverObject, 92 sizeof(PDO_DEVICE_DATA), 93 NULL, 94 FILE_DEVICE_CONTROLLER, 95 FILE_AUTOGENERATED_DEVICE_NAME, 96 FALSE, 97 &pdo); 98 99 if (!NT_SUCCESS (status)) { 100 return status; 101 } 102 103 pdoData = (PPDO_DEVICE_DATA) pdo->DeviceExtension; 104 pdoData->AcpiHandle = Device->handle; 105 106 // 107 // Copy the hardware IDs 108 // 109 index = 0; 110 index += swprintf(&temp[index], 111 L"ACPI\\%hs", 112 Device->pnp.hardware_id); 113 temp[index++] = UNICODE_NULL; 114 115 index += swprintf(&temp[index], 116 L"*%hs", 117 Device->pnp.hardware_id); 118 temp[index++] = UNICODE_NULL; 119 temp[index++] = UNICODE_NULL; 120 121 pdoData->HardwareIDs = ExAllocatePoolWithTag(NonPagedPool, index*sizeof(WCHAR), 'DpcA'); 122 123 124 if (!pdoData->HardwareIDs) { 125 IoDeleteDevice(pdo); 126 return STATUS_INSUFFICIENT_RESOURCES; 127 } 128 129 RtlCopyMemory (pdoData->HardwareIDs, temp, index*sizeof(WCHAR)); 130 Bus_InitializePdo (pdo, FdoData); 131 132 // 133 // Device Relation changes if a new pdo is created. So let 134 // the PNP system now about that. This forces it to send bunch of pnp 135 // queries and cause the function driver to be loaded. 136 // 137 138 //IoInvalidateDeviceRelations (FdoData->UnderlyingPDO, BusRelations); 139 140 return status; 141 } 142 143 144 /* looks alot like acpi_bus_walk doesnt it */ 145 NTSTATUS 146 ACPIEnumerateDevices(PFDO_DEVICE_DATA DeviceExtension) 147 { 148 ULONG Count = 0; 149 struct acpi_device *Device = acpi_root; 150 151 while(Device) 152 { 153 if (Device->status.present && Device->status.enabled && 154 Device->flags.hardware_id) 155 { 156 Bus_PlugInDevice(Device, DeviceExtension); 157 Count++; 158 } 159 160 if (HAS_CHILDREN(Device)) { 161 Device = NODE_TO_DEVICE(Device->children.next); 162 continue; 163 } 164 if (HAS_SIBLINGS(Device)) { 165 Device = NODE_TO_DEVICE(Device->node.next); 166 continue; 167 } 168 while ((Device = Device->parent)) { 169 if (HAS_SIBLINGS(Device)) { 170 Device = NODE_TO_DEVICE(Device->node.next); 171 break; 172 } 173 } 174 } 175 DPRINT("acpi device count: %d\n", Count); 176 return STATUS_SUCCESS; 177 } 178 179 /* EOF */ 180