xref: /reactos/drivers/bus/pcix/pci/state.c (revision c2c66aff)
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