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
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 /* FUNCTIONS ******************************************************************/
19 IO_COMPLETION_ROUTINE PciSetEventCompletion
;
23 PciSetEventCompletion(IN PDEVICE_OBJECT DeviceObject
,
27 PKEVENT Event
= (PVOID
)Context
;
30 UNREFERENCED_PARAMETER(DeviceObject
);
31 UNREFERENCED_PARAMETER(Irp
);
33 /* Set the event and return the appropriate status code */
34 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
35 return STATUS_MORE_PROCESSING_REQUIRED
;
40 PciCallDownIrpStack(IN PPCI_FDO_EXTENSION DeviceExtension
,
46 DPRINT1("PciCallDownIrpStack ...\n");
47 ASSERT_FDO(DeviceExtension
);
49 /* Initialize the wait event */
50 KeInitializeEvent(&Event
, SynchronizationEvent
, 0);
52 /* Setup a completion routine */
53 IoCopyCurrentIrpStackLocationToNext(Irp
);
54 IoSetCompletionRoutine(Irp
, PciSetEventCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
56 /* Call the attached device */
57 Status
= IoCallDriver(DeviceExtension
->AttachedDeviceObject
, Irp
);
58 if (Status
== STATUS_PENDING
)
60 /* Wait for it to complete the request, and get its status */
61 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
62 Status
= Irp
->IoStatus
.Status
;
65 /* Return that status back to the caller */
71 PciPassIrpFromFdoToPdo(IN PPCI_FDO_EXTENSION DeviceExtension
,
74 PIO_STACK_LOCATION IoStackLocation
;
76 DPRINT1("Pci PassIrp ...\n");
78 /* Get the stack location to check which function this is */
79 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
80 if (IoStackLocation
->MajorFunction
== IRP_MJ_POWER
)
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
);
89 /* For a normal IRP, just call the next driver in the stack */
90 IoSkipCurrentIrpStackLocation(Irp
);
91 Status
= IoCallDriver(DeviceExtension
->AttachedDeviceObject
, Irp
);
94 /* Return the status back to the caller */
100 PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject
,
103 PPCI_FDO_EXTENSION DeviceExtension
;
104 PIO_STACK_LOCATION IoStackLocation
;
105 PPCI_MJ_DISPATCH_TABLE IrpDispatchTable
;
108 PPCI_MN_DISPATCH_TABLE TableArray
= NULL
, Table
;
110 PCI_DISPATCH_STYLE DispatchStyle
= 0;
111 PCI_DISPATCH_FUNCTION DispatchFunction
= NULL
;
112 DPRINT1("PCI: Dispatch IRP\n");
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
));
120 /* Deleted extensions don't respond to IRPs */
121 if (DeviceExtension
->DeviceState
== PciDeleted
)
124 Status
= STATUS_NO_SUCH_DEVICE
;
129 /* Otherwise, get the dispatch table for the extension */
130 IrpDispatchTable
= DeviceExtension
->IrpDispatchTable
;
132 /* And choose which function table to use */
133 switch (IoStackLocation
->MajorFunction
)
137 /* Power Manager IRPs */
138 TableArray
= IrpDispatchTable
->PowerIrpDispatchTable
;
139 MaxMinor
= IrpDispatchTable
->PowerIrpMaximumMinorFunction
;
144 /* Plug-and-Play Manager IRPs */
145 TableArray
= IrpDispatchTable
->PnpIrpDispatchTable
;
146 MaxMinor
= IrpDispatchTable
->PnpIrpMaximumMinorFunction
;
149 case IRP_MJ_SYSTEM_CONTROL
:
152 DispatchFunction
= IrpDispatchTable
->SystemControlIrpDispatchFunction
;
153 DispatchStyle
= IrpDispatchTable
->SystemControlIrpDispatchStyle
;
159 /* Unrecognized IRPs */
160 DispatchFunction
= IrpDispatchTable
->OtherIrpDispatchFunction
;
161 DispatchStyle
= IrpDispatchTable
->OtherIrpDispatchStyle
;
166 /* Only deal with recognized IRPs */
167 if (MaxMinor
!= 0xFFFF)
169 /* Make sure the function is recognized */
170 if (IoStackLocation
->MinorFunction
> MaxMinor
)
172 /* Pick the terminator, which should return unrecognized */
173 Table
= &TableArray
[MaxMinor
+ 1];
177 /* Pick the appropriate table for this function */
178 Table
= &TableArray
[IoStackLocation
->MinorFunction
];
181 /* From that table, get the function code and dispatch style */
182 DispatchStyle
= Table
->DispatchStyle
;
183 DispatchFunction
= Table
->DispatchFunction
;
186 /* Print out debugging information, and see if we should break */
187 if (PciDebugIrpDispatchDisplay(IoStackLocation
,
191 /* The developer/user wants us to break for this IRP, do it */
195 /* Check if this IRP should be sent up the stack first */
196 if (DispatchStyle
== IRP_UPWARD
)
198 /* Do it now before handling it ourselves */
199 PciCallDownIrpStack(DeviceExtension
, Irp
);
202 /* Call the our driver's handler for this IRP and deal with the IRP */
203 Status
= DispatchFunction(Irp
, IoStackLocation
, DeviceExtension
);
204 switch (DispatchStyle
)
206 /* Complete IRPs are completely immediately by our driver */
211 /* Downward IRPs are send to the attached FDO */
216 /* Upward IRPs are completed immediately by our driver */
221 /* Dispatch IRPs are immediately returned */
225 /* There aren't any other dispatch styles! */
232 /* Pending IRPs are returned immediately */
233 if (Status
== STATUS_PENDING
) return Status
;
235 /* Handled IRPs return their status in the status block */
236 if (Status
!= STATUS_NOT_SUPPORTED
) Irp
->IoStatus
.Status
= Status
;
238 /* Successful, or unhandled IRPs that are "DOWNWARD" are sent to the PDO */
239 if ((PassToPdo
) && ((NT_SUCCESS(Status
)) || (Status
== STATUS_NOT_SUPPORTED
)))
241 /* Let the PDO deal with it */
242 Status
= PciPassIrpFromFdoToPdo(DeviceExtension
, Irp
);
246 /* Otherwise, the IRP is returned with its status */
247 Status
= Irp
->IoStatus
.Status
;
249 /* Power IRPs need to notify the Power Manager that the next IRP can go */
250 if (IoStackLocation
->MajorFunction
== IRP_MJ_POWER
) PoStartNextPowerIrp(Irp
);
252 /* And now this IRP can be completed */
253 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
256 /* And the status returned back to the caller */
262 PciIrpNotSupported(IN PIRP Irp
,
263 IN PIO_STACK_LOCATION IoStackLocation
,
264 IN PPCI_FDO_EXTENSION DeviceExtension
)
266 UNREFERENCED_PARAMETER(Irp
);
267 UNREFERENCED_PARAMETER(IoStackLocation
);
268 UNREFERENCED_PARAMETER(DeviceExtension
);
271 DPRINT1("WARNING: PCI received unsupported IRP!\n");
273 return STATUS_NOT_SUPPORTED
;
278 PciIrpInvalidDeviceRequest(IN PIRP Irp
,
279 IN PIO_STACK_LOCATION IoStackLocation
,
280 IN PPCI_FDO_EXTENSION DeviceExtension
)
282 UNREFERENCED_PARAMETER(Irp
);
283 UNREFERENCED_PARAMETER(IoStackLocation
);
284 UNREFERENCED_PARAMETER(DeviceExtension
);
287 return STATUS_INVALID_DEVICE_REQUEST
;