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 ******************************************************************/
21 PciSetEventCompletion(IN PDEVICE_OBJECT DeviceObject
,
25 PKEVENT Event
= (PVOID
)Context
;
28 /* Set the event and return the appropriate status code */
29 KeSetEvent(Event
, FALSE
, IO_NO_INCREMENT
);
30 return STATUS_MORE_PROCESSING_REQUIRED
;
35 PciCallDownIrpStack(IN PPCI_FDO_EXTENSION DeviceExtension
,
41 DPRINT1("PciCallDownIrpStack ...\n");
42 ASSERT_FDO(DeviceExtension
);
44 /* Initialize the wait event */
45 KeInitializeEvent(&Event
, SynchronizationEvent
, 0);
47 /* Setup a completion routine */
48 IoCopyCurrentIrpStackLocationToNext(Irp
);
49 IoSetCompletionRoutine(Irp
, PciSetEventCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
51 /* Call the attached device */
52 Status
= IofCallDriver(DeviceExtension
->AttachedDeviceObject
, Irp
);
53 if (Status
== STATUS_PENDING
)
55 /* Wait for it to complete the request, and get its status */
56 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
57 Status
= Irp
->IoStatus
.Status
;
60 /* Return that status back to the caller */
66 PciPassIrpFromFdoToPdo(IN PPCI_FDO_EXTENSION DeviceExtension
,
69 PIO_STACK_LOCATION IoStackLocation
;
71 DPRINT1("Pci PassIrp ...\n");
73 /* Get the stack location to check which function this is */
74 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
75 if (IoStackLocation
->MajorFunction
== IRP_MJ_POWER
)
77 /* Power IRPs are special since we have to notify the Power Manager */
78 IoCopyCurrentIrpStackLocationToNext(Irp
);
79 PoStartNextPowerIrp(Irp
);
80 Status
= PoCallDriver(DeviceExtension
->AttachedDeviceObject
, Irp
);
84 /* For a normal IRP, just call the next driver in the stack */
85 IoSkipCurrentIrpStackLocation(Irp
);
86 Status
= IofCallDriver(DeviceExtension
->AttachedDeviceObject
, Irp
);
89 /* Return the status back to the caller */
95 PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject
,
98 PPCI_FDO_EXTENSION DeviceExtension
;
99 PIO_STACK_LOCATION IoStackLocation
;
100 PPCI_MJ_DISPATCH_TABLE IrpDispatchTable
;
103 PPCI_MN_DISPATCH_TABLE TableArray
= NULL
, Table
;
105 PCI_DISPATCH_STYLE DispatchStyle
= 0;
106 PCI_DISPATCH_FUNCTION DispatchFunction
= NULL
;
107 DPRINT1("PCI: Dispatch IRP\n");
109 /* Get the extension and I/O stack location for this IRP */
110 DeviceExtension
= (PPCI_FDO_EXTENSION
)DeviceObject
->DeviceExtension
;
111 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
112 ASSERT((DeviceExtension
->ExtensionType
== PciPdoExtensionType
) ||
113 (DeviceExtension
->ExtensionType
== PciFdoExtensionType
));
115 /* Deleted extensions don't respond to IRPs */
116 if (DeviceExtension
->DeviceState
== PciDeleted
)
119 Status
= STATUS_NO_SUCH_DEVICE
;
124 /* Otherwise, get the dispatch table for the extension */
125 IrpDispatchTable
= DeviceExtension
->IrpDispatchTable
;
127 /* And choose which function table to use */
128 switch (IoStackLocation
->MajorFunction
)
132 /* Power Manager IRPs */
133 TableArray
= IrpDispatchTable
->PowerIrpDispatchTable
;
134 MaxMinor
= IrpDispatchTable
->PowerIrpMaximumMinorFunction
;
139 /* Plug-and-Play Manager IRPs */
140 TableArray
= IrpDispatchTable
->PnpIrpDispatchTable
;
141 MaxMinor
= IrpDispatchTable
->PnpIrpMaximumMinorFunction
;
144 case IRP_MJ_SYSTEM_CONTROL
:
147 DispatchFunction
= IrpDispatchTable
->SystemControlIrpDispatchFunction
;
148 DispatchStyle
= IrpDispatchTable
->SystemControlIrpDispatchStyle
;
154 /* Unrecognized IRPs */
155 DispatchFunction
= IrpDispatchTable
->OtherIrpDispatchFunction
;
156 DispatchStyle
= IrpDispatchTable
->OtherIrpDispatchStyle
;
161 /* Only deal with recognized IRPs */
162 if (MaxMinor
!= 0xFFFF)
164 /* Make sure the function is recognized */
165 if (IoStackLocation
->MinorFunction
> MaxMinor
)
167 /* Pick the terminator, which should return unrecognized */
168 Table
= &TableArray
[MaxMinor
+ 1];
172 /* Pick the appropriate table for this function */
173 Table
= &TableArray
[IoStackLocation
->MinorFunction
];
176 /* From that table, get the function code and dispatch style */
177 DispatchStyle
= Table
->DispatchStyle
;
178 DispatchFunction
= Table
->DispatchFunction
;
181 /* Print out debugging information, and see if we should break */
182 if (PciDebugIrpDispatchDisplay(IoStackLocation
,
186 /* The developer/user wants us to break for this IRP, do it */
190 /* Check if this IRP should be sent up the stack first */
191 if (DispatchStyle
== IRP_UPWARD
)
193 /* Do it now before handling it ourselves */
194 PciCallDownIrpStack(DeviceExtension
, Irp
);
197 /* Call the our driver's handler for this IRP and deal with the IRP */
198 Status
= DispatchFunction(Irp
, IoStackLocation
, DeviceExtension
);
199 switch (DispatchStyle
)
201 /* Complete IRPs are completely immediately by our driver */
206 /* Downward IRPs are send to the attached FDO */
211 /* Upward IRPs are completed immediately by our driver */
216 /* Dispatch IRPs are immediately returned */
220 /* There aren't any other dispatch styles! */
227 /* Pending IRPs are returned immediately */
228 if (Status
== STATUS_PENDING
) return Status
;
230 /* Handled IRPs return their status in the status block */
231 if (Status
!= STATUS_NOT_SUPPORTED
) Irp
->IoStatus
.Status
= Status
;
233 /* Successful, or unhandled IRPs that are "DOWNWARD" are sent to the PDO */
234 if ((PassToPdo
) && ((NT_SUCCESS(Status
)) || (Status
== STATUS_NOT_SUPPORTED
)))
236 /* Let the PDO deal with it */
237 Status
= PciPassIrpFromFdoToPdo(DeviceExtension
, Irp
);
241 /* Otherwise, the IRP is returned with its status */
242 Status
= Irp
->IoStatus
.Status
;
244 /* Power IRPs need to notify the Power Manager that the next IRP can go */
245 if (IoStackLocation
->MajorFunction
== IRP_MJ_POWER
) PoStartNextPowerIrp(Irp
);
247 /* And now this IRP can be completed */
248 IofCompleteRequest(Irp
, IO_NO_INCREMENT
);
251 /* And the status returned back to the caller */
257 PciIrpNotSupported(IN PIRP Irp
,
258 IN PIO_STACK_LOCATION IoStackLocation
,
259 IN PPCI_FDO_EXTENSION DeviceExtension
)
262 DPRINT1("WARNING: PCI received unsupported IRP!\n");
264 return STATUS_NOT_SUPPORTED
;
269 PciIrpInvalidDeviceRequest(IN PIRP Irp
,
270 IN PIO_STACK_LOCATION IoStackLocation
,
271 IN PPCI_FDO_EXTENSION DeviceExtension
)
274 return STATUS_INVALID_DEVICE_REQUEST
;