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