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
)
117 return STATUS_NOT_SUPPORTED
;
122 PciPdoIrpQueryRemoveDevice(IN PIRP Irp
,
123 IN PIO_STACK_LOCATION IoStackLocation
,
124 IN PPCI_PDO_EXTENSION DeviceExtension
)
128 return STATUS_NOT_SUPPORTED
;
133 PciPdoIrpRemoveDevice(IN PIRP Irp
,
134 IN PIO_STACK_LOCATION IoStackLocation
,
135 IN PPCI_PDO_EXTENSION DeviceExtension
)
139 return STATUS_NOT_SUPPORTED
;
144 PciPdoIrpCancelRemoveDevice(IN PIRP Irp
,
145 IN PIO_STACK_LOCATION IoStackLocation
,
146 IN PPCI_PDO_EXTENSION DeviceExtension
)
150 return STATUS_NOT_SUPPORTED
;
155 PciPdoIrpStopDevice(IN PIRP Irp
,
156 IN PIO_STACK_LOCATION IoStackLocation
,
157 IN PPCI_PDO_EXTENSION DeviceExtension
)
161 return STATUS_NOT_SUPPORTED
;
166 PciPdoIrpQueryStopDevice(IN PIRP Irp
,
167 IN PIO_STACK_LOCATION IoStackLocation
,
168 IN PPCI_PDO_EXTENSION DeviceExtension
)
172 return STATUS_NOT_SUPPORTED
;
177 PciPdoIrpCancelStopDevice(IN PIRP Irp
,
178 IN PIO_STACK_LOCATION IoStackLocation
,
179 IN PPCI_PDO_EXTENSION DeviceExtension
)
183 return STATUS_NOT_SUPPORTED
;
188 PciPdoIrpQueryInterface(IN PIRP Irp
,
189 IN PIO_STACK_LOCATION IoStackLocation
,
190 IN PPCI_PDO_EXTENSION DeviceExtension
)
194 return STATUS_NOT_SUPPORTED
;
199 PciPdoIrpQueryDeviceRelations(IN PIRP Irp
,
200 IN PIO_STACK_LOCATION IoStackLocation
,
201 IN PPCI_PDO_EXTENSION DeviceExtension
)
206 /* Are ejection relations being queried? */
207 if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== EjectionRelations
)
209 /* Call the worker function */
210 Status
= PciQueryEjectionRelations(DeviceExtension
,
211 (PDEVICE_RELATIONS
*)&Irp
->
212 IoStatus
.Information
);
214 else if (IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
216 /* The only other relation supported is the target device relation */
217 Status
= PciQueryTargetDeviceRelations(DeviceExtension
,
218 (PDEVICE_RELATIONS
*)&Irp
->
219 IoStatus
.Information
);
223 /* All other relations are unsupported */
224 Status
= STATUS_NOT_SUPPORTED
;
227 /* Return either the result of the worker function, or unsupported status */
233 PciPdoIrpQueryCapabilities(IN PIRP Irp
,
234 IN PIO_STACK_LOCATION IoStackLocation
,
235 IN PPCI_PDO_EXTENSION DeviceExtension
)
239 /* Call the worker function */
240 return PciQueryCapabilities(DeviceExtension
,
242 Parameters
.DeviceCapabilities
.Capabilities
);
247 PciPdoIrpQueryResources(IN PIRP Irp
,
248 IN PIO_STACK_LOCATION IoStackLocation
,
249 IN PPCI_PDO_EXTENSION DeviceExtension
)
253 /* Call the worker function */
254 return PciQueryResources(DeviceExtension
,
255 (PCM_RESOURCE_LIST
*)&Irp
->IoStatus
.Information
);
260 PciPdoIrpQueryResourceRequirements(IN PIRP Irp
,
261 IN PIO_STACK_LOCATION IoStackLocation
,
262 IN PPCI_PDO_EXTENSION DeviceExtension
)
266 /* Call the worker function */
267 return PciQueryRequirements(DeviceExtension
,
268 (PIO_RESOURCE_REQUIREMENTS_LIST
*)&Irp
->
269 IoStatus
.Information
);
274 PciPdoIrpQueryDeviceText(IN PIRP Irp
,
275 IN PIO_STACK_LOCATION IoStackLocation
,
276 IN PPCI_PDO_EXTENSION DeviceExtension
)
280 /* Call the worker function */
281 return PciQueryDeviceText(DeviceExtension
,
283 Parameters
.QueryDeviceText
.DeviceTextType
,
285 Parameters
.QueryDeviceText
.LocaleId
,
286 (PWCHAR
*)&Irp
->IoStatus
.Information
);
291 PciPdoIrpQueryId(IN PIRP Irp
,
292 IN PIO_STACK_LOCATION IoStackLocation
,
293 IN PPCI_PDO_EXTENSION DeviceExtension
)
297 /* Call the worker function */
298 return PciQueryId(DeviceExtension
,
299 IoStackLocation
->Parameters
.QueryId
.IdType
,
300 (PWCHAR
*)&Irp
->IoStatus
.Information
);
305 PciPdoIrpQueryBusInformation(IN PIRP Irp
,
306 IN PIO_STACK_LOCATION IoStackLocation
,
307 IN PPCI_PDO_EXTENSION DeviceExtension
)
311 /* Call the worker function */
312 return PciQueryBusInformation(DeviceExtension
,
313 (PPNP_BUS_INFORMATION
*)&Irp
->
314 IoStatus
.Information
);
319 PciPdoIrpReadConfig(IN PIRP Irp
,
320 IN PIO_STACK_LOCATION IoStackLocation
,
321 IN PPCI_PDO_EXTENSION DeviceExtension
)
325 return STATUS_NOT_SUPPORTED
;
330 PciPdoIrpWriteConfig(IN PIRP Irp
,
331 IN PIO_STACK_LOCATION IoStackLocation
,
332 IN PPCI_PDO_EXTENSION DeviceExtension
)
336 return STATUS_NOT_SUPPORTED
;
341 PciPdoIrpQueryDeviceState(IN PIRP Irp
,
342 IN PIO_STACK_LOCATION IoStackLocation
,
343 IN PPCI_PDO_EXTENSION DeviceExtension
)
347 return STATUS_NOT_SUPPORTED
;
352 PciPdoIrpDeviceUsageNotification(IN PIRP Irp
,
353 IN PIO_STACK_LOCATION IoStackLocation
,
354 IN PPCI_PDO_EXTENSION DeviceExtension
)
358 return STATUS_NOT_SUPPORTED
;
363 PciPdoIrpSurpriseRemoval(IN PIRP Irp
,
364 IN PIO_STACK_LOCATION IoStackLocation
,
365 IN PPCI_PDO_EXTENSION DeviceExtension
)
369 return STATUS_NOT_SUPPORTED
;
374 PciPdoIrpQueryLegacyBusInformation(IN PIRP Irp
,
375 IN PIO_STACK_LOCATION IoStackLocation
,
376 IN PPCI_PDO_EXTENSION DeviceExtension
)
380 return STATUS_NOT_SUPPORTED
;
385 PciPdoCreate(IN PPCI_FDO_EXTENSION DeviceExtension
,
386 IN PCI_SLOT_NUMBER Slot
,
387 OUT PDEVICE_OBJECT
*PdoDeviceObject
)
389 WCHAR DeviceName
[32];
390 UNICODE_STRING DeviceString
;
392 PDEVICE_OBJECT DeviceObject
;
393 PPCI_PDO_EXTENSION PdoExtension
;
394 ULONG SequenceNumber
;
397 /* Pick an atomically unique sequence number for this device */
398 SequenceNumber
= InterlockedIncrement(&PciPdoSequenceNumber
);
400 /* Create the standard PCI device name for a PDO */
401 swprintf(DeviceName
, L
"\\Device\\NTPNP_PCI%04d", SequenceNumber
);
402 RtlInitUnicodeString(&DeviceString
, DeviceName
);
404 /* Create the actual device now */
405 Status
= IoCreateDevice(DeviceExtension
->FunctionalDeviceObject
->DriverObject
,
406 sizeof(PCI_PDO_EXTENSION
),
408 FILE_DEVICE_BUS_EXTENDER
,
412 ASSERT(NT_SUCCESS(Status
));
414 /* Get the extension for it */
415 PdoExtension
= (PPCI_PDO_EXTENSION
)DeviceObject
->DeviceExtension
;
416 DPRINT1("PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
417 DeviceExtension
->BaseBus
,
418 Slot
.u
.bits
.DeviceNumber
,
419 Slot
.u
.bits
.FunctionNumber
,
421 DeviceObject
->DeviceExtension
);
423 /* Configure the extension */
424 PdoExtension
->ExtensionType
= PciPdoExtensionType
;
425 PdoExtension
->IrpDispatchTable
= &PciPdoDispatchTable
;
426 PdoExtension
->PhysicalDeviceObject
= DeviceObject
;
427 PdoExtension
->Slot
= Slot
;
428 PdoExtension
->PowerState
.CurrentSystemState
= PowerDeviceD0
;
429 PdoExtension
->PowerState
.CurrentDeviceState
= PowerDeviceD0
;
430 PdoExtension
->ParentFdoExtension
= DeviceExtension
;
432 /* Initialize the lock for arbiters and other interfaces */
433 KeInitializeEvent(&PdoExtension
->SecondaryExtLock
, SynchronizationEvent
, TRUE
);
435 /* Initialize the state machine */
436 PciInitializeState((PPCI_FDO_EXTENSION
)PdoExtension
);
438 /* Add the PDO to the parent's list */
439 PdoExtension
->Next
= NULL
;
440 PciInsertEntryAtTail((PSINGLE_LIST_ENTRY
)&DeviceExtension
->ChildPdoList
,
441 (PPCI_FDO_EXTENSION
)PdoExtension
,
442 &DeviceExtension
->ChildListLock
);
444 /* And finally return it to the caller */
445 *PdoDeviceObject
= DeviceObject
;
446 return STATUS_SUCCESS
;