Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

482 lines
16 KiB

/*++
Copyright (c) 2000 Microsoft Corporation All Rights Reserved
Module Name:
lower.c
Abstract:
This module contains the lower filter specific IRP handlers.
The functions in this module all have the same prototypes and so
are documented here:
NTSTATUS
HpsXxxLower(
IN PIRP Irp,
IN PHPS_DEVICE_EXTENSION Extension,
IN PIO_STACK_LOCATION IrpStack
)
Arguments:
Irp - a pointer to the IRP currently being handled
Extension - a pointer to the device extension of this device. In
some functions this is of type PHPS_COMMON_EXTENSION if this
reduced extension is all that is required.
IrpStack - the current IRP stack location
Return Value:
an NT status code
Environment:
Kernel Mode
Revision History:
Davis Walker (dwalker) Oct 1 2000
--*/
#include "hpsp.h"
NTSTATUS
HpsStartLower(
IN PIRP Irp,
IN PHPS_DEVICE_EXTENSION Extension,
IN PIO_STACK_LOCATION IrpStack
)
{
NTSTATUS status;
status = HpsDeferProcessing((PHPS_COMMON_EXTENSION)Extension,
Irp
);
if (!NT_SUCCESS(status)) {
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
status = IoSetDeviceInterfaceState(Extension->SymbolicName,
TRUE // enable
);
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
HpsRemoveLower(
IN PIRP Irp,
IN PHPS_DEVICE_EXTENSION Extension,
IN PIO_STACK_LOCATION IrpStack
)
{
ULONG i;
IoSetDeviceInterfaceState(Extension->SymbolicName,
FALSE
);
IoWMIRegistrationControl(Extension->Self,
WMIREG_ACTION_DEREGISTER
);
if (Extension->SoftDevices) {
for (i=0; i<Extension->HwInitData.NumSlots;i++) {
if (Extension->SoftDevices[i]) {
ExFreePool(Extension->SoftDevices[i]);
}
}
ExFreePool(Extension->SoftDevices);
}
if (Extension->SymbolicName) {
ExFreePool(Extension->SymbolicName);
}
if (Extension->WmiEventContext) {
ExFreePool(Extension->WmiEventContext);
}
return HpsRemoveCommon(Irp,
(PHPS_COMMON_EXTENSION)Extension,
IrpStack
);
}
NTSTATUS
HpsStopLower(
IN PIRP Irp,
IN PHPS_DEVICE_EXTENSION Extension,
IN PIO_STACK_LOCATION IrpStack
)
{
IoSetDeviceInterfaceState(Extension->SymbolicName,
FALSE
);
return HpsPassIrp(Irp,
(PHPS_COMMON_EXTENSION)Extension,
IrpStack
);
}
NTSTATUS
HpsQueryInterfaceLower(
IN PIRP Irp,
IN PHPS_DEVICE_EXTENSION Extension,
IN PIO_STACK_LOCATION IrpStack
)
{
NTSTATUS status = STATUS_NOT_SUPPORTED;
PHPS_REGISTER_INTERRUPT_INTERFACE interruptInterface;
PHPS_MEMORY_INTERFACE memInterface;
PHPS_PING_INTERFACE pingInterface;
if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
&GUID_BUS_INTERFACE_STANDARD
)) {
if (Extension->UseConfig) {
//
// Someone is requesting a bus interface standard. We need to capture
// this request and fill it in with our own.
//
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-IRP QueryInterface for Bus Interface\n"
);
if (IrpStack->Parameters.QueryInterface.Size <
sizeof(BUS_INTERFACE_STANDARD)) {
status = STATUS_NOT_SUPPORTED;
} else {
//
// This is a query for access to config space, which we need to trap
// after PCI has filled it in.
//
status = HpsDeferProcessing((PHPS_COMMON_EXTENSION)Extension,
Irp
);
if (NT_SUCCESS(status)) {
// PDO filled in the interface, so we can trap and modify it.
status = HpsTrapBusInterface(Extension,
IrpStack
);
//
// the status of the trap operation is the status of the IRP.
// complete the IRP with whatever status that happens to be.
//
Irp->IoStatus.Status = status;
}
//
// Complete the deferred IRP
//
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}
}
} else if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
&GUID_HPS_MEMORY_INTERFACE
)) {
if (IrpStack->Parameters.QueryInterface.Size <
sizeof(HPS_MEMORY_INTERFACE)) {
status = STATUS_NOT_SUPPORTED;
} else {
memInterface = (PHPS_MEMORY_INTERFACE)
IrpStack->Parameters.QueryInterface.Interface;
memInterface->Context = Extension;
memInterface->InterfaceReference = HpsMemoryInterfaceReference;
memInterface->InterfaceDereference = HpsMemoryInterfaceDereference;
memInterface->ReadRegister = HpsReadRegister;
memInterface->WriteRegister = HpsWriteRegister;
memInterface->InterfaceReference(memInterface->Context);
status = STATUS_SUCCESS;
}
} else if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
&GUID_HPS_PING_INTERFACE
)) {
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-IRP QueryInterface for Ping Interface\n"
);
if (IrpStack->Parameters.QueryInterface.Size <
sizeof(HPS_PING_INTERFACE)) {
status = STATUS_NOT_SUPPORTED;
} else {
//
// The upper filter is querying to see if there is another
// instance of the driver below it. Inform it that there is.
//
pingInterface = (PHPS_PING_INTERFACE)
IrpStack->Parameters.QueryInterface.Interface;
if (pingInterface->SenderDevice != Extension->Self) {
pingInterface->Context = Extension->Self;
pingInterface->InterfaceReference = HpsGenericInterfaceReference;
pingInterface->InterfaceDereference = HpsGenericInterfaceDereference;
}
pingInterface->InterfaceReference(pingInterface->Context);
status = STATUS_SUCCESS;
}
} else if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
&GUID_REGISTER_INTERRUPT_INTERFACE
)) {
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-IRP QueryInterface for Interrupt Interface\n"
);
if (IrpStack->Parameters.QueryInterface.Size <
sizeof(HPS_REGISTER_INTERRUPT_INTERFACE)) {
status = STATUS_NOT_SUPPORTED;
} else {
//
// The hotplug driver is querying for an interface that allows it
// to register a fake interrupt. Provide the interface.
//
interruptInterface = (PHPS_REGISTER_INTERRUPT_INTERFACE)
IrpStack->Parameters.QueryInterface.Interface;
interruptInterface->InterfaceReference = HpsGenericInterfaceReference;
interruptInterface->InterfaceDereference = HpsGenericInterfaceDereference;
interruptInterface->ConnectISR = HpsConnectInterrupt;
interruptInterface->DisconnectISR = HpsDisconnectInterrupt;
interruptInterface->SyncExecutionRoutine = HpsSynchronizeExecution;
interruptInterface->Context = Extension;
status = STATUS_SUCCESS;
}
}
if (NT_SUCCESS(status)) {
Irp->IoStatus.Status = status;
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(Extension->LowerDO,
Irp
);
}
NTSTATUS
HpsWriteConfigLower(
IN PIRP Irp,
IN PHPS_DEVICE_EXTENSION Extension,
IN PIO_STACK_LOCATION IrpStack
)
{
if (Extension->UseConfig) {
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-IRP Write Config at offset %d for length %d\n",
IrpStack->Parameters.ReadWriteConfig.Offset,
IrpStack->Parameters.ReadWriteConfig.Length
);
if (IS_SUBSET(IrpStack->Parameters.ReadWriteConfig.Offset,
IrpStack->Parameters.ReadWriteConfig.Length,
Extension->ConfigOffset,
sizeof(SHPC_CONFIG_SPACE)
)) {
//
// Handle the IRP internally. The request lines up with the config space
// offset of the SHPC capability.
//
HpsWriteConfig (Extension,
IrpStack->Parameters.ReadWriteConfig.Buffer,
IrpStack->Parameters.ReadWriteConfig.Offset,
IrpStack->Parameters.ReadWriteConfig.Length
);
//
// Since the write may have altered the register set, we have to recopy the
// result into the buffer before passing the IRP to Soft PCI
//
RtlCopyMemory(IrpStack->Parameters.ReadWriteConfig.Buffer,
(PUCHAR)&Extension->ConfigSpace + IrpStack->Parameters.ReadWriteConfig.Offset,
IrpStack->Parameters.ReadWriteConfig.Length
);
}
}
//
// We've handled the IRP internally, but we want to keep SoftPCI in the loop,
// so pass it down.
//
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver (Extension->LowerDO,
Irp
);
}
NTSTATUS
HpsDeviceControlLower(
PIRP Irp,
PHPS_DEVICE_EXTENSION Extension,
PIO_STACK_LOCATION IrpStack
)
{
NTSTATUS status;
PHPTEST_WRITE_CONFIG writeDescriptor;
PHPTEST_BRIDGE_INFO bridgeInfo;
switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_HPS_READ_REGISTERS:
//
// Usermode wants a copy of the register set. This is a test
// IOCTL
//
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-Device Control IOCTL_HPS_READ_REGISTERS\n"
);
if (!Irp->AssociatedIrp.SystemBuffer ||
(IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SHPC_WORKING_REGISTERS))) {
//
// We didn't get the buffer we expected. Fail.
//
return STATUS_INVALID_PARAMETER;
}
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
&Extension->RegisterSet,
sizeof(SHPC_WORKING_REGISTERS)
);
Irp->IoStatus.Information = sizeof(SHPC_WORKING_REGISTERS);
status = STATUS_SUCCESS;
break;
case IOCTL_HPS_READ_CAPABILITY:
//
// Usermode wants a copy of the SHPC capability structure. This
// is a test IOCTL
//
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-Device Control IOCTL_HPS_READ_CAPABILITY\n"
);
if (!Irp->AssociatedIrp.SystemBuffer ||
(IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SHPC_CONFIG_SPACE))) {
//
// We didn't get the buffer we expected. Fail.
//
return STATUS_INVALID_PARAMETER;
}
HpsHandleDirectReadConfig(Extension,
PCI_WHICHSPACE_CONFIG,
Irp->AssociatedIrp.SystemBuffer,
Extension->ConfigOffset,
sizeof(SHPC_CONFIG_SPACE)
);
Irp->IoStatus.Information = sizeof(SHPC_CONFIG_SPACE);
status = STATUS_SUCCESS;
break;
case IOCTL_HPS_WRITE_CAPABILITY:
//
// Usermode is overwriting the SHPC capability structure. This
// is a test IOCTL.
//
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-Device Control IOCTL_HPS_WRITE_CAPABILITY\n"
);
if (!Irp->AssociatedIrp.SystemBuffer ||
(IrpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(HPTEST_WRITE_CONFIG))) {
//
// We didn't get the buffer we expected. Fail.
//
return STATUS_INVALID_PARAMETER;
}
writeDescriptor = (PHPTEST_WRITE_CONFIG)Irp->AssociatedIrp.SystemBuffer;
HpsHandleDirectWriteConfig(Extension,
PCI_WHICHSPACE_CONFIG,
(PUCHAR)&writeDescriptor->Buffer + writeDescriptor->Offset,
Extension->ConfigOffset+writeDescriptor->Offset,
writeDescriptor->Length
);
status = STATUS_SUCCESS;
break;
case IOCTL_HPS_BRIDGE_INFO:
//
// Usermode is requesting the bus/dev/func for this device for
// identification purposes. This is a test IOCTL.
//
DbgPrintEx(DPFLTR_HPS_ID,
DPFLTR_INFO_LEVEL,
"HPS-Device Control IOCTL_HPS_BRIDGE_INFO\n"
);
if (!Irp->AssociatedIrp.SystemBuffer ||
(IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(HPTEST_BRIDGE_INFO))) {
//
// We didn't get the buffer we expected. Fail.
//
return STATUS_INVALID_PARAMETER;
}
bridgeInfo = (PHPTEST_BRIDGE_INFO)Irp->AssociatedIrp.SystemBuffer;
HpsGetBridgeInfo(Extension,
bridgeInfo
);
Irp->IoStatus.Information = sizeof(HPTEST_BRIDGE_INFO);
status = STATUS_SUCCESS;
break;
default:
status = STATUS_NOT_SUPPORTED;
}
return status;
}