/*** PRIVATE *****************************************************************/
+static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion;
+
+static NTSTATUS NTAPI
+ForwardIrpAndWaitCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ UNREFERENCED_PARAMETER(DeviceObject);
+ if (Irp->PendingReturned)
+ KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS NTAPI
+ForwardIrpAndWait(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ KEVENT Event;
+ NTSTATUS Status;
+ PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Ldo;
+ ASSERT(LowerDevice);
+
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+
+ IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
+
+ Status = IoCallDriver(LowerDevice, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+ if (NT_SUCCESS(Status))
+ Status = Irp->IoStatus.Status;
+ }
+
+ return Status;
+}
+
static NTSTATUS
FdoLocateChildDevice(
PPCI_DEVICE *Device,
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PCI_COMMON_CONFIG PciConfig;
- PLIST_ENTRY CurrentEntry;
PPCI_DEVICE Device;
PCI_SLOT_NUMBER SlotNumber;
ULONG DeviceNumber;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- /* Mark all devices to be removed. If we don't discover them again during
- enumeration, assume that they have been surprise removed */
- CurrentEntry = DeviceExtension->DeviceListHead.Flink;
- while (CurrentEntry != &DeviceExtension->DeviceListHead) {
- Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
- Device->RemovePending = TRUE;
- CurrentEntry = CurrentEntry->Flink;
- }
-
DeviceExtension->DeviceListCount = 0;
/* Enumerate devices on the PCI bus */
&DeviceExtension->DeviceListLock);
}
- /* Don't remove this device */
- Device->RemovePending = FALSE;
-
DeviceExtension->DeviceListCount++;
/* Skip to next device if the current one is not a multifunction device */
break;
}
- Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
-
Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
}
}
- if (!Device->RemovePending) {
- /* Reference the physical device object. The PnP manager
- will dereference it again when it is no longer needed */
- ObReferenceObject(Device->Pdo);
+ /* Reference the physical device object. The PnP manager
+ will dereference it again when it is no longer needed */
+ ObReferenceObject(Device->Pdo);
- Relations->Objects[i] = Device->Pdo;
+ Relations->Objects[i] = Device->Pdo;
- i++;
- }
+ i++;
CurrentEntry = CurrentEntry->Flink;
}
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
- PFDO_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
UNREFERENCED_PARAMETER(Irp);
DPRINT("Called\n");
- DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
if (IrpSp->Parameters.Power.Type == DevicePowerState) {
/* FIXME: Set device power state for the device */
Status = STATUS_UNSUCCESSFUL;
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpSp;
- NTSTATUS Status;
+ NTSTATUS Status = Irp->IoStatus.Status;
DPRINT("Called\n");
break;
#endif
case IRP_MN_QUERY_DEVICE_RELATIONS:
+ if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
+ break;
+
Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
- break;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
#if 0
case IRP_MN_QUERY_PNP_DEVICE_STATE:
Status = STATUS_NOT_IMPLEMENTED;
case IRP_MN_QUERY_REMOVE_DEVICE:
Status = STATUS_NOT_IMPLEMENTED;
break;
-
- case IRP_MN_QUERY_STOP_DEVICE:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case IRP_MN_REMOVE_DEVICE:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
#endif
case IRP_MN_START_DEVICE:
DPRINT("IRP_MN_START_DEVICE received\n");
- Status = FdoStartDevice(DeviceObject, Irp);
- break;
- case IRP_MN_STOP_DEVICE:
- /* Currently not supported */
+ Status = ForwardIrpAndWait(DeviceObject, Irp);
+ if (NT_SUCCESS(Status))
+ Status = FdoStartDevice(DeviceObject, Irp);
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+
+ case IRP_MN_QUERY_STOP_DEVICE:
+ /* We don't support stopping yet */
Status = STATUS_UNSUCCESSFUL;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+
+ case IRP_MN_STOP_DEVICE:
+ /* We can't fail this one so we fail the QUERY_STOP request that precedes it */
break;
#if 0
case IRP_MN_SURPRISE_REMOVAL:
Status = STATUS_NOT_IMPLEMENTED;
break;
#endif
- default:
- DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
- /* fall through */
-
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
- /*
- * Do NOT complete the IRP as it will be processed by the lower
- * device object, which will complete the IRP
- */
- IoSkipCurrentIrpStackLocation(Irp);
- Status = IoCallDriver(DeviceExtension->Ldo, Irp);
- return Status;
break;
- }
+ case IRP_MN_REMOVE_DEVICE:
+ /* Detach the device object from the device stack */
+ IoDetachDevice(DeviceExtension->Ldo);
+ /* Delete the device object */
+ IoDeleteDevice(DeviceObject);
- if (Status != STATUS_PENDING) {
- if (Status != STATUS_NOT_IMPLEMENTED)
- Irp->IoStatus.Status = Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ /* Return success */
+ Status = STATUS_SUCCESS;
+ break;
+ default:
+ DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
+ break;
}
+ Irp->IoStatus.Status = Status;
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(DeviceExtension->Ldo, Irp);
+
DPRINT("Leaving. Status 0x%X\n", Status);
return Status;