IRP_MN_START_DEVICE implement for ROOT FDO (PciFdoStartDevice)
authorevb <evb@svn.reactos.org>
Fri, 16 Jul 2010 01:14:52 +0000 (01:14 +0000)
committerevb <evb@svn.reactos.org>
Fri, 16 Jul 2010 01:14:52 +0000 (01:14 +0000)
PciInitializeArbiterRanges implement to scan arbiter   not yet construct since Arb library missing
Add PCI state machine (PciBeginStateTransition, PciCancelStateTransition, PciCommitStateTransition) andtransition array (PnpStateTransitionArray) to check if valid
Now IRP_MN_QUERY_DEVICE_RELATIONS sent to ROOT FDO means time to enumerate bus!

svn path=/trunk/; revision=48075

reactos/drivers/bus/pcix/arb/arb_comn.c
reactos/drivers/bus/pcix/fdo.c
reactos/drivers/bus/pcix/pci.h
reactos/drivers/bus/pcix/pci/state.c
reactos/drivers/bus/pcix/utils.c

index b66fb54..52e0fa4 100644 (file)
@@ -121,4 +121,83 @@ PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
     /* Return to caller */
     return Status;
 }
+
+NTSTATUS
+NTAPI
+PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
+                           IN PCM_RESOURCE_LIST Resources)
+{
+    //PPCI_PDO_EXTENSION PdoExtension;
+    CM_RESOURCE_TYPE DesiredType;
+    PVOID Instance;
+    PCI_SIGNATURE ArbiterType;
+
+    /* Arbiters should not already be initialized */
+    if (DeviceExtension->ArbitersInitialized)
+    {
+        /* Duplicated start request, fail initialization */
+        DPRINT1("PCI Warning hot start FDOx %08x, resource ranges not checked.\n", DeviceExtension);
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+    
+    /* Check for non-root FDO */
+    if (!PCI_IS_ROOT_FDO(DeviceExtension))
+    {
+        /* Grab the PDO */
+#if 0 // when pdo support
+        PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension;
+        ASSERT(PdoExtension->ExtensionType == PciPdoExtensionType);
+#endif
+        /* Multiple FDOs are not yet supported */
+        UNIMPLEMENTED;
+        while (TRUE);
+        return STATUS_SUCCESS;
+    }
+    
+    /* Loop all arbiters */
+    for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++)
+    {
+        /* Pick correct resource type for each arbiter */
+        if (ArbiterType == PciArb_Io)
+        {
+            /* I/O Port */
+            DesiredType = CmResourceTypePort;
+        }
+        else if (ArbiterType == PciArb_Memory)
+        {
+            /* Device RAM */
+            DesiredType = CmResourceTypeMemory;
+        }
+        else
+        {
+            /* Ignore anything else */
+            continue;
+        }
+        /* Find an arbiter of this type */
+        Instance = PciFindNextSecondaryExtension(&DeviceExtension->SecondaryExtension,
+                                                 ArbiterType);
+        if (Instance)
+        {
+            /*
+             * Now we should initialize it, not yet implemented because Arb
+             * library isn't yet implemented, not even the headers.
+             */
+            UNIMPLEMENTED;
+            //while (TRUE);
+        }
+        else
+        {
+            /* The arbiter was not found, this is an error! */
+            DPRINT1("PCI - FDO ext 0x%08x %s arbiter (REQUIRED) is missing.\n",
+                    DeviceExtension,
+                    PciArbiterNames[ArbiterType - PciArb_Io]);
+        }
+    }
+
+    /* Arbiters are now initialized */
+    DeviceExtension->ArbitersInitialized = TRUE;
+    return STATUS_SUCCESS;
+}
+
 /* EOF */
index 08d61ad..b00b67e 100644 (file)
@@ -76,9 +76,49 @@ 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;
+    DPRINT1("Resources: %p\n", Resources);
+    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
index 3ceaadb..3c48449 100644 (file)
@@ -309,7 +309,6 @@ PciCallDownIrpStack(
     IN PIRP Irp
 );
 
-
 //
 // Power Routines
 //
@@ -564,6 +563,13 @@ PcipLinkSecondaryExtension(
     IN PVOID Destructor
 );
 
+PPCI_SECONDARY_EXTENSION
+NTAPI
+PciFindNextSecondaryExtension(
+    IN PSINGLE_LIST_ENTRY ListHead,
+    IN PCI_SIGNATURE ExtensionType
+);
+
 //
 // Configuration Routines
 //
@@ -582,6 +588,28 @@ PciInitializeState(
     IN PPCI_FDO_EXTENSION DeviceExtension
 );
 
+NTSTATUS
+NTAPI
+PciBeginStateTransition(
+    IN PPCI_FDO_EXTENSION DeviceExtension,
+    IN PCI_STATE NewState
+);
+
+NTSTATUS
+NTAPI
+PciCancelStateTransition(
+    IN PPCI_FDO_EXTENSION DeviceExtension,
+    IN PCI_STATE NewState
+);
+
+VOID
+NTAPI
+PciCommitStateTransition(
+    IN PPCI_FDO_EXTENSION DeviceExtension,
+    IN PCI_STATE NewState
+);
+
+
 //
 // Arbiter Support
 //
@@ -591,6 +619,13 @@ PciInitializeArbiters(
     IN PPCI_FDO_EXTENSION FdoExtension
 );
 
+NTSTATUS
+NTAPI
+PciInitializeArbiterRanges(
+    IN PPCI_FDO_EXTENSION DeviceExtension,
+    IN PCM_RESOURCE_LIST Resources
+);
+
 //
 // Debug Helpers
 //
index 994000f..6219164 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
+PCHAR PciTransitionText[PciMaxObjectState + 1] =
+{
+    "PciNotStarted",
+    "PciStarted",
+    "PciDeleted",
+    "PciStopped",
+    "PciSurpriseRemoved",
+    "PciSynchronizedOperation",
+    "PciMaxObjectState"
+};
+
+NTSTATUS PnpStateCancelArray[PciMaxObjectState] =
+{
+    STATUS_INVALID_DEVICE_REQUEST,
+    STATUS_FAIL_CHECK,
+    STATUS_INVALID_DEVICE_STATE,
+    STATUS_INVALID_DEVICE_STATE,
+    STATUS_FAIL_CHECK,
+    STATUS_FAIL_CHECK
+};
+
+NTSTATUS PnpStateTransitionArray[PciMaxObjectState * PciMaxObjectState] =
+{
+    STATUS_SUCCESS,                 // Not Started -> Not Started
+    STATUS_SUCCESS,                 // Started -> Not Started
+    STATUS_FAIL_CHECK,              // Deleted -> Not Started
+    STATUS_SUCCESS,                 // Stopped -> Not Started
+    STATUS_FAIL_CHECK,              // Surprise Removed -> Not Started
+    STATUS_FAIL_CHECK,              // Synchronized Operation -> Not Started
+
+    STATUS_SUCCESS,                 // Not Started -> Started
+    STATUS_FAIL_CHECK,              // Started -> Started
+    STATUS_FAIL_CHECK,              // Deleted -> Started
+    STATUS_SUCCESS,                 // Stopped -> Started
+    STATUS_FAIL_CHECK,              // Surprise Removed -> Started
+    STATUS_FAIL_CHECK,              // Synchronized Operation -> Started
+
+    STATUS_SUCCESS,                 // Not Started -> Deleted
+    STATUS_SUCCESS,                 // Started -> Deleted
+    STATUS_FAIL_CHECK,              // Deleted -> Deleted
+    STATUS_FAIL_CHECK,              // Stopped -> Deleted
+    STATUS_SUCCESS,                 // Surprise Removed -> Deleted
+    STATUS_FAIL_CHECK,              // Synchronized Operation -> Deleted
+
+    STATUS_INVALID_DEVICE_REQUEST,  // Not Started -> Stopped
+    STATUS_SUCCESS,                 // Started -> Stopped
+    STATUS_FAIL_CHECK,              // Deleted -> Stopped
+    STATUS_FAIL_CHECK,              // Stopped -> Stopped
+    STATUS_FAIL_CHECK,              // Surprise Removed -> Stopped
+    STATUS_FAIL_CHECK,              // Synchronized Operation -> Stopped
+
+    STATUS_SUCCESS,                 // Not Started -> Surprise Removed
+    STATUS_SUCCESS,                 // Started -> Surprise Removed
+    STATUS_FAIL_CHECK,              // Deleted -> Surprise Removed
+    STATUS_SUCCESS,                 // Stopped -> Surprise Removed
+    STATUS_FAIL_CHECK,              // Surprise Removed -> Surprise Removed
+    STATUS_FAIL_CHECK,              // Synchronized Operation -> Surprise Removed
+
+    STATUS_SUCCESS,                 // Not Started -> Synchronized Operation
+    STATUS_SUCCESS,                 // Started -> Synchronized Operation
+    STATUS_INVALID_DEVICE_STATE,    // Deleted -> Synchronized Operation
+    STATUS_SUCCESS,                 // Stopped -> Synchronized Operation
+    STATUS_INVALID_DEVICE_STATE,    // Surprise Removed -> Synchronized Operation
+    STATUS_FAIL_CHECK               // Synchronized Operation -> Synchronized Operation
+};
+
 /* FUNCTIONS ******************************************************************/
 
 VOID
@@ -25,4 +91,104 @@ PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension)
     DeviceExtension->TentativeNextState = PciNotStarted;
 }
 
+NTSTATUS
+NTAPI
+PciBeginStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,
+                        IN PCI_STATE NewState)
+{
+    PCI_STATE CurrentState;
+    NTSTATUS Status;
+    DPRINT1("PCI Request to begin transition of Extension %p to %s ->",
+            DeviceExtension,
+            PciTransitionText[NewState]);
+
+    /* Assert the device isn't already in a pending transition */
+    ASSERT(DeviceExtension->TentativeNextState == DeviceExtension->DeviceState);
+
+    /* Assert this is a valid state */
+    CurrentState = DeviceExtension->DeviceState;
+    ASSERT(CurrentState < PciMaxObjectState);
+    ASSERT(NewState < PciMaxObjectState);
+
+    /* Lookup if this state transition is valid */
+    Status = PnpStateTransitionArray[CurrentState + 6 * NewState];
+    if (Status == STATUS_FAIL_CHECK)
+    {
+        /* Invalid transition (logical fault) */
+        DPRINT1("ERROR\nPCI: Error trying to enter state \"%s\" "
+                "from state \"%s\"\n",
+                PciTransitionText[NewState],
+                PciTransitionText[CurrentState]);
+        DbgBreakPoint();
+    }
+    else if (Status == STATUS_INVALID_DEVICE_REQUEST)
+    {
+        /* Invalid transition (illegal request) */
+        DPRINT1("ERROR\nPCI: Illegal request to try to enter state \"%s\" "
+                "from state \"%s\", rejecting",
+                PciTransitionText[NewState],
+                PciTransitionText[CurrentState]);
+    }
+
+    /* New state must be different from current, unless request is at fault */
+    ASSERT((NewState != DeviceExtension->DeviceState) || (!NT_SUCCESS(Status)));
+
+    /* Enter the new state if successful, and return state status */
+    if (NT_SUCCESS(Status)) DeviceExtension->TentativeNextState = NewState;
+    DbgPrint("%x\n", Status);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+PciCancelStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,
+                         IN PCI_STATE StateNotEntered)
+{
+    NTSTATUS Status;
+    DPRINT1("PCI Request to cancel transition of Extension %p to %s ->",
+            DeviceExtension,
+            PciTransitionText[StateNotEntered]);
+
+    /* The next state can't be the state the device is already in */
+    if (DeviceExtension->TentativeNextState == DeviceExtension->DeviceState)
+    {
+        /* It's too late since the state was already committed */
+        ASSERT(StateNotEntered < PciMaxObjectState);
+        ASSERT(PnpStateCancelArray[StateNotEntered] != STATUS_FAIL_CHECK);
+
+        /* Return failure */
+        Status = STATUS_INVALID_DEVICE_STATE;
+        DbgPrint("%x\n", Status);
+    }
+    else
+    {
+        /* The device hasn't yet entered the state, so it's still possible to cancel */
+        ASSERT(DeviceExtension->TentativeNextState == StateNotEntered);
+        DeviceExtension->TentativeNextState = DeviceExtension->DeviceState;
+
+        /* Return success */
+        Status = STATUS_SUCCESS;
+        DbgPrint("%x\n", Status);
+    }
+
+    /* Return the cancel state */
+    return Status;
+}
+
+VOID
+NTAPI
+PciCommitStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,
+                         IN PCI_STATE NewState)
+{
+    DPRINT1("PCI Commit transition of Extension %p to %s\n",
+            DeviceExtension, PciTransitionText[NewState]);
+
+    /* Make sure this is a valid commit */
+    ASSERT(NewState != PciSynchronizedOperation);
+    ASSERT(DeviceExtension->TentativeNextState == NewState);
+
+    /* Enter the new state */
+    DeviceExtension->DeviceState = NewState;
+}
+
 /* EOF */
index 91cd952..0684b17 100644 (file)
@@ -555,4 +555,24 @@ PciSendIoctl(IN PDEVICE_OBJECT DeviceObject,
     return Status;
 }
 
+PPCI_SECONDARY_EXTENSION
+NTAPI
+PciFindNextSecondaryExtension(IN PSINGLE_LIST_ENTRY ListHead,
+                              IN PCI_SIGNATURE ExtensionType)
+{
+    PSINGLE_LIST_ENTRY NextEntry;
+    PPCI_SECONDARY_EXTENSION Extension;
+
+    /* Scan the list */
+    for (NextEntry = ListHead; NextEntry; NextEntry = NextEntry->Next)
+    {
+        /* Grab each extension and check if it's the one requested */
+        Extension = CONTAINING_RECORD(NextEntry, PCI_SECONDARY_EXTENSION, List);
+        if (Extension->ExtensionType == ExtensionType) return Extension;
+    }
+
+    /* Nothing was found */
+    return NULL;
+}
+
 /* EOF */