📄 driverpn.c
字号:
break;
//
// 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
// hardware resources that were allocated for us when we got
// 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:
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: PROCESSING QUERY_STOP_DEVICE\n" );
#endif
//
// WE process this request before the BUS DRIVER
//
//
// 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.
//
code = CanStopDevice( devExt, Irp );
//
// Replace status code that's in the IRP to indicate our
// opinion about stopping the device. If we're
// OK with returning the resources, this will be
// STATUS_SUCCESS.
//
Irp->IoStatus.Status = code;
if ( !NT_SUCCESS( code ) )
{
//
// NOPE. Can't stop the device because, for some
// reason (perhaps because we can't return our
// resources). Too bad. Tell the PnP Manager that
// stopping right now is not an option for us.
//
// NOTE: NO NEED to pass IRP down if WE can't stop
// it doesn't matter if the Bus Driver can.
//
IoCompleteRequest( Irp, IO_NO_INCREMENT );
}
else
{
//
// We CAN stop our device and return the resources.
// Pass the IRP down to see if the bus driver is
// equally ammenable to the request.
//
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Agreeing to stop device.\n" );
#endif
//
// Set new state. This state results in no new
// requests being started on the device, but incoming
// requests are still allowed and queued.
//
devExt->State = STATE_STOP_PENDING;
//
// Pass this request on down to the bus driver
//
IoSkipCurrentIrpStackLocation( Irp );
code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );
}
break;
//
// 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
// result of receiving the QUERY_STOP IRP). After all in-
// progress requests are complete, we return our resources
// and wait for further instructions from the PnP Manager (
// which better include a START_DEVICE someplace down the line!).
//
// While in this state, any IRPs we receive will be queued
// for processing after we get the START_DEVICE.
//
case STATE_STOP_PENDING + IRP_MN_STOP_DEVICE:
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: PROCESSING STOP_DEVICE\n" );
#endif
//
// Assume success
//
devExt->State = STATE_STOPPED;
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: Waiting for in-progress requests to complete\n" );
#endif
//
// We process this request before passing it to the bus
// driver
//
//
// Wait until all active requests on the device have
// completed...
//
WaitForStop( devExt );
//
// There are NO ACTIVE IRPs on the device at this point.
//
//
// Return any resources we're using.
//
ReturnResources( devExt );
//
// NOTE: We DO NOT delete our device object here. This is
// one difference between a _STOP_DEVICE and _REMOVE_DEVICE.
//
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Passing along request\n" );
#endif
//
// Pass this request on down to the bus driver
//
IoSkipCurrentIrpStackLocation( Irp );
//
// We're cool with the stop...
//
Irp->IoStatus.Status = STATUS_SUCCESS;
code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );
break;
//
// 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 sort of says "never mind" about that stop.
//
// We restart our queues and return to Started state.
//
case STATE_STOP_PENDING + IRP_MN_CANCEL_STOP_DEVICE:
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: PROCESSING CANCEL_STOP\n" );
#endif
//
// fall through...
//
//
// STATE: REMOVE_PENDING
// IRP_MN: _CANCEL_REMOVE_DEVICE
//
// We're here because we've already received a QUERY_REMOVE,
// that we've agreed to. We've completed any pending I/O
// requests. Now we've received a CANCEL_REMOVE_DEVICE
// IRP, that sort of says "never mind" about that remove.
//
// We restart our queues and return to Started state.
//
case STATE_REMOVE_PENDING + IRP_MN_CANCEL_REMOVE_DEVICE:
#if PnP_DBG
if ( devExt->State == STATE_REMOVE_PENDING )
{
DbgPrint( "ProfiM PnP: DispatchPnp: PROCESSING CANCEL_REMOVE\n" );
}
#endif
//
// The Underlying BUS DRIVER must handle these IRPs
// before we do...
//
//
// We need to wait for the underlying bus driver to
// get restarted, before we can continue processing.
//
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp,
PnpComplete,
&eventWaitLowerDrivers,
TRUE,
TRUE,
TRUE );
code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );
if ( code == STATUS_PENDING )
{
KeWaitForSingleObject( &eventWaitLowerDrivers,
Executive,
KernelMode,
FALSE,
NULL );
}
//
// We're now in STARTED state
//
devExt->State = STATE_STARTED;
//
// Go see if there's a request that we can start now
//
ProcessQueuedRequests( devExt );
code = STATUS_SUCCESS;
Irp->IoStatus.Status = code;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
break;
default:
//
// DEFAULT CASE
// Just pass the request to the lower driver
//
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Default case: Just pass it along...\n" );
#endif
IoSkipCurrentIrpStackLocation( Irp );
code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );
break;
}
//
// Adjust in-progress request count
//
RequestDecrement( devExt );
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Leaving with new state " );
PrintState( devExt );
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: exit (%d.).\n",
devExt->OutstandingIO );
#endif
//
// We always finish our work in this function
//
ASSERT( code != STATUS_PENDING );
return( code );
}
//
// PnpComplete
//
// This is the completion routine for IRP_MJ_PNP requests
//
NTSTATUS PnpComplete( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
{
PIO_STACK_LOCATION iostack;
PKEVENT pEvent = ( PKEVENT ) Context;
NTSTATUS status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER( DeviceObject );
iostack = IoGetCurrentIrpStackLocation( Irp );
//
// Driver Writers, please note:
//
// The following code is only necessary IF (a) WE have a completion
// routine, AND (b) WE return STATUS_PENDING from our dispatch entry
// point after re-claiming the IRP. Since neither of these things
// is true... this code does not belong here.
//
// if (Irp->PendingReturned) {
//
// IoMarkIrpPending( Irp );
//
// }
switch ( iostack->MajorFunction )
{
case IRP_MJ_PNP:
KeSetEvent( pEvent, 0, FALSE );
//
// Take the IRP back so that we can continue using it during
// the IRP_MN_START_DEVICE dispatch routine.
// NB: we will have to call IoCompleteRequest
//
return STATUS_MORE_PROCESSING_REQUIRED;
break;
case IRP_MJ_POWER:
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: PnpComplete: NOT MJ_POWER support in this driver!\n" );
#endif
break;
default:
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: PnpComplete: NOT MJ_PNP or MJ_POWER IRP??\n" );
#endif
break;
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// StartDevice
//
// This function is called from the DispatchPnp Entry Point to
// actually start the hardware.
//
// INPUTS:
//
// DevExt - Address of our device extension.
// IoStackLocation -- Pointer to I/O Stack Location containing
// configuration information
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_SUCCESS;
//
// IRQL:
//
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS StartDevice( IN PPROFIM_DEVICE_EXTENSION DevExt,
IN PIO_STACK_LOCATION IoStackLocation )
{
NTSTATUS code = STATUS_SUCCESS;
ULONG index;
PDEVICE_DESCRIPTION deviceDescription;
PCM_RESOURCE_LIST pResourceList, pResourceListTranslated;
PCM_PARTIAL_RESOURCE_LIST prl, prlTranslated;
PCM_PARTIAL_RESOURCE_DESCRIPTOR prd, prdTranslated;
PCM_FULL_RESOURCE_DESCRIPTOR frd, frdTranslated;
HANDLE regKeyHandle;
PWCHAR dpHWID;
ULONG dpHWID_len;
PWCHAR pwc;
pci_device_id_t *device_id;
int ChipOptions = 0;
ULONG ProfiMBaudrate = 19200;
ULONG ProfiMMyAddress = 2;
ULONG Data;
int i;
if ( !DevExt )
{
DbgPrint( "PnP: StartDevice Error - DeviceExtension is NULL!" );
return STATUS_UNSUCCESSFUL;
}
if ( DevExt->magic != PROFIM_MAGIC )
{
DbgPrint( "PnP: StartDevice Error - Device Extension MAGIC is invalid!" );
return STATUS_UNSUCCESSFUL;
}
pResourceList = IoStackLocation->Parameters.StartDevice.AllocatedResources;
pResourceListTranslated = IoStackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
frd = &pResourceList->List[0];
frdTranslated = &pResourceListTranslated->List[0];
prl = &frd->PartialResourceList;
prlTranslated = &frdTranslated->PartialResourceList;
#if PnP_DBG
PrintResourceList( pResourceList );
PrintResourceList( pResourceListTranslated );
#endif
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -