|
|
/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
driver.c
Abstract:
ATMEPVC - Driver Entry and associated functions
Author:
Revision History:
Who When What -------- -------- ---- ADube 03-23-00 created, .
--*/
#include "precomp.h"
#pragma hdrstop
#pragma NDIS_INIT_FUNCTION(DriverEntry)
//
// temp global variables
//
NDIS_HANDLE ProtHandle, DriverHandle;
//
// global variables
//
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); NDIS_HANDLE ProtHandle = NULL; NDIS_HANDLE DriverHandle = NULL; NDIS_MEDIUM MediumArray[1] = { NdisMediumAtm };
LIST_ENTRY g_ProtocolList; EPVC_GLOBALS EpvcGlobals;
RM_STATUS epvcResHandleGlobalProtocolList( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr );
RM_STATUS epvcRegisterIMDriver( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr );
RM_STATUS epvcUnloadDriver( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr );
RM_STATUS epvcDeRegisterIMDriver( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr );
RM_STATUS epvcIMDriverRegistration( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr );
//--------------------------------------------------------------------------------
// //
// Global Root structure definitions //
// //
// //
//--------------------------------------------------------------------------------
// List of fixed resources used by ArpGlobals
//
enum { RTYPE_GLOBAL_PROTOCOL_LIST, RTYPE_GLOBAL_REGISTER_IM }; // EPVC_GLOBAL_RESOURCES;
//
// Identifies information pertaining to the use of the above resources.
// Following table MUST be in strict increasing order of the RTYPE_GLOBAL
// enum.
//
RM_RESOURCE_TABLE_ENTRY EpvcGlobals_ResourceTable[] = {
{RTYPE_GLOBAL_PROTOCOL_LIST, epvcResHandleGlobalProtocolList},
{RTYPE_GLOBAL_REGISTER_IM, epvcIMDriverRegistration}
};
// Static information about ArpGlobals.
//
RM_STATIC_OBJECT_INFO EpvcGlobals_StaticInfo = { 0, // TypeUID
0, // TypeFlags
"EpvcGlobals", // TypeName
0, // Timeout
NULL, // pfnCreate
NULL, // pfnDelete
NULL, // pfnVerifyLock
sizeof(EpvcGlobals_ResourceTable)/sizeof(EpvcGlobals_ResourceTable[1]), EpvcGlobals_ResourceTable };
//--------------------------------------------------------------------------------
// //
// Underlying Adapters. The Protocol gets called at BindAdapter for //
// each adapter //
// //
// //
//--------------------------------------------------------------------------------
// eovcAdapter_HashInfo contains information required maintain a hashtable
// of EPVC_ADAPTER objects.
//
RM_HASH_INFO epvcAdapter_HashInfo = { NULL, // pfnTableAllocator
NULL, // pfnTableDeallocator
epvcAdapterCompareKey, // fnCompare
// Function to generate a ULONG-sized hash.
//
epvcAdapterHash // pfnHash
};
// EpvcGlobals_AdapterStaticInfo contains static information about
// objects of type EPVC_ADAPTERS.
// It is a group of Adapters that the protocol has bound to
//
RM_STATIC_OBJECT_INFO EpvcGlobals_AdapterStaticInfo = { 0, // TypeUID
0, // TypeFlags
"Adapter", // TypeName
0, // Timeout
epvcAdapterCreate, // pfnCreate
epvcAdapterDelete, // pfnDelete
NULL, // pfnVerifyLock
0, // Size of resource table
NULL, // ResourceTable
&epvcAdapter_HashInfo };
//--------------------------------------------------------------------------------
// //
// Intermediate miniports - each hangs of a protocol block //
// //
// //
//--------------------------------------------------------------------------------
// arpAdapter_HashInfo contains information required maintain a hashtable
// of EPVC_ADAPTER objects.
//
RM_HASH_INFO epvc_I_Miniport_HashInfo= { NULL, // pfnTableAllocator
NULL, // pfnTableDeallocator
epvcIMiniportCompareKey, // fnCompare
// Function to generate a ULONG-sized hash.
//
epvcIMiniportHash // pfnHash
};
RM_STATIC_OBJECT_INFO EpvcGlobals_I_MiniportStaticInfo = { 0, // TypeUID
0, // TypeFlags
"IMiniport", // TypeName
0, // Timeout
epvcIMiniportCreate, // pfnCreate
epvcIMiniportDelete, // pfnDelete
NULL, // pfnVerifyLock
0, // Size of resource table
NULL, // ResourceTable
&epvc_I_Miniport_HashInfo };
//
// Variables used in debugging
//
#if DBG
ULONG g_ulTraceLevel= DEFAULTTRACELEVEL; ULONG g_ulTraceMask = DEFAULTTRACEMASK ; #endif
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { NDIS_STATUS Status; NTSTATUS NtStatus;
BOOLEAN AllocatedGlobals = FALSE; ENTER("DriverEntry", 0xbfcb7eb1)
RM_DECLARE_STACK_RECORD(SR)
TIMESTAMP("==>DriverEntry");
TRACE ( TL_T, TM_Dr,("==>Atm Epvc DriverEntry\n"));
do { //
// Inititalize the global variables
//
// Must be done before any RM apis are used.
//
RmInitializeRm();
RmInitializeLock( &EpvcGlobals.Lock, LOCKLEVEL_GLOBAL );
RmInitializeHeader( NULL, // pParentObject,
&EpvcGlobals.Hdr, ATMEPVC_GLOBALS_SIG , &EpvcGlobals.Lock, &EpvcGlobals_StaticInfo, NULL, // szDescription
&SR );
AllocatedGlobals = TRUE;
//
// Initialize globals
//
EpvcGlobals.driver.pDriverObject = DriverObject; EpvcGlobals.driver.pRegistryPath = RegistryPath;
//
// Register the IM Miniport with NDIS.
//
Status = RmLoadGenericResource( &EpvcGlobals.Hdr, RTYPE_GLOBAL_PROTOCOL_LIST, &SR );
if (FAIL(Status)) break;
//
// Register the protocol with NDIS.
//
Status = RmLoadGenericResource( &EpvcGlobals.Hdr, RTYPE_GLOBAL_REGISTER_IM, &SR );
if (FAIL(Status)) break;
} while (FALSE);
if (FAIL(Status)) { if (AllocatedGlobals) { RmUnloadAllGenericResources( &EpvcGlobals.Hdr, &SR ); RmDeallocateObject( &EpvcGlobals.Hdr, &SR ); }
// Must be done after any RM apis are used and async activity complete.
//
RmDeinitializeRm();
NtStatus = STATUS_UNSUCCESSFUL; } else { NtStatus = NDIS_STATUS_SUCCESS; }
EXIT()
TIMESTAMP("<==DriverEntry");
RM_ASSERT_CLEAR(&SR); return Status ;
}
VOID EpvcUnload( IN PDRIVER_OBJECT pDriverObject ) /*++
Routine Description:
This routine is called by the system prior to unloading us. Currently, we just undo everything we did in DriverEntry, that is, de-register ourselves as an NDIS protocol, and delete the device object we had created.
Arguments:
pDriverObject - Pointer to the driver object created by the system.
Return Value:
None
--*/ { NDIS_STATUS NdisStatus; ENTER("Unload", 0xc8482549) RM_DECLARE_STACK_RECORD(sr);
TIMESTAMP("==>Unload");
RmUnloadAllGenericResources(&EpvcGlobals.Hdr, &sr);
RmDeallocateObject(&EpvcGlobals.Hdr, &sr);
// Must be done after any RM apis are used and async activity complete.
//
RmDeinitializeRm();
// TODO? Block(250);
RM_ASSERT_CLEAR(&sr) EXIT() TIMESTAMP("<==Unload"); return; }
RM_STATUS epvcResHandleGlobalProtocolList( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD pSR ) { PEPVC_GLOBALS pGlobals = NULL;
ENTER("GlobalAdapterList", 0xb407e79e) TRACE (TL_T, TM_Dr, ("==>epvcResHandleGlobalProtocolList pObj %x, Op", pObj , Op ) );
pGlobals = CONTAINING_RECORD( pObj, EPVC_GLOBALS, Hdr);
//
//
if (Op == RM_RESOURCE_OP_LOAD) { //
// Allocate adapter list.
//
TR_WARN(("LOADING"));
RmInitializeGroup( pObj, // pParentObject
&EpvcGlobals_AdapterStaticInfo, // pStaticInfo
&(pGlobals->adapters.Group), // pGroup
"Adapters Group", // szDescription
pSR // pStackRecord
); } else if (Op == RM_RESOURCE_OP_UNLOAD) { //
// We're unloading this "resource", i.e., unloading and deallocating the
// global adapter list. We first unload and free all the adapters
// in the list, and then free the list itself.
//
TR_WARN(("UNLOADING")); //
// We expect there to be no adapter objects at this point.
//
ASSERT(pGlobals->adapters.Group.HashTable.NumItems == 0);
RmDeinitializeGroup(&pGlobals->adapters.Group, pSR); NdisZeroMemory(&(pGlobals->adapters), sizeof(pGlobals->adapters)); } else { // Unexpected op code.
//
ASSERT(!"Unexpected OpCode epvcResHandleGlobalProtocolList "); }
TRACE (TL_T, TM_Dr, ("<==epvcResHandleGlobalProtocolList Status %x", NDIS_STATUS_SUCCESS) );
EXIT() RM_ASSERT_CLEAR(pSR);
return NDIS_STATUS_SUCCESS;
}
RM_STATUS epvcIMDriverRegistration( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr ) { TRACE (TL_T, TM_Mp, ("epvcIMDriverRegistration Op %x", Op)); if (RM_RESOURCE_OP_LOAD == Op) { epvcRegisterIMDriver(pObj,Op,pvUserParams,psr); } else { epvcDeRegisterIMDriver(pObj,Op,pvUserParams,psr); }
return NDIS_STATUS_SUCCESS; }
RM_STATUS epvcRegisterIMDriver( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr ) { NDIS_STATUS Status = NDIS_STATUS_FAILURE; PEPVC_GLOBALS pGlobals = NULL; NDIS_PROTOCOL_CHARACTERISTICS PChars; NDIS_MINIPORT_CHARACTERISTICS MChars; NDIS_STRING Name;
ENTER("epvcRegisterIMDriver", 0x0d0f008a); pGlobals = CONTAINING_RECORD( pObj, EPVC_GLOBALS, Hdr);
TRACE (TL_T, TM_Dr, ("==>epvcRegisterIMDriver Globals %x", pObj) );
//
// Register the miniport with NDIS. Note that it is the miniport
// which was started as a driver and not the protocol. Also the miniport
// must be registered prior to the protocol since the protocol's BindAdapter
// handler can be initiated anytime and when it is, it must be ready to
// start driver instances.
//
NdisMInitializeWrapper(&pGlobals->driver.WrapperHandle, pGlobals->driver.pDriverObject, pGlobals->driver.pRegistryPath, NULL); NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
MChars.MajorNdisVersion = 5; MChars.MinorNdisVersion = 0;
MChars.InitializeHandler = EpvcInitialize; MChars.QueryInformationHandler = EpvcMpQueryInformation; MChars.SetInformationHandler = EpvcMpSetInformation; MChars.ResetHandler = MPReset; MChars.TransferDataHandler = MPTransferData; MChars.HaltHandler = EpvcHalt;
//
// We will disable the check for hang timeout so we do not
// need a check for hang handler!
//
MChars.CheckForHangHandler = NULL; MChars.SendHandler = NULL; MChars.ReturnPacketHandler = EpvcReturnPacket;
//
// Either the Send or the SendPackets handler should be specified.
// If SendPackets handler is specified, SendHandler is ignored
//
MChars.SendPacketsHandler = EpvcSendPackets;
Status = NdisIMRegisterLayeredMiniport(pGlobals->driver.WrapperHandle, &MChars, sizeof(MChars), &EpvcGlobals.driver.DriverHandle);
ASSERT (EpvcGlobals.driver.DriverHandle != NULL); if (Status != NDIS_STATUS_SUCCESS) { //
// todo: fix failure case
//
ASSERT (0); };
//
// Now register the protocol.
//
NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); PChars.MajorNdisVersion = 5; PChars.MinorNdisVersion = 0;
//
// Make sure the protocol-name matches the service-name under which this protocol is installed.
// This is needed to ensure that NDIS can correctly determine the binding and call us to bind
// to miniports below.
//
NdisInitUnicodeString(&Name, L"ATMEPVCP"); // Protocol name
PChars.Name = Name; PChars.OpenAdapterCompleteHandler = EpvcOpenAdapterComplete; PChars.CloseAdapterCompleteHandler = EpvcCloseAdapterComplete; PChars.SendCompleteHandler = NULL; PChars.TransferDataCompleteHandler = PtTransferDataComplete; PChars.ResetCompleteHandler = EpvcResetComplete; PChars.RequestCompleteHandler = EpvcRequestComplete ; PChars.ReceiveHandler = PtReceive; PChars.ReceiveCompleteHandler = EpvcPtReceiveComplete; PChars.StatusHandler = EpvcStatus; PChars.StatusCompleteHandler = PtStatusComplete; PChars.BindAdapterHandler = EpvcBindAdapter; PChars.UnbindAdapterHandler = EpvcUnbindAdapter; PChars.UnloadHandler = NULL; PChars.ReceivePacketHandler = PtReceivePacket; PChars.PnPEventHandler= EpvcPtPNPHandler; PChars.CoAfRegisterNotifyHandler = EpvcAfRegisterNotify; PChars.CoSendCompleteHandler = EpvcPtSendComplete; PChars.CoReceivePacketHandler = EpvcCoReceive;
{ //
// Update client characteristis
//
PNDIS_CLIENT_CHARACTERISTICS pNdisCC = &(pGlobals->ndis.CC);
NdisZeroMemory(pNdisCC, sizeof(*pNdisCC)); pNdisCC->MajorVersion = EPVC_NDIS_MAJOR_VERSION; pNdisCC->MinorVersion = EPVC_NDIS_MINOR_VERSION; pNdisCC->ClCreateVcHandler = EpvcClientCreateVc; pNdisCC->ClDeleteVcHandler = EpvcClientDeleteVc; pNdisCC->ClRequestHandler = EpvcCoRequest; pNdisCC->ClRequestCompleteHandler = EpvcCoRequestComplete; pNdisCC->ClOpenAfCompleteHandler = EpvcCoOpenAfComplete; pNdisCC->ClCloseAfCompleteHandler = EpvcCoCloseAfComplete; pNdisCC->ClMakeCallCompleteHandler = EpvcCoMakeCallComplete; pNdisCC->ClModifyCallQoSCompleteHandler = NULL; pNdisCC->ClIncomingCloseCallHandler = EpvcCoIncomingClose; pNdisCC->ClCallConnectedHandler = EpvcCoCallConnected; pNdisCC->ClCloseCallCompleteHandler = EpvcCoCloseCallComplete; pNdisCC->ClIncomingCallHandler = EpvcCoIncomingCall;
}
NdisRegisterProtocol(&Status, &pGlobals->driver.ProtocolHandle, &PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
ASSERT(Status == NDIS_STATUS_SUCCESS);
NdisMRegisterUnloadHandler(pGlobals->driver.WrapperHandle, EpvcUnload);
ASSERT (pGlobals == &EpvcGlobals);
NdisIMAssociateMiniport(EpvcGlobals.driver.DriverHandle, pGlobals->driver.ProtocolHandle);
EXIT() TRACE (TL_T, TM_Dr, ("<==epvcRegisterIMDriver ") );
return Status;
}
RM_STATUS epvcDeRegisterIMDriver( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr ) {
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
TRACE (TL_T, TM_Pt, ("== eovcDeRegisterIMDriver"));
while (NdisStatus != NDIS_STATUS_SUCCESS) { NdisDeregisterProtocol(&NdisStatus, EpvcGlobals.driver.ProtocolHandle); NdisMSleep(1000); }
return NdisStatus; }
void DbgMark(UINT Luid) { // do nothing useful, but do something specific, so that the compiler doesn't
// alias DbgMark to some other function that happens to do nothing.
//
static int i; i=Luid; }
|