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

extern WCHAR            gSradxbVersion[];

// 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" ) );

    SraDriverUnload(pDriverObject);
	
#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\\sradxb.log" );
    DigiDebugInitEx( pRegistryPath, 
                     DIGIPOWER|DIGIPNPCHILD|DIGIPNP|DIGICONFIG|DIGIINIT|DIGIINITLOUD|DIGIWARN|DIGIERROR|DIGIBREAK, DEBUGMODE_CONSOLE,
                     "sradxb",gSradxbVersion);

//	DigiDebugInit( pRegistryPath, DIGIWARN|DIGIERROR|DIGIBREAK, DEBUGMODE_CONSOLE );
#if DBG
    SRAPRINT(SRA_LOW_LEVEL,
             ( "SraDxb!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 ) ) {
        SRAPRINT(SRA_LOW_LEVEL,("Failed Driver Entry(DigiStrAllocUnicodeString) before Stratus Calls\n"));
        goto Exit;

    }


    Status = DigiRegOpenKey( &hKeyDriver, pRegistryPath->Buffer );
    if ( NT_ERROR( Status ) ) {
        SRAPRINT(SRA_LOW_LEVEL,("Failed Driver Entry(DigiRegOpenKey) before Stratus Calls\n"));
        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 ) )
        {
            SRAPRINT(SRA_LOW_LEVEL,("Failed DigiStrAllocUnicodeString in Driver Entry\n"));
            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 ) ) {
        SRAPRINT(SRA_LOW_LEVEL,("Failed Driver Entry (!DigiRegOpenKey) before Stratus Calls\n"));
        goto Exit;
    }

    Status = dxbStartAllAdapters( hKeyDriver, hKeyServices );
#endif

#ifdef STRATUS_DEVICE
    if ( NT_ERROR( Status ) ) {
        SRAPRINT(SRA_LOW_LEVEL,("DXB failed Driver Entry exiting driver entry \n"));
        goto Exit;
    }


    Status = SraDriverEntry(DriverObject, pRegistryPath);
    if ( NT_ERROR( Status ) ) {
        SRAPRINT(SRA_LOW_LEVEL,("Failed Driver Entry -SraDriverEntry\n"));
        goto Exit;
    }
#endif

 Exit:

    if ( hKeyServices )
        DigiRegCloseKey( hKeyServices );

    if ( hKeyDriver )
        DigiRegCloseKey( hKeyDriver );

    if( NT_ERROR( Status ) )
    {
        SRAPRINT(SRA_LOW_LEVEL,("Failing Driver Entry1\n"));
        DigiStrFreeUnicodeString( &gDriverRegPath );
        MemPrintQuit();
        DigiDisplayMemoryLeaks();
    }

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

    return( Status );
}
