1 /* $Id: fdo.c,v 1.5 2003/12/12 21:54:42 ekohl Exp $
3 * PROJECT: ReactOS PCI bus driver
5 * PURPOSE: PCI device object dispatch routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 10-09-2001 CSH Created
11 #include <ddk/ntddk.h>
19 /*** PRIVATE *****************************************************************/
24 PFDO_DEVICE_EXTENSION DeviceExtension
,
25 PCI_SLOT_NUMBER SlotNumber
,
26 PPCI_COMMON_CONFIG PciConfig
)
28 PLIST_ENTRY CurrentEntry
;
29 PPCI_DEVICE CurrentDevice
;
33 CurrentEntry
= DeviceExtension
->DeviceListHead
.Flink
;
34 while (CurrentEntry
!= &DeviceExtension
->DeviceListHead
) {
35 CurrentDevice
= CONTAINING_RECORD(CurrentEntry
, PCI_DEVICE
, ListEntry
);
37 /* If both vendor ID and device ID match, it is the same device */
38 if ((PciConfig
->VendorID
== CurrentDevice
->PciConfig
.VendorID
) &&
39 (PciConfig
->DeviceID
== CurrentDevice
->PciConfig
.DeviceID
) &&
40 (SlotNumber
.u
.AsULONG
== CurrentDevice
->SlotNumber
.u
.AsULONG
)) {
41 *Device
= CurrentDevice
;
43 return STATUS_SUCCESS
;
46 CurrentEntry
= CurrentEntry
->Flink
;
51 return STATUS_UNSUCCESSFUL
;
57 PDEVICE_OBJECT DeviceObject
)
59 PFDO_DEVICE_EXTENSION DeviceExtension
;
60 PCI_COMMON_CONFIG PciConfig
;
61 PLIST_ENTRY CurrentEntry
;
63 PCI_SLOT_NUMBER SlotNumber
;
71 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
73 /* Mark all devices to be removed. If we don't discover them again during
74 enumeration, assume that they have been surprise removed */
75 CurrentEntry
= DeviceExtension
->DeviceListHead
.Flink
;
76 while (CurrentEntry
!= &DeviceExtension
->DeviceListHead
) {
77 Device
= CONTAINING_RECORD(CurrentEntry
, PCI_DEVICE
, ListEntry
);
78 Device
->RemovePending
= TRUE
;
79 CurrentEntry
= CurrentEntry
->Flink
;
82 DeviceExtension
->DeviceListCount
= 0;
84 /* Enumerate devices on the PCI bus */
85 SlotNumber
.u
.AsULONG
= 0;
86 for (DeviceNumber
= 0; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
88 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
89 for (FunctionNumber
= 0; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
91 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
93 Size
= HalGetBusData(PCIConfiguration
,
94 DeviceExtension
->BusNumber
,
97 sizeof(PCI_COMMON_CONFIG
));
98 DPRINT("Size %lu\n", Size
);
99 if (Size
< sizeof(PCI_COMMON_CONFIG
))
101 if (FunctionNumber
== 0)
111 DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
112 DeviceExtension
->BusNumber
,
118 Status
= FdoLocateChildDevice(&Device
, DeviceExtension
, SlotNumber
, &PciConfig
);
119 if (!NT_SUCCESS(Status
))
121 Device
= (PPCI_DEVICE
)ExAllocatePool(PagedPool
, sizeof(PCI_DEVICE
));
124 /* FIXME: Cleanup resources for already discovered devices */
125 return STATUS_INSUFFICIENT_RESOURCES
;
128 RtlZeroMemory (Device
,
131 RtlCopyMemory (&Device
->SlotNumber
,
133 sizeof(PCI_SLOT_NUMBER
));
135 RtlCopyMemory (&Device
->PciConfig
,
137 sizeof(PCI_COMMON_CONFIG
));
139 ExInterlockedInsertTailList(
140 &DeviceExtension
->DeviceListHead
,
142 &DeviceExtension
->DeviceListLock
);
145 /* Don't remove this device */
146 Device
->RemovePending
= FALSE
;
148 DeviceExtension
->DeviceListCount
++;
154 return STATUS_SUCCESS
;
159 FdoQueryBusRelations(
160 IN PDEVICE_OBJECT DeviceObject
,
162 PIO_STACK_LOCATION IrpSp
)
164 PPDO_DEVICE_EXTENSION PdoDeviceExtension
;
165 PFDO_DEVICE_EXTENSION DeviceExtension
;
166 PDEVICE_RELATIONS Relations
;
167 PLIST_ENTRY CurrentEntry
;
170 BOOLEAN ErrorOccurred
;
171 NTSTATUS ErrorStatus
;
172 WCHAR Buffer
[MAX_PATH
];
178 ErrorStatus
= STATUS_INSUFFICIENT_RESOURCES
;
180 Status
= STATUS_SUCCESS
;
182 ErrorOccurred
= FALSE
;
184 FdoEnumerateDevices(DeviceObject
);
186 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
188 if (Irp
->IoStatus
.Information
) {
189 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
190 structure so we must merge this structure with our own */
193 Size
= sizeof(DEVICE_RELATIONS
) + sizeof(Relations
->Objects
) *
194 (DeviceExtension
->DeviceListCount
- 1);
195 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
197 return STATUS_INSUFFICIENT_RESOURCES
;
199 Relations
->Count
= DeviceExtension
->DeviceListCount
;
202 CurrentEntry
= DeviceExtension
->DeviceListHead
.Flink
;
203 while (CurrentEntry
!= &DeviceExtension
->DeviceListHead
) {
204 Device
= CONTAINING_RECORD(CurrentEntry
, PCI_DEVICE
, ListEntry
);
206 PdoDeviceExtension
= NULL
;
209 /* Create a physical device object for the
210 device as it does not already have one */
211 Status
= IoCreateDevice(
212 DeviceObject
->DriverObject
,
213 sizeof(PDO_DEVICE_EXTENSION
),
215 FILE_DEVICE_CONTROLLER
,
219 if (!NT_SUCCESS(Status
)) {
220 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status
);
221 ErrorStatus
= Status
;
222 ErrorOccurred
= TRUE
;
226 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
228 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
230 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
232 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
234 RtlZeroMemory(PdoDeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
236 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
238 PdoDeviceExtension
->Common
.DeviceObject
= Device
->Pdo
;
240 PdoDeviceExtension
->Common
.DevicePowerState
= PowerDeviceD0
;
242 /* FIXME: Get device properties (Hardware IDs, etc.) */
246 L
"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
247 Device
->PciConfig
.VendorID
,
248 Device
->PciConfig
.DeviceID
,
249 (Device
->PciConfig
.u
.type0
.SubSystemID
<< 16) +
250 Device
->PciConfig
.u
.type0
.SubVendorID
,
251 Device
->PciConfig
.RevisionID
);
253 if (!PciCreateUnicodeString(
254 &PdoDeviceExtension
->DeviceID
,
257 ErrorOccurred
= TRUE
;
261 DPRINT("DeviceID: %S\n", PdoDeviceExtension
->DeviceID
.Buffer
);
264 if (!Device
->RemovePending
) {
265 /* Reference the physical device object. The PnP manager
266 will dereference it again when it is no longer needed */
267 ObReferenceObject(Device
->Pdo
);
269 Relations
->Objects
[i
] = Device
->Pdo
;
274 CurrentEntry
= CurrentEntry
->Flink
;
278 /* FIXME: Cleanup all new PDOs created in this call. Please give me SEH!!! ;-) */
279 /* FIXME: Should IoAttachDeviceToDeviceStack() be undone? */
280 if (PdoDeviceExtension
) {
281 RtlFreeUnicodeString(&PdoDeviceExtension
->DeviceID
);
282 ExFreePool(PdoDeviceExtension
);
285 ExFreePool(Relations
);
289 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
299 IN PDEVICE_OBJECT DeviceObject
,
302 PFDO_DEVICE_EXTENSION DeviceExtension
;
306 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
308 assert(DeviceExtension
->State
== dsStopped
);
310 InitializeListHead(&DeviceExtension
->DeviceListHead
);
311 KeInitializeSpinLock(&DeviceExtension
->DeviceListLock
);
312 DeviceExtension
->DeviceListCount
= 0;
314 /* FIXME: Find a way to get this information */
315 DeviceExtension
->BusNumber
= 0;
317 DeviceExtension
->State
= dsStarted
;
319 //Irp->IoStatus.Information = 0;
321 return STATUS_SUCCESS
;
327 IN PDEVICE_OBJECT DeviceObject
,
329 PIO_STACK_LOCATION IrpSp
)
331 PFDO_DEVICE_EXTENSION DeviceExtension
;
336 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
338 if (IrpSp
->Parameters
.Power
.Type
== DevicePowerState
) {
339 /* FIXME: Set device power state for the device */
340 Status
= STATUS_UNSUCCESSFUL
;
342 Status
= STATUS_UNSUCCESSFUL
;
349 /*** PUBLIC ******************************************************************/
353 PDEVICE_OBJECT DeviceObject
,
356 * FUNCTION: Handle Plug and Play IRPs for the PCI device object
358 * DeviceObject = Pointer to functional device object of the PCI driver
359 * Irp = Pointer to IRP that should be handled
364 PFDO_DEVICE_EXTENSION DeviceExtension
;
365 PIO_STACK_LOCATION IrpSp
;
370 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
372 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
373 switch (IrpSp
->MinorFunction
) {
375 case IRP_MN_CANCEL_REMOVE_DEVICE
:
376 Status
= STATUS_NOT_IMPLEMENTED
;
379 case IRP_MN_CANCEL_STOP_DEVICE
:
380 Status
= STATUS_NOT_IMPLEMENTED
;
383 case IRP_MN_DEVICE_USAGE_NOTIFICATION
:
384 Status
= STATUS_NOT_IMPLEMENTED
;
387 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
388 Status
= STATUS_NOT_IMPLEMENTED
;
391 case IRP_MN_QUERY_DEVICE_RELATIONS
:
392 Status
= FdoQueryBusRelations(DeviceObject
, Irp
, IrpSp
);
395 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
396 Status
= STATUS_NOT_IMPLEMENTED
;
399 case IRP_MN_QUERY_REMOVE_DEVICE
:
400 Status
= STATUS_NOT_IMPLEMENTED
;
403 case IRP_MN_QUERY_STOP_DEVICE
:
404 Status
= STATUS_NOT_IMPLEMENTED
;
407 case IRP_MN_REMOVE_DEVICE
:
408 Status
= STATUS_NOT_IMPLEMENTED
;
411 case IRP_MN_START_DEVICE
:
412 DPRINT("IRP_MN_START_DEVICE received\n");
413 Status
= FdoStartDevice(DeviceObject
, Irp
);
415 case IRP_MN_STOP_DEVICE
:
416 /* Currently not supported */
417 Status
= STATUS_UNSUCCESSFUL
;
420 case IRP_MN_SURPRISE_REMOVAL
:
421 Status
= STATUS_NOT_IMPLEMENTED
;
425 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
428 * Do NOT complete the IRP as it will be processed by the lower
429 * device object, which will complete the IRP
431 IoSkipCurrentIrpStackLocation(Irp
);
432 Status
= IoCallDriver(DeviceExtension
->Ldo
, Irp
);
438 if (Status
!= STATUS_PENDING
) {
439 if (Status
!= STATUS_NOT_IMPLEMENTED
)
440 Irp
->IoStatus
.Status
= Status
;
441 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
444 DPRINT("Leaving. Status 0x%X\n", Status
);
452 PDEVICE_OBJECT DeviceObject
,
455 * FUNCTION: Handle power management IRPs for the PCI device object
457 * DeviceObject = Pointer to functional device object of the PCI driver
458 * Irp = Pointer to IRP that should be handled
463 PIO_STACK_LOCATION IrpSp
;
468 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
470 switch (IrpSp
->MinorFunction
) {
471 case IRP_MN_SET_POWER
:
472 Status
= FdoSetPower(DeviceObject
, Irp
, IrpSp
);
476 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
477 Status
= STATUS_NOT_IMPLEMENTED
;
481 if (Status
!= STATUS_PENDING
) {
482 Irp
->IoStatus
.Status
= Status
;
483 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
486 DPRINT("Leaving. Status 0x%X\n", Status
);