/*++
*******************************************************************************
* 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:

   digidxb.c

Abstract:

   This module contains required NT kernelmode driver entry and unload routines.
	Also any driver global data.

Author:

   Michael Zarns

--*/
#include "digidxb.h"

// Pointer to DriverObject.  Set in DriverEntry.
PDRIVER_OBJECT gpDriverObject;

// List of device extensions.  Built in DriverEntry, freed in DxbUnload.
LIST_ENTRY gDeviceExtList = {&gDeviceExtList, &gDeviceExtList};

// Global driver registry path.  Set in DriverEntry, freed in DxbUnload.
UNICODE_STRING gDriverRegPath = {0};

// Default pool tag for ExAllocatePoolWithTag memory allocations
ULONG DefaultPoolTag = (ULONG)('igiD');


STATIC VOID
DriverUnload(
	PDRIVER_OBJECT pDriverObject )
/*++

Description:

	Last chance to cleanup before driver is unloaded.  Everything alloc'd, created,
	or started in DriverEntry or otherwise should be freed, destroyed or stopped.

Parameters:

	pDriverObject
		The driver object for this driver.

Return Value:

	None

--*/
{
	UNREFERENCED_PARAMETER( pDriverObject );
	DigiDump( DIGIINIT,  ( "DXB!DxbUnload\n" ) );

#if !NT5_BUILD
	while ( !IsListEmpty( &gDeviceExtList ) )
	{
		PLIST_ENTRY pEntry;
		PDXB_DEVICE_EXTENSION pExt;

		pEntry = RemoveHeadList( &gDeviceExtList );

		pExt = CONTAINING_RECORD( pEntry, DXB_DEVICE_EXTENSION, ExtListEntry );
		ASSERT( pExt->Type == DXB_TYPE_DEVICE_EXT );

		pExt->StopAdapter( pExt );
		IoUnregisterShutdownNotification( pExt->pDeviceObject );
		dxbDeleteDevice( pExt );
	}
#endif

	DigiStrFreeUnicodeString( &gDriverRegPath );

	MemPrintQuit();
	DigiDisplayMemoryLeaks();
}


STATIC BOOLEAN DigiDontLoadDriver = FALSE;

NTSTATUS DriverEntry( IN PDRIVER_OBJECT  DriverObject, 
                      IN PUNICODE_STRING pRegistryPath );
#pragma alloc_text( INIT, DriverEntry )

NTSTATUS
DriverEntry(
	IN PDRIVER_OBJECT  DriverObject,
	IN PUNICODE_STRING pRegistryPath )
/*++

Routine Description:

   Driver main entry point.  NT calls this routine when loading the driver.

Arguments:

   DriverObject
		Defines this driver

   pRegistryPath
   	Unicode string which defines the registry path for this driver's service key.
		Typically, ...\ControlSetXXX\Services\DigiDxb.

Return Value:

   STATUS_SUCCESS - If the driver was successfully loaded, or error.

--*/
{
	NTSTATUS Status;
	HANDLE hKeyDriver = NULL;
	HANDLE hKeyServices = NULL;

	DigiInitMem( 'bxdD' );
	MemPrintInitialize( "\\SystemRoot\\digidxb.log" );
	DigiDebugInit( pRegistryPath, DIGIPOWER|DIGIPNPCHILD|DIGIPNP|DIGICONFIG|DIGIINIT|DIGIINITLOUD|DIGIWARN|DIGIERROR|DIGIBREAK, DEBUGMODE_CONSOLE );
//	DigiDebugInit( pRegistryPath, DIGIWARN|DIGIERROR|DIGIBREAK, DEBUGMODE_CONSOLE );
#if DBG
	(void)DbgPrint( "\n"
	                "DXB!DriverEntry:\n"
	                "   gDebugMask         = 0x%x\n"
	                "   gDebugMode         = 0x%x\n"
	                "   DigiDontLoadDriver = 0x%x\n\n",
	                &gDebugMask, &gDebugMode, &DigiDontLoadDriver );
#endif
	gpDriverObject = DriverObject;

	Status = DigiStrAllocUnicodeString( &gDriverRegPath, pRegistryPath->Buffer, NULL, NULL );
	if ( NT_ERROR( Status ) )
		goto Exit;

	Status = DigiRegOpenKey( &hKeyDriver, pRegistryPath->Buffer );
	if ( NT_ERROR( Status ) )
		goto Exit;

	// Wanna break?
	if( DigiDbgBreakOnEntryEnabled() )
		DbgBreakPoint();

	if( DigiDontLoadDriver )
	{
		Status = STATUS_CANCELLED;
		goto Exit;
	}

	// IMPORTANT: Init the dispatch table before initializing the adapters.  In the
	// process of initializing adapters, send myself IRPs via this dispatch table.
	DriverObject->DriverUnload                          = DriverUnload;
	DriverObject->MajorFunction[IRP_MJ_CREATE]          = DxbDeviceCreate;
	DriverObject->MajorFunction[IRP_MJ_CLOSE]           = DxbDeviceClose;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = DxbDeviceIoControl;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP]         = DxbDeviceCleanup;
	DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]        = DxbDeviceShutdown;

#if NT5_BUILD
	DriverObject->MajorFunction[IRP_MJ_PNP]             = DxbDevicePnp;
	DriverObject->MajorFunction[IRP_MJ_POWER]           = DxbDevicePower;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL]  = DxbDeviceSystemControl;
	DriverObject->DriverExtension->AddDevice            = DxbAddDevice;
#else

	// Build a path to the Services registry key and open it
	{
		UNICODE_STRING Services;
		Status = DigiStrAllocUnicodeString( &Services, pRegistryPath->Buffer, NULL, NULL );
		if ( NT_SUCCESS( Status ) )
		{
			while ( (WCHAR)Services.Buffer[Services.Length/sizeof(WCHAR)] != (WCHAR)'\\' )
				Services.Length -= sizeof(WCHAR);
			Services.Buffer[Services.Length/sizeof(WCHAR)] = '\0';

			Status = DigiRegOpenKey( &hKeyServices, Services.Buffer );
			DigiStrFreeUnicodeString( &Services );
		}
	}

	if ( NT_ERROR( Status ) )
		goto Exit;

	Status = dxbStartAllAdapters( hKeyDriver, hKeyServices );
#endif

Exit:

	if ( hKeyServices )
		DigiRegCloseKey( hKeyServices );

	if ( hKeyDriver )
		DigiRegCloseKey( hKeyDriver );

	if( NT_ERROR( Status ) )
	{
		DigiStrFreeUnicodeString( &gDriverRegPath );
		MemPrintQuit();
		DigiDisplayMemoryLeaks();
	}

	DigiDump( DIGIINIT, ( "DigiDxb!DriverEntry: Leave, Status 0x%08x\n", Status ) );

	return( Status );
}
