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