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