📄 pnp.c
字号:
/*++
Module Name:
Pnp.c
Abstract:
Plug and Play module
Environment:
kernel mode only
Notes:
Copyright (c) 1997-2000 Maverick Corporation. All Rights Reserved.
Revision History:
04/26/00: created
--*/
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "usbcom.h"
ULONG GlobalPdaCount = 0;
VOID
ASICInitRoutine(
IN PDEVICE_OBJECT DeviceObject
)
{
PURB Urb;
PIRP Irp;
CHAR StackSize;
PDEVICE_OBJECT stackDeviceObject;
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION NextStack;
ULONG UrbSize;
ULONG i;
NTSTATUS ntStatus = STATUS_SUCCESS;
NTSTATUS waitStatus;
#define INIT_ARRAY_SIZE 3
USHORT AsicInitData[INIT_ARRAY_SIZE][3] =
{ {0xF4,0x0000,0x0000 },
{0xFA,0x0011,0x0060 },
{0xFA,0x0008,0x0081 }
};
DeviceExtension = DeviceObject->DeviceExtension;
stackDeviceObject = DeviceExtension->TopOfStackDeviceObject;
// Allocate IRP for our I/O request
StackSize = (CCHAR)(DeviceExtension->TopOfStackDeviceObject->StackSize + 1);
Irp = IoAllocateIrp(StackSize, FALSE);
if (!Irp) {
DbgPrint("Failure due to memory error\n");
// Can't init ASIC
return;
}
// Allocate URB. It will be reused for the data transfer, so insure
// it is large enough for both control and bulk transfers
UrbSize = sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
Urb = ExAllocatePool(NonPagedPool, UrbSize);
if (!Urb)
{
DbgPrint ("Failure due to memory error\n");
IoFreeIrp(Irp);
return;
}
for(i= 0; i < INIT_ARRAY_SIZE; i++)
{
KEVENT initASICEvent;
KeInitializeEvent(&initASICEvent, NotificationEvent, FALSE);
// Build URB for the ADSC command used to send the CDB to our USB drive
UsbBuildVendorRequest(
Urb,
URB_FUNCTION_VENDOR_DEVICE,
(USHORT) sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
0,
0,
(UCHAR) AsicInitData[i][0], //ADSC,
AsicInitData[i][1], //ADSC,
AsicInitData[i][2], //ADSC,
NULL,
NULL,
0,
NULL
);
NextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(NextStack != NULL);
ASSERT(DeviceObject->StackSize>1);
// Initialize our Irp
NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextStack->Parameters.Others.Argument1 = Urb;
NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
// Register our Irp completion handler
IoSetCompletionRoutine (
Irp,
UsbCom_IrpCompletionRoutine,
&initASICEvent,
TRUE, // invoke on success
TRUE, // invoke on error
TRUE // invoke on cancellation of the Irp
);
UsbCom_IncrementIoCount(DeviceObject);
// Pass Irp to the USB driver stack
ntStatus = IoCallDriver(stackDeviceObject, Irp);
if (ntStatus == STATUS_PENDING) {
// wait for irp to complete
waitStatus = KeWaitForSingleObject(
&initASICEvent,
Suspended,
KernelMode,
FALSE,
NULL
);
}
UsbCom_DecrementIoCount(DeviceObject);
}
IoFreeIrp(Irp);
ExFreePool(Urb);
}
NTSTATUS
UsbCom_ProcessPnPIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch table routine for IRP_MJ_PNP.
Process the Plug and Play IRPs sent to this device.
Arguments:
DeviceObject - pointer to our FDO (Functional Device Object)
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
NTSTATUS waitStatus;
PDEVICE_OBJECT stackDeviceObject;
KEVENT startDeviceEvent;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get a pointer to the device extension
//
deviceExtension = DeviceObject->DeviceExtension;
stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
DbgPrint("enter UsbCom_ProcessPnPIrp() IRP_MJ_PNP, minor %s, -- %x\n",
UsbCom_StringForPnpMnFunc( irpStack->MinorFunction ), irpStack->MinorFunction );
// inc the FDO device extension's pending IO count for this Irp
UsbCom_IncrementIoCount(DeviceObject);
ASSERT( IRP_MJ_PNP == irpStack->MajorFunction );
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
// The PnP Manager sends this IRP after it has assigned resources,
// if any, to the device. The device may have been recently enumerated
// and is being started for the first time, or the device may be
// restarting after being stopped for resource reconfiguration.
// Initialize an event we can wait on for the PDO to be done with this irp
KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
// Set a completion routine so it can signal our event when
// the PDO is done with the Irp
IoSetCompletionRoutine(Irp,
UsbCom_IrpCompletionRoutine,
&startDeviceEvent, // pass the event to the completion routine as the Context
TRUE, // invoke on success
TRUE, // invoke on error
TRUE); // invoke on cancellation
// let the PDO process the IRP
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
// if PDO is not done yet, wait for the event to be set in our completion routine
if (ntStatus == STATUS_PENDING) {
// wait for irp to complete
waitStatus = KeWaitForSingleObject(
&startDeviceEvent,
Suspended,
KernelMode,
FALSE,
NULL);
ntStatus = Irp->IoStatus.Status;
}
if (NT_SUCCESS(ntStatus)) {
// Now we're ready to do our own startup processing.
// USB client drivers such as us set up URBs (USB Request Packets) to send requests
// to the host controller driver (HCD). The URB structure defines a format for all
// possible commands that can be sent to a USB device.
// Here, we request the device descriptor and store it,
// and configure the device.
ntStatus = UsbCom_StartDevice(DeviceObject);
Irp->IoStatus.Status = ntStatus;
}
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
#ifdef USE_SMARTNIC
// Initialize
ASICInitRoutine(DeviceObject);
// Give the device another second to settle.
KeStallExecutionProcessor(1000);
#endif
UsbCom_DecrementIoCount(DeviceObject);
return ntStatus; // end, case IRP_MN_START_DEVICE
case IRP_MN_QUERY_STOP_DEVICE:
// The IRP_MN_QUERY_STOP_DEVICE/IRP_MN_STOP_DEVICE sequence only occurs
// during "polite" shutdowns, such as the user explicitily requesting the
// service be stopped in, or requesting unplug from the Pnp tray icon.
// This sequence is NOT received during "impolite" shutdowns,
// such as someone suddenly yanking the USB cord or otherwise
// unexpectedly disabling/resetting the device.
// If a driver sets STATUS_SUCCESS for this IRP,
// the driver must not start any operations on the device that
// would prevent that driver from successfully completing an IRP_MN_STOP_DEVICE
// for the device.
// For mass storage devices such as disk drives, while the device is in the
// stop-pending state,the driver holds IRPs that require access to the device,
// but for most USB devices, there is no 'persistent storage', so we will just
// refuse any more IO until restarted or the stop is cancelled
// If a driver in the device stack determines that the device cannot be
// stopped for resource reconfiguration, the driver is not required to pass
// the IRP down the device stack. If a query-stop IRP fails,
// the PnP Manager sends an IRP_MN_CANCEL_STOP_DEVICE to the device stack,
// notifying the drivers for the device that the query has been cancelled
// and that the device will not be stopped.
// It is possible to receive this irp when the device has not been started
// ( as on a boot device )
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_QUERY_STOP_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
UsbCom_DecrementIoCount(DeviceObject);
return ntStatus;
}
// Cancel any pending io requests; we may not have gotten a query first!
// UsbCom_CancelPendingIo( DeviceObject );
// If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
// This call will also close the pipes; if any user close calls get through,
// they will be noops
UsbCom_AbortPipes( DeviceObject );
deviceExtension->StopDeviceRequested = TRUE;
// Wait for any io request pending in our driver to
// complete before returning success.
// This event is set when deviceExtension->PendingIoCount goes to 1
waitStatus = KeWaitForSingleObject(
&deviceExtension->NoPendingIoEvent,
Suspended,
KernelMode,
FALSE,
NULL);
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_QUERY_STOP_DEVICE
case IRP_MN_CANCEL_STOP_DEVICE:
// The PnP Manager uses this IRP to inform the drivers for a device
// that the device will not be stopped for resource reconfiguration.
// This should only be received after a successful IRP_MN_QUERY_STOP_DEVICE.
// It is possible to receive this irp when the device has not been started
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
DbgPrint("UsbCom_ProcessPnPIrp() IRP_MN_CANCEL_STOP_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
UsbCom_DecrementIoCount(DeviceObject);
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -