mirror of https://github.com/tongzx/nt5src
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.
1088 lines
25 KiB
1088 lines
25 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
SERVICE.C
|
|
|
|
Abstract:
|
|
|
|
Services provided to the DBC port driver
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#include <wdm.h>
|
|
#include "stdarg.h"
|
|
#include "stdio.h"
|
|
|
|
#include "dbci.h"
|
|
#include "dbclass.h"
|
|
#include "dbfilter.h"
|
|
|
|
#define DBCLASS
|
|
#include "dbclib.h"
|
|
#undef DBCLASS
|
|
|
|
extern PDBC_CONTEXT DBCLASS_ControllerList;
|
|
extern KSPIN_LOCK DBCLASS_ControllerListSpin;
|
|
extern LIST_ENTRY DBCLASS_DevicePdoList;
|
|
extern LIST_ENTRY DBCLASS_BusFilterMdoList;
|
|
|
|
NTSTATUS
|
|
DBCLASS_Initialize(
|
|
)
|
|
{
|
|
// temp init code.
|
|
static init = 0;
|
|
|
|
if (init)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#if DBG
|
|
DBCLASS_GetClassGlobalDebugRegistryParameters();
|
|
BRK_ON_TRAP();
|
|
#endif
|
|
|
|
DBCLASS_KdPrint((1, "'Initailize DBC Class Driver\n"));
|
|
#ifdef DEBUG_LOG
|
|
//
|
|
// Initialize our debug trace log
|
|
//
|
|
DBCLASS_LogInit();
|
|
#endif
|
|
|
|
DBCLASS_ControllerList = NULL;
|
|
KeInitializeSpinLock(&DBCLASS_ControllerListSpin);
|
|
InitializeListHead(&DBCLASS_DevicePdoList);
|
|
InitializeListHead(&DBCLASS_BusFilterMdoList);
|
|
init = 1;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#if 0
|
|
__declspec(dllexport)
|
|
NTSTATUS
|
|
DllInitialize(
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
{
|
|
TEST_TRAP();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Installable driver initialization entry point.
|
|
This entry point is called directly by the I/O system.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - pointer to the driver object
|
|
|
|
RegistryPath - pointer to a unicode string representing the path
|
|
to driver-specific key in the registry
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
TEST_TRAP();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DBCLASS_RegisterController(
|
|
IN ULONG DbclassVersion,
|
|
IN PDEVICE_OBJECT ControllerFdo,
|
|
IN PDEVICE_OBJECT TopOfPdoStack,
|
|
IN PDEVICE_OBJECT ControllerPdo,
|
|
IN ULONG ControllerSig
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function registers a DBC with the class driver, the
|
|
FDO of the DBC is passed in along with the PDO for the DBC.
|
|
|
|
The class driver uses this information to locate the
|
|
correct instances of the DB Class Driver FDOs.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PDBC_CONTEXT dbcContext;
|
|
KIRQL irql;
|
|
NTSTATUS ntStatus;
|
|
|
|
#if DBG
|
|
DBCLASS_GetClassGlobalDebugRegistryParameters();
|
|
#endif
|
|
|
|
DBCLASS_KdPrint((0, "'Class Registration\n"));
|
|
LOGENTRY(LOG_MISC, 'REGc', ControllerFdo, 0, 0);
|
|
|
|
// initialize here
|
|
DBCLASS_Initialize();
|
|
|
|
// search our list if we find the TopOfStack device
|
|
// object then this must be a filter driver, otherwise
|
|
// allocate a new context structure for this controller
|
|
|
|
if (ControllerSig == DBC_OEM_FILTER_SIG)
|
|
{
|
|
|
|
KeAcquireSpinLock(&DBCLASS_ControllerListSpin, &irql);
|
|
|
|
dbcContext = DBCLASS_ControllerList;
|
|
|
|
while (dbcContext)
|
|
{
|
|
|
|
if (dbcContext->TopOfStack == TopOfPdoStack)
|
|
{
|
|
|
|
// we have a DBC filter, update our
|
|
// TopOfStack DeviceObject so that
|
|
// the filter gets called first
|
|
|
|
DBCLASS_KdPrint((0, "'>Registering Filter\n"));
|
|
|
|
dbcContext->TopOfStack = ControllerFdo;
|
|
|
|
KeReleaseSpinLock(&DBCLASS_ControllerListSpin, irql);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
dbcContext = dbcContext->Next;
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&DBCLASS_ControllerListSpin, irql);
|
|
|
|
DBCLASS_KdPrint((0, "'>Register Filter, could not find controller?\n"));
|
|
|
|
}
|
|
else
|
|
{
|
|
// create a context structure for this controller
|
|
DBCLASS_KdPrint((0, "'>Registering Controller\n"));
|
|
|
|
KeAcquireSpinLock(&DBCLASS_ControllerListSpin, &irql);
|
|
|
|
dbcContext = DbcExAllocatePool(NonPagedPool, sizeof(*dbcContext));
|
|
if (dbcContext)
|
|
{
|
|
RtlZeroMemory(dbcContext, sizeof(*dbcContext));
|
|
|
|
dbcContext->Sig = DBC_CONTEXT_SIG;
|
|
dbcContext->Next = DBCLASS_ControllerList;
|
|
DBCLASS_ControllerList = dbcContext;
|
|
dbcContext->TopOfStack = ControllerFdo;
|
|
dbcContext->ControllerFdo = ControllerFdo;
|
|
// consider ourselves initially stopped
|
|
dbcContext->Stopped = TRUE;
|
|
dbcContext->ControllerSig = ControllerSig;
|
|
dbcContext->ControllerPdo = ControllerPdo;
|
|
dbcContext->TopOfPdoStack = TopOfPdoStack;
|
|
|
|
DBCLASS_KdPrint((0, "'ControllerFdo (%08X) ControllerPdo (%08X) TopOfPdoStack (%08X) TopOfStack (%08X) DbcContext (%08X)\n",
|
|
dbcContext->ControllerFdo, dbcContext->ControllerPdo, dbcContext->TopOfPdoStack, dbcContext->TopOfStack, dbcContext));
|
|
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
KeReleaseSpinLock(&DBCLASS_ControllerListSpin, irql);
|
|
|
|
}
|
|
|
|
LOGENTRY(LOG_MISC, 'rEGc', ControllerFdo, ntStatus, 0);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DBCLASS_PortQDeviceRelationsComplete(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the device object
|
|
|
|
Irp - a pointer to the irp
|
|
|
|
Context - NULL ptr
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDBC_CONTEXT dbcContext = Context;
|
|
PIO_STACK_LOCATION irpStack;
|
|
PDEVICE_RELATIONS oldList, newList;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
ULONG pdoCount, i;
|
|
|
|
// we are interested in REMOVAL_RELATIONS
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
DBCLASS_ASSERT(IRP_MJ_PNP == irpStack->MajorFunction);
|
|
DBCLASS_ASSERT(IRP_MN_QUERY_DEVICE_RELATIONS == irpStack->MinorFunction);
|
|
|
|
switch (irpStack->Parameters.QueryDeviceRelations.Type)
|
|
{
|
|
case RemovalRelations:
|
|
|
|
//
|
|
// Add the PDOs for the device bay devices to the list
|
|
//
|
|
|
|
oldList = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
|
|
newList = NULL;
|
|
|
|
if (oldList)
|
|
{
|
|
pdoCount = oldList->Count;
|
|
}
|
|
else
|
|
{
|
|
// empty list
|
|
pdoCount = 0;
|
|
}
|
|
|
|
//
|
|
// count our PDOs
|
|
//
|
|
|
|
for (i=1; i<=NUMBER_OF_BAYS(dbcContext); i++)
|
|
{
|
|
if (dbcContext->BayInformation[i].DeviceFilterObject)
|
|
{
|
|
pdoCount++;
|
|
}
|
|
}
|
|
|
|
if (pdoCount)
|
|
{
|
|
newList = ExAllocatePoolWithTag(PagedPool, sizeof(*newList) +
|
|
(pdoCount - 1) * sizeof(PDEVICE_OBJECT), DBC_TAG);
|
|
}
|
|
|
|
if (newList)
|
|
{
|
|
newList->Count = pdoCount = 0;
|
|
|
|
// add the old list to the new list
|
|
|
|
if (oldList)
|
|
{
|
|
for (i=0; i< oldList->Count; i++)
|
|
{
|
|
newList->Objects[pdoCount] = oldList->Objects[i];
|
|
newList->Count++;
|
|
pdoCount++;
|
|
}
|
|
}
|
|
|
|
// free the old list
|
|
|
|
ExFreePool(oldList);
|
|
|
|
// add our PDOs to the list;
|
|
|
|
for (i=1; i<=NUMBER_OF_BAYS(dbcContext); i++)
|
|
{
|
|
|
|
if (dbcContext->BayInformation[i].DeviceFilterObject)
|
|
{
|
|
|
|
deviceExtension =
|
|
dbcContext->BayInformation[i].DeviceFilterObject->DeviceExtension;
|
|
|
|
newList->Objects[pdoCount] =
|
|
deviceExtension->PhysicalDeviceObject;
|
|
|
|
pdoCount++;
|
|
newList->Count++;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Information = PtrToUlong(newList);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
DBCLASS_UnRegisterController(
|
|
IN PDEVICE_OBJECT ControllerFdo,
|
|
IN PDEVICE_OBJECT TopOfStack
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
// locate which instance of the class driver is associated
|
|
// with this DBC.
|
|
|
|
PDBC_CONTEXT dbcContext = NULL;
|
|
PDBC_CONTEXT prev = NULL;
|
|
|
|
prev = dbcContext = DBCLASS_ControllerList;
|
|
|
|
while (dbcContext)
|
|
{
|
|
|
|
if (dbcContext->ControllerFdo == ControllerFdo)
|
|
{
|
|
// remove controller
|
|
|
|
DBCLASS_KdPrint((0, "'>UnRegister Controller\n"));
|
|
|
|
DBCLASS_KdPrint((0, "'ControllerFdo (%08X) ControllerPdo (%08X) TopOfPdoStack (%08X) TopOfStack (%08X) FilterMDOUSB (%08X) DbcContext (%08X)\n",
|
|
dbcContext->ControllerFdo, dbcContext->ControllerPdo, dbcContext->TopOfPdoStack, dbcContext->TopOfStack, dbcContext->BusFilterMdoUSB, dbcContext));
|
|
|
|
|
|
// unlink
|
|
if (DBCLASS_ControllerList == dbcContext)
|
|
{
|
|
DBCLASS_ControllerList = dbcContext->Next;
|
|
}
|
|
else
|
|
{
|
|
DBCLASS_ASSERT(prev->Next == dbcContext);
|
|
prev->Next = dbcContext->Next;
|
|
}
|
|
|
|
DBCLASS_RemoveControllerFromMdo(dbcContext);
|
|
|
|
DbcExFreePool(dbcContext);
|
|
break;
|
|
}
|
|
|
|
prev = dbcContext;
|
|
dbcContext = dbcContext->Next;
|
|
}
|
|
|
|
LOGENTRY(LOG_MISC, 'UNRc', dbcContext, 0, 0);
|
|
|
|
#if DBG
|
|
if (dbcContext == NULL)
|
|
{
|
|
DBCLASS_KdPrint((0, "'Controller not Found\n"));
|
|
TRAP();
|
|
}
|
|
#endif
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DBCLASS_ClassDispatch(
|
|
IN PDEVICE_OBJECT ControllerFdo,
|
|
IN PIRP Irp,
|
|
IN PBOOLEAN HandledByClass
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS ntStatus;
|
|
PDBC_CONTEXT dbcContext;
|
|
|
|
*HandledByClass = FALSE;
|
|
dbcContext = DBCLASS_GetDbcContext(ControllerFdo);
|
|
|
|
LOGENTRY(LOG_MISC, 'dIRP', ControllerFdo, 0, Irp);
|
|
|
|
if (dbcContext == NULL)
|
|
{
|
|
DBCLASS_KdPrint((0, "'Invalid ControllerFdo passed in\n"));
|
|
TRAP();
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
*HandledByClass = TRUE;
|
|
goto DBCLASS_Dispatch_Done;
|
|
}
|
|
|
|
ntStatus = Irp->IoStatus.Status;
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
switch (irpStack->MajorFunction)
|
|
{
|
|
|
|
case IRP_MJ_POWER:
|
|
|
|
ntStatus = DBCLASS_ClassPower(ControllerFdo,
|
|
Irp,
|
|
HandledByClass);
|
|
goto DBCLASS_Dispatch_Exit;
|
|
break; /* IRP_MJ_POWER */
|
|
|
|
case IRP_MJ_PNP:
|
|
switch (irpStack->MinorFunction)
|
|
{
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
// handle Q_BUS_RELATIONS for the port driver
|
|
|
|
*HandledByClass = TRUE;
|
|
// hook the completion and pass on
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
DBCLASS_PortQDeviceRelationsComplete,
|
|
dbcContext,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
ntStatus = IoCallDriver(dbcContext->TopOfStack, Irp);
|
|
// we did the calldown for the port driver so
|
|
// all we do now is exit
|
|
goto DBCLASS_Dispatch_Exit;
|
|
|
|
break;
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
DBCLASS_KdPrint((1, "'IRP_MN_START_DEVICE\n"));
|
|
ntStatus = DBCLASS_StartController(dbcContext,
|
|
Irp,
|
|
HandledByClass);
|
|
break;
|
|
|
|
#if 0
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
#if DBG
|
|
if (irpStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) {
|
|
DBCLASS_KdPrint((1, "'IRP_MN_QUERY_REMOVE_DEVICE\n"));
|
|
} else {
|
|
DBCLASS_KdPrint((1, "'IRP_MN_QUERY_STOP_DEVICE\n"));
|
|
}
|
|
#endif
|
|
// would like to eject the devices at this
|
|
// point -- instead I will fail if we have devices in
|
|
// the bays!
|
|
|
|
{
|
|
BOOLEAN empty = TRUE;
|
|
USHORT bay;
|
|
|
|
for (bay=1; bay <=NUMBER_OF_BAYS(dbcContext); bay++)
|
|
{
|
|
if (dbcContext->BayInformation[bay].DeviceFilterObject !=
|
|
NULL)
|
|
{
|
|
empty = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!empty)
|
|
{
|
|
*HandledByClass = TRUE;
|
|
ntStatus = STATUS_UNSUCCESSFUL;
|
|
DBCLASS_KdPrint((1, "'Bays not Empty!"));
|
|
goto DBCLASS_Dispatch_Done;
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
case IRP_MN_STOP_DEVICE:
|
|
DBCLASS_KdPrint((1, "'IRP_MN_STOP_DEVICE\n"));
|
|
ntStatus = DBCLASS_StopController(dbcContext,
|
|
Irp,
|
|
HandledByClass);
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
// free allocated resources
|
|
ntStatus = DBCLASS_CleanupController(dbcContext);
|
|
}
|
|
|
|
dbcContext->Stopped = TRUE;
|
|
LOGENTRY(LOG_MISC, 'STPd', dbcContext, 0, ntStatus);
|
|
break;
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
DBCLASS_KdPrint((1, "'IRP_MN_REMOVE_DEVICE\n"));
|
|
DBCLASS_KdPrint((1, "'FDO (%08X)\n", ControllerFdo));
|
|
|
|
if (!dbcContext->Stopped)
|
|
{
|
|
ntStatus = DBCLASS_StopController(dbcContext,
|
|
Irp,
|
|
HandledByClass);
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
// free allocated resources
|
|
ntStatus = DBCLASS_CleanupController(dbcContext);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ntStatus = STATUS_SUCCESS;
|
|
}
|
|
|
|
LOGENTRY(LOG_MISC, 'RMVd', dbcContext, 0, ntStatus);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IRP_MJ_CREATE:
|
|
case IRP_MJ_CLOSE:
|
|
ntStatus = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Irp is not interesting to us
|
|
LOGENTRY(LOG_MISC, 'pIRP', ControllerFdo, 0, Irp);
|
|
break;
|
|
}; /* case MJ_FUNCTION */
|
|
|
|
|
|
DBCLASS_Dispatch_Done:
|
|
|
|
if (*HandledByClass)
|
|
{
|
|
DBCLASS_KdPrint((2, "'Completing Irp\n"));
|
|
Irp->IoStatus.Status = ntStatus;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
DBCLASS_Dispatch_Exit:
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DBCLASS_FilterDispatch(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
figure out what type of FDO we are and dispatch to
|
|
the appropriate handler
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Device bay Filter FDO
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS ntStatus;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
BOOLEAN handled = FALSE;
|
|
PDEVICE_OBJECT topOfStackDeviceObject;
|
|
ULONG MinFunc, MajFunc;
|
|
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
topOfStackDeviceObject = deviceExtension->TopOfStackDeviceObject;
|
|
|
|
LOGENTRY(LOG_MISC, 'FLT>', 0, DeviceObject, Irp);
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
MinFunc = irpStack->MinorFunction;
|
|
MajFunc = irpStack->MajorFunction;
|
|
|
|
// figure out what kind of PDO this call is bound for
|
|
|
|
switch(deviceExtension->FdoType)
|
|
{
|
|
case DB_FDO_BUS_IGNORE:
|
|
break;
|
|
|
|
case DB_FDO_BUS_UNKNOWN:
|
|
|
|
ntStatus = DBCLASS_BusFilterDispatch(
|
|
DeviceObject,
|
|
Irp,
|
|
&handled);
|
|
break;
|
|
|
|
case DB_FDO_USBHUB_BUS:
|
|
|
|
ntStatus = DBCLASS_UsbhubBusFilterDispatch(
|
|
DeviceObject,
|
|
Irp,
|
|
&handled);
|
|
break;
|
|
case DB_FDO_USB_DEVICE:
|
|
case DB_FDO_1394_DEVICE:
|
|
|
|
ntStatus = DBCLASS_PdoFilterDispatch(
|
|
DeviceObject,
|
|
Irp,
|
|
&handled);
|
|
break;
|
|
case DB_FDO_1394_BUS:
|
|
|
|
ntStatus = DBCLASS_1394BusFilterDispatch(
|
|
DeviceObject,
|
|
Irp,
|
|
&handled);
|
|
break;
|
|
default:
|
|
DBCLASS_KdPrint((0, "'Invalid Extension Signature"));
|
|
TRAP();
|
|
}
|
|
|
|
if (!handled)
|
|
{
|
|
|
|
if(MajFunc == IRP_MJ_POWER)
|
|
{
|
|
PoStartNextPowerIrp(Irp);
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
ntStatus = PoCallDriver(topOfStackDeviceObject, Irp);
|
|
|
|
if(ntStatus)
|
|
{
|
|
DBCLASS_KdPrint((2, "'Filter Power Dispatch Status (%08X)\n", ntStatus));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// all filters behave pretty much the same
|
|
// if the routine we called did not want to
|
|
// handle the IRP we take the default action
|
|
// here.
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
ntStatus = IoCallDriver(topOfStackDeviceObject, Irp);
|
|
|
|
if(ntStatus)
|
|
{
|
|
DBCLASS_KdPrint((2, "'Filter Dispatch Status (%08X)\n", ntStatus));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
LOGENTRY(LOG_MISC, 'PNP<', ntStatus, DeviceObject, 0);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
#if 0
|
|
NTSTATUS
|
|
DBCLASS_SetD0_Complete(
|
|
PDEVICE_OBJECT ControllerFdo,
|
|
PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called by port driver when the port driver
|
|
enters D0.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Device bay Filter FDO
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDBC_CONTEXT dbcContext;
|
|
|
|
LOGENTRY(LOG_MISC, 'D0cp', 0, ControllerFdo, Irp);
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
dbcContext = DBCLASS_GetDbcContext(ControllerFdo);
|
|
|
|
DBCLASS_KdPrint((0, "'Set DevicePowerState = D0\n"));
|
|
dbcContext->CurrentDevicePowerState = PowerDeviceD0;
|
|
|
|
return ntStatus;
|
|
}
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
DBCLASS_RegisterBusFilter(
|
|
ULONG DbclassVersion,
|
|
PDRIVER_OBJECT FilterDriverObject,
|
|
PDEVICE_OBJECT FilterMdo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
find the controller for this PDO and associate the
|
|
PDO with the correct bay
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
deviceExtension = FilterMdo->DeviceExtension;
|
|
|
|
// initialize here
|
|
DBCLASS_Initialize();
|
|
|
|
LOGENTRY(LOG_MISC, 'rPDO', 0, FilterMdo, 0);
|
|
DBCLASS_KdPrint((0, "'Register Bus Filter FDO(%x)\n", FilterMdo));
|
|
|
|
// The bus filter handle one instance of the 1394 bus --
|
|
// which may have multiple DBCs associated with it.
|
|
// therefore we don't use the Context field in the bus filter
|
|
// extension
|
|
|
|
deviceExtension->DbcContext = (PDBC_CONTEXT) -1;
|
|
|
|
// Put the filter MDO on our list of bus filters
|
|
|
|
DBCLASS_AddBusFilterMDOToList(FilterMdo);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DBCLASS_AddBusFilterMDOToList(
|
|
PDEVICE_OBJECT BusFilterMdo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds a bus filter to our internal list
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDBCLASS_PDO_LIST newEntry;
|
|
|
|
newEntry = ExAllocatePool(NonPagedPool, sizeof(DBCLASS_PDO_LIST));
|
|
|
|
DBCLASS_ASSERT(newEntry);
|
|
|
|
if (newEntry == NULL)
|
|
{
|
|
TRAP();
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
// Fill in fields in new entry
|
|
|
|
newEntry->FilterDeviceObject = BusFilterMdo;
|
|
|
|
// Add new entry to end of list
|
|
InsertTailList(&DBCLASS_BusFilterMdoList, &newEntry->ListEntry);
|
|
|
|
DBCLASS_KdPrint((2, "'AddBusFilterMdo (%08X)\n", BusFilterMdo));
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
DBCLASS_RemoveBusFilterMDOFromList(
|
|
IN PDEVICE_OBJECT BusFilterMdo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes a bus filter from the internal list
|
|
|
|
Arguments:
|
|
|
|
BusFilterMdo - a pointer to the device object to remove.
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
|
|
{
|
|
PDBCLASS_PDO_LIST entry;
|
|
PLIST_ENTRY listEntry;
|
|
|
|
listEntry = &DBCLASS_BusFilterMdoList;
|
|
|
|
if (!IsListEmpty(listEntry))
|
|
{
|
|
listEntry = DBCLASS_BusFilterMdoList.Flink;
|
|
}
|
|
|
|
while (listEntry != &DBCLASS_BusFilterMdoList)
|
|
{
|
|
|
|
entry = CONTAINING_RECORD(listEntry,
|
|
DBCLASS_PDO_LIST,
|
|
ListEntry);
|
|
|
|
DBCLASS_ASSERT(entry);
|
|
|
|
if (entry->FilterDeviceObject == BusFilterMdo)
|
|
break;
|
|
|
|
listEntry = entry->ListEntry.Flink;
|
|
|
|
}
|
|
|
|
// we should always find it
|
|
DBCLASS_ASSERT(listEntry != &DBCLASS_BusFilterMdoList);
|
|
|
|
DBCLASS_KdPrint((2, "'RemoveBusFilterMdo (%08X)\n", BusFilterMdo));
|
|
|
|
RemoveEntryList(listEntry);
|
|
ExFreePool(entry);
|
|
}
|
|
|
|
|
|
VOID
|
|
DBCLASS_Refresh1394(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes a bus filter from the internal list
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the device object to remove.
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
|
|
{
|
|
PDBCLASS_PDO_LIST entry;
|
|
PLIST_ENTRY listEntry;
|
|
PDEVICE_EXTENSION busFilterDeviceExtension;
|
|
PDEVICE_OBJECT FilterDevObj;
|
|
|
|
listEntry = &DBCLASS_BusFilterMdoList;
|
|
|
|
if (!IsListEmpty(listEntry)) {
|
|
listEntry = DBCLASS_BusFilterMdoList.Flink;
|
|
}
|
|
|
|
while (listEntry != &DBCLASS_BusFilterMdoList)
|
|
{
|
|
|
|
entry = CONTAINING_RECORD(listEntry,
|
|
DBCLASS_PDO_LIST,
|
|
ListEntry);
|
|
|
|
DBCLASS_ASSERT(entry);
|
|
|
|
FilterDevObj = entry->FilterDeviceObject;
|
|
|
|
DBCLASS_KdPrint((2, "'Refresh1394 Entry (%08X) FilterDevObj (%08X)\n", entry, FilterDevObj));
|
|
|
|
if(FilterDevObj)
|
|
{
|
|
busFilterDeviceExtension =
|
|
FilterDevObj->DeviceExtension;
|
|
|
|
if(busFilterDeviceExtension)
|
|
{
|
|
if (busFilterDeviceExtension->FdoType == DB_FDO_1394_BUS)
|
|
{
|
|
DBCLASS_KdPrint((0, "'IoInvalidate 1394\n"));
|
|
IoInvalidateDeviceRelations(busFilterDeviceExtension->PhysicalDeviceObject,
|
|
BusRelations);
|
|
}
|
|
}
|
|
}
|
|
|
|
listEntry = entry->ListEntry.Flink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DBCLASS_RemoveControllerFromMdo(PDBC_CONTEXT DbcContext)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes reference to USB controller from a filter
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
|
|
{
|
|
PDBCLASS_PDO_LIST entry;
|
|
PLIST_ENTRY listEntry;
|
|
PDEVICE_EXTENSION busFilterDeviceExtension;
|
|
PDEVICE_OBJECT FilterDevObj;
|
|
|
|
listEntry = &DBCLASS_DevicePdoList;
|
|
|
|
if (!IsListEmpty(listEntry))
|
|
{
|
|
listEntry = DBCLASS_DevicePdoList.Flink;
|
|
}
|
|
|
|
while (listEntry != &DBCLASS_DevicePdoList)
|
|
{
|
|
|
|
entry = CONTAINING_RECORD(listEntry,
|
|
DBCLASS_PDO_LIST,
|
|
ListEntry);
|
|
|
|
DBCLASS_ASSERT(entry);
|
|
|
|
FilterDevObj = entry->FilterDeviceObject;
|
|
|
|
if(FilterDevObj)
|
|
{
|
|
busFilterDeviceExtension =
|
|
FilterDevObj->DeviceExtension;
|
|
|
|
if(busFilterDeviceExtension)
|
|
{
|
|
if (busFilterDeviceExtension->DbcContext == DbcContext)
|
|
{
|
|
DBCLASS_KdPrint((2, "'Remove Controller From FilterDevObj (%08X)\n", FilterDevObj));
|
|
|
|
busFilterDeviceExtension->DbcContext = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
listEntry = entry->ListEntry.Flink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|