mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 05:08:39 +00:00
196 lines
7 KiB
C
196 lines
7 KiB
C
/*
|
|
* PROJECT: ReactOS PCI Bus Driver
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
* FILE: drivers/bus/pci/pci/state.c
|
|
* PURPOSE: Bus/Device State Support
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include <pci.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* 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
|
|
NTAPI
|
|
PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension)
|
|
{
|
|
/* Set the initial state */
|
|
DeviceExtension->DeviceState = PciNotStarted;
|
|
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 */
|