Reactos
at master 289 lines 9.2 kB view raw
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 18IO_COMPLETION_ROUTINE PciSetEventCompletion; 19 20NTSTATUS 21NTAPI 22PciSetEventCompletion(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 37NTSTATUS 38NTAPI 39PciCallDownIrpStack(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 68NTSTATUS 69NTAPI 70PciPassIrpFromFdoToPdo(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 97NTSTATUS 98NTAPI 99PciDispatchIrp(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 259NTSTATUS 260NTAPI 261PciIrpNotSupported(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 275NTSTATUS 276NTAPI 277PciIrpInvalidDeviceRequest(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 */