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