//*****************************************************************************
//* FILE NAME:       w2k_pnp.c
//* FILE CONTAINS:
//* DESCRIPTION:     PnP support for Win 2000.
//* NOTES:           This file is used for Win 2000 only.
//*****************************************************************************
//*                   INTEL CORPORATION PROPRIETARY INFORMATION
//*     This software is supplied under the terms of a license agreement or
//*     nondisclosure agreement with Intel Corporation and may not be copied
//*     or disclosed except in accordance with the terms of that agreement.
//*           Copyright (c) 1995-2000 Intel Corporation.  All Rights Reserved.
//*****************************************************************************

//*****************************************************************************
//* INCLUDES
//*****************************************************************************

//-----------------------------------------------------------------------------
// Local Includes
//-----------------------------------------------------------------------------

#include "CompDiag.h"
#include "w2k_drv.h"
#include "w2k_pnp.h"
#include "DiagMsg.h"

//*****************************************************************************
//* FUNCTIONS
//*****************************************************************************

//=============================================================================
// gtDecodePnP_IRP(...)
//-----------------------------------------------------------------------------
// Decode PnP IRP
//
// Decode the PnP minor function IRP.  Called when PnP IRP is received.
//
// Arguments:
//
//    Minor Function Code - Specifies the specific minor function code.
//
//    Default Win 2000 Device Extension - This contains the info specific to
//    the Win 2000 implementation.
//
//    IRP pointer - This is the IRP to be decoded.
//
// Returns:
//
//    STATUS_SUCCESS if successful.
//=============================================================================

NTSTATUS gtDecodePnP_IRP
  (
   UCHAR                            aucMinorFuncCode,
   struct S_Win2000_DevExt         *astpFDO_DevExt,
   IN PIRP                          atpIRP
   )
  {
   NTSTATUS tStatus = STATUS_SUCCESS;

   atpIRP->IoStatus.Information  = 0;
   atpIRP->IoStatus.Status       = STATUS_SUCCESS;

   //--------------------------------------------------------------------------
   // Decode the PnP minor function code.
   //--------------------------------------------------------------------------

   switch (aucMinorFuncCode)
     {
      case IRP_MN_START_DEVICE: //---------------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_Stopped)
           { 
            D_DiagMsg0( D_Error,D_DC_Errors,"Expected device to be in stopped and "
                        "waiting for resources"
                        );

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         //--------------------------------------------------------------------
         // If interface class GUID was specified, then enable interface.
         //--------------------------------------------------------------------

         if (gtpInterfaceClassGUID)
   		   IoSetDeviceInterfaceState(&astpFDO_DevExt->tInterfaceSymLinkName,TRUE);

         astpFDO_DevExt->bPaused          = FALSE;
         astpFDO_DevExt->bDeviceConnected = TRUE;

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_Started;
         break;

      case IRP_MN_QUERY_REMOVE_DEVICE: //--------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_Started)
           { 
            D_DiagMsg0(D_Error,D_DC_Errors,"Expected device to be started");

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_RemovePending;
         break;

      case IRP_MN_REMOVE_DEVICE: //--------------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_RemovePending)
           { 
            D_DiagMsg0(D_Error,D_DC_Errors,"Expected device to be pending remove");

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         astpFDO_DevExt->bPaused          = TRUE;
         astpFDO_DevExt->bDeviceConnected = FALSE;
         astpFDO_DevExt->bRemoveDevice    = TRUE;

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_DeviceNotPresent;

         break;

      case IRP_MN_CANCEL_REMOVE_DEVICE: //-------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_RemovePending)
           { 
            D_DiagMsg0(D_Error,D_DC_Errors,"Expected device to be pending remove");

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         astpFDO_DevExt->bPaused          = FALSE;
         astpFDO_DevExt->bDeviceConnected = TRUE;

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_Started;
         break;

      case IRP_MN_QUERY_STOP_DEVICE: //----------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_Started)
           { 
            D_DiagMsg0(D_Error,D_DC_Errors,"Expected device to be started");

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         astpFDO_DevExt->bPaused          = TRUE;
         astpFDO_DevExt->bDeviceConnected = FALSE;

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_StopPending;
         break;

      case IRP_MN_STOP_DEVICE: //----------------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_StopPending)
           { 
            D_DiagMsg0(D_Error,D_DC_Errors,"Expected device to be pending stop");

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_Stopped;

         break;

      case IRP_MN_CANCEL_STOP_DEVICE: //---------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_StopPending)
           { 
            D_DiagMsg0(D_Error,D_DC_Errors,"Expected device to be pending stop");

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         astpFDO_DevExt->bPaused          = FALSE;
         astpFDO_DevExt->bDeviceConnected = TRUE;

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_Started;
         break;

      case IRP_MN_SURPRISE_REMOVAL: //-----------------------------------------

         if (astpFDO_DevExt->ePnP_DeviceState != E_PnP_State_Started)
           { 
            D_DiagMsg0(D_Error,D_DC_Errors,"Expected device to be started");

            atpIRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
            break;
            }

         astpFDO_DevExt->ePnP_DeviceState = E_PnP_State_SuprisedRemoved;

         break;

      //-----------------------------------------------------------------------
      // Don't qualify other PnP IRPs.
      //-----------------------------------------------------------------------

      case IRP_MN_QUERY_DEVICE_RELATIONS:
      case IRP_MN_QUERY_INTERFACE:
      case IRP_MN_QUERY_CAPABILITIES:
      case IRP_MN_QUERY_RESOURCES:
      case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
      case IRP_MN_QUERY_DEVICE_TEXT:
      case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:

      case IRP_MN_READ_CONFIG:
      case IRP_MN_WRITE_CONFIG:
      case IRP_MN_EJECT:
      case IRP_MN_SET_LOCK:
      case IRP_MN_QUERY_ID:
      case IRP_MN_QUERY_PNP_DEVICE_STATE:
      case IRP_MN_QUERY_BUS_INFORMATION:
      case IRP_MN_DEVICE_USAGE_NOTIFICATION:
         break;
      }

   //--------------------------------------------------------------------------
   // Pass on IRP to lower-level device object.  The PDO will pass the IRP to
   // The bus driver.
   //--------------------------------------------------------------------------

   IoSkipCurrentIrpStackLocation(atpIRP);

   tStatus = IoCallDriver(astpFDO_DevExt->tpLowerDeviceObject,atpIRP);

   return (tStatus);
   }
