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