📄 usbfx2lk_pnp.cpp
字号:
// In either case, we pass the IRP all the way down. When it's
// done we can then read the list of device resources pointed to
// in the IRP Stack Location.
//
case (STATE_NEVER_STARTED + IRP_MN_START_DEVICE):
//
// If we've never been started, we'll need to
// enable our device interface.
//
// Note that we don't disable our interface on
// a STOP. It's really only a transient
// state and there's no reason why we shouldn't
// let users open up our device and queue I/O
// to it while we're in it.
//
enableInterface = TRUE;
//
// Fall through...
//
case (STATE_STOPPED + IRP_MN_START_DEVICE): {
//
// This is a BUS FIRST Irp. The bus driver is involved in
// the allocation of resources for us, so we must give
// it to him first to fill in our stack location with
// our resources.
//
status = OsrForwardIrpSynchronous(devExt,Irp);
//
// Is the bus driver OK with us starting?
//
if (NT_SUCCESS(status)) {
//
// Excellent...Try starting our device!
//
status = OsrStartDevice(devExt);
if (NT_SUCCESS(status)) {
//
// Indicate the initial power state of the device to the
// power manager by calling PoSetPowerState.
//
powerState.DeviceState = PowerDeviceD0;
PoSetPowerState(DeviceObject, DevicePowerState, powerState);
//
// Enable SS if the user wants it. The decision
// about whether or not SS is enabled by the user
// is done under lock within EnableSelectiveSuspend
//
EnableSelectiveSuspend(devExt);
OsrUpdateDeviceState(devExt, STATE_STARTED);
//
// IF you registered a device interface, using
// IoRegisterDeviceInterface(), and you're coming
// out of the NEVER_STARTED state, you'll also need to
// set the interface state here to ENABLED. This is
// done with the following call.
//
if (enableInterface) {
status = IoSetDeviceInterfaceState(
&devExt->InterfaceName,
TRUE);
if (!NT_SUCCESS(status)) {
//
// We won't consider this to be fatal. Currently the only reason
// for it happening is if the interface is already enabled, in
// which case it's a bug and this DbgPrint should suffice.
//
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("OsrPnp: IoSetDeviceInterfaceState failed! Returned status 0x%8.8x (%s)\n",
status, OsrNtStatusToString(status)));
}
}
//
// Initialize WaitWake Information and queue a wait
// wake IRP to the host if waking is enabled for the device.
//
devExt->FlagWWOutstanding = 0;
devExt->FlagWWCancel = 0;
devExt->WaitWakeIrp = NULL;
if(devExt->DeviceCapabilitiesInitialized && devExt->WaitWakeEnable) {
IssueWaitWake(devExt);
}
//
// If we were stopped, our queues were stalled and
// we need to restart them. We are guaranteed to
// be powered up here.
//
OsrProcessQueuedRequests(devExt);
} else {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("OsrPnp: Unable to start device! Status = 0x%8.8x (%s)\n",
status, OsrNtStatusToString(status)));
}
} else {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("OsrPnp: Request to start failed! Status = 0x%8.8x (%s)\n",
status, OsrNtStatusToString(status)));
}
//
// Fill in the completion status...
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
//
// We need to call IoCompleteRequest on it
// to finish processing.
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
return status;
}
//
// STATE: STARTED
// IRP_MN: _QUERY_STOP_DEVICE
//
// We're here if we're running and the PnP Manager sends us
// a QUERY_STOP_DEVICE request. He'll do this if he wants to
// rebalance resources to see if we're willing to give up the
// anything we setup during our IRP_MN_START_DEVICE.
//
// To proess this QUERY_STOP, we check to see if the stop is
// acceptable to us (in this driver it always is), and then
// we just transition the device to STOP_PENDING state. In
// this state, new requests that arrive are queued. When a
// currently in-progress request is completed, a new request
// is NOT started. Thus, ON OUR DEVICE, we sort of hope that
// between the QUERY_STOP IRP arrive and actual STOP IRP arriving
// that any in-progress I/O will complete of its own accord.
// We like this scheme, particularly because at least on NT
// during startup the device seems to get lots of QUERY_STOP
// IRPs, that are just followed by CANCEL_STOP. Thus, we think
// it would be unfortunate to do anything radical with the
// outstanding requests (like cancel them) when we receive a
// QUERY_STOP.
//
case (STATE_STARTED + IRP_MN_QUERY_STOP_DEVICE): {
//
// See if we're OK with stopping the device at this point.
// We do NOT actually RETURN the resources here... we
// just affirm or deny that we're OK with returning them.
//
status = OsrCanStopDevice(devExt, Irp);
if (!NT_SUCCESS(status)) {
//
// Nope...We can't stop the device
// so there's no need to pass it
// down to see if anyone else can stop.
// Just complete the Irp and return...
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
return status;
}
//
// We're cool with being stopped.
//
//
// Power the device up if it isn't already.
// Do this before changing the device's
// PnP state.
//
SSPowerDeviceIfSuspended(devExt);
//
// If enabled, disable selective suspend. We'll
// enable it again if we get a cancel.
//
DisableSelectiveSuspend(devExt);
//
// Set new state. This state results in no new
// requests being started on the device, but incoming
// requests are still allowed and queued.
//
OsrUpdateDeviceState(devExt, STATE_STOP_PENDING);
//
// Wait until all active requests on the device have
// completed so that we can return our resources
// in the STOP case.
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrWaitForStop(devExt);
//
// Replace status code that's in the IRP to indicate our
// opinion about stopping the device. If we're
// OK with being stopped this HAS to be
// STATUS_SUCCESS.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// Pass this request on down to the next driver
//
IoSkipCurrentIrpStackLocation(Irp);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
status = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
return status;
}
//
// STATE: STOP_PENDING
// IRP_MN: _CANCEL_STOP_DEVICE
//
// We're here because we've already received a QUERY_STOP,
// that we've agreed to. We've completed any pending I/O
// requests. Now we've received a CANCEL_STOP_DEVICE
// IRP, that says "never mind" about that stop.
//
// We (hopefully) restart our queues and return to Started state.
//
case (STATE_STOP_PENDING + IRP_MN_CANCEL_STOP_DEVICE): {
//
// OK, so we're not going to be stopped...
//
//
// This is a BUS FIRST Irp.
//
status = OsrForwardIrpSynchronous(devExt,Irp);
if (NT_SUCCESS(status)) {
//
// We're now back to a STARTED state
//
OsrUpdateDeviceState(devExt, STATE_STARTED);
status = STATUS_SUCCESS;
//
// Start processing any I/O that may have
// been queued due to the QUERY_STOP...
//
OsrProcessQueuedRequests(devExt);
} else {
//
// EEP! This is a fatal error if you're running
// verifier. We'll print out and hope the
// machine stays standing. If a debugger is attached
// we'll break into it...
//
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_PNP_INFO,
("OsrPnp: A device in the stack has FAILED CANCEL_STOP!! Returned status 0x%8.8x (%s)\n",
Irp->IoStatus.Status, OsrNtStatusToString(Irp->IoStatus.Status)));
//
// Use KdBreakPoint instead of DbgBreakPoint so that
// we only break in the checked build...
//
KdBreakPoint();
}
//
// Re-enable selective suspend (if enabled)
//
EnableSelectiveSuspend(devExt);
//
// Put the Completion Status into the Irp.
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
//
// OsrForwardIrpSynchronous is just a nice little
// wrapper that sets a completion routine, calls
// the next lowest driver, waits, and then reclaims the Irp
// for us in the completion routine by returning
// STATUS_MORE_PROCESSING_REQUIRED (or calls
// IoForwardIrpSynchronously to do all of that if
// we're built for XP and later). Just as if we
// had carried these steps out by ourselves, we now
// own the Irp and need to call IoCompleteRequest on it
// to finish processing.
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("OsrPnp: Finished! Leaving with state %s\n",
OsrPrintState(devExt)));
return status;
}
//
// STATE: STOP_PENDING
// IRP_MN: _STOP_DEVICE
//
// We're in this state because we previously received a
// QUERY_STOP_DEVICE, that we agreed that we could grant.
// Thus, we're waiting to receive a STOP_DEVICE request.
// To process this request, we first wait for any in-progress
// requests to complete (note that no NEW requests have been
// started since the transition to STOP_PENDING state as a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -