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
)
82 UNREFERENCED_PARAMETER(Irp
);
83 UNREFERENCED_PARAMETER(IoStackLocation
);
84 UNREFERENCED_PARAMETER(DeviceExtension
);
86 UNIMPLEMENTED_DBGBREAK();
87 return STATUS_NOT_SUPPORTED
;
92 PciPdoSetPowerState(IN PIRP Irp
,
93 IN PIO_STACK_LOCATION IoStackLocation
,
94 IN PPCI_PDO_EXTENSION DeviceExtension
)
96 UNREFERENCED_PARAMETER(Irp
);
97 UNREFERENCED_PARAMETER(IoStackLocation
);
98 UNREFERENCED_PARAMETER(DeviceExtension
);
101 return STATUS_NOT_SUPPORTED
;
106 PciPdoIrpQueryPower(IN PIRP Irp
,
107 IN PIO_STACK_LOCATION IoStackLocation
,
108 IN PPCI_PDO_EXTENSION DeviceExtension
)
110 UNREFERENCED_PARAMETER(Irp
);
111 UNREFERENCED_PARAMETER(IoStackLocation
);
112 UNREFERENCED_PARAMETER(DeviceExtension
);
114 UNIMPLEMENTED_DBGBREAK();
115 return STATUS_NOT_SUPPORTED
;
120 PciPdoIrpStartDevice(IN PIRP Irp
,
121 IN PIO_STACK_LOCATION IoStackLocation
,
122 IN PPCI_PDO_EXTENSION DeviceExtension
)
125 BOOLEAN Changed
, DoReset
;
126 POWER_STATE PowerState
;
129 UNREFERENCED_PARAMETER(Irp
);
133 /* Begin entering the start phase */
134 Status
= PciBeginStateTransition((PVOID
)DeviceExtension
, PciStarted
);
135 if (!NT_SUCCESS(Status
)) return Status
;
137 /* Check if this is a VGA device */
138 if (((DeviceExtension
->BaseClass
== PCI_CLASS_PRE_20
) &&
139 (DeviceExtension
->SubClass
== PCI_SUBCLASS_PRE_20_VGA
)) ||
140 ((DeviceExtension
->BaseClass
== PCI_CLASS_DISPLAY_CTLR
) &&
141 (DeviceExtension
->SubClass
== PCI_SUBCLASS_VID_VGA_CTLR
)))
143 /* Always force it on */
144 DeviceExtension
->CommandEnables
|= (PCI_ENABLE_IO_SPACE
|
145 PCI_ENABLE_MEMORY_SPACE
);
148 /* Check if native IDE is enabled and it owns the I/O ports */
149 if (DeviceExtension
->IoSpaceUnderNativeIdeControl
)
151 /* Then don't allow I/O access */
152 DeviceExtension
->CommandEnables
&= ~PCI_ENABLE_IO_SPACE
;
155 /* Always enable bus mastering */
156 DeviceExtension
->CommandEnables
|= PCI_ENABLE_BUS_MASTER
;
158 /* Check if the OS assigned resources differ from the PCI configuration */
159 Changed
= PciComputeNewCurrentSettings(DeviceExtension
,
160 IoStackLocation
->Parameters
.
161 StartDevice
.AllocatedResources
);
164 /* Remember this for later */
165 DeviceExtension
->MovedDevice
= TRUE
;
170 DPRINT1("PCI - START not changing resource settings.\n");
173 /* Check if the device was sleeping */
174 if (DeviceExtension
->PowerState
.CurrentDeviceState
!= PowerDeviceD0
)
177 Status
= PciSetPowerManagedDevicePowerState(DeviceExtension
,
180 if (!NT_SUCCESS(Status
))
182 /* Powerup fail, fail the request */
183 PciCancelStateTransition((PVOID
)DeviceExtension
, PciStarted
);
184 return STATUS_DEVICE_POWER_FAILURE
;
187 /* Tell the power manager that the device is powered up */
188 PowerState
.DeviceState
= PowerDeviceD0
;
189 PoSetPowerState(DeviceExtension
->PhysicalDeviceObject
,
193 /* Update internal state */
194 DeviceExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
196 /* This device's resources and decodes will need to be reset */
200 /* Update resource information now that the device is powered up and active */
201 Status
= PciSetResources(DeviceExtension
, DoReset
, TRUE
);
202 if (!NT_SUCCESS(Status
))
204 /* That failed, so cancel the transition */
205 PciCancelStateTransition((PVOID
)DeviceExtension
, PciStarted
);
209 /* Fully commit, as the device is now started up and ready to go */
210 PciCommitStateTransition((PVOID
)DeviceExtension
, PciStarted
);
213 /* Return the result of the start request */
219 PciPdoIrpQueryRemoveDevice(IN PIRP Irp
,
220 IN PIO_STACK_LOCATION IoStackLocation
,
221 IN PPCI_PDO_EXTENSION DeviceExtension
)
223 UNREFERENCED_PARAMETER(Irp
);
224 UNREFERENCED_PARAMETER(IoStackLocation
);
225 UNREFERENCED_PARAMETER(DeviceExtension
);
228 return STATUS_NOT_SUPPORTED
;
233 PciPdoIrpRemoveDevice(IN PIRP Irp
,
234 IN PIO_STACK_LOCATION IoStackLocation
,
235 IN PPCI_PDO_EXTENSION DeviceExtension
)
237 UNREFERENCED_PARAMETER(Irp
);
238 UNREFERENCED_PARAMETER(IoStackLocation
);
239 UNREFERENCED_PARAMETER(DeviceExtension
);
241 UNIMPLEMENTED_DBGBREAK();
242 return STATUS_NOT_SUPPORTED
;
247 PciPdoIrpCancelRemoveDevice(IN PIRP Irp
,
248 IN PIO_STACK_LOCATION IoStackLocation
,
249 IN PPCI_PDO_EXTENSION DeviceExtension
)
251 UNREFERENCED_PARAMETER(Irp
);
252 UNREFERENCED_PARAMETER(IoStackLocation
);
253 UNREFERENCED_PARAMETER(DeviceExtension
);
255 UNIMPLEMENTED_DBGBREAK();
256 return STATUS_NOT_SUPPORTED
;
261 PciPdoIrpStopDevice(IN PIRP Irp
,
262 IN PIO_STACK_LOCATION IoStackLocation
,
263 IN PPCI_PDO_EXTENSION DeviceExtension
)
265 UNREFERENCED_PARAMETER(Irp
);
266 UNREFERENCED_PARAMETER(IoStackLocation
);
267 UNREFERENCED_PARAMETER(DeviceExtension
);
269 UNIMPLEMENTED_DBGBREAK();
270 return STATUS_NOT_SUPPORTED
;
275 PciPdoIrpQueryStopDevice(IN PIRP Irp
,
276 IN PIO_STACK_LOCATION IoStackLocation
,
277 IN PPCI_PDO_EXTENSION DeviceExtension
)
279 UNREFERENCED_PARAMETER(Irp
);
280 UNREFERENCED_PARAMETER(IoStackLocation
);
281 UNREFERENCED_PARAMETER(DeviceExtension
);
283 UNIMPLEMENTED_DBGBREAK();
284 return STATUS_NOT_SUPPORTED
;
289 PciPdoIrpCancelStopDevice(IN PIRP Irp
,
290 IN PIO_STACK_LOCATION IoStackLocation
,
291 IN PPCI_PDO_EXTENSION DeviceExtension
)
293 UNREFERENCED_PARAMETER(Irp
);
294 UNREFERENCED_PARAMETER(IoStackLocation
);
295 UNREFERENCED_PARAMETER(DeviceExtension
);
297 UNIMPLEMENTED_DBGBREAK();
298 return STATUS_NOT_SUPPORTED
;
303 PciPdoIrpQueryInterface(IN PIRP Irp
,
304 IN PIO_STACK_LOCATION IoStackLocation
,
305 IN PPCI_PDO_EXTENSION DeviceExtension
)
307 UNREFERENCED_PARAMETER(Irp
);
308 UNREFERENCED_PARAMETER(IoStackLocation
);
309 UNREFERENCED_PARAMETER(DeviceExtension
);
311 UNIMPLEMENTED_DBGBREAK();
312 return STATUS_NOT_SUPPORTED
;
317 PciPdoIrpQueryDeviceRelations(IN PIRP Irp
,
318 IN PIO_STACK_LOCATION IoStackLocation
,
319 IN PPCI_PDO_EXTENSION DeviceExtension
)
324 /* Are ejection relations being queried? */
325 if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== EjectionRelations
)
327 /* Call the worker function */
328 Status
= PciQueryEjectionRelations(DeviceExtension
,
329 (PDEVICE_RELATIONS
*)&Irp
->
330 IoStatus
.Information
);
332 else if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
334 /* The only other relation supported is the target device relation */
335 Status
= PciQueryTargetDeviceRelations(DeviceExtension
,
336 (PDEVICE_RELATIONS
*)&Irp
->
337 IoStatus
.Information
);
341 /* All other relations are unsupported */
342 Status
= STATUS_NOT_SUPPORTED
;
345 /* Return either the result of the worker function, or unsupported status */
351 PciPdoIrpQueryCapabilities(IN PIRP Irp
,
352 IN PIO_STACK_LOCATION IoStackLocation
,
353 IN PPCI_PDO_EXTENSION DeviceExtension
)
357 UNREFERENCED_PARAMETER(Irp
);
359 /* Call the worker function */
360 return PciQueryCapabilities(DeviceExtension
,
362 Parameters
.DeviceCapabilities
.Capabilities
);
367 PciPdoIrpQueryResources(IN PIRP Irp
,
368 IN PIO_STACK_LOCATION IoStackLocation
,
369 IN PPCI_PDO_EXTENSION DeviceExtension
)
373 UNREFERENCED_PARAMETER(IoStackLocation
);
375 /* Call the worker function */
376 return PciQueryResources(DeviceExtension
,
377 (PCM_RESOURCE_LIST
*)&Irp
->IoStatus
.Information
);
382 PciPdoIrpQueryResourceRequirements(IN PIRP Irp
,
383 IN PIO_STACK_LOCATION IoStackLocation
,
384 IN PPCI_PDO_EXTENSION DeviceExtension
)
388 UNREFERENCED_PARAMETER(IoStackLocation
);
390 /* Call the worker function */
391 return PciQueryRequirements(DeviceExtension
,
392 (PIO_RESOURCE_REQUIREMENTS_LIST
*)&Irp
->
393 IoStatus
.Information
);
398 PciPdoIrpQueryDeviceText(IN PIRP Irp
,
399 IN PIO_STACK_LOCATION IoStackLocation
,
400 IN PPCI_PDO_EXTENSION DeviceExtension
)
404 /* Call the worker function */
405 return PciQueryDeviceText(DeviceExtension
,
407 Parameters
.QueryDeviceText
.DeviceTextType
,
409 Parameters
.QueryDeviceText
.LocaleId
,
410 (PWCHAR
*)&Irp
->IoStatus
.Information
);
415 PciPdoIrpQueryId(IN PIRP Irp
,
416 IN PIO_STACK_LOCATION IoStackLocation
,
417 IN PPCI_PDO_EXTENSION DeviceExtension
)
421 /* Call the worker function */
422 return PciQueryId(DeviceExtension
,
423 IoStackLocation
->Parameters
.QueryId
.IdType
,
424 (PWCHAR
*)&Irp
->IoStatus
.Information
);
429 PciPdoIrpQueryBusInformation(IN PIRP Irp
,
430 IN PIO_STACK_LOCATION IoStackLocation
,
431 IN PPCI_PDO_EXTENSION DeviceExtension
)
435 UNREFERENCED_PARAMETER(IoStackLocation
);
437 /* Call the worker function */
438 return PciQueryBusInformation(DeviceExtension
,
439 (PPNP_BUS_INFORMATION
*)&Irp
->
440 IoStatus
.Information
);
445 PciPdoIrpReadConfig(IN PIRP Irp
,
446 IN PIO_STACK_LOCATION IoStackLocation
,
447 IN PPCI_PDO_EXTENSION DeviceExtension
)
449 UNREFERENCED_PARAMETER(Irp
);
450 UNREFERENCED_PARAMETER(IoStackLocation
);
451 UNREFERENCED_PARAMETER(DeviceExtension
);
453 UNIMPLEMENTED_DBGBREAK();
454 return STATUS_NOT_SUPPORTED
;
459 PciPdoIrpWriteConfig(IN PIRP Irp
,
460 IN PIO_STACK_LOCATION IoStackLocation
,
461 IN PPCI_PDO_EXTENSION DeviceExtension
)
463 UNREFERENCED_PARAMETER(Irp
);
464 UNREFERENCED_PARAMETER(IoStackLocation
);
465 UNREFERENCED_PARAMETER(DeviceExtension
);
467 UNIMPLEMENTED_DBGBREAK();
468 return STATUS_NOT_SUPPORTED
;
473 PciPdoIrpQueryDeviceState(IN PIRP Irp
,
474 IN PIO_STACK_LOCATION IoStackLocation
,
475 IN PPCI_PDO_EXTENSION DeviceExtension
)
477 UNREFERENCED_PARAMETER(Irp
);
478 UNREFERENCED_PARAMETER(IoStackLocation
);
479 UNREFERENCED_PARAMETER(DeviceExtension
);
482 return STATUS_NOT_SUPPORTED
;
487 PciPdoIrpDeviceUsageNotification(IN PIRP Irp
,
488 IN PIO_STACK_LOCATION IoStackLocation
,
489 IN PPCI_PDO_EXTENSION DeviceExtension
)
491 UNREFERENCED_PARAMETER(Irp
);
492 UNREFERENCED_PARAMETER(IoStackLocation
);
493 UNREFERENCED_PARAMETER(DeviceExtension
);
495 UNIMPLEMENTED_DBGBREAK();
496 return STATUS_NOT_SUPPORTED
;
501 PciPdoIrpSurpriseRemoval(IN PIRP Irp
,
502 IN PIO_STACK_LOCATION IoStackLocation
,
503 IN PPCI_PDO_EXTENSION DeviceExtension
)
505 UNREFERENCED_PARAMETER(Irp
);
506 UNREFERENCED_PARAMETER(IoStackLocation
);
507 UNREFERENCED_PARAMETER(DeviceExtension
);
509 UNIMPLEMENTED_DBGBREAK();
510 return STATUS_NOT_SUPPORTED
;
515 PciPdoIrpQueryLegacyBusInformation(IN PIRP Irp
,
516 IN PIO_STACK_LOCATION IoStackLocation
,
517 IN PPCI_PDO_EXTENSION DeviceExtension
)
519 UNREFERENCED_PARAMETER(Irp
);
520 UNREFERENCED_PARAMETER(IoStackLocation
);
521 UNREFERENCED_PARAMETER(DeviceExtension
);
523 UNIMPLEMENTED_DBGBREAK();
524 return STATUS_NOT_SUPPORTED
;
529 PciPdoCreate(IN PPCI_FDO_EXTENSION DeviceExtension
,
530 IN PCI_SLOT_NUMBER Slot
,
531 OUT PDEVICE_OBJECT
*PdoDeviceObject
)
533 WCHAR DeviceName
[32];
534 UNICODE_STRING DeviceString
;
536 PDEVICE_OBJECT DeviceObject
;
537 PPCI_PDO_EXTENSION PdoExtension
;
538 ULONG SequenceNumber
;
541 /* Pick an atomically unique sequence number for this device */
542 SequenceNumber
= InterlockedIncrement(&PciPdoSequenceNumber
);
544 /* Create the standard PCI device name for a PDO */
545 swprintf(DeviceName
, L
"\\Device\\NTPNP_PCI%04d", SequenceNumber
);
546 RtlInitUnicodeString(&DeviceString
, DeviceName
);
548 /* Create the actual device now */
549 Status
= IoCreateDevice(DeviceExtension
->FunctionalDeviceObject
->DriverObject
,
550 sizeof(PCI_PDO_EXTENSION
),
552 FILE_DEVICE_BUS_EXTENDER
,
556 ASSERT(NT_SUCCESS(Status
));
558 /* Get the extension for it */
559 PdoExtension
= (PPCI_PDO_EXTENSION
)DeviceObject
->DeviceExtension
;
560 DPRINT1("PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
561 DeviceExtension
->BaseBus
,
562 Slot
.u
.bits
.DeviceNumber
,
563 Slot
.u
.bits
.FunctionNumber
,
565 DeviceObject
->DeviceExtension
);
567 /* Configure the extension */
568 PdoExtension
->ExtensionType
= PciPdoExtensionType
;
569 PdoExtension
->IrpDispatchTable
= &PciPdoDispatchTable
;
570 PdoExtension
->PhysicalDeviceObject
= DeviceObject
;
571 PdoExtension
->Slot
= Slot
;
572 PdoExtension
->PowerState
.CurrentSystemState
= PowerDeviceD0
;
573 PdoExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
574 PdoExtension
->ParentFdoExtension
= DeviceExtension
;
576 /* Initialize the lock for arbiters and other interfaces */
577 KeInitializeEvent(&PdoExtension
->SecondaryExtLock
, SynchronizationEvent
, TRUE
);
579 /* Initialize the state machine */
580 PciInitializeState((PPCI_FDO_EXTENSION
)PdoExtension
);
582 /* Add the PDO to the parent's list */
583 PdoExtension
->Next
= NULL
;
584 PciInsertEntryAtTail((PSINGLE_LIST_ENTRY
)&DeviceExtension
->ChildPdoList
,
585 (PPCI_FDO_EXTENSION
)PdoExtension
,
586 &DeviceExtension
->ChildListLock
);
588 /* And finally return it to the caller */
589 *PdoDeviceObject
= DeviceObject
;
590 return STATUS_SUCCESS
;