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
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 SINGLE_LIST_ENTRY PciFdoExtensionListHead
;
18 BOOLEAN PciBreakOnDefault
;
20 PCI_MN_DISPATCH_TABLE PciFdoDispatchPowerTable
[] =
22 {IRP_DISPATCH
, PciFdoWaitWake
},
23 {IRP_DOWNWARD
, PciIrpNotSupported
},
24 {IRP_DOWNWARD
, PciFdoSetPowerState
},
25 {IRP_DOWNWARD
, PciFdoIrpQueryPower
},
26 {IRP_DOWNWARD
, PciIrpNotSupported
}
29 PCI_MN_DISPATCH_TABLE PciFdoDispatchPnpTable
[] =
31 {IRP_UPWARD
, PciFdoIrpStartDevice
},
32 {IRP_DOWNWARD
, PciFdoIrpQueryRemoveDevice
},
33 {IRP_DISPATCH
, PciFdoIrpRemoveDevice
},
34 {IRP_DOWNWARD
, PciFdoIrpCancelRemoveDevice
},
35 {IRP_DOWNWARD
, PciFdoIrpStopDevice
},
36 {IRP_DOWNWARD
, PciFdoIrpQueryStopDevice
},
37 {IRP_DOWNWARD
, PciFdoIrpCancelStopDevice
},
38 {IRP_DOWNWARD
, PciFdoIrpQueryDeviceRelations
},
39 {IRP_DISPATCH
, PciFdoIrpQueryInterface
},
40 {IRP_UPWARD
, PciFdoIrpQueryCapabilities
},
41 {IRP_DOWNWARD
, PciIrpNotSupported
},
42 {IRP_DOWNWARD
, PciIrpNotSupported
},
43 {IRP_DOWNWARD
, PciIrpNotSupported
},
44 {IRP_DOWNWARD
, PciIrpNotSupported
},
45 {IRP_DOWNWARD
, PciIrpNotSupported
},
46 {IRP_DOWNWARD
, PciIrpNotSupported
},
47 {IRP_DOWNWARD
, PciIrpNotSupported
},
48 {IRP_DOWNWARD
, PciIrpNotSupported
},
49 {IRP_DOWNWARD
, PciIrpNotSupported
},
50 {IRP_DOWNWARD
, PciIrpNotSupported
},
51 {IRP_DOWNWARD
, PciIrpNotSupported
},
52 {IRP_DOWNWARD
, PciIrpNotSupported
},
53 {IRP_UPWARD
, PciFdoIrpDeviceUsageNotification
},
54 {IRP_DOWNWARD
, PciFdoIrpSurpriseRemoval
},
55 {IRP_DOWNWARD
, PciFdoIrpQueryLegacyBusInformation
},
56 {IRP_DOWNWARD
, PciIrpNotSupported
}
59 PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable
=
61 IRP_MN_QUERY_LEGACY_BUS_INFORMATION
,
62 PciFdoDispatchPnpTable
,
64 PciFdoDispatchPowerTable
,
71 /* FUNCTIONS ******************************************************************/
75 PciFdoIrpStartDevice(IN PIRP Irp
,
76 IN PIO_STACK_LOCATION IoStackLocation
,
77 IN PPCI_FDO_EXTENSION DeviceExtension
)
81 return STATUS_NOT_SUPPORTED
;
86 PciFdoIrpQueryRemoveDevice(IN PIRP Irp
,
87 IN PIO_STACK_LOCATION IoStackLocation
,
88 IN PPCI_FDO_EXTENSION DeviceExtension
)
92 return STATUS_NOT_SUPPORTED
;
97 PciFdoIrpRemoveDevice(IN PIRP Irp
,
98 IN PIO_STACK_LOCATION IoStackLocation
,
99 IN PPCI_FDO_EXTENSION DeviceExtension
)
103 return STATUS_NOT_SUPPORTED
;
108 PciFdoIrpCancelRemoveDevice(IN PIRP Irp
,
109 IN PIO_STACK_LOCATION IoStackLocation
,
110 IN PPCI_FDO_EXTENSION DeviceExtension
)
114 return STATUS_NOT_SUPPORTED
;
119 PciFdoIrpStopDevice(IN PIRP Irp
,
120 IN PIO_STACK_LOCATION IoStackLocation
,
121 IN PPCI_FDO_EXTENSION DeviceExtension
)
125 return STATUS_NOT_SUPPORTED
;
130 PciFdoIrpQueryStopDevice(IN PIRP Irp
,
131 IN PIO_STACK_LOCATION IoStackLocation
,
132 IN PPCI_FDO_EXTENSION DeviceExtension
)
136 return STATUS_NOT_SUPPORTED
;
141 PciFdoIrpCancelStopDevice(IN PIRP Irp
,
142 IN PIO_STACK_LOCATION IoStackLocation
,
143 IN PPCI_FDO_EXTENSION DeviceExtension
)
147 return STATUS_NOT_SUPPORTED
;
152 PciFdoIrpQueryDeviceRelations(IN PIRP Irp
,
153 IN PIO_STACK_LOCATION IoStackLocation
,
154 IN PPCI_FDO_EXTENSION DeviceExtension
)
158 return STATUS_NOT_SUPPORTED
;
163 PciFdoIrpQueryInterface(IN PIRP Irp
,
164 IN PIO_STACK_LOCATION IoStackLocation
,
165 IN PPCI_FDO_EXTENSION DeviceExtension
)
169 return STATUS_NOT_SUPPORTED
;
174 PciFdoIrpQueryCapabilities(IN PIRP Irp
,
175 IN PIO_STACK_LOCATION IoStackLocation
,
176 IN PPCI_FDO_EXTENSION DeviceExtension
)
180 return STATUS_NOT_SUPPORTED
;
185 PciFdoIrpDeviceUsageNotification(IN PIRP Irp
,
186 IN PIO_STACK_LOCATION IoStackLocation
,
187 IN PPCI_FDO_EXTENSION DeviceExtension
)
191 return STATUS_NOT_SUPPORTED
;
196 PciFdoIrpSurpriseRemoval(IN PIRP Irp
,
197 IN PIO_STACK_LOCATION IoStackLocation
,
198 IN PPCI_FDO_EXTENSION DeviceExtension
)
202 return STATUS_NOT_SUPPORTED
;
207 PciFdoIrpQueryLegacyBusInformation(IN PIRP Irp
,
208 IN PIO_STACK_LOCATION IoStackLocation
,
209 IN PPCI_FDO_EXTENSION DeviceExtension
)
213 return STATUS_NOT_SUPPORTED
;
218 PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension
)
220 ACPI_EVAL_INPUT_BUFFER InputBuffer
;
221 PACPI_EVAL_OUTPUT_BUFFER OutputBuffer
;
226 /* We should receive 4 parameters, per the HPP specification */
227 Length
= sizeof(ACPI_EVAL_OUTPUT_BUFFER
) + 4 * sizeof(ACPI_METHOD_ARGUMENT
);
229 /* Allocate the buffer to hold the parameters */
230 OutputBuffer
= ExAllocatePoolWithTag(PagedPool
, Length
, PCI_POOL_TAG
);
231 if (!OutputBuffer
) return;
233 /* Initialize the output and input buffers. The method is _HPP */
234 RtlZeroMemory(OutputBuffer
, Length
);
235 *(PULONG
)InputBuffer
.MethodName
= 'PPH_';
236 InputBuffer
.Signature
= ACPI_EVAL_INPUT_BUFFER_SIGNATURE
;
239 /* Send the IOCTL to the ACPI driver */
240 Status
= PciSendIoctl(FdoExtension
->PhysicalDeviceObject
,
241 IOCTL_ACPI_EVAL_METHOD
,
246 if (!NT_SUCCESS(Status
))
248 /* The method failed, check if we can salvage data from parent */
249 if (!PCI_IS_ROOT_FDO(FdoExtension
))
251 /* Copy the root bus' hot plug parameters */
252 FdoExtension
->HotPlugParameters
= FdoExtension
->ParentFdoExtension
->HotPlugParameters
;
255 /* Nothing more to do on this path */
259 /* ACPI sent back some data. 4 parameters are expected in the output */
260 if (OutputBuffer
->Count
!= 4) break;
262 /* HotPlug PCI Support not yet implemented */
267 /* Free the buffer and return */
268 ExFreePoolWithTag(OutputBuffer
, 0);
273 PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension
,
274 IN PDEVICE_OBJECT DeviceObject
,
275 IN PDEVICE_OBJECT PhysicalDeviceObject
)
277 /* Initialize the extension */
278 RtlZeroMemory(FdoExtension
, sizeof(PCI_FDO_EXTENSION
));
280 /* Setup the common fields */
281 FdoExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
282 FdoExtension
->FunctionalDeviceObject
= DeviceObject
;
283 FdoExtension
->ExtensionType
= PciFdoExtensionType
;
284 FdoExtension
->PowerState
.CurrentSystemState
= PowerSystemWorking
;
285 FdoExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
286 FdoExtension
->IrpDispatchTable
= &PciFdoDispatchTable
;
288 /* Initialize the extension locks */
289 KeInitializeEvent(&FdoExtension
->SecondaryExtLock
, SynchronizationEvent
, TRUE
);
290 KeInitializeEvent(&FdoExtension
->ChildListLock
, SynchronizationEvent
, TRUE
);
292 /* Initialize the default state */
293 PciInitializeState(FdoExtension
);
298 PciAddDevice(IN PDRIVER_OBJECT DriverObject
,
299 IN PDEVICE_OBJECT PhysicalDeviceObject
)
301 PCM_RESOURCE_LIST Descriptor
;
302 PDEVICE_OBJECT AttachedTo
;
303 PPCI_FDO_EXTENSION FdoExtension
;
304 PPCI_FDO_EXTENSION ParentExtension
;
305 PDEVICE_OBJECT DeviceObject
;
306 UCHAR Buffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
307 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
;
310 UNICODE_STRING ValueName
;
313 DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n",
314 PhysicalDeviceObject
, &PhysicalDeviceObject
->DriverObject
->DriverName
);
316 /* Zero out variables so failure path knows what to do */
320 /* Check if there's already a device extension for this bus */
321 ParentExtension
= PciFindParentPciFdoExtension(PhysicalDeviceObject
,
325 /* More than one PCI bus, this is not expected yet */
330 /* Create the FDO for the bus */
331 Status
= IoCreateDevice(DriverObject
,
332 sizeof(PCI_FDO_EXTENSION
),
334 FILE_DEVICE_BUS_EXTENDER
,
338 if (!NT_SUCCESS(Status
)) break;
340 /* Initialize the extension for the FDO */
341 FdoExtension
= DeviceObject
->DeviceExtension
;
342 PciInitializeFdoExtensionCommonFields(DeviceObject
->DeviceExtension
,
344 PhysicalDeviceObject
);
346 /* Attach to the root PDO */
347 Status
= STATUS_NO_SUCH_DEVICE
;
348 AttachedTo
= IoAttachDeviceToDeviceStack(DeviceObject
,
349 PhysicalDeviceObject
);
350 ASSERT(AttachedTo
!= NULL
);
351 if (!AttachedTo
) break;
352 FdoExtension
->AttachedDeviceObject
= AttachedTo
;
355 /* More than one PCI bus, this is not expected yet */
361 /* Query the boot configuration */
362 Status
= PciGetDeviceProperty(PhysicalDeviceObject
,
363 DevicePropertyBootConfiguration
,
364 (PVOID
*)&Descriptor
);
365 if (!NT_SUCCESS(Status
))
367 /* No configuration has been set */
372 /* Root PDO in ReactOS does not assign boot resources */
379 /* Root PDO in ReactOS does not assign boot resources */
385 /* Default configuration isn't the normal path on Windows */
386 if (PciBreakOnDefault
)
388 /* If a second bus is found and there's still no data, crash */
389 KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL
,
391 (ULONG_PTR
)DeviceObject
,
396 /* Warn that a default configuration will be used, and set bus 0 */
397 DPRINT1("PCI Will use default configuration.\n");
398 PciBreakOnDefault
= TRUE
;
399 FdoExtension
->BaseBus
= 0;
402 /* This is the root bus */
403 FdoExtension
->BusRootFdoExtension
= FdoExtension
;
406 /* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */
407 Status
= PciGetConfigHandlers(FdoExtension
);
408 if (!NT_SUCCESS(Status
)) break;
410 /* Initialize all the supported PCI arbiters */
411 Status
= PciInitializeArbiters(FdoExtension
);
412 if (!NT_SUCCESS(Status
)) break;
414 /* This is a real FDO, insert it into the list */
415 FdoExtension
->Fake
= FALSE
;
416 PciInsertEntryAtTail(&PciFdoExtensionListHead
,
420 /* Open the device registry key so that we can query the errata flags */
421 IoOpenDeviceRegistryKey(DeviceObject
,
422 PLUGPLAY_REGKEY_DEVICE
,
426 /* Open the value that contains errata flags for this bus instance */
427 RtlInitUnicodeString(&ValueName
, L
"HackFlags");
428 Status
= ZwQueryValueKey(KeyHandle
,
430 KeyValuePartialInformation
,
435 if (NT_SUCCESS(Status
))
437 /* Make sure the data is of expected type and size */
438 if ((ValueInfo
->Type
== REG_DWORD
) &&
439 (ValueInfo
->DataLength
== sizeof(ULONG
)))
441 /* Read the flags for this bus */
442 FdoExtension
->BusHackFlags
= *(PULONG
)&ValueInfo
->Data
;
446 /* Query ACPI for PCI HotPlug Support */
447 PciGetHotPlugParameters(FdoExtension
);
449 /* The Bus FDO is now initialized */
450 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
451 DPRINT1("PCI Root FDO Added: %p %p\n", DeviceObject
, FdoExtension
);
452 return STATUS_SUCCESS
;
455 /* This is the failure path */
456 ASSERT(!NT_SUCCESS(Status
));
457 if (AttachedTo
) IoDetachDevice(AttachedTo
);
458 if (DeviceObject
) IoDeleteDevice(DeviceObject
);