/*++
*******************************************************************************
* Copyright (c) 1990-98 Digi International Inc., All Rights Reserved			*
* 																				*
* This software contains proprietary and confidential information of Digi		*
* International Inc.  By accepting transfer of this copy, Recipient agrees		*
* to retain this software in confidence, to prevent disclosure to others,		*
* and to make no use of this software other than that for which it was			*
* delivered.  This is an unpublished copyrighted work of Digi International		*
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly		*
* prohibited.																	*
* 																				*
* Restricted Rights Legend														*
*																				*
* Use, duplication, or disclosure by the Government is subject to				*
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in			*
* Technical Data and Computer Software clause at DFARS 252.227-7031 or			*
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -			*
* Restricted Rights at 48 CFR 52.227-19, as applicable.							*
*																				*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343			*
*																				*
*******************************************************************************

  Module Name:

   power.c

Abstract:

   This module contains handler routines for IRP_MJ_POWER requests.

Author:

   Jeff Romatoski

--*/

#define UNICODE
#include <ntddk.h>

// Streams Headers
#include "types.h"
#include "wan_proto.h"
#include "wan_control.h"
 
#include "dsapi.h"
#include "dsioctl.h"
#include "dsmp.h"
#include "dgsna.h"
#include "ioctls.h"
#include "power.h"
#include "pnp.h"

#include "digilib.h"
#include "dxbreg.h"

#if NT5_BUILD


NTSTATUS
DgSnaPowerFdo(
	PPORT_EXT				pFdoExt,
	PIRP					pIrp, 
	PIO_STACK_LOCATION		pIos
	)
/*++

Description:

	Dispatch routine for all adapter FDO related Power requests.

Parameters:

	pFdoExt
		Device extension for our FDO which describes the adapter.
	
	pIrp
		Request.

	pIos
		Parameters passed along with Irp.

Return Value:

	STATUS_SUCCESS, or some error value.  If failing the request, do not forward to 
	lower driver!

--*/
{
	ULONG const Minor	= pIos->MinorFunction;
	NTSTATUS Status		= STATUS_SUCCESS;

	switch ( Minor )
	{
		case IRP_MN_SET_POWER:
			
			switch ( pIos->Parameters.Power.Type )
			{
				case SystemPowerState:

					DigiDump( DIGIPNP, ( "DIGISNA!DgSnaDevicePower:  Current SystemPowerState = %s\n",
										DigiGetPowerSystemState(pIos->Parameters.Power.State.SystemState)));

					switch ( pIos->Parameters.Power.State.SystemState )
					{
						case PowerSystemWorking:
						{
							if ( pFdoExt->PowerState != PowerDeviceD0 )
							{
								// Transition from power off to power on.  Startup card
								POWER_STATE NewState;
								ASSERT( pFdoExt->PowerState == PowerDeviceD3 );// We only use two power states!
								NewState.DeviceState = pFdoExt->PowerState = PowerDeviceD0;
								// NOTE: DigiPowerComplete forwards (and completes) the Irp, don't do it here!
								Status = PoRequestPowerIrp( pFdoExt->pPdo,
															IRP_MN_SET_POWER,
															NewState,
															DigiPowerComplete,
															pIrp,
															NULL );
							}
							else
							{
								PoStartNextPowerIrp( pIrp );
								DgSnaIoCompleteRequest( pIrp, Status, 0 );
							}
							break;
						}

						case PowerSystemSleeping1:
						case PowerSystemSleeping2:
						case PowerSystemSleeping3:
						case PowerSystemHibernate:
						{
							// Transition from power on to power off.  Shutdown card.
							if ( pFdoExt->PowerState == PowerDeviceD0 )
							{
								POWER_STATE NewState;
								NewState.DeviceState = pFdoExt->PowerState = PowerDeviceD3;
								// NOTE: dxbPowerComplete forwards the Irp, don't do it here!
								Status = PoRequestPowerIrp( pFdoExt->pPdo,
															IRP_MN_SET_POWER,
															NewState,
															DigiPowerComplete,
															pIrp,
															NULL );
							}
							else
							{
								PoStartNextPowerIrp( pIrp );
								DgSnaIoCompleteRequest( pIrp, Status, 0 );
							}
							break;
						}

						case PowerSystemShutdown:
							Status = DigiPowerForwardIrp( pFdoExt->pNextDeviceObject, pIrp );
							break;

						default:
							DigiDump( DIGIPNP, ( "*** DIGISNA!DgSnaPowerSetFdo: Invalid PowerSystem state 0x%x! ***\n",
													pIos->Parameters.Power.State.SystemState ) );
							Status = DigiPowerForwardIrp( pFdoExt->pNextDeviceObject, pIrp );
							break;
					}
					break;

				case DevicePowerState:

					DigiDump( DIGIPNP, ( "DIGISNA!DgSnaDevicePower: DevicePowerState = %s\n",
												DigiGetPowerDeviceState(pIos->Parameters.Power.State.DeviceState) ) );

					switch ( pIos->Parameters.Power.State.DeviceState )
					{
						case PowerDeviceD0:
							Status = DigiPowerForwardIrpWait( pFdoExt->pNextDeviceObject, pIrp );
							(void)DgSnaFdoStartDevice( pFdoExt, NULL, NULL );	
							PoStartNextPowerIrp( pIrp );
							DgSnaIoCompleteRequest( pIrp, Status, 0 );
							break;

						case PowerDeviceD1:
						case PowerDeviceD2:
						case PowerDeviceD3:
							(void)DgSnaFdoStopDevice( pFdoExt, NULL, NULL );
							Status = DigiPowerForwardIrp( pFdoExt->pNextDeviceObject, pIrp );
							break;

						default:
							Status = DigiPowerForwardIrp( pFdoExt->pNextDeviceObject, pIrp );
							break;
					}
					break;

				default:
					DigiDump( DIGIPNP, ( "*** DIGISNA!DgSnaPowerSetFdo: Invalid Power.Type 0x%x! ***\n",
												pIos->Parameters.Power.Type ) );
					Status = DigiPowerForwardIrp( pFdoExt->pNextDeviceObject, pIrp );
					break;
			}
			break;

		case IRP_MN_QUERY_POWER:
			switch ( pIos->Parameters.Power.Type )
			{
				case SystemPowerState:
					DigiDump( DIGIPNP, ( " DIGISNA!DgSnaPowerSetFdo: QueryPower - SystemPowerState = %s\n",
												DigiGetPowerSystemState(pIos->Parameters.Power.State.SystemState) ) );
					break;

				case DevicePowerState:
					DigiDump( DIGIPNP, ( " DIGISNA!DgSnaPowerSetFdo: QueryPower - DevicePowerState = %s\n",
												DigiGetPowerDeviceState(pIos->Parameters.Power.State.DeviceState) ) )
					break;
			}
			Status = DigiPowerForwardIrp( pFdoExt->pNextDeviceObject, pIrp );
			break;

		case IRP_MN_WAIT_WAKE:
		case IRP_MN_POWER_SEQUENCE:
		default:
			DigiDump( DIGIPNP, ( "DIGISNA!DgSnaPowerSetFdo: Passing unhandled Power Irp %s on to PDO!\n",
										DigiGetPowerIrpName( Minor ) ) );
			Status = DigiPowerForwardIrp( pFdoExt->pNextDeviceObject, pIrp );
			break;
	}

	if ( !NT_SUCCESS( Status ) )
	{
		DigiDump( DIGIPNP, ( "DIGISNA!DgSnaPowerFdo: %s, returning status 0x%x\n", DigiGetPowerIrpName(Minor), Status ) );
	}
	return Status;

}


NTSTATUS
DgSnaDevicePower(
	IN PDEVICE_OBJECT pDevice,
	IN PIRP           pIrp
	)
/*++

Description:

	The primary dispatch routine for IRP_MJ_POWER requests.

Parameters:

	Standard NT Dispatch routine parameters.

Return Value:

	STATUS_SUCCESS if request completed successfully.

--*/
{
	PPORT_EXT			pFdoExt = (PPORT_EXT) pDevice->DeviceExtension;
	PIO_STACK_LOCATION	pIos	= IoGetCurrentIrpStackLocation( pIrp );
	ULONG				Minor	= pIos->MinorFunction;
	NTSTATUS			Status;

	DigiDump( DIGIPNP, ( "DIGISNA!DgSnaDevicePower: Enter, %s, pFdoExt 0x%08x, pIrp 0x%08x\n", 
	          DigiGetPowerIrpName(Minor),
	          pFdoExt,
			  pIrp ) );

	// All Current Digi Sna Devices are FDO's.  Go Process the Irp.
	Status = DgSnaPowerFdo( pFdoExt, pIrp, pIos );


	DigiDump( DIGIPNP, ( "DIGISNA!DgSnaDevicePower: Leave %s, pFdoExt 0x%08x, pIrp 0x%08x, Status 0x%x\n",
							 DigiGetPnpIrpName(Minor), 
							 pFdoExt,
							 pIrp,
							 Status ) );
	return Status;
}


#endif