📄 isopnp.c
字号:
/*++
Copyright (c) 2004 Microsoft Corporation
Module Name:
isopnp.c
Abstract:
Isoch USB device driver for Intel 82930 USB test board
Plug and Play module
Environment:
Kernel mode
Notes:
Copyright (c) 2004 Microsoft Corporation.
All Rights Reserved.
--*/
#include "isousb.h"
#include "isopnp.h"
#include "isopwr.h"
#include "isodev.h"
#include "isowmi.h"
#include "isousr.h"
#include "isorwr.h"
#include "isostrm.h"
NTSTATUS
IsoUsb_DispatchPnP(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these requests the driver will completely ignore.
In all cases it must pass on the IRP to the lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
KEVENT startDeviceEvent;
NTSTATUS ntStatus;
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
deviceExtension = DeviceObject->DeviceExtension;
//
// since the device is removed, fail the Irp.
//
if(Removed == deviceExtension->DeviceState) {
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
IsoUsb_DbgPrint(3, ("///////////////////////////////////////////\n"));
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchPnP::"));
IsoUsb_IoIncrement(deviceExtension);
if(irpStack->MinorFunction == IRP_MN_START_DEVICE) {
ASSERT(deviceExtension->IdleReqPend == 0);
}
else {
if(deviceExtension->SSEnable) {
CancelSelectSuspend(deviceExtension);
}
}
IsoUsb_DbgPrint(2, (PnPMinorFunctionString(irpStack->MinorFunction)));
switch(irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
ntStatus = HandleStartDevice(DeviceObject, Irp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
//
// if we cannot stop the device, we fail the query stop irp
//
ntStatus = CanStopDevice(DeviceObject, Irp);
if(NT_SUCCESS(ntStatus)) {
ntStatus = HandleQueryStopDevice(DeviceObject, Irp);
return ntStatus;
}
break;
case IRP_MN_CANCEL_STOP_DEVICE:
ntStatus = HandleCancelStopDevice(DeviceObject, Irp);
break;
case IRP_MN_STOP_DEVICE:
ntStatus = HandleStopDevice(DeviceObject, Irp);
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchPnP::IRP_MN_STOP_DEVICE::"));
IsoUsb_IoDecrement(deviceExtension);
return ntStatus;
case IRP_MN_QUERY_REMOVE_DEVICE:
//
// if we cannot remove the device, we fail the query remove irp
//
ntStatus = CanRemoveDevice(DeviceObject, Irp);
if(NT_SUCCESS(ntStatus)) {
ntStatus = HandleQueryRemoveDevice(DeviceObject, Irp);
return ntStatus;
}
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
ntStatus = HandleCancelRemoveDevice(DeviceObject, Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
ntStatus = HandleSurpriseRemoval(DeviceObject, Irp);
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchPnP::IRP_MN_SURPRISE_REMOVAL::"));
IsoUsb_IoDecrement(deviceExtension);
return ntStatus;
case IRP_MN_REMOVE_DEVICE:
ntStatus = HandleRemoveDevice(DeviceObject, Irp);
return ntStatus;
case IRP_MN_QUERY_CAPABILITIES:
ntStatus = HandleQueryCapabilities(DeviceObject, Irp);
break;
default:
IoSkipCurrentIrpStackLocation(Irp);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchPnP::default::"));
IsoUsb_IoDecrement(deviceExtension);
return ntStatus;
} // switch
//
// complete request
//
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// decrement count
//
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchPnP::"));
IsoUsb_IoDecrement(deviceExtension);
return ntStatus;
}
NTSTATUS
HandleStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the dispatch routine for RP_MJ_PNP, IRP_MN_START_DEVICE
The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context
of a system thread.
This IRP must be handled first by the underlying bus driver for a
device and then by each higher driver in the device stack.
Arguments:
DeviceObject - pointer to a device object.
Irp - I/O request packet
Return Value:
NT status value
--*/
{
PDEVICE_EXTENSION deviceExtension;
KIRQL oldIrql;
LARGE_INTEGER dueTime;
NTSTATUS ntStatus;
IsoUsb_DbgPrint(3, ("HandleStartDevice - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
// Pass the IRP_MN_START_DEVICE Irp down the stack first before we
// do anything.
//
ntStatus = IsoUsb_SyncPassDownIrp(DeviceObject,
Irp);
if (!NT_SUCCESS(ntStatus))
{
IsoUsb_DbgPrint(1, ("Lower drivers failed IRP_MN_START_DEVICE\n"));
return ntStatus;
}
// If this is the first time the device as been started, retrieve the
// Device and Configuration Descriptors from the device.
//
if (deviceExtension->DeviceDescriptor == NULL)
{
ntStatus = IsoUsb_GetDescriptors(DeviceObject);
if (!NT_SUCCESS(ntStatus))
{
return ntStatus;
}
}
// Now configure the device
//
ntStatus = IsoUsb_SelectConfiguration(DeviceObject);
if (!NT_SUCCESS(ntStatus))
{
return ntStatus;
}
//
// enable the symbolic links for system components to open
// handles to the device
//
ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName,
TRUE);
if(!NT_SUCCESS(ntStatus)) {
IsoUsb_DbgPrint(1, ("IoSetDeviceInterfaceState:enable:failed\n"));
return ntStatus;
}
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(deviceExtension, Working);
deviceExtension->QueueState = AllowRequests;
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
//
// initialize wait wake outstanding flag to false.
// and issue a wait wake.
deviceExtension->FlagWWOutstanding = 0;
deviceExtension->FlagWWCancel = 0;
deviceExtension->WaitWakeIrp = NULL;
if(deviceExtension->WaitWakeEnable) {
IssueWaitWake(deviceExtension);
}
ProcessQueuedRequests(deviceExtension);
if(WinXpOrBetter == deviceExtension->WdmVersion) {
deviceExtension->SSEnable = deviceExtension->SSRegistryEnable;
//
// set timer for selective suspend requests.
//
if(deviceExtension->SSEnable) {
dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms
KeSetTimerEx(&deviceExtension->Timer,
dueTime,
IDLE_INTERVAL, // 5000 ms
&deviceExtension->DeferredProcCall);
deviceExtension->FreeIdleIrpCount = 0;
}
}
if((Win2kOrBetter == deviceExtension->WdmVersion) ||
(WinXpOrBetter == deviceExtension->WdmVersion)) {
deviceExtension->IsDeviceHighSpeed = 0;
GetBusInterfaceVersion(DeviceObject);
}
IsoUsb_DbgPrint(3, ("HandleStartDevice - ends\n"));
return ntStatus;
}
NTSTATUS
CanStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine determines whether the device can be safely stopped. In our
particular case, we'll assume we can always stop the device.
A device might fail the request if it doesn't have a queue for the
requests it might come or if it was notified that it is in the paging
path.
Arguments:
DeviceObject - pointer to the device object.
Irp - pointer to the current IRP.
Return Value:
STATUS_SUCCESS if the device can be safely stopped, an appropriate
NT Status if not.
--*/
{
//
// We assume we can stop the device
//
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
return STATUS_SUCCESS;
}
NTSTATUS
HandleQueryStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services the Irps of minor type IRP_MN_QUERY_STOP_DEVICE
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
IsoUsb_DbgPrint(3, ("HandleQueryStopDevice - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// If we can stop the device, we need to set the QueueState to
// HoldRequests so further requests will be queued.
//
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(deviceExtension, PendingStop);
deviceExtension->QueueState = HoldRequests;
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
//
// wait for the existing ones to be finished.
// first, decrement this operation
//
IsoUsb_DbgPrint(3, ("HandleQueryStopDevice::"));
IsoUsb_IoDecrement(deviceExtension);
KeWaitForSingleObject(&deviceExtension->StopEvent,
Executive,
KernelMode,
FALSE,
NULL);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -