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

📄 driverpn.c

📁 profibus-dp主站源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      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 + -