1 /* 2 * PROJECT: ReactOS PCI Bus Driver 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: drivers/bus/pci/fdo.c 5 * PURPOSE: FDO Device Management 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <pci.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS ********************************************************************/ 17 18 SINGLE_LIST_ENTRY PciFdoExtensionListHead; 19 BOOLEAN PciBreakOnDefault; 20 21 PCI_MN_DISPATCH_TABLE PciFdoDispatchPowerTable[] = 22 { 23 {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoWaitWake}, 24 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 25 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoSetPowerState}, 26 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryPower}, 27 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported} 28 }; 29 30 PCI_MN_DISPATCH_TABLE PciFdoDispatchPnpTable[] = 31 { 32 {IRP_UPWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpStartDevice}, 33 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryRemoveDevice}, 34 {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoIrpRemoveDevice}, 35 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpCancelRemoveDevice}, 36 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpStopDevice}, 37 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryStopDevice}, 38 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpCancelStopDevice}, 39 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryDeviceRelations}, 40 {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryInterface}, 41 {IRP_UPWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryCapabilities}, 42 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 43 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 44 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 45 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 46 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 47 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 48 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 49 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 50 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 51 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 52 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 53 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}, 54 {IRP_UPWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpDeviceUsageNotification}, 55 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpSurpriseRemoval}, 56 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryLegacyBusInformation}, 57 {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported} 58 }; 59 60 PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable = 61 { 62 IRP_MN_QUERY_LEGACY_BUS_INFORMATION, 63 PciFdoDispatchPnpTable, 64 IRP_MN_QUERY_POWER, 65 PciFdoDispatchPowerTable, 66 IRP_DOWNWARD, 67 (PCI_DISPATCH_FUNCTION)PciIrpNotSupported, 68 IRP_DOWNWARD, 69 (PCI_DISPATCH_FUNCTION)PciIrpNotSupported 70 }; 71 72 /* FUNCTIONS ******************************************************************/ 73 74 NTSTATUS 75 NTAPI 76 PciFdoIrpStartDevice(IN PIRP Irp, 77 IN PIO_STACK_LOCATION IoStackLocation, 78 IN PPCI_FDO_EXTENSION DeviceExtension) 79 { 80 NTSTATUS Status; 81 PCM_RESOURCE_LIST Resources; 82 PAGED_CODE(); 83 84 /* The device stack must be starting the FDO in a success path */ 85 if (!NT_SUCCESS(Irp->IoStatus.Status)) return STATUS_NOT_SUPPORTED; 86 87 /* Attempt to switch the state machine to the started state */ 88 Status = PciBeginStateTransition(DeviceExtension, PciStarted); 89 if (!NT_SUCCESS(Status)) return Status; 90 91 /* Check for any boot-provided resources */ 92 Resources = IoStackLocation->Parameters.StartDevice.AllocatedResources; 93 if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension))) 94 { 95 /* These resources would only be for non-root FDOs, unhandled for now */ 96 ASSERT(Resources->Count == 1); 97 UNIMPLEMENTED_DBGBREAK(); 98 } 99 100 /* Initialize the arbiter for this FDO */ 101 Status = PciInitializeArbiterRanges(DeviceExtension, Resources); 102 if (!NT_SUCCESS(Status)) 103 { 104 /* Cancel the transition if this failed */ 105 PciCancelStateTransition(DeviceExtension, PciStarted); 106 return Status; 107 } 108 109 /* Again, check for boot-provided resources for non-root FDO */ 110 if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension))) 111 { 112 /* Unhandled for now */ 113 ASSERT(Resources->Count == 1); 114 UNIMPLEMENTED_DBGBREAK(); 115 } 116 117 /* Commit the transition to the started state */ 118 PciCommitStateTransition(DeviceExtension, PciStarted); 119 return STATUS_SUCCESS; 120 } 121 122 NTSTATUS 123 NTAPI 124 PciFdoIrpQueryRemoveDevice(IN PIRP Irp, 125 IN PIO_STACK_LOCATION IoStackLocation, 126 IN PPCI_FDO_EXTENSION DeviceExtension) 127 { 128 UNREFERENCED_PARAMETER(Irp); 129 UNREFERENCED_PARAMETER(IoStackLocation); 130 UNREFERENCED_PARAMETER(DeviceExtension); 131 132 UNIMPLEMENTED; 133 return STATUS_NOT_SUPPORTED; 134 } 135 136 NTSTATUS 137 NTAPI 138 PciFdoIrpRemoveDevice(IN PIRP Irp, 139 IN PIO_STACK_LOCATION IoStackLocation, 140 IN PPCI_FDO_EXTENSION DeviceExtension) 141 { 142 UNREFERENCED_PARAMETER(Irp); 143 UNREFERENCED_PARAMETER(IoStackLocation); 144 UNREFERENCED_PARAMETER(DeviceExtension); 145 146 UNIMPLEMENTED_DBGBREAK(); 147 return STATUS_NOT_SUPPORTED; 148 } 149 150 NTSTATUS 151 NTAPI 152 PciFdoIrpCancelRemoveDevice(IN PIRP Irp, 153 IN PIO_STACK_LOCATION IoStackLocation, 154 IN PPCI_FDO_EXTENSION DeviceExtension) 155 { 156 UNREFERENCED_PARAMETER(Irp); 157 UNREFERENCED_PARAMETER(IoStackLocation); 158 UNREFERENCED_PARAMETER(DeviceExtension); 159 160 UNIMPLEMENTED_DBGBREAK(); 161 return STATUS_NOT_SUPPORTED; 162 } 163 164 NTSTATUS 165 NTAPI 166 PciFdoIrpStopDevice(IN PIRP Irp, 167 IN PIO_STACK_LOCATION IoStackLocation, 168 IN PPCI_FDO_EXTENSION DeviceExtension) 169 { 170 UNREFERENCED_PARAMETER(Irp); 171 UNREFERENCED_PARAMETER(IoStackLocation); 172 UNREFERENCED_PARAMETER(DeviceExtension); 173 174 UNIMPLEMENTED_DBGBREAK(); 175 return STATUS_NOT_SUPPORTED; 176 } 177 178 NTSTATUS 179 NTAPI 180 PciFdoIrpQueryStopDevice(IN PIRP Irp, 181 IN PIO_STACK_LOCATION IoStackLocation, 182 IN PPCI_FDO_EXTENSION DeviceExtension) 183 { 184 UNREFERENCED_PARAMETER(Irp); 185 UNREFERENCED_PARAMETER(IoStackLocation); 186 UNREFERENCED_PARAMETER(DeviceExtension); 187 188 UNIMPLEMENTED_DBGBREAK(); 189 return STATUS_NOT_SUPPORTED; 190 } 191 192 NTSTATUS 193 NTAPI 194 PciFdoIrpCancelStopDevice(IN PIRP Irp, 195 IN PIO_STACK_LOCATION IoStackLocation, 196 IN PPCI_FDO_EXTENSION DeviceExtension) 197 { 198 UNREFERENCED_PARAMETER(Irp); 199 UNREFERENCED_PARAMETER(IoStackLocation); 200 UNREFERENCED_PARAMETER(DeviceExtension); 201 202 UNIMPLEMENTED_DBGBREAK(); 203 return STATUS_NOT_SUPPORTED; 204 } 205 206 NTSTATUS 207 NTAPI 208 PciFdoIrpQueryDeviceRelations(IN PIRP Irp, 209 IN PIO_STACK_LOCATION IoStackLocation, 210 IN PPCI_FDO_EXTENSION DeviceExtension) 211 { 212 NTSTATUS Status; 213 PAGED_CODE(); 214 215 /* Are bus relations being queried? */ 216 if (IoStackLocation->Parameters.QueryDeviceRelations.Type != BusRelations) 217 { 218 /* The FDO is a bus, so only bus relations can be obtained */ 219 Status = STATUS_NOT_SUPPORTED; 220 } 221 else 222 { 223 /* Scan the PCI bus and build the device relations for the caller */ 224 Status = PciQueryDeviceRelations(DeviceExtension, 225 (PDEVICE_RELATIONS*) 226 &Irp->IoStatus.Information); 227 } 228 229 /* Return the enumeration status back */ 230 return Status; 231 } 232 233 NTSTATUS 234 NTAPI 235 PciFdoIrpQueryInterface(IN PIRP Irp, 236 IN PIO_STACK_LOCATION IoStackLocation, 237 IN PPCI_FDO_EXTENSION DeviceExtension) 238 { 239 NTSTATUS Status; 240 PAGED_CODE(); 241 ASSERT(DeviceExtension->ExtensionType == PciFdoExtensionType); 242 243 /* Deleted extensions don't respond to IRPs */ 244 if (DeviceExtension->DeviceState == PciDeleted) 245 { 246 /* Hand it back to try to deal with it */ 247 return PciPassIrpFromFdoToPdo(DeviceExtension, Irp); 248 } 249 250 /* Query our driver for this interface */ 251 Status = PciQueryInterface(DeviceExtension, 252 IoStackLocation->Parameters.QueryInterface. 253 InterfaceType, 254 IoStackLocation->Parameters.QueryInterface. 255 Size, 256 IoStackLocation->Parameters.QueryInterface. 257 Version, 258 IoStackLocation->Parameters.QueryInterface. 259 InterfaceSpecificData, 260 IoStackLocation->Parameters.QueryInterface. 261 Interface, 262 FALSE); 263 if (NT_SUCCESS(Status)) 264 { 265 /* We found it, let the PDO handle it */ 266 Irp->IoStatus.Status = Status; 267 return PciPassIrpFromFdoToPdo(DeviceExtension, Irp); 268 } 269 else if (Status == STATUS_NOT_SUPPORTED) 270 { 271 /* Otherwise, we can't handle it, let someone else down the stack try */ 272 Status = PciCallDownIrpStack(DeviceExtension, Irp); 273 if (Status == STATUS_NOT_SUPPORTED) 274 { 275 /* They can't either, try a last-resort interface lookup */ 276 Status = PciQueryInterface(DeviceExtension, 277 IoStackLocation->Parameters.QueryInterface. 278 InterfaceType, 279 IoStackLocation->Parameters.QueryInterface. 280 Size, 281 IoStackLocation->Parameters.QueryInterface. 282 Version, 283 IoStackLocation->Parameters.QueryInterface. 284 InterfaceSpecificData, 285 IoStackLocation->Parameters.QueryInterface. 286 Interface, 287 TRUE); 288 } 289 } 290 291 /* Has anyone claimed this interface yet? */ 292 if (Status == STATUS_NOT_SUPPORTED) 293 { 294 /* No, return the original IRP status */ 295 Status = Irp->IoStatus.Status; 296 } 297 else 298 { 299 /* Yes, set the new IRP status */ 300 Irp->IoStatus.Status = Status; 301 } 302 303 /* Complete this IRP */ 304 IoCompleteRequest(Irp, IO_NO_INCREMENT); 305 return Status; 306 } 307 308 NTSTATUS 309 NTAPI 310 PciFdoIrpQueryCapabilities(IN PIRP Irp, 311 IN PIO_STACK_LOCATION IoStackLocation, 312 IN PPCI_FDO_EXTENSION DeviceExtension) 313 { 314 PDEVICE_CAPABILITIES Capabilities; 315 PAGED_CODE(); 316 ASSERT_FDO(DeviceExtension); 317 318 UNREFERENCED_PARAMETER(Irp); 319 320 /* Get the capabilities */ 321 Capabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities; 322 323 /* Inherit wake levels and power mappings from the higher-up capabilities */ 324 DeviceExtension->PowerState.SystemWakeLevel = Capabilities->SystemWake; 325 DeviceExtension->PowerState.DeviceWakeLevel = Capabilities->DeviceWake; 326 RtlCopyMemory(DeviceExtension->PowerState.SystemStateMapping, 327 Capabilities->DeviceState, 328 sizeof(DeviceExtension->PowerState.SystemStateMapping)); 329 330 /* Dump the capabilities and return success */ 331 PciDebugDumpQueryCapabilities(Capabilities); 332 return STATUS_SUCCESS; 333 } 334 335 NTSTATUS 336 NTAPI 337 PciFdoIrpDeviceUsageNotification(IN PIRP Irp, 338 IN PIO_STACK_LOCATION IoStackLocation, 339 IN PPCI_FDO_EXTENSION DeviceExtension) 340 { 341 UNREFERENCED_PARAMETER(Irp); 342 UNREFERENCED_PARAMETER(IoStackLocation); 343 UNREFERENCED_PARAMETER(DeviceExtension); 344 345 UNIMPLEMENTED_DBGBREAK(); 346 return STATUS_NOT_SUPPORTED; 347 } 348 349 NTSTATUS 350 NTAPI 351 PciFdoIrpSurpriseRemoval(IN PIRP Irp, 352 IN PIO_STACK_LOCATION IoStackLocation, 353 IN PPCI_FDO_EXTENSION DeviceExtension) 354 { 355 UNREFERENCED_PARAMETER(Irp); 356 UNREFERENCED_PARAMETER(IoStackLocation); 357 UNREFERENCED_PARAMETER(DeviceExtension); 358 359 UNIMPLEMENTED_DBGBREAK(); 360 return STATUS_NOT_SUPPORTED; 361 } 362 363 NTSTATUS 364 NTAPI 365 PciFdoIrpQueryLegacyBusInformation(IN PIRP Irp, 366 IN PIO_STACK_LOCATION IoStackLocation, 367 IN PPCI_FDO_EXTENSION DeviceExtension) 368 { 369 UNREFERENCED_PARAMETER(Irp); 370 UNREFERENCED_PARAMETER(IoStackLocation); 371 UNREFERENCED_PARAMETER(DeviceExtension); 372 373 UNIMPLEMENTED_DBGBREAK(); 374 return STATUS_NOT_SUPPORTED; 375 } 376 377 VOID 378 NTAPI 379 PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension) 380 { 381 ACPI_EVAL_INPUT_BUFFER InputBuffer; 382 PACPI_EVAL_OUTPUT_BUFFER OutputBuffer; 383 ULONG Length; 384 NTSTATUS Status; 385 PAGED_CODE(); 386 387 /* We should receive 4 parameters, per the HPP specification */ 388 Length = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 4 * sizeof(ACPI_METHOD_ARGUMENT); 389 390 /* Allocate the buffer to hold the parameters */ 391 OutputBuffer = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG); 392 if (!OutputBuffer) return; 393 394 /* Initialize the output and input buffers. The method is _HPP */ 395 RtlZeroMemory(OutputBuffer, Length); 396 *(PULONG)InputBuffer.MethodName = 'PPH_'; 397 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; 398 do 399 { 400 /* Send the IOCTL to the ACPI driver */ 401 Status = PciSendIoctl(FdoExtension->PhysicalDeviceObject, 402 IOCTL_ACPI_EVAL_METHOD, 403 &InputBuffer, 404 sizeof(InputBuffer), 405 OutputBuffer, 406 Length); 407 if (!NT_SUCCESS(Status)) 408 { 409 /* The method failed, check if we can salvage data from parent */ 410 if (!PCI_IS_ROOT_FDO(FdoExtension)) 411 { 412 /* Copy the root bus' hot plug parameters */ 413 FdoExtension->HotPlugParameters = FdoExtension->ParentFdoExtension->HotPlugParameters; 414 } 415 416 /* Nothing more to do on this path */ 417 break; 418 } 419 420 /* ACPI sent back some data. 4 parameters are expected in the output */ 421 if (OutputBuffer->Count != 4) break; 422 423 /* HotPlug PCI Support not yet implemented */ 424 UNIMPLEMENTED_DBGBREAK(); 425 } while (FALSE); 426 427 /* Free the buffer and return */ 428 ExFreePoolWithTag(OutputBuffer, 0); 429 } 430 431 VOID 432 NTAPI 433 PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension, 434 IN PDEVICE_OBJECT DeviceObject, 435 IN PDEVICE_OBJECT PhysicalDeviceObject) 436 { 437 /* Initialize the extension */ 438 RtlZeroMemory(FdoExtension, sizeof(PCI_FDO_EXTENSION)); 439 440 /* Setup the common fields */ 441 FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject; 442 FdoExtension->FunctionalDeviceObject = DeviceObject; 443 FdoExtension->ExtensionType = PciFdoExtensionType; 444 FdoExtension->PowerState.CurrentSystemState = PowerSystemWorking; 445 FdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0; 446 FdoExtension->IrpDispatchTable = &PciFdoDispatchTable; 447 448 /* Initialize the extension locks */ 449 KeInitializeEvent(&FdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE); 450 KeInitializeEvent(&FdoExtension->ChildListLock, SynchronizationEvent, TRUE); 451 452 /* Initialize the default state */ 453 PciInitializeState(FdoExtension); 454 } 455 456 NTSTATUS 457 NTAPI 458 PciAddDevice(IN PDRIVER_OBJECT DriverObject, 459 IN PDEVICE_OBJECT PhysicalDeviceObject) 460 { 461 PCM_RESOURCE_LIST Descriptor; 462 PDEVICE_OBJECT AttachedTo; 463 PPCI_FDO_EXTENSION FdoExtension; 464 PPCI_FDO_EXTENSION ParentExtension; 465 PPCI_PDO_EXTENSION PdoExtension; 466 PDEVICE_OBJECT DeviceObject; 467 UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; 468 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer; 469 NTSTATUS Status; 470 HANDLE KeyHandle; 471 UNICODE_STRING ValueName; 472 ULONG ResultLength; 473 PAGED_CODE(); 474 DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n", 475 PhysicalDeviceObject, &PhysicalDeviceObject->DriverObject->DriverName); 476 477 /* Zero out variables so failure path knows what to do */ 478 AttachedTo = NULL; 479 FdoExtension = NULL; 480 PdoExtension = NULL; 481 DeviceObject = NULL; 482 483 do 484 { 485 /* Check if there's already a device extension for this bus */ 486 ParentExtension = PciFindParentPciFdoExtension(PhysicalDeviceObject, 487 &PciGlobalLock); 488 if (ParentExtension) 489 { 490 /* Make sure we find a real PDO */ 491 PdoExtension = PhysicalDeviceObject->DeviceExtension; 492 ASSERT_PDO(PdoExtension); 493 494 /* Make sure it's a PCI-to-PCI bridge */ 495 if ((PdoExtension->BaseClass != PCI_CLASS_BRIDGE_DEV) || 496 (PdoExtension->SubClass != PCI_SUBCLASS_BR_PCI_TO_PCI)) 497 { 498 /* This should never happen */ 499 DPRINT1("PCI - PciAddDevice for Non-Root/Non-PCI-PCI bridge,\n" 500 " Class %02x, SubClass %02x, will not add.\n", 501 PdoExtension->BaseClass, 502 PdoExtension->SubClass); 503 ASSERT((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) && 504 (PdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)); 505 506 /* Enter the failure path */ 507 Status = STATUS_INVALID_DEVICE_REQUEST; 508 break; 509 } 510 511 /* Subordinate bus on the bridge */ 512 DPRINT1("PCI - AddDevice (new bus is child of bus 0x%x).\n", 513 ParentExtension->BaseBus); 514 515 /* Make sure PCI bus numbers are configured */ 516 if (!PciAreBusNumbersConfigured(PdoExtension)) 517 { 518 /* This is a critical failure */ 519 DPRINT1("PCI - Bus numbers not configured for bridge (0x%x.0x%x.0x%x)\n", 520 ParentExtension->BaseBus, 521 PdoExtension->Slot.u.bits.DeviceNumber, 522 PdoExtension->Slot.u.bits.FunctionNumber); 523 524 /* Enter the failure path */ 525 Status = STATUS_INVALID_DEVICE_REQUEST; 526 break; 527 } 528 } 529 530 /* Create the FDO for the bus */ 531 Status = IoCreateDevice(DriverObject, 532 sizeof(PCI_FDO_EXTENSION), 533 NULL, 534 FILE_DEVICE_BUS_EXTENDER, 535 0, 536 0, 537 &DeviceObject); 538 if (!NT_SUCCESS(Status)) break; 539 540 /* Initialize the extension for the FDO */ 541 FdoExtension = DeviceObject->DeviceExtension; 542 PciInitializeFdoExtensionCommonFields(DeviceObject->DeviceExtension, 543 DeviceObject, 544 PhysicalDeviceObject); 545 546 /* Attach to the root PDO */ 547 Status = STATUS_NO_SUCH_DEVICE; 548 AttachedTo = IoAttachDeviceToDeviceStack(DeviceObject, 549 PhysicalDeviceObject); 550 ASSERT(AttachedTo != NULL); 551 if (!AttachedTo) break; 552 FdoExtension->AttachedDeviceObject = AttachedTo; 553 554 /* Check if this is a child bus, or the root */ 555 if (ParentExtension) 556 { 557 /* The child inherits root data */ 558 FdoExtension->BaseBus = PdoExtension->Dependent.type1.SecondaryBus; 559 FdoExtension->BusRootFdoExtension = ParentExtension->BusRootFdoExtension; 560 PdoExtension->BridgeFdoExtension = FdoExtension; 561 FdoExtension->ParentFdoExtension = ParentExtension; 562 } 563 else 564 { 565 /* Query the boot configuration */ 566 Status = PciGetDeviceProperty(PhysicalDeviceObject, 567 DevicePropertyBootConfiguration, 568 (PVOID*)&Descriptor); 569 if (!NT_SUCCESS(Status)) 570 { 571 /* No configuration has been set */ 572 Descriptor = NULL; 573 } 574 else 575 { 576 /* Root PDO in ReactOS does not assign boot resources */ 577 UNIMPLEMENTED_DBGBREAK("Encountered during setup\n"); 578 Descriptor = NULL; 579 } 580 581 if (Descriptor) 582 { 583 /* Root PDO in ReactOS does not assign boot resources */ 584 UNIMPLEMENTED_DBGBREAK(); 585 } 586 else 587 { 588 /* Default configuration isn't the normal path on Windows */ 589 if (PciBreakOnDefault) 590 { 591 /* If a second bus is found and there's still no data, crash */ 592 KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL, 593 0xDEAD0010u, 594 (ULONG_PTR)DeviceObject, 595 0, 596 0); 597 } 598 599 /* Warn that a default configuration will be used, and set bus 0 */ 600 DPRINT1("PCI Will use default configuration.\n"); 601 PciBreakOnDefault = TRUE; 602 FdoExtension->BaseBus = 0; 603 } 604 605 /* This is the root bus */ 606 FdoExtension->BusRootFdoExtension = FdoExtension; 607 } 608 609 /* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */ 610 Status = PciGetConfigHandlers(FdoExtension); 611 if (!NT_SUCCESS(Status)) break; 612 613 /* Initialize all the supported PCI arbiters */ 614 Status = PciInitializeArbiters(FdoExtension); 615 if (!NT_SUCCESS(Status)) break; 616 617 /* This is a real FDO, insert it into the list */ 618 FdoExtension->Fake = FALSE; 619 PciInsertEntryAtTail(&PciFdoExtensionListHead, 620 FdoExtension, 621 &PciGlobalLock); 622 623 /* Open the device registry key so that we can query the errata flags */ 624 IoOpenDeviceRegistryKey(DeviceObject, 625 PLUGPLAY_REGKEY_DEVICE, 626 KEY_ALL_ACCESS, 627 &KeyHandle), 628 629 /* Open the value that contains errata flags for this bus instance */ 630 RtlInitUnicodeString(&ValueName, L"HackFlags"); 631 Status = ZwQueryValueKey(KeyHandle, 632 &ValueName, 633 KeyValuePartialInformation, 634 ValueInfo, 635 sizeof(Buffer), 636 &ResultLength); 637 ZwClose(KeyHandle); 638 if (NT_SUCCESS(Status)) 639 { 640 /* Make sure the data is of expected type and size */ 641 if ((ValueInfo->Type == REG_DWORD) && 642 (ValueInfo->DataLength == sizeof(ULONG))) 643 { 644 /* Read the flags for this bus */ 645 FdoExtension->BusHackFlags = *(PULONG)&ValueInfo->Data; 646 } 647 } 648 649 /* Query ACPI for PCI HotPlug Support */ 650 PciGetHotPlugParameters(FdoExtension); 651 652 /* The Bus FDO is now initialized */ 653 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 654 return STATUS_SUCCESS; 655 } while (FALSE); 656 657 /* This is the failure path */ 658 ASSERT(!NT_SUCCESS(Status)); 659 660 /* Check if the FDO extension exists */ 661 if (FdoExtension) DPRINT1("Should destroy secondaries\n"); 662 663 /* Delete device objects */ 664 if (AttachedTo) IoDetachDevice(AttachedTo); 665 if (DeviceObject) IoDeleteDevice(DeviceObject); 666 return Status; 667 } 668 669 /* EOF */ 670