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 *******************************************************************/
16 /* GLOBALS ********************************************************************/
18 LONG PciPdoSequenceNumber
;
20 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION
, DeviceState
) == FIELD_OFFSET(PCI_PDO_EXTENSION
, DeviceState
));
21 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION
, TentativeNextState
) == FIELD_OFFSET(PCI_PDO_EXTENSION
, TentativeNextState
));
22 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION
, List
) == FIELD_OFFSET(PCI_PDO_EXTENSION
, Next
));
24 PCI_MN_DISPATCH_TABLE PciPdoDispatchPowerTable
[] =
26 {IRP_DISPATCH
, (PCI_DISPATCH_FUNCTION
)PciPdoWaitWake
},
27 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
28 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoSetPowerState
},
29 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryPower
},
30 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
}
33 PCI_MN_DISPATCH_TABLE PciPdoDispatchPnpTable
[] =
35 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpStartDevice
},
36 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryRemoveDevice
},
37 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpRemoveDevice
},
38 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpCancelRemoveDevice
},
39 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpStopDevice
},
40 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryStopDevice
},
41 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpCancelStopDevice
},
42 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryDeviceRelations
},
43 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryInterface
},
44 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryCapabilities
},
45 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryResources
},
46 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryResourceRequirements
},
47 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryDeviceText
},
48 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
49 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
50 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpReadConfig
},
51 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpWriteConfig
},
52 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
53 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
},
54 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryId
},
55 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryDeviceState
},
56 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryBusInformation
},
57 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpDeviceUsageNotification
},
58 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpSurpriseRemoval
},
59 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciPdoIrpQueryLegacyBusInformation
},
60 {IRP_COMPLETE
, (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
}
63 PCI_MJ_DISPATCH_TABLE PciPdoDispatchTable
=
65 IRP_MN_QUERY_LEGACY_BUS_INFORMATION
,
66 PciPdoDispatchPnpTable
,
68 PciPdoDispatchPowerTable
,
70 (PCI_DISPATCH_FUNCTION
)PciIrpNotSupported
,
72 (PCI_DISPATCH_FUNCTION
)PciIrpInvalidDeviceRequest
75 /* FUNCTIONS ******************************************************************/
79 PciPdoWaitWake(IN PIRP Irp
,
80 IN PIO_STACK_LOCATION IoStackLocation
,
81 IN PPCI_PDO_EXTENSION DeviceExtension
)
83 UNREFERENCED_PARAMETER(Irp
);
84 UNREFERENCED_PARAMETER(IoStackLocation
);
85 UNREFERENCED_PARAMETER(DeviceExtension
);
87 UNIMPLEMENTED_DBGBREAK();
88 return STATUS_NOT_SUPPORTED
;
93 PciPdoSetPowerState(IN PIRP Irp
,
94 IN PIO_STACK_LOCATION IoStackLocation
,
95 IN PPCI_PDO_EXTENSION DeviceExtension
)
97 UNREFERENCED_PARAMETER(Irp
);
98 UNREFERENCED_PARAMETER(IoStackLocation
);
99 UNREFERENCED_PARAMETER(DeviceExtension
);
102 return STATUS_NOT_SUPPORTED
;
107 PciPdoIrpQueryPower(IN PIRP Irp
,
108 IN PIO_STACK_LOCATION IoStackLocation
,
109 IN PPCI_PDO_EXTENSION DeviceExtension
)
111 UNREFERENCED_PARAMETER(Irp
);
112 UNREFERENCED_PARAMETER(IoStackLocation
);
113 UNREFERENCED_PARAMETER(DeviceExtension
);
115 UNIMPLEMENTED_DBGBREAK();
116 return STATUS_NOT_SUPPORTED
;
121 PciPdoIrpStartDevice(IN PIRP Irp
,
122 IN PIO_STACK_LOCATION IoStackLocation
,
123 IN PPCI_PDO_EXTENSION DeviceExtension
)
126 BOOLEAN Changed
, DoReset
;
127 POWER_STATE PowerState
;
130 UNREFERENCED_PARAMETER(Irp
);
134 /* Begin entering the start phase */
135 Status
= PciBeginStateTransition((PVOID
)DeviceExtension
, PciStarted
);
136 if (!NT_SUCCESS(Status
)) return Status
;
138 /* Check if this is a VGA device */
139 if (((DeviceExtension
->BaseClass
== PCI_CLASS_PRE_20
) &&
140 (DeviceExtension
->SubClass
== PCI_SUBCLASS_PRE_20_VGA
)) ||
141 ((DeviceExtension
->BaseClass
== PCI_CLASS_DISPLAY_CTLR
) &&
142 (DeviceExtension
->SubClass
== PCI_SUBCLASS_VID_VGA_CTLR
)))
144 /* Always force it on */
145 DeviceExtension
->CommandEnables
|= (PCI_ENABLE_IO_SPACE
|
146 PCI_ENABLE_MEMORY_SPACE
);
149 /* Check if native IDE is enabled and it owns the I/O ports */
150 if (DeviceExtension
->IoSpaceUnderNativeIdeControl
)
152 /* Then don't allow I/O access */
153 DeviceExtension
->CommandEnables
&= ~PCI_ENABLE_IO_SPACE
;
156 /* Always enable bus mastering */
157 DeviceExtension
->CommandEnables
|= PCI_ENABLE_BUS_MASTER
;
159 /* Check if the OS assigned resources differ from the PCI configuration */
160 Changed
= PciComputeNewCurrentSettings(DeviceExtension
,
161 IoStackLocation
->Parameters
.
162 StartDevice
.AllocatedResources
);
165 /* Remember this for later */
166 DeviceExtension
->MovedDevice
= TRUE
;
171 DPRINT1("PCI - START not changing resource settings.\n");
174 /* Check if the device was sleeping */
175 if (DeviceExtension
->PowerState
.CurrentDeviceState
!= PowerDeviceD0
)
178 Status
= PciSetPowerManagedDevicePowerState(DeviceExtension
,
181 if (!NT_SUCCESS(Status
))
183 /* Powerup fail, fail the request */
184 PciCancelStateTransition((PVOID
)DeviceExtension
, PciStarted
);
185 return STATUS_DEVICE_POWER_FAILURE
;
188 /* Tell the power manager that the device is powered up */
189 PowerState
.DeviceState
= PowerDeviceD0
;
190 PoSetPowerState(DeviceExtension
->PhysicalDeviceObject
,
194 /* Update internal state */
195 DeviceExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
197 /* This device's resources and decodes will need to be reset */
201 /* Update resource information now that the device is powered up and active */
202 Status
= PciSetResources(DeviceExtension
, DoReset
, TRUE
);
203 if (!NT_SUCCESS(Status
))
205 /* That failed, so cancel the transition */
206 PciCancelStateTransition((PVOID
)DeviceExtension
, PciStarted
);
210 /* Fully commit, as the device is now started up and ready to go */
211 PciCommitStateTransition((PVOID
)DeviceExtension
, PciStarted
);
214 /* Return the result of the start request */
220 PciPdoIrpQueryRemoveDevice(IN PIRP Irp
,
221 IN PIO_STACK_LOCATION IoStackLocation
,
222 IN PPCI_PDO_EXTENSION DeviceExtension
)
224 UNREFERENCED_PARAMETER(Irp
);
225 UNREFERENCED_PARAMETER(IoStackLocation
);
226 UNREFERENCED_PARAMETER(DeviceExtension
);
229 return STATUS_NOT_SUPPORTED
;
234 PciPdoIrpRemoveDevice(IN PIRP Irp
,
235 IN PIO_STACK_LOCATION IoStackLocation
,
236 IN PPCI_PDO_EXTENSION DeviceExtension
)
238 UNREFERENCED_PARAMETER(Irp
);
239 UNREFERENCED_PARAMETER(IoStackLocation
);
240 UNREFERENCED_PARAMETER(DeviceExtension
);
242 UNIMPLEMENTED_DBGBREAK();
243 return STATUS_NOT_SUPPORTED
;
248 PciPdoIrpCancelRemoveDevice(IN PIRP Irp
,
249 IN PIO_STACK_LOCATION IoStackLocation
,
250 IN PPCI_PDO_EXTENSION DeviceExtension
)
252 UNREFERENCED_PARAMETER(Irp
);
253 UNREFERENCED_PARAMETER(IoStackLocation
);
254 UNREFERENCED_PARAMETER(DeviceExtension
);
256 UNIMPLEMENTED_DBGBREAK();
257 return STATUS_NOT_SUPPORTED
;
262 PciPdoIrpStopDevice(IN PIRP Irp
,
263 IN PIO_STACK_LOCATION IoStackLocation
,
264 IN PPCI_PDO_EXTENSION DeviceExtension
)
266 UNREFERENCED_PARAMETER(Irp
);
267 UNREFERENCED_PARAMETER(IoStackLocation
);
268 UNREFERENCED_PARAMETER(DeviceExtension
);
270 UNIMPLEMENTED_DBGBREAK();
271 return STATUS_NOT_SUPPORTED
;
276 PciPdoIrpQueryStopDevice(IN PIRP Irp
,
277 IN PIO_STACK_LOCATION IoStackLocation
,
278 IN PPCI_PDO_EXTENSION DeviceExtension
)
280 UNREFERENCED_PARAMETER(Irp
);
281 UNREFERENCED_PARAMETER(IoStackLocation
);
282 UNREFERENCED_PARAMETER(DeviceExtension
);
284 UNIMPLEMENTED_DBGBREAK();
285 return STATUS_NOT_SUPPORTED
;
290 PciPdoIrpCancelStopDevice(IN PIRP Irp
,
291 IN PIO_STACK_LOCATION IoStackLocation
,
292 IN PPCI_PDO_EXTENSION DeviceExtension
)
294 UNREFERENCED_PARAMETER(Irp
);
295 UNREFERENCED_PARAMETER(IoStackLocation
);
296 UNREFERENCED_PARAMETER(DeviceExtension
);
298 UNIMPLEMENTED_DBGBREAK();
299 return STATUS_NOT_SUPPORTED
;
304 PciPdoIrpQueryInterface(IN PIRP Irp
,
305 IN PIO_STACK_LOCATION IoStackLocation
,
306 IN PPCI_PDO_EXTENSION DeviceExtension
)
308 UNREFERENCED_PARAMETER(Irp
);
309 UNREFERENCED_PARAMETER(IoStackLocation
);
310 UNREFERENCED_PARAMETER(DeviceExtension
);
312 UNIMPLEMENTED_DBGBREAK();
313 return STATUS_NOT_SUPPORTED
;
318 PciPdoIrpQueryDeviceRelations(IN PIRP Irp
,
319 IN PIO_STACK_LOCATION IoStackLocation
,
320 IN PPCI_PDO_EXTENSION DeviceExtension
)
325 /* Are ejection relations being queried? */
326 if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== EjectionRelations
)
328 /* Call the worker function */
329 Status
= PciQueryEjectionRelations(DeviceExtension
,
330 (PDEVICE_RELATIONS
*)&Irp
->
331 IoStatus
.Information
);
333 else if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
335 /* The only other relation supported is the target device relation */
336 Status
= PciQueryTargetDeviceRelations(DeviceExtension
,
337 (PDEVICE_RELATIONS
*)&Irp
->
338 IoStatus
.Information
);
342 /* All other relations are unsupported */
343 Status
= STATUS_NOT_SUPPORTED
;
346 /* Return either the result of the worker function, or unsupported status */
352 PciPdoIrpQueryCapabilities(IN PIRP Irp
,
353 IN PIO_STACK_LOCATION IoStackLocation
,
354 IN PPCI_PDO_EXTENSION DeviceExtension
)
358 UNREFERENCED_PARAMETER(Irp
);
360 /* Call the worker function */
361 return PciQueryCapabilities(DeviceExtension
,
363 Parameters
.DeviceCapabilities
.Capabilities
);
368 PciPdoIrpQueryResources(IN PIRP Irp
,
369 IN PIO_STACK_LOCATION IoStackLocation
,
370 IN PPCI_PDO_EXTENSION DeviceExtension
)
374 UNREFERENCED_PARAMETER(IoStackLocation
);
376 /* Call the worker function */
377 return PciQueryResources(DeviceExtension
,
378 (PCM_RESOURCE_LIST
*)&Irp
->IoStatus
.Information
);
383 PciPdoIrpQueryResourceRequirements(IN PIRP Irp
,
384 IN PIO_STACK_LOCATION IoStackLocation
,
385 IN PPCI_PDO_EXTENSION DeviceExtension
)
389 UNREFERENCED_PARAMETER(IoStackLocation
);
391 /* Call the worker function */
392 return PciQueryRequirements(DeviceExtension
,
393 (PIO_RESOURCE_REQUIREMENTS_LIST
*)&Irp
->
394 IoStatus
.Information
);
399 PciPdoIrpQueryDeviceText(IN PIRP Irp
,
400 IN PIO_STACK_LOCATION IoStackLocation
,
401 IN PPCI_PDO_EXTENSION DeviceExtension
)
405 /* Call the worker function */
406 return PciQueryDeviceText(DeviceExtension
,
408 Parameters
.QueryDeviceText
.DeviceTextType
,
410 Parameters
.QueryDeviceText
.LocaleId
,
411 (PWCHAR
*)&Irp
->IoStatus
.Information
);
416 PciPdoIrpQueryId(IN PIRP Irp
,
417 IN PIO_STACK_LOCATION IoStackLocation
,
418 IN PPCI_PDO_EXTENSION DeviceExtension
)
422 /* Call the worker function */
423 return PciQueryId(DeviceExtension
,
424 IoStackLocation
->Parameters
.QueryId
.IdType
,
425 (PWCHAR
*)&Irp
->IoStatus
.Information
);
430 PciPdoIrpQueryBusInformation(IN PIRP Irp
,
431 IN PIO_STACK_LOCATION IoStackLocation
,
432 IN PPCI_PDO_EXTENSION DeviceExtension
)
436 UNREFERENCED_PARAMETER(IoStackLocation
);
438 /* Call the worker function */
439 return PciQueryBusInformation(DeviceExtension
,
440 (PPNP_BUS_INFORMATION
*)&Irp
->
441 IoStatus
.Information
);
446 PciPdoIrpReadConfig(IN PIRP Irp
,
447 IN PIO_STACK_LOCATION IoStackLocation
,
448 IN PPCI_PDO_EXTENSION DeviceExtension
)
450 UNREFERENCED_PARAMETER(Irp
);
451 UNREFERENCED_PARAMETER(IoStackLocation
);
452 UNREFERENCED_PARAMETER(DeviceExtension
);
454 UNIMPLEMENTED_DBGBREAK();
455 return STATUS_NOT_SUPPORTED
;
460 PciPdoIrpWriteConfig(IN PIRP Irp
,
461 IN PIO_STACK_LOCATION IoStackLocation
,
462 IN PPCI_PDO_EXTENSION DeviceExtension
)
464 UNREFERENCED_PARAMETER(Irp
);
465 UNREFERENCED_PARAMETER(IoStackLocation
);
466 UNREFERENCED_PARAMETER(DeviceExtension
);
468 UNIMPLEMENTED_DBGBREAK();
469 return STATUS_NOT_SUPPORTED
;
474 PciPdoIrpQueryDeviceState(IN PIRP Irp
,
475 IN PIO_STACK_LOCATION IoStackLocation
,
476 IN PPCI_PDO_EXTENSION DeviceExtension
)
478 UNREFERENCED_PARAMETER(Irp
);
479 UNREFERENCED_PARAMETER(IoStackLocation
);
480 UNREFERENCED_PARAMETER(DeviceExtension
);
483 return STATUS_NOT_SUPPORTED
;
488 PciPdoIrpDeviceUsageNotification(IN PIRP Irp
,
489 IN PIO_STACK_LOCATION IoStackLocation
,
490 IN PPCI_PDO_EXTENSION DeviceExtension
)
492 UNREFERENCED_PARAMETER(Irp
);
493 UNREFERENCED_PARAMETER(IoStackLocation
);
494 UNREFERENCED_PARAMETER(DeviceExtension
);
496 UNIMPLEMENTED_DBGBREAK();
497 return STATUS_NOT_SUPPORTED
;
502 PciPdoIrpSurpriseRemoval(IN PIRP Irp
,
503 IN PIO_STACK_LOCATION IoStackLocation
,
504 IN PPCI_PDO_EXTENSION DeviceExtension
)
506 UNREFERENCED_PARAMETER(Irp
);
507 UNREFERENCED_PARAMETER(IoStackLocation
);
508 UNREFERENCED_PARAMETER(DeviceExtension
);
510 UNIMPLEMENTED_DBGBREAK();
511 return STATUS_NOT_SUPPORTED
;
516 PciPdoIrpQueryLegacyBusInformation(IN PIRP Irp
,
517 IN PIO_STACK_LOCATION IoStackLocation
,
518 IN PPCI_PDO_EXTENSION DeviceExtension
)
520 UNREFERENCED_PARAMETER(Irp
);
521 UNREFERENCED_PARAMETER(IoStackLocation
);
522 UNREFERENCED_PARAMETER(DeviceExtension
);
524 UNIMPLEMENTED_DBGBREAK();
525 return STATUS_NOT_SUPPORTED
;
530 PciPdoCreate(IN PPCI_FDO_EXTENSION DeviceExtension
,
531 IN PCI_SLOT_NUMBER Slot
,
532 OUT PDEVICE_OBJECT
*PdoDeviceObject
)
534 WCHAR DeviceName
[32];
535 UNICODE_STRING DeviceString
;
537 PDEVICE_OBJECT DeviceObject
;
538 PPCI_PDO_EXTENSION PdoExtension
;
539 ULONG SequenceNumber
;
542 /* Pick an atomically unique sequence number for this device */
543 SequenceNumber
= InterlockedIncrement(&PciPdoSequenceNumber
);
545 /* Create the standard PCI device name for a PDO */
546 swprintf(DeviceName
, L
"\\Device\\NTPNP_PCI%04d", SequenceNumber
);
547 RtlInitUnicodeString(&DeviceString
, DeviceName
);
549 /* Create the actual device now */
550 Status
= IoCreateDevice(DeviceExtension
->FunctionalDeviceObject
->DriverObject
,
551 sizeof(PCI_PDO_EXTENSION
),
553 FILE_DEVICE_BUS_EXTENDER
,
557 ASSERT(NT_SUCCESS(Status
));
559 /* Get the extension for it */
560 PdoExtension
= (PPCI_PDO_EXTENSION
)DeviceObject
->DeviceExtension
;
561 DPRINT1("PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
562 DeviceExtension
->BaseBus
,
563 Slot
.u
.bits
.DeviceNumber
,
564 Slot
.u
.bits
.FunctionNumber
,
566 DeviceObject
->DeviceExtension
);
568 /* Configure the extension */
569 PdoExtension
->ExtensionType
= PciPdoExtensionType
;
570 PdoExtension
->IrpDispatchTable
= &PciPdoDispatchTable
;
571 PdoExtension
->PhysicalDeviceObject
= DeviceObject
;
572 PdoExtension
->Slot
= Slot
;
573 PdoExtension
->PowerState
.CurrentSystemState
= PowerDeviceD0
;
574 PdoExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
575 PdoExtension
->ParentFdoExtension
= DeviceExtension
;
577 /* Initialize the lock for arbiters and other interfaces */
578 KeInitializeEvent(&PdoExtension
->SecondaryExtLock
, SynchronizationEvent
, TRUE
);
580 /* Initialize the state machine */
581 PciInitializeState((PPCI_FDO_EXTENSION
)PdoExtension
);
583 /* Add the PDO to the parent's list */
584 PdoExtension
->Next
= NULL
;
585 PciInsertEntryAtTail((PSINGLE_LIST_ENTRY
)&DeviceExtension
->ChildPdoList
,
586 (PPCI_FDO_EXTENSION
)PdoExtension
,
587 &DeviceExtension
->ChildListLock
);
589 /* And finally return it to the caller */
590 *PdoDeviceObject
= DeviceObject
;
591 return STATUS_SUCCESS
;