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
PciFdoIrpStartDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpQueryRemoveDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpRemoveDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpCancelRemoveDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpStopDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpQueryStopDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpCancelStopDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpQueryDeviceRelations(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpQueryInterface(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpQueryCapabilities(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpDeviceUsageNotification(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpSurpriseRemoval(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciFdoIrpQueryLegacyBusInformation(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)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
PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension)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
PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension,IN PDEVICE_OBJECT DeviceObject,IN PDEVICE_OBJECT PhysicalDeviceObject)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
PciAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PhysicalDeviceObject)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