⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driverpn.c

📁 profibus-dp主站源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      // do not have a set of hardware resources from the PnP Manager.
      //
      // The PnP Manager is now giving us a set of resources, and 
      // asking us to start the device.
      //
      // In this case, we pass the IRP all the way down.  When it's
      // done (and our completion routine is called) we can then
      // read the list of device resources pointed to in the IRP
      // Stack Location.
      //
    case STATE_STOPPED + IRP_MN_START_DEVICE:
    case STATE_NEVER_STARTED + IRP_MN_START_DEVICE:
      DbgPrint( "ProfiM PnP: DispatchPnp: PROCESSING START_DEVICE\n" );

      //
      // The BUS DRIVER handles this IRP before we do
      //
      IoCopyCurrentIrpStackLocationToNext( Irp );

      //
      // Call PnpComplete() when this IRP is done...
      //
      IoSetCompletionRoutine( Irp,
                              PnpComplete,
                              &eventWaitLowerDrivers,
                              TRUE,
                              TRUE,
                              TRUE );

      //
      // Send the IRP to the bus driver.  Let's see what HE
      // thinks.
      //
      code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );

      if ( STATUS_PENDING == code )
      {
        KeWaitForSingleObject( &eventWaitLowerDrivers,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );

        code = Irp->IoStatus.Status;
      }

      //
      // Can the bus driver do the start?
      //
      if ( NT_SUCCESS( code ) )
      {
        //
        // Yup.  Go initialize the device.  The CmResourceLists
        // are pointed to by the IoStackLocation.
        //
        code = StartDevice( devExt, ioStackLocation );

        //
        // If the our StartDevice function succeeded, the
        // device is now "officially" started!
        //
        if ( NT_SUCCESS( code ) )
        {
          devExt->State = STATE_STARTED;
        }
      }
      else
      {
        //
        // The bus driver has declined to start the device.
        // Oh well...
        //
#if PnP_DBG
        DbgPrint( "ProfiM PnP: DispatchPnp: IoCallDriver() for START fails! 0x%0x \n",
                  code );
#endif
      }

      //
      // We must now complete the IRP, since we stopped it in the
      // completetion routine with MORE_PROCESSING_REQUIRED.
      //
      Irp->IoStatus.Status = code;

      Irp->IoStatus.Information = 0;

      IoCompleteRequest( Irp, IO_NO_INCREMENT );

      break;



      //
      // STATE:   STARTED
      // IRP_MN:  _QUERY_REMOVE
      //
      // We're here because we're running, and the PnP Manager wants
      // to "nicely" remove our device.  This is the orderly way
      // PnP Manager handles device disconnections (as opposed to
      // doing a SURPRISE_REMOVAL).
      //
      // What we do here is (a) change the state of the device such
      // that newly arriving requests will be rejected, (b) wait for
      // all requests to complete on the device, and (c) pass the
      // request on down.
      //
    case STATE_STARTED + IRP_MN_QUERY_REMOVE_DEVICE:
#if PnP_DBG
      PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: PROCESSING QUERY_REMOVE_DEVICE\n" );
#endif
      //
      // WE process this request FIRST
      //

      //
      // See if we're OK with removing 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 = CanRemoveDevice( 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 remove 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
      {
#if PnP_DBG
        DbgPrint( "ProfiM PnP: DispatchPnp: Waiting for pending requests to complete. (%d. remain)\n",
                  devExt->OutstandingIO );
#endif

        //
        // Set new state -- This state results in any new
        // requests received at our dispatch entry points
        // being REJECTED... any request still on the queues
        // are allowed to complete, however.
        //
        devExt->State = STATE_REMOVE_PENDING;

        //
        // Decrement our reference on the device here, and then
        // wait until there are no requests active or on the
        // device's queues.
        //
        RequestDecrement( devExt );

        WaitForRemove( devExt );

        //
        // OK.  No further requests remain.  Let the bus driver
        // know.

        //
        // DECREMENTED REQUEST COUNT above.  Return immediately
        // below.
        //
#if PnP_DBG
        PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Leaving With state: " );
        PrintState( devExt );
        PB_DbgPrintL1( "\n" );
#endif
        //
        // Pass this request on down to the bus driver
        //
        IoSkipCurrentIrpStackLocation( Irp );

        return( IoCallDriver( devExt->DeviceToSendIrpsTo, Irp ) );
      }
      break;

      //
      // STATE:   REMOVE_PENDING
      // IRP_MN:  _REMOVE_DEVICE
      //
      // We're here because we've previously received notification
      // of the intention to remove the device in an orderly way.
      // We return our resources here, and then tear down our device
      // object.  Note that there can be no requests pending at this
      // point, because we finished them all during QUERY_REMOVE
      // processing (before entering RemovePending state)
      //
    case STATE_REMOVE_PENDING + IRP_MN_REMOVE_DEVICE:
      //
      // All queued and active IRPs are complete at this point.
      //

      //
      // Fall through...
      //

      //
      // STATE:   SURPRISE_REMOVED
      // IRP_MN:  _REMOVE_DEVICE
      //
      // We're here because we've previously received notification
      // of a "surprise" removal.  At this point, we just tear down
      // our device object
      //
    case STATE_SURPRISE_REMOVED + IRP_MN_REMOVE_DEVICE:
      //
      // Removing the device at this point is NOT optional.
      //
#if PnP_DBG
      DbgPrint( "ProfiM PnP: DispatchPnp: REMOVE_DEVICE\n" );
#endif

      //
      // Device has been removed
      //
      devExt->State = STATE_REMOVED;

      //
      // Return any resources we're using.
      //
      ReturnResources( devExt );

      //
      // Decrement our reference on the device here, and then
      // wait until we can remove the device.  Because we would
      // have gotten a prior warning of this removal (via an
      // IRP_MN_SUPRISE_REMOVAL or an IRP_MN_QUERY_REMOVE) and
      // at that time transitioned state appropriately, there
      // should be no requests outstanding here.
      //
      RequestDecrement( devExt );

#if PnP_DBG
      DbgPrint( "ProfiM PnP: DispatchPnp: Waiting for pending requests to complete. %d. remain\n",
                devExt->OutstandingIO );
#endif
      WaitForRemove( devExt );

      //
      // WE process this request first
      //

      // Remember next target of IRP
      targetDevice = devExt->DeviceToSendIrpsTo;

      //
      // Remove and return our device object
      //
      RemoveDevice( devExt->DeviceObject );

      //
      // Indidcate that we've successfully processed the IRP
      //
      Irp->IoStatus.Status = STATUS_SUCCESS;

      //
      // Pass this request on down to the bus driver
      //
      IoSkipCurrentIrpStackLocation( Irp );

      code = IoCallDriver( targetDevice, Irp );

      ASSERT( code != STATUS_PENDING );

      //
      // IMPORTANT: We decremented our I/O In Progress count
      // above... We don't want to decrement it again, so we
      // return right here.
      //
#if PnP_DBG
      PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Leaving with state: STATE_REMOVE\n" );
#endif
      return( code );

      break;

      //
      // STATE:   STARTED
      // IRP_MN:  _SURPRISE_REMOVAL
      //
      // We're here when the device is running, and a device is
      // forcibly removed.  PnP Manager will send us a remove device
      // IRP when we're supposed to actually return our resources
      // and the like.
      //
      // Note that this is a "best effort" activity.  It is quite
      // possible, due to timing issues etc, that we'll crash the
      // system because the device is gone.  While we'll TRY not
      // to do this, it is within the rules.
      //
      // THIS IRP IS NOT SENT ON Win9x.
      //
    case STATE_STARTED + IRP_MN_SURPRISE_REMOVAL:
      devExt->State = STATE_SURPRISE_REMOVED;

      //
      // We handle this request before the bus driver
      //

      //
      // Cancel any pending requests... make sure
      // the active requests get stopped within a second (with
      // no hardware access, as a result of setting the state
      // above).
      //
      ClearQueues( devExt );

      //
      // We're happy... sort of.  Note that it's not "legal"
      // to fail this request.  Afterall, what woudl that MEAN?
      //
      Irp->IoStatus.Status = STATUS_SUCCESS;

      //
      // Pass this request on down to the bus driver
      //
      IoSkipCurrentIrpStackLocation( Irp );

      code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );

      break;

      //
      // STATE:   STARTED
      // IRP_MN:  _REMOVE_DEVICE
      //
      // We're here when the device is running, and a device is
      // forcibly removed.
      //
      // Note that like getting a SUPRISE_REMOVAL IRP on NT trying
      // to handle a removal directly from started state is a "best
      // effort" type of activity.  We'll do what we can but it's
      // possible, due to timing issues etc, that we'll crash the
      // system because the device is gone.  While we'll TRY not
      // to do this, it could be unavoidable.  Oh well.
      //
      // ON NT, we'd get an IRP_MN_SURPRISE_REMOVAL instead of this
      // IRP in this state.  We get this only on Win9x systems.
      //
    case STATE_STARTED + IRP_MN_REMOVE_DEVICE:
#if PnP_DBG
      DbgPrint( "ProfiM PnP: DispatchPnp: REMOVE_DEVICE\n" );
#endif
      devExt->State = STATE_REMOVED;

      //
      // We handle this request before the bus driver
      // Note that this is another one of those requests we're
      // not "allowed" to fail.
      //

      //
      // Cancel any pending requests... make sure
      // the active requests get stopped within a second (with
      // no hardware access, as a result of setting the state
      // above).
      //
      ClearQueues( devExt );

      //
      // Return any resources we're using.
      //
      ReturnResources( devExt );

      //
      // Removing the device at this point is NOT optional.
      //

      //
      // Detach from the PDO 
      //
      IoDetachDevice( devExt->DeviceToSendIrpsTo );
      targetDevice = devExt->DeviceToSendIrpsTo;
      devExt->DeviceToSendIrpsTo = NULL;

      //
      // Decrement our reference on the device here, and then
      // wait until we can remove the device.
      //
      RequestDecrement( devExt );

#if PnP_DBG
      PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Waiting for pending requests to complete. %d. remain\n",
                     devExt->OutstandingIO );
#endif

      WaitForRemove( devExt );

      //
      // OK!  Now we can return our device object
      //
      RemoveDevice( devExt->DeviceObject );

      //
      // Tell the underlying driver we're cool
      //
      Irp->IoStatus.Status = STATUS_SUCCESS;

      //
      // Pass this request on down to the bus driver
      //
      IoSkipCurrentIrpStackLocation( Irp );

      code = IoCallDriver( targetDevice, Irp );

      ASSERT( code != STATUS_PENDING );

      //
      // IMPORTANT: We decremented our I/O In Progress count
      // above... We don't want to decrement it again, so we
      // return right here.
      //
#if PnP_DBG
      PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Leaving with state: STATE_REMOVED\n" );
#endif
      return( code );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -