[PCI]
[reactos.git] / reactos / drivers / bus / pci / fdo.c
index f0bc9d6..b6753e1 100644 (file)
 
 /*** 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,
@@ -176,7 +216,7 @@ FdoQueryBusRelations(
   IN PIRP Irp,
   PIO_STACK_LOCATION IrpSp)
 {
-  PPDO_DEVICE_EXTENSION PdoDeviceExtension;
+  PPDO_DEVICE_EXTENSION PdoDeviceExtension = NULL;
   PFDO_DEVICE_EXTENSION DeviceExtension;
   PDEVICE_RELATIONS Relations;
   PLIST_ENTRY CurrentEntry;
@@ -187,6 +227,8 @@ FdoQueryBusRelations(
   ULONG Size;
   ULONG i;
 
+  UNREFERENCED_PARAMETER(IrpSp);
+
   DPRINT("Called\n");
 
   ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
@@ -206,7 +248,7 @@ FdoQueryBusRelations(
 
   Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
     (DeviceExtension->DeviceListCount - 1);
-  Relations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, Size, TAG_PCI);
+  Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
   if (!Relations)
     return STATUS_INSUFFICIENT_RESOURCES;
 
@@ -237,8 +279,6 @@ FdoQueryBusRelations(
         break;
       }
 
-      Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
-
       Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
       //Device->Pdo->Flags |= DO_POWER_PAGABLE;
@@ -356,7 +396,6 @@ FdoStartDevice(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp)
 {
-  static BOOLEAN FoundBuggyAllocatedResourcesList = FALSE;
   PFDO_DEVICE_EXTENSION DeviceExtension;
   PCM_RESOURCE_LIST AllocatedResources;
   PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
@@ -368,16 +407,6 @@ FdoStartDevice(
   DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
   AllocatedResources = IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources;
-  /* HACK due to a bug in ACPI driver, which doesn't report the bus number */
-  if (!FoundBuggyAllocatedResourcesList &&
-      (!AllocatedResources || AllocatedResources->Count == 0))
-  {
-    FoundBuggyAllocatedResourcesList = TRUE;
-    DPRINT1("No bus number resource found (bug in acpi.sys?), assuming bus number #0\n");
-    DeviceExtension->BusNumber = 0;
-    goto next;
-  }
-  /* END HACK */
   if (!AllocatedResources)
   {
     DPRINT("No allocated resources sent to driver\n");
@@ -394,6 +423,9 @@ FdoStartDevice(
 
   ASSERT(DeviceExtension->State == dsStopped);
 
+  /* By default, use the bus number in the resource list header */
+  DeviceExtension->BusNumber = AllocatedResources->List[0].BusNumber;
+
   for (i = 0; i < AllocatedResources->List[0].PartialResourceList.Count; i++)
   {
     ResourceDescriptor = &AllocatedResources->List[0].PartialResourceList.PartialDescriptors[i];
@@ -403,22 +435,18 @@ FdoStartDevice(
       {
         if (FoundBusNumber || ResourceDescriptor->u.BusNumber.Length != 1)
           return STATUS_INVALID_PARAMETER;
+        /* Use this one instead */
+        ASSERT(AllocatedResources->List[0].BusNumber == ResourceDescriptor->u.BusNumber.Start);
         DeviceExtension->BusNumber = ResourceDescriptor->u.BusNumber.Start;
         DPRINT("Found bus number resource: %lu\n", DeviceExtension->BusNumber);
         FoundBusNumber = TRUE;
         break;
       }
       default:
-        DPRINT1("Unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type);
+        DPRINT("Unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type);
     }
   }
-  if (!FoundBusNumber)
-  {
-    DPRINT("Some required resources were not found in allocated resources list\n");
-    return STATUS_INSUFFICIENT_RESOURCES;
-  }
 
-next:
   InitializeListHead(&DeviceExtension->DeviceListHead);
   KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
   DeviceExtension->DeviceListCount = 0;
@@ -444,6 +472,8 @@ FdoSetPower(
   PFDO_DEVICE_EXTENSION DeviceExtension;
   NTSTATUS Status;
 
+  UNREFERENCED_PARAMETER(Irp);
+
   DPRINT("Called\n");
 
   DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@@ -476,7 +506,7 @@ FdoPnpControl(
 {
   PFDO_DEVICE_EXTENSION DeviceExtension;
   PIO_STACK_LOCATION IrpSp;
-  NTSTATUS Status;
+  NTSTATUS Status = Irp->IoStatus.Status;
 
   DPRINT("Called\n");
 
@@ -502,8 +532,13 @@ FdoPnpControl(
     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;
@@ -523,38 +558,37 @@ FdoPnpControl(
 #endif
   case IRP_MN_START_DEVICE:
     DPRINT("IRP_MN_START_DEVICE received\n");
-    Status = FdoStartDevice(DeviceObject, Irp);
-    break;
+    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_STOP_DEVICE:
     /* Currently not supported */
     Status = STATUS_UNSUCCESSFUL;
-    break;
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return Status;
 #if 0
   case IRP_MN_SURPRISE_REMOVAL:
     Status = STATUS_NOT_IMPLEMENTED;
     break;
 #endif
+  case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+    break;
+  case IRP_MN_REMOVE_DEVICE:
+    DPRINT1("IRP_MN_REMOVE_DEVICE is UNIMPLEMENTED!\n");
+    break;
   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;
   }
 
-
-  if (Status != STATUS_PENDING) {
-    if (Status != STATUS_NOT_IMPLEMENTED)
-      Irp->IoStatus.Status = Status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-  }
+  Irp->IoStatus.Status = Status;
+  IoSkipCurrentIrpStackLocation(Irp);
+  Status = IoCallDriver(DeviceExtension->Ldo, Irp);
 
   DPRINT("Leaving. Status 0x%X\n", Status);