xref: /reactos/drivers/bus/pcix/dispatch.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/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