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
15 /*** PRIVATE *****************************************************************/
20 PFDO_DEVICE_EXTENSION DeviceExtension,
21 PPCI_COMMON_CONFIG PciConfig)
23 PLIST_ENTRY CurrentEntry;
24 PPCI_DEVICE CurrentDevice;
26 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
27 while (CurrentEntry != &DeviceExtension->DeviceListHead) {
28 CurrentDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
30 /* If both vendor ID and device ID match, it is the same device */
31 if ((PciConfig->VendorID == CurrentDevice->PciConfig.VendorID) &&
32 (PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID)) {
33 *Device = CurrentDevice;
34 return STATUS_SUCCESS;
37 CurrentEntry = CurrentEntry->Flink;
41 return STATUS_UNSUCCESSFUL;
47 PDEVICE_OBJECT DeviceObject)
49 PFDO_DEVICE_EXTENSION DeviceExtension;
50 PCI_COMMON_CONFIG PciConfig;
51 PLIST_ENTRY CurrentEntry;
59 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
61 /* Mark all devices to be removed. If we don't discover them again during
62 enumeration, assume that they have been surprise removed */
63 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
64 while (CurrentEntry != &DeviceExtension->DeviceListHead) {
65 Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
66 Device->RemovePending = TRUE;
67 CurrentEntry = CurrentEntry->Flink;
70 DeviceExtension->DeviceListCount = 0;
72 /* Enumerate devices on the PCI bus */
73 for (Slot = 0; Slot < 256; Slot++)
76 DeviceExtension->BusNumber,
80 sizeof(PCI_COMMON_CONFIG));
83 DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
84 DeviceExtension->BusNumber,
90 Status = FdoLocateChildDevice(&Device, DeviceExtension, &PciConfig);
91 if (!NT_SUCCESS(Status)) {
92 Device = (PPCI_DEVICE)ExAllocatePool(PagedPool, sizeof(PCI_DEVICE));
95 /* FIXME: Cleanup resources for already discovered devices */
96 return STATUS_INSUFFICIENT_RESOURCES;
99 RtlZeroMemory(Device, sizeof(PCI_DEVICE));
101 RtlMoveMemory(&Device->PciConfig, &PciConfig, sizeof(PCI_COMMON_CONFIG));
103 ExInterlockedInsertTailList(
104 &DeviceExtension->DeviceListHead,
106 &DeviceExtension->DeviceListLock);
109 /* Don't remove this device */
110 Device->RemovePending = FALSE;
112 DeviceExtension->DeviceListCount++;
116 return STATUS_SUCCESS;
121 FdoQueryBusRelations(
122 IN PDEVICE_OBJECT DeviceObject,
124 PIO_STACK_LOCATION IrpSp)
126 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
127 PFDO_DEVICE_EXTENSION DeviceExtension;
128 PDEVICE_RELATIONS Relations;
129 PLIST_ENTRY CurrentEntry;
132 BOOLEAN ErrorOccurred;
133 NTSTATUS ErrorStatus;
134 WCHAR Buffer[MAX_PATH];
140 ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
142 Status = STATUS_SUCCESS;
144 ErrorOccurred = FALSE;
146 FdoEnumerateDevices(DeviceObject);
148 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
150 if (Irp->IoStatus.Information) {
151 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
152 structure so we must merge this structure with our own */
155 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
156 (DeviceExtension->DeviceListCount - 1);
157 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
159 return STATUS_INSUFFICIENT_RESOURCES;
161 Relations->Count = DeviceExtension->DeviceListCount;
164 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
165 while (CurrentEntry != &DeviceExtension->DeviceListHead) {
166 Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
168 PdoDeviceExtension = NULL;
171 /* Create a physical device object for the
172 device as it does not already have one */
173 Status = IoCreateDevice(
174 DeviceObject->DriverObject,
175 sizeof(PDO_DEVICE_EXTENSION),
177 FILE_DEVICE_CONTROLLER,
181 if (!NT_SUCCESS(Status)) {
182 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
183 ErrorStatus = Status;
184 ErrorOccurred = TRUE;
188 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
190 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
192 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
194 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
196 RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
198 PdoDeviceExtension->Common.IsFDO = FALSE;
200 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
202 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
204 /* FIXME: Get device properties (Hardware IDs, etc.) */
208 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
209 Device->PciConfig.VendorID,
210 Device->PciConfig.DeviceID,
211 Device->PciConfig.u.type0.SubSystemID,
212 Device->PciConfig.RevisionID);
214 if (!PciCreateUnicodeString(
215 &PdoDeviceExtension->DeviceID,
218 ErrorOccurred = TRUE;
222 DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceID.Buffer);
225 if (!Device->RemovePending) {
226 /* Reference the physical device object. The PnP manager
227 will dereference it again when it is no longer needed */
228 ObReferenceObject(Device->Pdo);
230 Relations->Objects[i] = Device->Pdo;
235 CurrentEntry = CurrentEntry->Flink;
239 /* FIXME: Cleanup all new PDOs created in this call. Please give me SEH!!! ;-) */
240 /* FIXME: Should IoAttachDeviceToDeviceStack() be undone? */
241 if (PdoDeviceExtension) {
242 RtlFreeUnicodeString(&PdoDeviceExtension->DeviceID);
243 ExFreePool(PdoDeviceExtension);
246 ExFreePool(Relations);
250 Irp->IoStatus.Information = (ULONG_PTR)Relations;
258 IN PDEVICE_OBJECT DeviceObject,
261 PFDO_DEVICE_EXTENSION DeviceExtension;
265 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
267 assert(DeviceExtension->State == dsStopped);
269 InitializeListHead(&DeviceExtension->DeviceListHead);
270 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
271 DeviceExtension->DeviceListCount = 0;
273 PciBusConfigType = PciGetBusConfigType();
275 DPRINT("Bus configuration is %d\n", PciBusConfigType);
277 if (PciBusConfigType != pbtUnknown) {
278 /* At least one PCI bus is found */
281 /* FIXME: Find a way to get this information */
282 DeviceExtension->BusNumber = 0;
284 DeviceExtension->State = dsStarted;
286 //Irp->IoStatus.Information = 0;
288 return STATUS_SUCCESS;
294 IN PDEVICE_OBJECT DeviceObject,
296 PIO_STACK_LOCATION IrpSp)
298 PFDO_DEVICE_EXTENSION DeviceExtension;
303 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
305 if (IrpSp->Parameters.Power.Type == DevicePowerState) {
306 /* FIXME: Set device power state for the device */
307 Status = STATUS_UNSUCCESSFUL;
309 Status = STATUS_UNSUCCESSFUL;
316 /*** PUBLIC ******************************************************************/
320 PDEVICE_OBJECT DeviceObject,
323 * FUNCTION: Handle Plug and Play IRPs for the PCI device object
325 * DeviceObject = Pointer to functional device object of the PCI driver
326 * Irp = Pointer to IRP that should be handled
331 PFDO_DEVICE_EXTENSION DeviceExtension;
332 PIO_STACK_LOCATION IrpSp;
337 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
339 IrpSp = IoGetCurrentIrpStackLocation(Irp);
340 switch (IrpSp->MinorFunction) {
342 case IRP_MN_CANCEL_REMOVE_DEVICE:
343 Status = STATUS_NOT_IMPLEMENTED;
346 case IRP_MN_CANCEL_STOP_DEVICE:
347 Status = STATUS_NOT_IMPLEMENTED;
350 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
351 Status = STATUS_NOT_IMPLEMENTED;
354 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
355 Status = STATUS_NOT_IMPLEMENTED;
358 case IRP_MN_QUERY_DEVICE_RELATIONS:
359 Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
362 case IRP_MN_QUERY_PNP_DEVICE_STATE:
363 Status = STATUS_NOT_IMPLEMENTED;
366 case IRP_MN_QUERY_REMOVE_DEVICE:
367 Status = STATUS_NOT_IMPLEMENTED;
370 case IRP_MN_QUERY_STOP_DEVICE:
371 Status = STATUS_NOT_IMPLEMENTED;
374 case IRP_MN_REMOVE_DEVICE:
375 Status = STATUS_NOT_IMPLEMENTED;
378 case IRP_MN_START_DEVICE:
379 DPRINT("IRP_MN_START_DEVICE received\n");
380 Status = FdoStartDevice(DeviceObject, Irp);
382 case IRP_MN_STOP_DEVICE:
383 /* Currently not supported */
384 Status = STATUS_UNSUCCESSFUL;
387 case IRP_MN_SURPRISE_REMOVAL:
388 Status = STATUS_NOT_IMPLEMENTED;
392 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
395 * Do NOT complete the IRP as it will be processed by the lower
396 * device object, which will complete the IRP
398 IoSkipCurrentIrpStackLocation(Irp);
399 Status = IoCallDriver(DeviceExtension->Ldo, Irp);
405 if (Status != STATUS_PENDING) {
406 if (Status != STATUS_NOT_IMPLEMENTED)
407 Irp->IoStatus.Status = Status;
408 IoCompleteRequest(Irp, IO_NO_INCREMENT);
411 DPRINT("Leaving. Status 0x%X\n", Status);
419 PDEVICE_OBJECT DeviceObject,
422 * FUNCTION: Handle power management IRPs for the PCI device object
424 * DeviceObject = Pointer to functional device object of the PCI driver
425 * Irp = Pointer to IRP that should be handled
430 PIO_STACK_LOCATION IrpSp;
435 IrpSp = IoGetCurrentIrpStackLocation(Irp);
437 switch (IrpSp->MinorFunction) {
438 case IRP_MN_SET_POWER:
439 Status = FdoSetPower(DeviceObject, Irp, IrpSp);
443 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
444 Status = STATUS_NOT_IMPLEMENTED;
448 if (Status != STATUS_PENDING) {
449 Irp->IoStatus.Status = Status;
450 IoCompleteRequest(Irp, IO_NO_INCREMENT);
453 DPRINT("Leaving. Status 0x%X\n", Status);