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