+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;
+}
+