2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/pdo.c
5 * PURPOSE: PDO Device Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 LONG PciPdoSequenceNumber
;
19 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION
, DeviceState
) == FIELD_OFFSET(PCI_PDO_EXTENSION
, DeviceState
));
20 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION
, TentativeNextState
) == FIELD_OFFSET(PCI_PDO_EXTENSION
, TentativeNextState
));
21 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION
, List
) == FIELD_OFFSET(PCI_PDO_EXTENSION
, Next
));
23 PCI_MN_DISPATCH_TABLE PciPdoDispatchPowerTable
[] =
25 {IRP_DISPATCH
, (PCI_DISPATCH_FUNCTION
)PciPdoWaitWake
},
26 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
27 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoSetPowerState
},
28 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryPower
},
29 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
}
32 PCI_MN_DISPATCH_TABLE PciPdoDispatchPnpTable
[] =
34 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpStartDevice
},
35 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryRemoveDevice
},
36 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpRemoveDevice
},
37 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpCancelRemoveDevice
},
38 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpStopDevice
},
39 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryStopDevice
},
40 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpCancelStopDevice
},
41 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryDeviceRelations
},
42 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryInterface
},
43 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryCapabilities
},
44 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryResources
},
45 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryResourceRequirements
},
46 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryDeviceText
},
47 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
48 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
49 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpReadConfig
},
50 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpWriteConfig
},
51 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
52 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
53 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryId
},
54 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryDeviceState
},
55 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryBusInformation
},
56 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpDeviceUsageNotification
},
57 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpSurpriseRemoval
},
58 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryLegacyBusInformation
},
59 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
}
62 PCI_MJ_DISPATCH_TABLE PciPdoDispatchTable
=
64 IRP_MN_QUERY_LEGACY_BUS_INFORMATION
,
65 PciPdoDispatchPnpTable
,
67 PciPdoDispatchPowerTable
,
69 (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
,
71 (PCI_DISPATCH_FUNCTION
)PciIrpInvalidDeviceRequest
74 /* FUNCTIONS ******************************************************************/
78 PciPdoWaitWake(IN PIRP Irp
,
79 IN PIO_STACK_LOCATION IoStackLocation
,
80 IN PPCI_PDO_EXTENSION DeviceExtension
)
84 return STATUS_NOT_SUPPORTED
;
89 PciPdoSetPowerState(IN PIRP Irp
,
90 IN PIO_STACK_LOCATION IoStackLocation
,
91 IN PPCI_PDO_EXTENSION DeviceExtension
)
95 return STATUS_NOT_SUPPORTED
;
100 PciPdoIrpQueryPower(IN PIRP Irp
,
101 IN PIO_STACK_LOCATION IoStackLocation
,
102 IN PPCI_PDO_EXTENSION DeviceExtension
)
106 return STATUS_NOT_SUPPORTED
;
111 PciPdoIrpStartDevice(IN PIRP Irp
,
112 IN PIO_STACK_LOCATION IoStackLocation
,
113 IN PPCI_PDO_EXTENSION DeviceExtension
)
116 BOOLEAN Changed
, DoReset
;
117 POWER_STATE PowerState
;
122 /* Begin entering the start phase */
123 Status
= PciBeginStateTransition((PVOID
)DeviceExtension
, PciStarted
);
124 if (!NT_SUCCESS(Status
)) return Status
;
126 /* Check if this is a VGA device */
127 if (((DeviceExtension
->BaseClass
== PCI_CLASS_PRE_20
) &&
128 (DeviceExtension
->SubClass
== PCI_SUBCLASS_PRE_20_VGA
)) ||
129 ((DeviceExtension
->BaseClass
== PCI_CLASS_DISPLAY_CTLR
) &&
130 (DeviceExtension
->SubClass
== PCI_SUBCLASS_VID_VGA_CTLR
)))
132 /* Always force it on */
133 DeviceExtension
->CommandEnables
|= (PCI_ENABLE_IO_SPACE
|
134 PCI_ENABLE_MEMORY_SPACE
);
137 /* Check if native IDE is enabled and it owns the I/O ports */
138 if (DeviceExtension
->IoSpaceUnderNativeIdeControl
)
140 /* Then don't allow I/O access */
141 DeviceExtension
->CommandEnables
&= ~PCI_ENABLE_IO_SPACE
;
144 /* Always enable bus mastering */
145 DeviceExtension
->CommandEnables
|= PCI_ENABLE_BUS_MASTER
;
147 /* Check if the OS assigned resources differ from the PCI configuration */
148 Changed
= PciComputeNewCurrentSettings(DeviceExtension
,
149 IoStackLocation
->Parameters
.
150 StartDevice
.AllocatedResources
);
153 /* Remember this for later */
154 DeviceExtension
->MovedDevice
= TRUE
;
159 DPRINT1("PCI - START not changing resource settings.\n");
162 /* Check if the device was sleeping */
163 if (DeviceExtension
->PowerState
.CurrentDeviceState
!= PowerDeviceD0
)
166 Status
= PciSetPowerManagedDevicePowerState(DeviceExtension
,
169 if (!NT_SUCCESS(Status
))
171 /* Powerup fail, fail the request */
172 PciCancelStateTransition((PVOID
)DeviceExtension
, PciStarted
);
173 return STATUS_DEVICE_POWER_FAILURE
;
176 /* Tell the power manager that the device is powered up */
177 PowerState
.DeviceState
= PowerDeviceD0
;
178 PoSetPowerState(DeviceExtension
->PhysicalDeviceObject
,
182 /* Update internal state */
183 DeviceExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
185 /* This device's resources and decodes will need to be reset */
189 /* Update resource information now that the device is powered up and active */
190 Status
= PciSetResources(DeviceExtension
, DoReset
, TRUE
);
191 if (!NT_SUCCESS(Status
))
193 /* That failed, so cancel the transition */
194 PciCancelStateTransition((PVOID
)DeviceExtension
, PciStarted
);
198 /* Fully commit, as the device is now started up and ready to go */
199 PciCommitStateTransition((PVOID
)DeviceExtension
, PciStarted
);
202 /* Return the result of the start request */
208 PciPdoIrpQueryRemoveDevice(IN PIRP Irp
,
209 IN PIO_STACK_LOCATION IoStackLocation
,
210 IN PPCI_PDO_EXTENSION DeviceExtension
)
214 return STATUS_NOT_SUPPORTED
;
219 PciPdoIrpRemoveDevice(IN PIRP Irp
,
220 IN PIO_STACK_LOCATION IoStackLocation
,
221 IN PPCI_PDO_EXTENSION DeviceExtension
)
225 return STATUS_NOT_SUPPORTED
;
230 PciPdoIrpCancelRemoveDevice(IN PIRP Irp
,
231 IN PIO_STACK_LOCATION IoStackLocation
,
232 IN PPCI_PDO_EXTENSION DeviceExtension
)
236 return STATUS_NOT_SUPPORTED
;
241 PciPdoIrpStopDevice(IN PIRP Irp
,
242 IN PIO_STACK_LOCATION IoStackLocation
,
243 IN PPCI_PDO_EXTENSION DeviceExtension
)
247 return STATUS_NOT_SUPPORTED
;
252 PciPdoIrpQueryStopDevice(IN PIRP Irp
,
253 IN PIO_STACK_LOCATION IoStackLocation
,
254 IN PPCI_PDO_EXTENSION DeviceExtension
)
258 return STATUS_NOT_SUPPORTED
;
263 PciPdoIrpCancelStopDevice(IN PIRP Irp
,
264 IN PIO_STACK_LOCATION IoStackLocation
,
265 IN PPCI_PDO_EXTENSION DeviceExtension
)
269 return STATUS_NOT_SUPPORTED
;
274 PciPdoIrpQueryInterface(IN PIRP Irp
,
275 IN PIO_STACK_LOCATION IoStackLocation
,
276 IN PPCI_PDO_EXTENSION DeviceExtension
)
280 return STATUS_NOT_SUPPORTED
;
285 PciPdoIrpQueryDeviceRelations(IN PIRP Irp
,
286 IN PIO_STACK_LOCATION IoStackLocation
,
287 IN PPCI_PDO_EXTENSION DeviceExtension
)
292 /* Are ejection relations being queried? */
293 if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== EjectionRelations
)
295 /* Call the worker function */
296 Status
= PciQueryEjectionRelations(DeviceExtension
,
297 (PDEVICE_RELATIONS
*)&Irp
->
298 IoStatus
.Information
);
300 else if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
302 /* The only other relation supported is the target device relation */
303 Status
= PciQueryTargetDeviceRelations(DeviceExtension
,
304 (PDEVICE_RELATIONS
*)&Irp
->
305 IoStatus
.Information
);
309 /* All other relations are unsupported */
310 Status
= STATUS_NOT_SUPPORTED
;
313 /* Return either the result of the worker function, or unsupported status */
319 PciPdoIrpQueryCapabilities(IN PIRP Irp
,
320 IN PIO_STACK_LOCATION IoStackLocation
,
321 IN PPCI_PDO_EXTENSION DeviceExtension
)
325 /* Call the worker function */
326 return PciQueryCapabilities(DeviceExtension
,
328 Parameters
.DeviceCapabilities
.Capabilities
);
333 PciPdoIrpQueryResources(IN PIRP Irp
,
334 IN PIO_STACK_LOCATION IoStackLocation
,
335 IN PPCI_PDO_EXTENSION DeviceExtension
)
339 /* Call the worker function */
340 return PciQueryResources(DeviceExtension
,
341 (PCM_RESOURCE_LIST
*)&Irp
->IoStatus
.Information
);
346 PciPdoIrpQueryResourceRequirements(IN PIRP Irp
,
347 IN PIO_STACK_LOCATION IoStackLocation
,
348 IN PPCI_PDO_EXTENSION DeviceExtension
)
352 /* Call the worker function */
353 return PciQueryRequirements(DeviceExtension
,
354 (PIO_RESOURCE_REQUIREMENTS_LIST
*)&Irp
->
355 IoStatus
.Information
);
360 PciPdoIrpQueryDeviceText(IN PIRP Irp
,
361 IN PIO_STACK_LOCATION IoStackLocation
,
362 IN PPCI_PDO_EXTENSION DeviceExtension
)
366 /* Call the worker function */
367 return PciQueryDeviceText(DeviceExtension
,
369 Parameters
.QueryDeviceText
.DeviceTextType
,
371 Parameters
.QueryDeviceText
.LocaleId
,
372 (PWCHAR
*)&Irp
->IoStatus
.Information
);
377 PciPdoIrpQueryId(IN PIRP Irp
,
378 IN PIO_STACK_LOCATION IoStackLocation
,
379 IN PPCI_PDO_EXTENSION DeviceExtension
)
383 /* Call the worker function */
384 return PciQueryId(DeviceExtension
,
385 IoStackLocation
->Parameters
.QueryId
.IdType
,
386 (PWCHAR
*)&Irp
->IoStatus
.Information
);
391 PciPdoIrpQueryBusInformation(IN PIRP Irp
,
392 IN PIO_STACK_LOCATION IoStackLocation
,
393 IN PPCI_PDO_EXTENSION DeviceExtension
)
397 /* Call the worker function */
398 return PciQueryBusInformation(DeviceExtension
,
399 (PPNP_BUS_INFORMATION
*)&Irp
->
400 IoStatus
.Information
);
405 PciPdoIrpReadConfig(IN PIRP Irp
,
406 IN PIO_STACK_LOCATION IoStackLocation
,
407 IN PPCI_PDO_EXTENSION DeviceExtension
)
411 return STATUS_NOT_SUPPORTED
;
416 PciPdoIrpWriteConfig(IN PIRP Irp
,
417 IN PIO_STACK_LOCATION IoStackLocation
,
418 IN PPCI_PDO_EXTENSION DeviceExtension
)
422 return STATUS_NOT_SUPPORTED
;
427 PciPdoIrpQueryDeviceState(IN PIRP Irp
,
428 IN PIO_STACK_LOCATION IoStackLocation
,
429 IN PPCI_PDO_EXTENSION DeviceExtension
)
433 return STATUS_NOT_SUPPORTED
;
438 PciPdoIrpDeviceUsageNotification(IN PIRP Irp
,
439 IN PIO_STACK_LOCATION IoStackLocation
,
440 IN PPCI_PDO_EXTENSION DeviceExtension
)
444 return STATUS_NOT_SUPPORTED
;
449 PciPdoIrpSurpriseRemoval(IN PIRP Irp
,
450 IN PIO_STACK_LOCATION IoStackLocation
,
451 IN PPCI_PDO_EXTENSION DeviceExtension
)
455 return STATUS_NOT_SUPPORTED
;
460 PciPdoIrpQueryLegacyBusInformation(IN PIRP Irp
,
461 IN PIO_STACK_LOCATION IoStackLocation
,
462 IN PPCI_PDO_EXTENSION DeviceExtension
)
466 return STATUS_NOT_SUPPORTED
;
471 PciPdoCreate(IN PPCI_FDO_EXTENSION DeviceExtension
,
472 IN PCI_SLOT_NUMBER Slot
,
473 OUT PDEVICE_OBJECT
*PdoDeviceObject
)
475 WCHAR DeviceName
[32];
476 UNICODE_STRING DeviceString
;
478 PDEVICE_OBJECT DeviceObject
;
479 PPCI_PDO_EXTENSION PdoExtension
;
480 ULONG SequenceNumber
;
483 /* Pick an atomically unique sequence number for this device */
484 SequenceNumber
= InterlockedIncrement(&PciPdoSequenceNumber
);
486 /* Create the standard PCI device name for a PDO */
487 swprintf(DeviceName
, L
"\\Device\\NTPNP_PCI%04d", SequenceNumber
);
488 RtlInitUnicodeString(&DeviceString
, DeviceName
);
490 /* Create the actual device now */
491 Status
= IoCreateDevice(DeviceExtension
->FunctionalDeviceObject
->DriverObject
,
492 sizeof(PCI_PDO_EXTENSION
),
494 FILE_DEVICE_BUS_EXTENDER
,
498 ASSERT(NT_SUCCESS(Status
));
500 /* Get the extension for it */
501 PdoExtension
= (PPCI_PDO_EXTENSION
)DeviceObject
->DeviceExtension
;
502 DPRINT1("PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
503 DeviceExtension
->BaseBus
,
504 Slot
.u
.bits
.DeviceNumber
,
505 Slot
.u
.bits
.FunctionNumber
,
507 DeviceObject
->DeviceExtension
);
509 /* Configure the extension */
510 PdoExtension
->ExtensionType
= PciPdoExtensionType
;
511 PdoExtension
->IrpDispatchTable
= &PciPdoDispatchTable
;
512 PdoExtension
->PhysicalDeviceObject
= DeviceObject
;
513 PdoExtension
->Slot
= Slot
;
514 PdoExtension
->PowerState
.CurrentSystemState
= PowerDeviceD0
;
515 PdoExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
516 PdoExtension
->ParentFdoExtension
= DeviceExtension
;
518 /* Initialize the lock for arbiters and other interfaces */
519 KeInitializeEvent(&PdoExtension
->SecondaryExtLock
, SynchronizationEvent
, TRUE
);
521 /* Initialize the state machine */
522 PciInitializeState((PPCI_FDO_EXTENSION
)PdoExtension
);
524 /* Add the PDO to the parent's list */
525 PdoExtension
->Next
= NULL
;
526 PciInsertEntryAtTail((PSINGLE_LIST_ENTRY
)&DeviceExtension
->ChildPdoList
,
527 (PPCI_FDO_EXTENSION
)PdoExtension
,
528 &DeviceExtension
->ChildListLock
);
530 /* And finally return it to the caller */
531 *PdoDeviceObject
= DeviceObject
;
532 return STATUS_SUCCESS
;