Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290/* * 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 <pci.h>
#define NDEBUG#include <debug.h>
/* FUNCTIONS ******************************************************************/
IO_COMPLETION_ROUTINE PciSetEventCompletion;
NTSTATUSNTAPIPciSetEventCompletion(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;}
NTSTATUSNTAPIPciCallDownIrpStack(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;}
NTSTATUSNTAPIPciPassIrpFromFdoToPdo(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;}
NTSTATUSNTAPIPciDispatchIrp(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;}
NTSTATUSNTAPIPciIrpNotSupported(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;}
NTSTATUSNTAPIPciIrpInvalidDeviceRequest(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 */