/* * PROJECT: ReactOS PCI Bus Driver * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: drivers/bus/pci/dispatch.c * PURPOSE: WDM Dispatch Routines * PROGRAMMERS: ReactOS Portable Systems Group */ /* INCLUDES *******************************************************************/ #include #define NDEBUG #include /* FUNCTIONS ******************************************************************/ IO_COMPLETION_ROUTINE PciSetEventCompletion; NTSTATUS NTAPI PciSetEventCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PKEVENT Event = (PVOID)Context; ASSERT(Event); UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Irp); /* Set the event and return the appropriate status code */ KeSetEvent(Event, IO_NO_INCREMENT, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS NTAPI PciCallDownIrpStack(IN PPCI_FDO_EXTENSION DeviceExtension, IN PIRP Irp) { NTSTATUS Status; KEVENT Event; PAGED_CODE(); DPRINT1("PciCallDownIrpStack ...\n"); ASSERT_FDO(DeviceExtension); /* Initialize the wait event */ KeInitializeEvent(&Event, SynchronizationEvent, 0); /* Setup a completion routine */ IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, PciSetEventCompletion, &Event, TRUE, TRUE, TRUE); /* Call the attached device */ Status = IoCallDriver(DeviceExtension->AttachedDeviceObject, Irp); if (Status == STATUS_PENDING) { /* Wait for it to complete the request, and get its status */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } /* Return that status back to the caller */ return Status; } NTSTATUS NTAPI PciPassIrpFromFdoToPdo(IN PPCI_FDO_EXTENSION DeviceExtension, IN PIRP Irp) { PIO_STACK_LOCATION IoStackLocation; NTSTATUS Status; DPRINT1("Pci PassIrp ...\n"); /* Get the stack location to check which function this is */ IoStackLocation = IoGetCurrentIrpStackLocation(Irp); if (IoStackLocation->MajorFunction == IRP_MJ_POWER) { /* Power IRPs are special since we have to notify the Power Manager */ IoCopyCurrentIrpStackLocationToNext(Irp); PoStartNextPowerIrp(Irp); Status = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp); } else { /* For a normal IRP, just call the next driver in the stack */ IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(DeviceExtension->AttachedDeviceObject, Irp); } /* Return the status back to the caller */ return Status; } NTSTATUS NTAPI PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PPCI_FDO_EXTENSION DeviceExtension; PIO_STACK_LOCATION IoStackLocation; PPCI_MJ_DISPATCH_TABLE IrpDispatchTable; BOOLEAN PassToPdo; NTSTATUS Status; PPCI_MN_DISPATCH_TABLE TableArray = NULL, Table; USHORT MaxMinor; PCI_DISPATCH_STYLE DispatchStyle = 0; PCI_DISPATCH_FUNCTION DispatchFunction = NULL; DPRINT1("PCI: Dispatch IRP\n"); /* Get the extension and I/O stack location for this IRP */ DeviceExtension = (PPCI_FDO_EXTENSION)DeviceObject->DeviceExtension; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); ASSERT((DeviceExtension->ExtensionType == PciPdoExtensionType) || (DeviceExtension->ExtensionType == PciFdoExtensionType)); /* Deleted extensions don't respond to IRPs */ if (DeviceExtension->DeviceState == PciDeleted) { /* Fail this IRP */ Status = STATUS_NO_SUCH_DEVICE; PassToPdo = FALSE; } else { /* Otherwise, get the dispatch table for the extension */ IrpDispatchTable = DeviceExtension->IrpDispatchTable; /* And choose which function table to use */ switch (IoStackLocation->MajorFunction) { case IRP_MJ_POWER: /* Power Manager IRPs */ TableArray = IrpDispatchTable->PowerIrpDispatchTable; MaxMinor = IrpDispatchTable->PowerIrpMaximumMinorFunction; break; case IRP_MJ_PNP: /* Plug-and-Play Manager IRPs */ TableArray = IrpDispatchTable->PnpIrpDispatchTable; MaxMinor = IrpDispatchTable->PnpIrpMaximumMinorFunction; break; case IRP_MJ_SYSTEM_CONTROL: /* WMI IRPs */ DispatchFunction = IrpDispatchTable->SystemControlIrpDispatchFunction; DispatchStyle = IrpDispatchTable->SystemControlIrpDispatchStyle; MaxMinor = 0xFFFF; break; default: /* Unrecognized IRPs */ DispatchFunction = IrpDispatchTable->OtherIrpDispatchFunction; DispatchStyle = IrpDispatchTable->OtherIrpDispatchStyle; MaxMinor = 0xFFFF; break; } /* Only deal with recognized IRPs */ if (MaxMinor != 0xFFFF) { /* Make sure the function is recognized */ if (IoStackLocation->MinorFunction > MaxMinor) { /* Pick the terminator, which should return unrecognized */ Table = &TableArray[MaxMinor + 1]; } else { /* Pick the appropriate table for this function */ Table = &TableArray[IoStackLocation->MinorFunction]; } /* From that table, get the function code and dispatch style */ DispatchStyle = Table->DispatchStyle; DispatchFunction = Table->DispatchFunction; } /* Print out debugging information, and see if we should break */ if (PciDebugIrpDispatchDisplay(IoStackLocation, DeviceExtension, MaxMinor)) { /* The developer/user wants us to break for this IRP, do it */ DbgBreakPoint(); } /* Check if this IRP should be sent up the stack first */ if (DispatchStyle == IRP_UPWARD) { /* Do it now before handling it ourselves */ PciCallDownIrpStack(DeviceExtension, Irp); } /* Call the our driver's handler for this IRP and deal with the IRP */ Status = DispatchFunction(Irp, IoStackLocation, DeviceExtension); switch (DispatchStyle) { /* Complete IRPs are completely immediately by our driver */ case IRP_COMPLETE: PassToPdo = FALSE; break; /* Downward IRPs are send to the attached FDO */ case IRP_DOWNWARD: PassToPdo = TRUE; break; /* Upward IRPs are completed immediately by our driver */ case IRP_UPWARD: PassToPdo = FALSE; break; /* Dispatch IRPs are immediately returned */ case IRP_DISPATCH: return Status; /* There aren't any other dispatch styles! */ default: ASSERT(FALSE); return Status; } } /* Pending IRPs are returned immediately */ if (Status == STATUS_PENDING) return Status; /* Handled IRPs return their status in the status block */ if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status; /* Successful, or unhandled IRPs that are "DOWNWARD" are sent to the PDO */ if ((PassToPdo) && ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))) { /* Let the PDO deal with it */ Status = PciPassIrpFromFdoToPdo(DeviceExtension, Irp); } else { /* Otherwise, the IRP is returned with its status */ Status = Irp->IoStatus.Status; /* Power IRPs need to notify the Power Manager that the next IRP can go */ if (IoStackLocation->MajorFunction == IRP_MJ_POWER) PoStartNextPowerIrp(Irp); /* And now this IRP can be completed */ IoCompleteRequest(Irp, IO_NO_INCREMENT); } /* And the status returned back to the caller */ return Status; } NTSTATUS NTAPI PciIrpNotSupported(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension) { UNREFERENCED_PARAMETER(Irp); UNREFERENCED_PARAMETER(IoStackLocation); UNREFERENCED_PARAMETER(DeviceExtension); /* Not supported */ DPRINT1("WARNING: PCI received unsupported IRP!\n"); //DbgBreakPoint(); return STATUS_NOT_SUPPORTED; } NTSTATUS NTAPI PciIrpInvalidDeviceRequest(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension) { UNREFERENCED_PARAMETER(Irp); UNREFERENCED_PARAMETER(IoStackLocation); UNREFERENCED_PARAMETER(DeviceExtension); /* Not supported */ return STATUS_INVALID_DEVICE_REQUEST; } /* EOF */