9512fdcc9c22eaa750f1247f945ca02f75537b4f
[reactos.git] / reactos / drivers / bus / pcix / dispatch.c
1 /*
2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/dispatch.c
5 * PURPOSE: WDM Dispatch Routines
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 /* FUNCTIONS ******************************************************************/
18
19 IO_COMPLETION_ROUTINE PciSetEventCompletion;
20
21 NTSTATUS
22 NTAPI
23 PciSetEventCompletion(IN PDEVICE_OBJECT DeviceObject,
24 IN PIRP Irp,
25 IN PVOID Context)
26 {
27 PKEVENT Event = (PVOID)Context;
28 ASSERT(Event);
29
30 UNREFERENCED_PARAMETER(DeviceObject);
31 UNREFERENCED_PARAMETER(Irp);
32
33 /* Set the event and return the appropriate status code */
34 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
35 return STATUS_MORE_PROCESSING_REQUIRED;
36 }
37
38 NTSTATUS
39 NTAPI
40 PciCallDownIrpStack(IN PPCI_FDO_EXTENSION DeviceExtension,
41 IN PIRP Irp)
42 {
43 NTSTATUS Status;
44 KEVENT Event;
45 PAGED_CODE();
46 DPRINT1("PciCallDownIrpStack ...\n");
47 ASSERT_FDO(DeviceExtension);
48
49 /* Initialize the wait event */
50 KeInitializeEvent(&Event, SynchronizationEvent, 0);
51
52 /* Setup a completion routine */
53 IoCopyCurrentIrpStackLocationToNext(Irp);
54 IoSetCompletionRoutine(Irp, PciSetEventCompletion, &Event, TRUE, TRUE, TRUE);
55
56 /* Call the attached device */
57 Status = IoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
58 if (Status == STATUS_PENDING)
59 {
60 /* Wait for it to complete the request, and get its status */
61 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
62 Status = Irp->IoStatus.Status;
63 }
64
65 /* Return that status back to the caller */
66 return Status;
67 }
68
69 NTSTATUS
70 NTAPI
71 PciPassIrpFromFdoToPdo(IN PPCI_FDO_EXTENSION DeviceExtension,
72 IN PIRP Irp)
73 {
74 PIO_STACK_LOCATION IoStackLocation;
75 NTSTATUS Status;
76 DPRINT1("Pci PassIrp ...\n");
77
78 /* Get the stack location to check which function this is */
79 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
80 if (IoStackLocation->MajorFunction == IRP_MJ_POWER)
81 {
82 /* Power IRPs are special since we have to notify the Power Manager */
83 IoCopyCurrentIrpStackLocationToNext(Irp);
84 PoStartNextPowerIrp(Irp);
85 Status = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
86 }
87 else
88 {
89 /* For a normal IRP, just call the next driver in the stack */
90 IoSkipCurrentIrpStackLocation(Irp);
91 Status = IoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
92 }
93
94 /* Return the status back to the caller */
95 return Status;
96 }
97
98 NTSTATUS
99 NTAPI
100 PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject,
101 IN PIRP Irp)
102 {
103 PPCI_FDO_EXTENSION DeviceExtension;
104 PIO_STACK_LOCATION IoStackLocation;
105 PPCI_MJ_DISPATCH_TABLE IrpDispatchTable;
106 BOOLEAN PassToPdo;
107 NTSTATUS Status;
108 PPCI_MN_DISPATCH_TABLE TableArray = NULL, Table;
109 USHORT MaxMinor;
110 PCI_DISPATCH_STYLE DispatchStyle = 0;
111 PCI_DISPATCH_FUNCTION DispatchFunction = NULL;
112 DPRINT1("PCI: Dispatch IRP\n");
113
114 /* Get the extension and I/O stack location for this IRP */
115 DeviceExtension = (PPCI_FDO_EXTENSION)DeviceObject->DeviceExtension;
116 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
117 ASSERT((DeviceExtension->ExtensionType == PciPdoExtensionType) ||
118 (DeviceExtension->ExtensionType == PciFdoExtensionType));
119
120 /* Deleted extensions don't respond to IRPs */
121 if (DeviceExtension->DeviceState == PciDeleted)
122 {
123 /* Fail this IRP */
124 Status = STATUS_NO_SUCH_DEVICE;
125 PassToPdo = FALSE;
126 }
127 else
128 {
129 /* Otherwise, get the dispatch table for the extension */
130 IrpDispatchTable = DeviceExtension->IrpDispatchTable;
131
132 /* And choose which function table to use */
133 switch (IoStackLocation->MajorFunction)
134 {
135 case IRP_MJ_POWER:
136
137 /* Power Manager IRPs */
138 TableArray = IrpDispatchTable->PowerIrpDispatchTable;
139 MaxMinor = IrpDispatchTable->PowerIrpMaximumMinorFunction;
140 break;
141
142 case IRP_MJ_PNP:
143
144 /* Plug-and-Play Manager IRPs */
145 TableArray = IrpDispatchTable->PnpIrpDispatchTable;
146 MaxMinor = IrpDispatchTable->PnpIrpMaximumMinorFunction;
147 break;
148
149 case IRP_MJ_SYSTEM_CONTROL:
150
151 /* WMI IRPs */
152 DispatchFunction = IrpDispatchTable->SystemControlIrpDispatchFunction;
153 DispatchStyle = IrpDispatchTable->SystemControlIrpDispatchStyle;
154 MaxMinor = 0xFFFF;
155 break;
156
157 default:
158
159 /* Unrecognized IRPs */
160 DispatchFunction = IrpDispatchTable->OtherIrpDispatchFunction;
161 DispatchStyle = IrpDispatchTable->OtherIrpDispatchStyle;
162 MaxMinor = 0xFFFF;
163 break;
164 }
165
166 /* Only deal with recognized IRPs */
167 if (MaxMinor != 0xFFFF)
168 {
169 /* Make sure the function is recognized */
170 if (IoStackLocation->MinorFunction > MaxMinor)
171 {
172 /* Pick the terminator, which should return unrecognized */
173 Table = &TableArray[MaxMinor + 1];
174 }
175 else
176 {
177 /* Pick the appropriate table for this function */
178 Table = &TableArray[IoStackLocation->MinorFunction];
179 }
180
181 /* From that table, get the function code and dispatch style */
182 DispatchStyle = Table->DispatchStyle;
183 DispatchFunction = Table->DispatchFunction;
184 }
185
186 /* Print out debugging information, and see if we should break */
187 if (PciDebugIrpDispatchDisplay(IoStackLocation,
188 DeviceExtension,
189 MaxMinor))
190 {
191 /* The developer/user wants us to break for this IRP, do it */
192 DbgBreakPoint();
193 }
194
195 /* Check if this IRP should be sent up the stack first */
196 if (DispatchStyle == IRP_UPWARD)
197 {
198 /* Do it now before handling it ourselves */
199 PciCallDownIrpStack(DeviceExtension, Irp);
200 }
201
202 /* Call the our driver's handler for this IRP and deal with the IRP */
203 Status = DispatchFunction(Irp, IoStackLocation, DeviceExtension);
204 switch (DispatchStyle)
205 {
206 /* Complete IRPs are completely immediately by our driver */
207 case IRP_COMPLETE:
208 PassToPdo = FALSE;
209 break;
210
211 /* Downward IRPs are send to the attached FDO */
212 case IRP_DOWNWARD:
213 PassToPdo = TRUE;
214 break;
215
216 /* Upward IRPs are completed immediately by our driver */
217 case IRP_UPWARD:
218 PassToPdo = FALSE;
219 break;
220
221 /* Dispatch IRPs are immediately returned */
222 case IRP_DISPATCH:
223 return Status;
224
225 /* There aren't any other dispatch styles! */
226 default:
227 ASSERT(FALSE);
228 return Status;
229 }
230 }
231
232 /* Pending IRPs are returned immediately */
233 if (Status == STATUS_PENDING) return Status;
234
235 /* Handled IRPs return their status in the status block */
236 if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
237
238 /* Successful, or unhandled IRPs that are "DOWNWARD" are sent to the PDO */
239 if ((PassToPdo) && ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED)))
240 {
241 /* Let the PDO deal with it */
242 Status = PciPassIrpFromFdoToPdo(DeviceExtension, Irp);
243 }
244 else
245 {
246 /* Otherwise, the IRP is returned with its status */
247 Status = Irp->IoStatus.Status;
248
249 /* Power IRPs need to notify the Power Manager that the next IRP can go */
250 if (IoStackLocation->MajorFunction == IRP_MJ_POWER) PoStartNextPowerIrp(Irp);
251
252 /* And now this IRP can be completed */
253 IoCompleteRequest(Irp, IO_NO_INCREMENT);
254 }
255
256 /* And the status returned back to the caller */
257 return Status;
258 }
259
260 NTSTATUS
261 NTAPI
262 PciIrpNotSupported(IN PIRP Irp,
263 IN PIO_STACK_LOCATION IoStackLocation,
264 IN PPCI_FDO_EXTENSION DeviceExtension)
265 {
266 UNREFERENCED_PARAMETER(Irp);
267 UNREFERENCED_PARAMETER(IoStackLocation);
268 UNREFERENCED_PARAMETER(DeviceExtension);
269
270 /* Not supported */
271 DPRINT1("WARNING: PCI received unsupported IRP!\n");
272 //DbgBreakPoint();
273 return STATUS_NOT_SUPPORTED;
274 }
275
276 NTSTATUS
277 NTAPI
278 PciIrpInvalidDeviceRequest(IN PIRP Irp,
279 IN PIO_STACK_LOCATION IoStackLocation,
280 IN PPCI_FDO_EXTENSION DeviceExtension)
281 {
282 UNREFERENCED_PARAMETER(Irp);
283 UNREFERENCED_PARAMETER(IoStackLocation);
284 UNREFERENCED_PARAMETER(DeviceExtension);
285
286 /* Not supported */
287 return STATUS_INVALID_DEVICE_REQUEST;
288 }
289
290 /* EOF */