/*++
*********************************************************************************
* Copyright (c) 1990-99 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:

   Pnp.c

Abstract:

   This module contains DSTREAMS provider Common Plug and Play Function.

Author:

   Jeff Romatoski

--*/

#include "Digilib.h"    // defines NT5_BUILD

#if NT5_BUILD

#include "Pnp.h"
#include "DsPnP.h"



// Globals
PNP_DRIVER_DATA		gDriverData;



NTSTATUS
DsPnpInitialize(
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PPNP_INIT_DATA	InitializationData
    )

/*++

Routine Description:

    This routine is called by a class driver during its
    DriverEntry routine to initialize the driver.

Arguments:

    PDRIVER_OBJECT     - Driver Object.
    InitializationData - Device-specific driver's initialization data.

Return Value:

    A valid NTSTATUS code.

--*/

{

    NTSTATUS	status = STATUS_SUCCESS;

    PAGED_CODE();

	DigiDump(DEBUG_DIGIPNP, ( "DsPnpInitialize:  %08x\n", DriverObject ) );

    // Copy the initialization data into the global driver object

    RtlCopyMemory(
        &(gDriverData.InitData),
        InitializationData,
        sizeof(PNP_INIT_DATA));

	gDriverData.DriverObject = DriverObject;

    return status;
}


NTSTATUS
DsPnpAddDevice( 
	IN	PDRIVER_OBJECT		pDriverObject,
	IN	PDEVICE_OBJECT		pFunctionalDeviceObject,
	IN	PDEVICE_OBJECT		pPhysicalDeviceObject,
	IN	PUNICODE_STRING		pucInstance,
	IN	PUNICODE_STRING		pucDeviceName,
	OUT PPPNP_FDO_EXTENSION	ppfdoExtension
    )

/*++

Routine Description:

    This routine is called by a class driver during its
    DriverEntry routine to initialize the driver.

Arguments:

    PDRIVER_OBJECT   - Driver Object.
    PDEVICE_OBJECT	 - The Lower Level Device to Attach to.

Return Value:

    A valid NTSTATUS code.

--*/

{
	PPNP_FDO_EXTENSION		pfdoExtension;
	NTSTATUS				Status = STATUS_SUCCESS;

	// Initialize the output pointer
	*ppfdoExtension = (PPNP_FDO_EXTENSION) NULL;

	// Now we will create an FDO Extension for the Driver FDO.
	pfdoExtension = DigiAllocMem( NonPagedPool, sizeof(PNP_FDO_EXTENSION) );

	if (pfdoExtension)
	{

		pfdoExtension->pDriverFdo	= pFunctionalDeviceObject;
		pfdoExtension->pPdo			= pPhysicalDeviceObject;
		pfdoExtension->DeviceType	= PNP_DEVICE_TYPE_FDO;
		pfdoExtension->PnpState		= PNP_ADDED;

		// Initialize the Power State
		{
			POWER_STATE State;
			State.DeviceState = pfdoExtension->PowerState = PowerDeviceD0;
			(void)PoSetPowerState( pfdoExtension->pDriverFdo, DevicePowerState, State );
		}

		pFunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

		// Set both PDO and FDO PAGABLE flags.  This forces SET_POWER apis to be called
		// at PASSIVE_LEVEL rather than DISPATCH_LEVEL.
		pFunctionalDeviceObject->Flags |= DO_POWER_PAGABLE;
		pPhysicalDeviceObject->Flags   |= DO_POWER_PAGABLE;

		// Attach the FDO to the PDO (Build the Device Stack)
		pfdoExtension->pNextDeviceObject = IoAttachDeviceToDeviceStack( pFunctionalDeviceObject, pPhysicalDeviceObject );

		// Save the Instance Name
		pfdoExtension->Instance.Buffer			= pfdoExtension->InstanceBuffer;
		pfdoExtension->Instance.MaximumLength	= sizeof pfdoExtension->InstanceBuffer;
		pfdoExtension->Instance.Length			= 0;
		RtlAppendUnicodeStringToString( &pfdoExtension->Instance, pucInstance );

		// Save the Device Name
		pfdoExtension->DeviceName.Buffer		= pfdoExtension->DeviceNameBuffer;
		pfdoExtension->DeviceName.MaximumLength	= sizeof pfdoExtension->DeviceNameBuffer;
		pfdoExtension->DeviceName.Length		= 0;
		RtlAppendUnicodeStringToString( &pfdoExtension->DeviceName, pucDeviceName );

		DigiInitializeSpinLock( &pfdoExtension->ChildListLock );
		InitializeListHead( &pfdoExtension->ChildListHead );

		DigiDump( DEBUG_DIGIPNP, ( "DsPnp!DsPnpAddDevice: DriverObject 0x%x, PDO  0x%x\n"
								 "               FDO 0x%x, FDO Extension 0x%x\n"
								 "               NextLowerDevice 0x%x\n"
								 "               Instance %S\n"
								 "               Status 0x%x\n",
								 pDriverObject, pPhysicalDeviceObject, 
								 pFunctionalDeviceObject, pfdoExtension, 
								 pfdoExtension->pNextDeviceObject, 
								 pfdoExtension->Instance.Buffer, 
								 Status ) );


		*ppfdoExtension = pfdoExtension;

	}
	else
	{
		Status = STATUS_INSUFFICIENT_RESOURCES;
	}

	return Status;
}

#endif // NT5_BUILD
