mirror of
https://github.com/reactos/reactos.git
synced 2024-09-06 10:52:52 +00:00
290 lines
9 KiB
C
290 lines
9 KiB
C
/*
|
|
* 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;
|
|
|
|
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 */
|