1 #include "precomp.h" 2 3 #define NDEBUG 4 #include <debug.h> 5 6 NTSTATUS 7 Bus_PlugInDevice ( 8 struct acpi_device *Device, 9 PFDO_DEVICE_DATA FdoData 10 ); 11 12 #ifdef ALLOC_PRAGMA 13 #pragma alloc_text (PAGE, Bus_PnP) 14 #pragma alloc_text (PAGE, Bus_PlugInDevice) 15 #pragma alloc_text (PAGE, Bus_InitializePdo) 16 #pragma alloc_text (PAGE, Bus_DestroyPdo) 17 #pragma alloc_text (PAGE, Bus_FDO_PnP) 18 #pragma alloc_text (PAGE, Bus_StartFdo) 19 #pragma alloc_text (PAGE, Bus_SendIrpSynchronously) 20 #endif 21 22 23 NTSTATUS 24 NTAPI 25 Bus_PnP ( 26 PDEVICE_OBJECT DeviceObject, 27 PIRP Irp 28 ) 29 { 30 PIO_STACK_LOCATION irpStack; 31 NTSTATUS status; 32 PCOMMON_DEVICE_DATA commonData; 33 34 PAGED_CODE (); 35 36 irpStack = IoGetCurrentIrpStackLocation (Irp); 37 ASSERT (IRP_MJ_PNP == irpStack->MajorFunction); 38 39 commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; 40 41 42 if (commonData->IsFDO) { 43 DPRINT("FDO %s IRP:0x%p\n", 44 PnPMinorFunctionString(irpStack->MinorFunction), 45 Irp); 46 // 47 // Request is for the bus FDO 48 // 49 status = Bus_FDO_PnP ( 50 DeviceObject, 51 Irp, 52 irpStack, 53 (PFDO_DEVICE_DATA) commonData); 54 } else { 55 DPRINT("PDO %s IRP: 0x%p\n", 56 PnPMinorFunctionString(irpStack->MinorFunction), 57 Irp); 58 // 59 // Request is for the child PDO. 60 // 61 status = Bus_PDO_PnP ( 62 DeviceObject, 63 Irp, 64 irpStack, 65 (PPDO_DEVICE_DATA) commonData); 66 } 67 68 return status; 69 } 70 71 NTSTATUS 72 Bus_FDO_PnP ( 73 PDEVICE_OBJECT DeviceObject, 74 PIRP Irp, 75 PIO_STACK_LOCATION IrpStack, 76 PFDO_DEVICE_DATA DeviceData 77 ) 78 { 79 NTSTATUS status; 80 ULONG length, prevcount, numPdosPresent; 81 PLIST_ENTRY entry; 82 PPDO_DEVICE_DATA pdoData; 83 PDEVICE_RELATIONS relations, oldRelations; 84 85 PAGED_CODE (); 86 87 switch (IrpStack->MinorFunction) { 88 89 case IRP_MN_START_DEVICE: 90 91 status = Bus_StartFdo (DeviceData, Irp); 92 93 94 // 95 // We must now complete the IRP, since we stopped it in the 96 // completion routine with MORE_PROCESSING_REQUIRED. 97 // 98 99 Irp->IoStatus.Status = status; 100 IoCompleteRequest (Irp, IO_NO_INCREMENT); 101 102 return status; 103 104 case IRP_MN_QUERY_STOP_DEVICE: 105 106 // 107 // The PnP manager is trying to stop the device 108 // for resource rebalancing. 109 // 110 SET_NEW_PNP_STATE(DeviceData->Common, StopPending); 111 Irp->IoStatus.Status = STATUS_SUCCESS; 112 break; 113 114 case IRP_MN_CANCEL_STOP_DEVICE: 115 116 // 117 // The PnP Manager sends this IRP, at some point after an 118 // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a 119 // device that the device will not be stopped for 120 // resource reconfiguration. 121 // 122 // 123 // First check to see whether you have received cancel-stop 124 // without first receiving a query-stop. This could happen if 125 // someone above us fails a query-stop and passes down the subsequent 126 // cancel-stop. 127 // 128 129 if (StopPending == DeviceData->Common.DevicePnPState) 130 { 131 // 132 // We did receive a query-stop, so restore. 133 // 134 RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common); 135 ASSERT(DeviceData->Common.DevicePnPState == Started); 136 } 137 Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP. 138 break; 139 140 case IRP_MN_QUERY_DEVICE_RELATIONS: 141 142 DPRINT("\tQueryDeviceRelation Type: %s\n", 143 DbgDeviceRelationString(\ 144 IrpStack->Parameters.QueryDeviceRelations.Type)); 145 146 if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) { 147 // 148 // We don't support any other Device Relations 149 // 150 break; 151 } 152 153 154 ExAcquireFastMutex (&DeviceData->Mutex); 155 156 oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information; 157 if (oldRelations) { 158 prevcount = oldRelations->Count; 159 if (!DeviceData->NumPDOs) { 160 // 161 // There is a device relations struct already present and we have 162 // nothing to add to it, so just call IoSkip and IoCall 163 // 164 ExReleaseFastMutex (&DeviceData->Mutex); 165 break; 166 } 167 } 168 else { 169 prevcount = 0; 170 } 171 172 // 173 // Calculate the number of PDOs actually present on the bus 174 // 175 numPdosPresent = 0; 176 for (entry = DeviceData->ListOfPDOs.Flink; 177 entry != &DeviceData->ListOfPDOs; 178 entry = entry->Flink) { 179 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); 180 numPdosPresent++; 181 } 182 183 // 184 // Need to allocate a new relations structure and add our 185 // PDOs to it. 186 // 187 188 length = sizeof(DEVICE_RELATIONS) + 189 (((numPdosPresent + prevcount) - 1) * sizeof (PDEVICE_OBJECT)); 190 191 relations = ExAllocatePoolWithTag(PagedPool, length, 'IpcA'); 192 193 if (NULL == relations) { 194 // 195 // Fail the IRP 196 // 197 ExReleaseFastMutex (&DeviceData->Mutex); 198 Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES; 199 IoCompleteRequest (Irp, IO_NO_INCREMENT); 200 return status; 201 202 } 203 204 // 205 // Copy in the device objects so far 206 // 207 if (prevcount) { 208 RtlCopyMemory (relations->Objects, oldRelations->Objects, 209 prevcount * sizeof (PDEVICE_OBJECT)); 210 } 211 212 relations->Count = prevcount + numPdosPresent; 213 214 // 215 // For each PDO present on this bus add a pointer to the device relations 216 // buffer, being sure to take out a reference to that object. 217 // The Plug & Play system will dereference the object when it is done 218 // with it and free the device relations buffer. 219 // 220 221 for (entry = DeviceData->ListOfPDOs.Flink; 222 entry != &DeviceData->ListOfPDOs; 223 entry = entry->Flink) { 224 225 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); 226 relations->Objects[prevcount] = pdoData->Common.Self; 227 ObReferenceObject (pdoData->Common.Self); 228 prevcount++; 229 } 230 231 DPRINT("\t#PDOs present = %d\n\t#PDOs reported = %d\n", 232 DeviceData->NumPDOs, relations->Count); 233 234 // 235 // Replace the relations structure in the IRP with the new 236 // one. 237 // 238 if (oldRelations) { 239 ExFreePoolWithTag(oldRelations, 0); 240 } 241 Irp->IoStatus.Information = (ULONG_PTR) relations; 242 243 ExReleaseFastMutex (&DeviceData->Mutex); 244 245 // 246 // Set up and pass the IRP further down the stack 247 // 248 Irp->IoStatus.Status = STATUS_SUCCESS; 249 break; 250 251 default: 252 253 // 254 // In the default case we merely call the next driver. 255 // We must not modify Irp->IoStatus.Status or complete the IRP. 256 // 257 258 break; 259 } 260 261 IoSkipCurrentIrpStackLocation (Irp); 262 status = IoCallDriver (DeviceData->NextLowerDriver, Irp); 263 return STATUS_SUCCESS; 264 } 265 266 NTSTATUS 267 Bus_StartFdo ( 268 PFDO_DEVICE_DATA FdoData, 269 PIRP Irp ) 270 { 271 NTSTATUS status; 272 POWER_STATE powerState; 273 ACPI_STATUS AcpiStatus; 274 275 PAGED_CODE (); 276 277 FdoData->Common.DevicePowerState = PowerDeviceD0; 278 powerState.DeviceState = PowerDeviceD0; 279 PoSetPowerState ( FdoData->Common.Self, DevicePowerState, powerState ); 280 281 SET_NEW_PNP_STATE(FdoData->Common, Started); 282 283 AcpiStatus = AcpiInitializeSubsystem(); 284 if(ACPI_FAILURE(AcpiStatus)){ 285 DPRINT1("Unable to AcpiInitializeSubsystem\n"); 286 return STATUS_UNSUCCESSFUL; 287 } 288 289 AcpiStatus = AcpiInitializeTables(NULL, 16, 0); 290 if (ACPI_FAILURE(AcpiStatus)){ 291 DPRINT1("Unable to AcpiInitializeTables\n"); 292 return STATUS_UNSUCCESSFUL; 293 } 294 295 AcpiStatus = AcpiLoadTables(); 296 if(ACPI_FAILURE(AcpiStatus)){ 297 DPRINT1("Unable to AcpiLoadTables\n"); 298 AcpiTerminate(); 299 return STATUS_UNSUCCESSFUL; 300 } 301 302 status = acpi_create_volatile_registry_tables(); 303 if (!NT_SUCCESS(status)) 304 { 305 DPRINT1("Unable to create ACPI tables in registry\n"); 306 } 307 308 DPRINT("Acpi subsystem init\n"); 309 /* Initialize ACPI bus manager */ 310 AcpiStatus = acpi_init(); 311 if (!ACPI_SUCCESS(AcpiStatus)) { 312 DPRINT1("acpi_init() failed with status 0x%X\n", AcpiStatus); 313 AcpiTerminate(); 314 return STATUS_UNSUCCESSFUL; 315 } 316 status = ACPIEnumerateDevices(FdoData); 317 318 return status; 319 } 320 321 NTSTATUS 322 Bus_SendIrpSynchronously ( 323 PDEVICE_OBJECT DeviceObject, 324 PIRP Irp 325 ) 326 { 327 KEVENT event; 328 NTSTATUS status; 329 330 PAGED_CODE(); 331 332 KeInitializeEvent(&event, NotificationEvent, FALSE); 333 334 IoCopyCurrentIrpStackLocationToNext(Irp); 335 336 IoSetCompletionRoutine(Irp, 337 Bus_CompletionRoutine, 338 &event, 339 TRUE, 340 TRUE, 341 TRUE 342 ); 343 344 status = IoCallDriver(DeviceObject, Irp); 345 346 // 347 // Wait for lower drivers to be done with the Irp. 348 // Important thing to note here is when you allocate 349 // the memory for an event in the stack you must do a 350 // KernelMode wait instead of UserMode to prevent 351 // the stack from getting paged out. 352 // 353 354 if (status == STATUS_PENDING) { 355 KeWaitForSingleObject(&event, 356 Executive, 357 KernelMode, 358 FALSE, 359 NULL 360 ); 361 status = Irp->IoStatus.Status; 362 } 363 364 return status; 365 } 366 367 NTSTATUS 368 NTAPI 369 Bus_CompletionRoutine( 370 PDEVICE_OBJECT DeviceObject, 371 PIRP Irp, 372 PVOID Context 373 ) 374 { 375 UNREFERENCED_PARAMETER (DeviceObject); 376 377 // 378 // If the lower driver didn't return STATUS_PENDING, we don't need to 379 // set the event because we won't be waiting on it. 380 // This optimization avoids grabbing the dispatcher lock and improves perf. 381 // 382 if (Irp->PendingReturned != FALSE) { 383 384 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE); 385 } 386 return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP 387 } 388 389 NTSTATUS 390 Bus_DestroyPdo ( 391 PDEVICE_OBJECT Device, 392 PPDO_DEVICE_DATA PdoData 393 ) 394 { 395 PAGED_CODE (); 396 397 // 398 // BusEnum does not queue any irps at this time so we have nothing to do. 399 // 400 401 // 402 // Free any resources. 403 // 404 405 if (PdoData->HardwareIDs) { 406 ExFreePoolWithTag(PdoData->HardwareIDs, 'DpcA'); 407 PdoData->HardwareIDs = NULL; 408 } 409 410 DPRINT("\tDeleting PDO: 0x%p\n", Device); 411 IoDeleteDevice (Device); 412 return STATUS_SUCCESS; 413 } 414 415 416 VOID 417 Bus_InitializePdo ( 418 PDEVICE_OBJECT Pdo, 419 PFDO_DEVICE_DATA FdoData 420 ) 421 { 422 PPDO_DEVICE_DATA pdoData; 423 int acpistate; 424 DEVICE_POWER_STATE ntState; 425 426 PAGED_CODE (); 427 428 pdoData = (PPDO_DEVICE_DATA) Pdo->DeviceExtension; 429 430 DPRINT("pdo 0x%p, extension 0x%p\n", Pdo, pdoData); 431 432 if (pdoData->AcpiHandle) 433 acpi_bus_get_power(pdoData->AcpiHandle, &acpistate); 434 else 435 acpistate = ACPI_STATE_D0; 436 437 switch(acpistate) 438 { 439 case ACPI_STATE_D0: 440 ntState = PowerDeviceD0; 441 break; 442 case ACPI_STATE_D1: 443 ntState = PowerDeviceD1; 444 break; 445 case ACPI_STATE_D2: 446 ntState = PowerDeviceD2; 447 break; 448 case ACPI_STATE_D3: 449 ntState = PowerDeviceD3; 450 break; 451 default: 452 DPRINT1("Unknown power state (%d) returned by acpi\n",acpistate); 453 ntState = PowerDeviceUnspecified; 454 break; 455 } 456 457 // 458 // Initialize the rest 459 // 460 pdoData->Common.IsFDO = FALSE; 461 pdoData->Common.Self = Pdo; 462 463 pdoData->ParentFdo = FdoData->Common.Self; 464 465 466 INITIALIZE_PNP_STATE(pdoData->Common); 467 468 pdoData->Common.DevicePowerState = ntState; 469 pdoData->Common.SystemPowerState = FdoData->Common.SystemPowerState; 470 471 ExAcquireFastMutex (&FdoData->Mutex); 472 InsertTailList(&FdoData->ListOfPDOs, &pdoData->Link); 473 FdoData->NumPDOs++; 474 ExReleaseFastMutex (&FdoData->Mutex); 475 476 // This should be the last step in initialization. 477 Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 478 479 } 480 481 #if DBG 482 483 PCHAR 484 PnPMinorFunctionString ( 485 UCHAR MinorFunction 486 ) 487 { 488 switch (MinorFunction) 489 { 490 case IRP_MN_START_DEVICE: 491 return "IRP_MN_START_DEVICE"; 492 case IRP_MN_QUERY_REMOVE_DEVICE: 493 return "IRP_MN_QUERY_REMOVE_DEVICE"; 494 case IRP_MN_REMOVE_DEVICE: 495 return "IRP_MN_REMOVE_DEVICE"; 496 case IRP_MN_CANCEL_REMOVE_DEVICE: 497 return "IRP_MN_CANCEL_REMOVE_DEVICE"; 498 case IRP_MN_STOP_DEVICE: 499 return "IRP_MN_STOP_DEVICE"; 500 case IRP_MN_QUERY_STOP_DEVICE: 501 return "IRP_MN_QUERY_STOP_DEVICE"; 502 case IRP_MN_CANCEL_STOP_DEVICE: 503 return "IRP_MN_CANCEL_STOP_DEVICE"; 504 case IRP_MN_QUERY_DEVICE_RELATIONS: 505 return "IRP_MN_QUERY_DEVICE_RELATIONS"; 506 case IRP_MN_QUERY_INTERFACE: 507 return "IRP_MN_QUERY_INTERFACE"; 508 case IRP_MN_QUERY_CAPABILITIES: 509 return "IRP_MN_QUERY_CAPABILITIES"; 510 case IRP_MN_QUERY_RESOURCES: 511 return "IRP_MN_QUERY_RESOURCES"; 512 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 513 return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS"; 514 case IRP_MN_QUERY_DEVICE_TEXT: 515 return "IRP_MN_QUERY_DEVICE_TEXT"; 516 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 517 return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS"; 518 case IRP_MN_READ_CONFIG: 519 return "IRP_MN_READ_CONFIG"; 520 case IRP_MN_WRITE_CONFIG: 521 return "IRP_MN_WRITE_CONFIG"; 522 case IRP_MN_EJECT: 523 return "IRP_MN_EJECT"; 524 case IRP_MN_SET_LOCK: 525 return "IRP_MN_SET_LOCK"; 526 case IRP_MN_QUERY_ID: 527 return "IRP_MN_QUERY_ID"; 528 case IRP_MN_QUERY_PNP_DEVICE_STATE: 529 return "IRP_MN_QUERY_PNP_DEVICE_STATE"; 530 case IRP_MN_QUERY_BUS_INFORMATION: 531 return "IRP_MN_QUERY_BUS_INFORMATION"; 532 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 533 return "IRP_MN_DEVICE_USAGE_NOTIFICATION"; 534 case IRP_MN_SURPRISE_REMOVAL: 535 return "IRP_MN_SURPRISE_REMOVAL"; 536 case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: 537 return "IRP_MN_QUERY_LEGACY_BUS_INFORMATION"; 538 default: 539 return "unknown_pnp_irp"; 540 } 541 } 542 543 PCHAR 544 DbgDeviceRelationString( 545 DEVICE_RELATION_TYPE Type 546 ) 547 { 548 switch (Type) 549 { 550 case BusRelations: 551 return "BusRelations"; 552 case EjectionRelations: 553 return "EjectionRelations"; 554 case RemovalRelations: 555 return "RemovalRelations"; 556 case TargetDeviceRelation: 557 return "TargetDeviceRelation"; 558 default: 559 return "UnKnown Relation"; 560 } 561 } 562 563 PCHAR 564 DbgDeviceIDString( 565 BUS_QUERY_ID_TYPE Type 566 ) 567 { 568 switch (Type) 569 { 570 case BusQueryDeviceID: 571 return "BusQueryDeviceID"; 572 case BusQueryHardwareIDs: 573 return "BusQueryHardwareIDs"; 574 case BusQueryCompatibleIDs: 575 return "BusQueryCompatibleIDs"; 576 case BusQueryInstanceID: 577 return "BusQueryInstanceID"; 578 case BusQueryDeviceSerialNumber: 579 return "BusQueryDeviceSerialNumber"; 580 default: 581 return "UnKnown ID"; 582 } 583 } 584 585 #endif 586 587 588