[USB]
[reactos.git] / reactos / drivers / bus / pcix / fdo.c
index d7c5115..785dfca 100644 (file)
@@ -19,41 +19,41 @@ BOOLEAN PciBreakOnDefault;
 
 PCI_MN_DISPATCH_TABLE PciFdoDispatchPowerTable[] =
 {
-    {IRP_DISPATCH, PciFdoWaitWake},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciFdoSetPowerState},
-    {IRP_DOWNWARD, PciFdoIrpQueryPower},
-    {IRP_DOWNWARD, PciIrpNotSupported}
+    {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoWaitWake},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoSetPowerState},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryPower},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
 };
 
 PCI_MN_DISPATCH_TABLE PciFdoDispatchPnpTable[] =
 {
-    {IRP_UPWARD,   PciFdoIrpStartDevice},
-    {IRP_DOWNWARD, PciFdoIrpQueryRemoveDevice},
-    {IRP_DISPATCH, PciFdoIrpRemoveDevice},
-    {IRP_DOWNWARD, PciFdoIrpCancelRemoveDevice},
-    {IRP_DOWNWARD, PciFdoIrpStopDevice},
-    {IRP_DOWNWARD, PciFdoIrpQueryStopDevice},
-    {IRP_DOWNWARD, PciFdoIrpCancelStopDevice},
-    {IRP_DOWNWARD, PciFdoIrpQueryDeviceRelations},
-    {IRP_DISPATCH, PciFdoIrpQueryInterface},
-    {IRP_UPWARD,   PciFdoIrpQueryCapabilities},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_DOWNWARD, PciIrpNotSupported},
-    {IRP_UPWARD,   PciFdoIrpDeviceUsageNotification},
-    {IRP_DOWNWARD, PciFdoIrpSurpriseRemoval},
-    {IRP_DOWNWARD, PciFdoIrpQueryLegacyBusInformation},
-    {IRP_DOWNWARD, PciIrpNotSupported}
+    {IRP_UPWARD,   (PCI_DISPATCH_FUNCTION)PciFdoIrpStartDevice},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryRemoveDevice},
+    {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoIrpRemoveDevice},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpCancelRemoveDevice},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpStopDevice},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryStopDevice},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpCancelStopDevice},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryDeviceRelations},
+    {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryInterface},
+    {IRP_UPWARD,   (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryCapabilities},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_UPWARD,   (PCI_DISPATCH_FUNCTION)PciFdoIrpDeviceUsageNotification},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpSurpriseRemoval},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryLegacyBusInformation},
+    {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
 };
 
 PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable =
@@ -63,9 +63,9 @@ PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable =
     IRP_MN_QUERY_POWER,
     PciFdoDispatchPowerTable,
     IRP_DOWNWARD,
-    PciIrpNotSupported,
+    (PCI_DISPATCH_FUNCTION)PciIrpNotSupported,
     IRP_DOWNWARD,
-    PciIrpNotSupported
+    (PCI_DISPATCH_FUNCTION)PciIrpNotSupported
 };
 
 /* FUNCTIONS ******************************************************************/
@@ -76,9 +76,48 @@ PciFdoIrpStartDevice(IN PIRP Irp,
                      IN PIO_STACK_LOCATION IoStackLocation,
                      IN PPCI_FDO_EXTENSION DeviceExtension)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
-    return STATUS_NOT_SUPPORTED;
+    NTSTATUS Status;
+    PCM_RESOURCE_LIST Resources;
+    PAGED_CODE();
+
+    /* The device stack must be starting the FDO in a success path */
+    if (!NT_SUCCESS(Irp->IoStatus.Status)) return STATUS_NOT_SUPPORTED;
+
+    /* Attempt to switch the state machine to the started state */
+    Status = PciBeginStateTransition(DeviceExtension, PciStarted);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Check for any boot-provided resources */
+    Resources = IoStackLocation->Parameters.StartDevice.AllocatedResources;
+    if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension)))
+    {
+        /* These resources would only be for non-root FDOs, unhandled for now */
+        ASSERT(Resources->Count == 1);
+        UNIMPLEMENTED;
+        while (TRUE);
+    }
+
+    /* Initialize the arbiter for this FDO */
+    Status = PciInitializeArbiterRanges(DeviceExtension, Resources);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Cancel the transition if this failed */
+        PciCancelStateTransition(DeviceExtension, PciStarted);
+        return Status;
+    }
+
+    /* Again, check for boot-provided resources for non-root FDO */
+    if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension)))
+    {
+        /* Unhandled for now */
+        ASSERT(Resources->Count == 1);
+        UNIMPLEMENTED;
+        while (TRUE);
+    }
+
+    /* Commit the transition to the started state */
+    PciCommitStateTransition(DeviceExtension, PciStarted);
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -88,7 +127,6 @@ PciFdoIrpQueryRemoveDevice(IN PIRP Irp,
                            IN PPCI_FDO_EXTENSION DeviceExtension)
 {
     UNIMPLEMENTED;
-    while (TRUE);
     return STATUS_NOT_SUPPORTED;
 }
 
@@ -153,9 +191,25 @@ PciFdoIrpQueryDeviceRelations(IN PIRP Irp,
                               IN PIO_STACK_LOCATION IoStackLocation,
                               IN PPCI_FDO_EXTENSION DeviceExtension)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
-    return STATUS_NOT_SUPPORTED;
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Are bus relations being queried? */
+    if (IoStackLocation->Parameters.QueryDeviceRelations.Type != BusRelations)
+    {
+        /* The FDO is a bus, so only bus relations can be obtained */
+        Status = STATUS_NOT_SUPPORTED;
+    }
+    else
+    {
+        /* Scan the PCI bus and build the device relations for the caller */
+        Status = PciQueryDeviceRelations(DeviceExtension,
+                                         (PDEVICE_RELATIONS*)
+                                         &Irp->IoStatus.Information);
+    }
+
+    /* Return the enumeration status back */
+    return Status;
 }
 
 NTSTATUS
@@ -164,9 +218,73 @@ PciFdoIrpQueryInterface(IN PIRP Irp,
                         IN PIO_STACK_LOCATION IoStackLocation,
                         IN PPCI_FDO_EXTENSION DeviceExtension)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
-    return STATUS_NOT_SUPPORTED;
+    NTSTATUS Status;
+    PAGED_CODE();
+    ASSERT(DeviceExtension->ExtensionType == PciFdoExtensionType);
+
+    /* Deleted extensions don't respond to IRPs */
+    if (DeviceExtension->DeviceState == PciDeleted)
+    {
+        /* Hand it back to try to deal with it */
+        return PciPassIrpFromFdoToPdo(DeviceExtension, Irp);
+    }
+
+    /* Query our driver for this interface */
+    Status = PciQueryInterface(DeviceExtension,
+                               IoStackLocation->Parameters.QueryInterface.
+                               InterfaceType,
+                               IoStackLocation->Parameters.QueryInterface.
+                               Size,
+                               IoStackLocation->Parameters.QueryInterface.
+                               Version,
+                               IoStackLocation->Parameters.QueryInterface.
+                               InterfaceSpecificData,
+                               IoStackLocation->Parameters.QueryInterface.
+                               Interface,
+                               FALSE);
+    if (NT_SUCCESS(Status))
+    {
+        /* We found it, let the PDO handle it */
+        Irp->IoStatus.Status = Status;
+        return PciPassIrpFromFdoToPdo(DeviceExtension, Irp);
+    }
+    else if (Status == STATUS_NOT_SUPPORTED)
+    {
+        /* Otherwise, we can't handle it, let someone else down the stack try */
+        Status = PciCallDownIrpStack(DeviceExtension, Irp);
+        if (Status == STATUS_NOT_SUPPORTED)
+        {
+            /* They can't either, try a last-resort interface lookup */
+            Status = PciQueryInterface(DeviceExtension,
+                                       IoStackLocation->Parameters.QueryInterface.
+                                       InterfaceType,
+                                       IoStackLocation->Parameters.QueryInterface.
+                                       Size,
+                                       IoStackLocation->Parameters.QueryInterface.
+                                       Version,
+                                       IoStackLocation->Parameters.QueryInterface.
+                                       InterfaceSpecificData,
+                                       IoStackLocation->Parameters.QueryInterface.
+                                       Interface,
+                                       TRUE);
+        }
+    }
+
+    /* Has anyone claimed this interface yet? */
+    if (Status == STATUS_NOT_SUPPORTED)
+    {
+        /* No, return the original IRP status */
+        Status = Irp->IoStatus.Status;
+    }
+    else
+    {
+        /* Yes, set the new IRP status */
+        Irp->IoStatus.Status = Status;
+    }
+
+    /* Complete this IRP */
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return Status;
 }
 
 NTSTATUS
@@ -175,9 +293,23 @@ PciFdoIrpQueryCapabilities(IN PIRP Irp,
                            IN PIO_STACK_LOCATION IoStackLocation,
                            IN PPCI_FDO_EXTENSION DeviceExtension)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
-    return STATUS_NOT_SUPPORTED;
+    PDEVICE_CAPABILITIES Capabilities;
+    PAGED_CODE();
+    ASSERT_FDO(DeviceExtension);
+
+    /* Get the capabilities */
+    Capabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities;
+
+    /* Inherit wake levels and power mappings from the higher-up capabilities */
+    DeviceExtension->PowerState.SystemWakeLevel = Capabilities->SystemWake;
+    DeviceExtension->PowerState.DeviceWakeLevel = Capabilities->DeviceWake;
+    RtlCopyMemory(DeviceExtension->PowerState.SystemStateMapping,
+                  Capabilities->DeviceState,
+                  sizeof(DeviceExtension->PowerState.SystemStateMapping));
+
+    /* Dump the capabilities and return success */
+    PciDebugDumpQueryCapabilities(Capabilities);
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -302,6 +434,7 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject,
     PDEVICE_OBJECT AttachedTo;
     PPCI_FDO_EXTENSION FdoExtension;
     PPCI_FDO_EXTENSION ParentExtension;
+    PPCI_PDO_EXTENSION PdoExtension;
     PDEVICE_OBJECT DeviceObject;
     UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
@@ -315,6 +448,8 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject,
 
     /* Zero out variables so failure path knows what to do */
     AttachedTo = NULL;
+    FdoExtension = NULL;
+    PdoExtension = NULL;
     do
     {
         /* Check if there's already a device extension for this bus */
@@ -322,9 +457,44 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject,
                                                        &PciGlobalLock);
         if (ParentExtension)
         {
-            /* More than one PCI bus, this is not expected yet */
-            UNIMPLEMENTED;
-            while (TRUE);
+            /* Make sure we find a real PDO */
+            PdoExtension = PhysicalDeviceObject->DeviceExtension;
+            ASSERT_PDO(PdoExtension);
+
+            /* Make sure it's a PCI-to-PCI bridge */
+            if ((PdoExtension->BaseClass != PCI_CLASS_BRIDGE_DEV) ||
+                (PdoExtension->SubClass != PCI_SUBCLASS_BR_PCI_TO_PCI))
+            {
+                /* This should never happen */
+                DPRINT1("PCI - PciAddDevice for Non-Root/Non-PCI-PCI bridge,\n"
+                        "      Class %02x, SubClass %02x, will not add.\n",
+                        PdoExtension->BaseClass,
+                        PdoExtension->SubClass);
+                ASSERT((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+                       (PdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI));
+
+                /* Enter the failure path */
+                Status = STATUS_INVALID_DEVICE_REQUEST;
+                break;
+            }
+
+            /* Subordinate bus on the bridge */
+            DPRINT1("PCI - AddDevice (new bus is child of bus 0x%x).\n",
+                    ParentExtension->BaseBus);
+
+            /* Make sure PCI bus numbers are configured */
+            if (!PciAreBusNumbersConfigured(PdoExtension))
+            {
+                /* This is a critical failure */
+                DPRINT1("PCI - Bus numbers not configured for bridge (0x%x.0x%x.0x%x)\n",
+                        ParentExtension->BaseBus,
+                        PdoExtension->Slot.u.bits.DeviceNumber,
+                        PdoExtension->Slot.u.bits.FunctionNumber);
+
+                /* Enter the failure path */
+                Status = STATUS_INVALID_DEVICE_REQUEST;
+                break;
+            }
         }
 
         /* Create the FDO for the bus */
@@ -350,11 +520,15 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject,
         ASSERT(AttachedTo != NULL);
         if (!AttachedTo) break;
         FdoExtension->AttachedDeviceObject = AttachedTo;
+
+        /* Check if this is a child bus, or the root */
         if (ParentExtension)
         {
-            /* More than one PCI bus, this is not expected yet */
-            UNIMPLEMENTED;
-            while (TRUE);
+            /* The child inherits root data */
+            FdoExtension->BaseBus = PdoExtension->Dependent.type1.SecondaryBus;
+            FdoExtension->BusRootFdoExtension = ParentExtension->BusRootFdoExtension;
+            PdoExtension->BridgeFdoExtension = FdoExtension;
+            FdoExtension->ParentFdoExtension = ParentExtension;
         }
         else
         {
@@ -371,7 +545,9 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject,
             {
                 /* Root PDO in ReactOS does not assign boot resources */
                 UNIMPLEMENTED;
-                while (TRUE);
+//                while (TRUE);
+                DPRINT1("Encountered during setup\n");
+                Descriptor = NULL;
             }
 
             if (Descriptor)
@@ -448,12 +624,16 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject,
 
         /* The Bus FDO is now initialized */
         DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
-        DPRINT1("PCI Root FDO Added: %p %p\n", DeviceObject, FdoExtension);
         return STATUS_SUCCESS;
     } while (FALSE);
 
     /* This is the failure path */
     ASSERT(!NT_SUCCESS(Status));
+
+    /* Check if the FDO extension exists */
+    if (FdoExtension) DPRINT1("Should destroy secondaries\n");
+
+    /* Delete device objects */
     if (AttachedTo) IoDetachDevice(AttachedTo);
     if (DeviceObject) IoDeleteDevice(DeviceObject);
     return Status;