1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS PCI Bus Driver
3*c2c66affSColin Finck * LICENSE: BSD - See COPYING.ARM in the top level directory
4*c2c66affSColin Finck * FILE: drivers/bus/pci/pci/state.c
5*c2c66affSColin Finck * PURPOSE: Bus/Device State Support
6*c2c66affSColin Finck * PROGRAMMERS: ReactOS Portable Systems Group
7*c2c66affSColin Finck */
8*c2c66affSColin Finck
9*c2c66affSColin Finck /* INCLUDES *******************************************************************/
10*c2c66affSColin Finck
11*c2c66affSColin Finck #include <pci.h>
12*c2c66affSColin Finck
13*c2c66affSColin Finck #define NDEBUG
14*c2c66affSColin Finck #include <debug.h>
15*c2c66affSColin Finck
16*c2c66affSColin Finck /* GLOBALS ********************************************************************/
17*c2c66affSColin Finck
18*c2c66affSColin Finck PCHAR PciTransitionText[PciMaxObjectState + 1] =
19*c2c66affSColin Finck {
20*c2c66affSColin Finck "PciNotStarted",
21*c2c66affSColin Finck "PciStarted",
22*c2c66affSColin Finck "PciDeleted",
23*c2c66affSColin Finck "PciStopped",
24*c2c66affSColin Finck "PciSurpriseRemoved",
25*c2c66affSColin Finck "PciSynchronizedOperation",
26*c2c66affSColin Finck "PciMaxObjectState"
27*c2c66affSColin Finck };
28*c2c66affSColin Finck
29*c2c66affSColin Finck NTSTATUS PnpStateCancelArray[PciMaxObjectState] =
30*c2c66affSColin Finck {
31*c2c66affSColin Finck STATUS_INVALID_DEVICE_REQUEST,
32*c2c66affSColin Finck STATUS_FAIL_CHECK,
33*c2c66affSColin Finck STATUS_INVALID_DEVICE_STATE,
34*c2c66affSColin Finck STATUS_INVALID_DEVICE_STATE,
35*c2c66affSColin Finck STATUS_FAIL_CHECK,
36*c2c66affSColin Finck STATUS_FAIL_CHECK
37*c2c66affSColin Finck };
38*c2c66affSColin Finck
39*c2c66affSColin Finck NTSTATUS PnpStateTransitionArray[PciMaxObjectState * PciMaxObjectState] =
40*c2c66affSColin Finck {
41*c2c66affSColin Finck STATUS_SUCCESS, // Not Started -> Not Started
42*c2c66affSColin Finck STATUS_SUCCESS, // Started -> Not Started
43*c2c66affSColin Finck STATUS_FAIL_CHECK, // Deleted -> Not Started
44*c2c66affSColin Finck STATUS_SUCCESS, // Stopped -> Not Started
45*c2c66affSColin Finck STATUS_FAIL_CHECK, // Surprise Removed -> Not Started
46*c2c66affSColin Finck STATUS_FAIL_CHECK, // Synchronized Operation -> Not Started
47*c2c66affSColin Finck
48*c2c66affSColin Finck STATUS_SUCCESS, // Not Started -> Started
49*c2c66affSColin Finck STATUS_FAIL_CHECK, // Started -> Started
50*c2c66affSColin Finck STATUS_FAIL_CHECK, // Deleted -> Started
51*c2c66affSColin Finck STATUS_SUCCESS, // Stopped -> Started
52*c2c66affSColin Finck STATUS_FAIL_CHECK, // Surprise Removed -> Started
53*c2c66affSColin Finck STATUS_FAIL_CHECK, // Synchronized Operation -> Started
54*c2c66affSColin Finck
55*c2c66affSColin Finck STATUS_SUCCESS, // Not Started -> Deleted
56*c2c66affSColin Finck STATUS_SUCCESS, // Started -> Deleted
57*c2c66affSColin Finck STATUS_FAIL_CHECK, // Deleted -> Deleted
58*c2c66affSColin Finck STATUS_FAIL_CHECK, // Stopped -> Deleted
59*c2c66affSColin Finck STATUS_SUCCESS, // Surprise Removed -> Deleted
60*c2c66affSColin Finck STATUS_FAIL_CHECK, // Synchronized Operation -> Deleted
61*c2c66affSColin Finck
62*c2c66affSColin Finck STATUS_INVALID_DEVICE_REQUEST, // Not Started -> Stopped
63*c2c66affSColin Finck STATUS_SUCCESS, // Started -> Stopped
64*c2c66affSColin Finck STATUS_FAIL_CHECK, // Deleted -> Stopped
65*c2c66affSColin Finck STATUS_FAIL_CHECK, // Stopped -> Stopped
66*c2c66affSColin Finck STATUS_FAIL_CHECK, // Surprise Removed -> Stopped
67*c2c66affSColin Finck STATUS_FAIL_CHECK, // Synchronized Operation -> Stopped
68*c2c66affSColin Finck
69*c2c66affSColin Finck STATUS_SUCCESS, // Not Started -> Surprise Removed
70*c2c66affSColin Finck STATUS_SUCCESS, // Started -> Surprise Removed
71*c2c66affSColin Finck STATUS_FAIL_CHECK, // Deleted -> Surprise Removed
72*c2c66affSColin Finck STATUS_SUCCESS, // Stopped -> Surprise Removed
73*c2c66affSColin Finck STATUS_FAIL_CHECK, // Surprise Removed -> Surprise Removed
74*c2c66affSColin Finck STATUS_FAIL_CHECK, // Synchronized Operation -> Surprise Removed
75*c2c66affSColin Finck
76*c2c66affSColin Finck STATUS_SUCCESS, // Not Started -> Synchronized Operation
77*c2c66affSColin Finck STATUS_SUCCESS, // Started -> Synchronized Operation
78*c2c66affSColin Finck STATUS_INVALID_DEVICE_STATE, // Deleted -> Synchronized Operation
79*c2c66affSColin Finck STATUS_SUCCESS, // Stopped -> Synchronized Operation
80*c2c66affSColin Finck STATUS_INVALID_DEVICE_STATE, // Surprise Removed -> Synchronized Operation
81*c2c66affSColin Finck STATUS_FAIL_CHECK // Synchronized Operation -> Synchronized Operation
82*c2c66affSColin Finck };
83*c2c66affSColin Finck
84*c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
85*c2c66affSColin Finck
86*c2c66affSColin Finck VOID
87*c2c66affSColin Finck NTAPI
PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension)88*c2c66affSColin Finck PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension)
89*c2c66affSColin Finck {
90*c2c66affSColin Finck /* Set the initial state */
91*c2c66affSColin Finck DeviceExtension->DeviceState = PciNotStarted;
92*c2c66affSColin Finck DeviceExtension->TentativeNextState = PciNotStarted;
93*c2c66affSColin Finck }
94*c2c66affSColin Finck
95*c2c66affSColin Finck NTSTATUS
96*c2c66affSColin Finck NTAPI
PciBeginStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,IN PCI_STATE NewState)97*c2c66affSColin Finck PciBeginStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,
98*c2c66affSColin Finck IN PCI_STATE NewState)
99*c2c66affSColin Finck {
100*c2c66affSColin Finck PCI_STATE CurrentState;
101*c2c66affSColin Finck NTSTATUS Status;
102*c2c66affSColin Finck DPRINT1("PCI Request to begin transition of Extension %p to %s ->",
103*c2c66affSColin Finck DeviceExtension,
104*c2c66affSColin Finck PciTransitionText[NewState]);
105*c2c66affSColin Finck
106*c2c66affSColin Finck /* Assert the device isn't already in a pending transition */
107*c2c66affSColin Finck ASSERT(DeviceExtension->TentativeNextState == DeviceExtension->DeviceState);
108*c2c66affSColin Finck
109*c2c66affSColin Finck /* Assert this is a valid state */
110*c2c66affSColin Finck CurrentState = DeviceExtension->DeviceState;
111*c2c66affSColin Finck ASSERT(CurrentState < PciMaxObjectState);
112*c2c66affSColin Finck ASSERT(NewState < PciMaxObjectState);
113*c2c66affSColin Finck
114*c2c66affSColin Finck /* Lookup if this state transition is valid */
115*c2c66affSColin Finck Status = PnpStateTransitionArray[CurrentState + 6 * NewState];
116*c2c66affSColin Finck if (Status == STATUS_FAIL_CHECK)
117*c2c66affSColin Finck {
118*c2c66affSColin Finck /* Invalid transition (logical fault) */
119*c2c66affSColin Finck DPRINT1("ERROR\nPCI: Error trying to enter state \"%s\" "
120*c2c66affSColin Finck "from state \"%s\"\n",
121*c2c66affSColin Finck PciTransitionText[NewState],
122*c2c66affSColin Finck PciTransitionText[CurrentState]);
123*c2c66affSColin Finck DbgBreakPoint();
124*c2c66affSColin Finck }
125*c2c66affSColin Finck else if (Status == STATUS_INVALID_DEVICE_REQUEST)
126*c2c66affSColin Finck {
127*c2c66affSColin Finck /* Invalid transition (illegal request) */
128*c2c66affSColin Finck DPRINT1("ERROR\nPCI: Illegal request to try to enter state \"%s\" "
129*c2c66affSColin Finck "from state \"%s\", rejecting",
130*c2c66affSColin Finck PciTransitionText[NewState],
131*c2c66affSColin Finck PciTransitionText[CurrentState]);
132*c2c66affSColin Finck }
133*c2c66affSColin Finck
134*c2c66affSColin Finck /* New state must be different from current, unless request is at fault */
135*c2c66affSColin Finck ASSERT((NewState != DeviceExtension->DeviceState) || (!NT_SUCCESS(Status)));
136*c2c66affSColin Finck
137*c2c66affSColin Finck /* Enter the new state if successful, and return state status */
138*c2c66affSColin Finck if (NT_SUCCESS(Status)) DeviceExtension->TentativeNextState = NewState;
139*c2c66affSColin Finck DbgPrint("%x\n", Status);
140*c2c66affSColin Finck return Status;
141*c2c66affSColin Finck }
142*c2c66affSColin Finck
143*c2c66affSColin Finck NTSTATUS
144*c2c66affSColin Finck NTAPI
PciCancelStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,IN PCI_STATE StateNotEntered)145*c2c66affSColin Finck PciCancelStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,
146*c2c66affSColin Finck IN PCI_STATE StateNotEntered)
147*c2c66affSColin Finck {
148*c2c66affSColin Finck NTSTATUS Status;
149*c2c66affSColin Finck DPRINT1("PCI Request to cancel transition of Extension %p to %s ->",
150*c2c66affSColin Finck DeviceExtension,
151*c2c66affSColin Finck PciTransitionText[StateNotEntered]);
152*c2c66affSColin Finck
153*c2c66affSColin Finck /* The next state can't be the state the device is already in */
154*c2c66affSColin Finck if (DeviceExtension->TentativeNextState == DeviceExtension->DeviceState)
155*c2c66affSColin Finck {
156*c2c66affSColin Finck /* It's too late since the state was already committed */
157*c2c66affSColin Finck ASSERT(StateNotEntered < PciMaxObjectState);
158*c2c66affSColin Finck ASSERT(PnpStateCancelArray[StateNotEntered] != STATUS_FAIL_CHECK);
159*c2c66affSColin Finck
160*c2c66affSColin Finck /* Return failure */
161*c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_STATE;
162*c2c66affSColin Finck DbgPrint("%x\n", Status);
163*c2c66affSColin Finck }
164*c2c66affSColin Finck else
165*c2c66affSColin Finck {
166*c2c66affSColin Finck /* The device hasn't yet entered the state, so it's still possible to cancel */
167*c2c66affSColin Finck ASSERT(DeviceExtension->TentativeNextState == StateNotEntered);
168*c2c66affSColin Finck DeviceExtension->TentativeNextState = DeviceExtension->DeviceState;
169*c2c66affSColin Finck
170*c2c66affSColin Finck /* Return success */
171*c2c66affSColin Finck Status = STATUS_SUCCESS;
172*c2c66affSColin Finck DbgPrint("%x\n", Status);
173*c2c66affSColin Finck }
174*c2c66affSColin Finck
175*c2c66affSColin Finck /* Return the cancel state */
176*c2c66affSColin Finck return Status;
177*c2c66affSColin Finck }
178*c2c66affSColin Finck
179*c2c66affSColin Finck VOID
180*c2c66affSColin Finck NTAPI
PciCommitStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,IN PCI_STATE NewState)181*c2c66affSColin Finck PciCommitStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension,
182*c2c66affSColin Finck IN PCI_STATE NewState)
183*c2c66affSColin Finck {
184*c2c66affSColin Finck DPRINT1("PCI Commit transition of Extension %p to %s\n",
185*c2c66affSColin Finck DeviceExtension, PciTransitionText[NewState]);
186*c2c66affSColin Finck
187*c2c66affSColin Finck /* Make sure this is a valid commit */
188*c2c66affSColin Finck ASSERT(NewState != PciSynchronizedOperation);
189*c2c66affSColin Finck ASSERT(DeviceExtension->TentativeNextState == NewState);
190*c2c66affSColin Finck
191*c2c66affSColin Finck /* Enter the new state */
192*c2c66affSColin Finck DeviceExtension->DeviceState = NewState;
193*c2c66affSColin Finck }
194*c2c66affSColin Finck
195*c2c66affSColin Finck /* EOF */
196