/* 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 */
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
/* 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
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 */