|
|
//
// Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
//
// nt.c
//
// IEEE1394 mini-port/call-manager driver
//
// Main routine (DriverEntry) and global data definitions
//
// 12/28/98 adube
// 9/5/99 alid: added callback registeration and interface to enum1394
//
#include "precomp.h"
//-----------------------------------------------------------------------------
// Local prototypes
//-----------------------------------------------------------------------------
extern NDIS_SPIN_LOCK g_DriverLock; extern LIST_ENTRY g_AdapterList;
NDIS_STATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
VOID NicUnloadHandler( IN PDRIVER_OBJECT DriverObject );
// Mark routine to be unloaded after initialization.
//
#pragma NDIS_INIT_FUNCTION(DriverEntry)
//-----------------------------------------------------------------------------
// Routines
//-----------------------------------------------------------------------------
NDIS_STATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
// Standard 'DriverEntry' driver initialization entrypoint called by the
// I/0 system at IRQL PASSIVE_LEVEL before any other call to the driver.
//
// On NT, 'DriverObject' is the driver object created by the I/0 system
// and 'RegistryPath' specifies where driver specific parameters are
// stored. These arguments are opaque to this driver (and should remain
// so for portability) which only forwards them to the NDIS wrapper.
//
// Returns the value returned by NdisMRegisterMiniport, per the doc on
// "DriverEntry of NDIS Miniport Drivers".
//
{ NDIS_STATUS NdisStatus; NTSTATUS NtStatus = STATUS_SUCCESS; NDIS_MINIPORT_CHARACTERISTICS nmc; NDIS_HANDLE NdisWrapperHandle; UNICODE_STRING CallbackObjectName; OBJECT_ATTRIBUTES ObjectAttr; BOOLEAN fDerefCallbackObject = FALSE, fDeregisterCallback = FALSE; PDEVICE_OBJECT pDummyDeviceObject;
TRACE( TL_I, TM_Init, ( " Nic1394 - DriverEntry" ) );
do { #ifdef CHANGE_MEDIUMS
DbgPrint ("Nic1394 Driver Entry - Medium Type %x", &g_ulMedium); DbgBreakPoint();
#else
//
// Now depending on the ETHERNET preprocessor, define a medium
//
#ifdef _ETHERNET_
g_ulMedium = NdisMedium802_3; #else
g_ulMedium = NdisMedium1394; #endif // _ETHERNET_
#endif // CHANGE_MEDIUMS
// Register this driver with the NDIS wrapper. This call must occur
// before any other NdisXxx calls.
//
NdisMInitializeWrapper( &NdisWrapperHandle, DriverObject, RegistryPath, NULL );
// Set up the mini-port characteristics table that tells NDIS how to call
// our mini-port.
//
NdisZeroMemory( &nmc, sizeof(nmc) );
nmc.MajorNdisVersion = NDIS_MajorVersion; nmc.MinorNdisVersion = NDIS_MinorVersion;
// nmc.CheckForHangHandler = CheckForHang;
// no DisableInterruptHandler
// no EnableInterruptHandler
nmc.HaltHandler = NicMpHalt; // no HandleInterruptHandler
nmc.InitializeHandler = NicMpInitialize; // no ISRHandler
// no QueryInformationHandler (see CoRequestHandler)
nmc.ResetHandler = NicMpReset; // no SendHandler (see CoSendPacketsHandler)
// no WanSendHandler (see CoSendPacketsHandler)
// no SetInformationHandler (see CoRequestHandler)
// no TransferDataHandler
// no WanTransferDataHandler
// nmc.ReturnPacketHandler = NicMpReturnPacket;
// no SendPacketsHandler (see CoSendPacketsHandler)
// no AllocateCompleteHandler
nmc.CoActivateVcHandler = NicMpCoActivateVc; nmc.CoDeactivateVcHandler= NicMpCoDeactivateVc; nmc.CoSendPacketsHandler = NicMpCoSendPackets; nmc.CoRequestHandler = NicMpCoRequest; nmc.ReturnPacketHandler = NicReturnPacket;
#ifdef _ETHERNET_
nmc.QueryInformationHandler = NicEthQueryInformation; nmc.SetInformationHandler = NicEthSetInformation; nmc.SendPacketsHandler = NicMpSendPackets;
#endif
//
// Create a dummy device object
//
#ifdef Win9X
IoCreateDevice(DriverObject, 0, NULL, FILE_DEVICE_PHYSICAL_NETCARD, 0, FALSE,// exclusive flag
&pDummyDeviceObject); #endif
// Register this driver as the IEEE1394 mini-port. This will result in NDIS
// calling back at NicMpInitialize.
//
TRACE( TL_V, TM_Init, ( "NdisMRegMp" ) ); NdisStatus = NdisMRegisterMiniport( NdisWrapperHandle, &nmc, sizeof(nmc) ); TRACE( TL_A, TM_Init, ( "NdisMRegMp=$%x", NdisStatus ) );
//
if (NdisStatus == NDIS_STATUS_SUCCESS) { { extern CALLSTATS g_stats; extern NDIS_SPIN_LOCK g_lockStats;
NdisZeroMemory( &g_stats, sizeof(g_stats) ); NdisAllocateSpinLock( &g_lockStats ); } // Initialize driver-wide lock and adapter list.
//
{
NdisAllocateSpinLock( &g_DriverLock ); InitializeListHead( &g_AdapterList ); }
//
// BINARY_COMPATIBILITY_BUG
//
#if NDIS_NT
NdisMRegisterUnloadHandler(NdisWrapperHandle, NicUnloadHandler); #endif
#ifdef PSDEBUG
{ extern LIST_ENTRY g_listDebugPs; extern NDIS_SPIN_LOCK g_lockDebugPs;
InitializeListHead( &g_listDebugPs ); NdisAllocateSpinLock( &g_lockDebugPs ); } #endif
//
// create a named Callback object with os
// then register a callback routine with send a notification to all modules that
// have a Callback routine registered with this function
// if enum1394 is already loaded, this will let it know the nic driver is loaded
// the enum1394 will get the driver registeration entry points from the notification
// callback and calls NicRegisterDriver to pass the enum entry points
// if enum1394 is not loaded and gets loaded later, it will send a notication to modules
// who have registered with this callback object and passes its own driver registeration
// the purpose of passign the entry points this way vs. exporting them, is to avoid
// getting loaded as a DLL which fatal for both nic1394 and enum1394
//
//
// every Callback object is identified by a name.
//
RtlInitUnicodeString(&CallbackObjectName, NDIS1394_CALLBACK_NAME);
InitializeObjectAttributes(&ObjectAttr, &CallbackObjectName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL); NtStatus = ExCreateCallback(&Nic1394CallbackObject, &ObjectAttr, TRUE, // allow creating the object if it does not exist
TRUE); // allow mutiple callback registeration
if (!NT_SUCCESS(NtStatus)) { TRACE( TL_A, TM_All, ("Nic1394 DriverEntry: failed to create a Callback object. Status %lx\n", NtStatus)); NtStatus = STATUS_UNSUCCESSFUL; break; }
fDerefCallbackObject = TRUE; Nic1394CallbackRegisterationHandle = ExRegisterCallback(Nic1394CallbackObject, Nic1394Callback, (PVOID)NULL); if (Nic1394CallbackRegisterationHandle == NULL) { TRACE(TL_A, TM_All, ("Nic1394 DriverEntry: failed to register a Callback routine%lx\n")); NtStatus = STATUS_UNSUCCESSFUL; break; } fDeregisterCallback = TRUE;
//
// now notify enum1394 (if it is already loaded) use Arg1 to tell it where
// the notification is coming from
//
ExNotifyCallback(Nic1394CallbackObject, (PVOID)NDIS1394_CALLBACK_SOURCE_NIC1394, (PVOID)&Nic1394Characteristics);
NtStatus = STATUS_SUCCESS; fDerefCallbackObject = fDeregisterCallback = FALSE; } else { NdisTerminateWrapper( NdisWrapperHandle, NULL ); NtStatus = NdisStatus; break; } } while (FALSE);
if (fDerefCallbackObject) { ObDereferenceObject(Nic1394CallbackObject); }
if (fDeregisterCallback) { ExUnregisterCallback(Nic1394CallbackRegisterationHandle); } if (NtStatus != STATUS_SUCCESS) { if (NdisEnum1394DeregisterDriver != NULL) NdisEnum1394DeregisterDriver(); } return NtStatus; }
VOID NicUnloadHandler( IN PDRIVER_OBJECT DriverObject ) { ASSERT(IsListEmpty(&g_AdapterList));
if (NdisEnum1394DeregisterDriver != NULL) { NdisEnum1394DeregisterDriver(); }
if (Nic1394CallbackRegisterationHandle != NULL) { ExUnregisterCallback(Nic1394CallbackRegisterationHandle); } if (Nic1394CallbackObject != NULL) { ObDereferenceObject(Nic1394CallbackObject); } return; }
VOID nicDeregisterWithEnum ()
{
if (NdisEnum1394DeregisterDriver != NULL) { NdisEnum1394DeregisterDriver(); }
}
VOID nicDeregisterWithKernel () {
if (Nic1394CallbackRegisterationHandle != NULL) { ExUnregisterCallback(Nic1394CallbackRegisterationHandle); } if (Nic1394CallbackObject != NULL) { ObDereferenceObject(Nic1394CallbackObject); }
}
//
// the registeration entry for enum1394
// typically this will be only called if enum1394 detects the presence of
// the nic1394 through receiving a call back notification. this is how enum1394
// lets nic1394 know that it is there and ready.
// if nic1394 detects the presence of the enum1394 by receiving a notification
// callbak, it will call NdisEunm1394RegisterDriver and in that case enum1394
// will -not- call Nic1394RegisterDriver.
//
NTSTATUS NicRegisterEnum1394( IN PNDISENUM1394_CHARACTERISTICS NdisEnum1394Characteristcis ) { PADAPTERCB pAdapter; LIST_ENTRY *pAdapterListEntry; NdisEnum1394RegisterDriver = NdisEnum1394Characteristcis->RegisterDriverHandler; NdisEnum1394DeregisterDriver = NdisEnum1394Characteristcis->DeregisterDriverHandler; NdisEnum1394RegisterAdapter = NdisEnum1394Characteristcis->RegisterAdapterHandler; NdisEnum1394DeregisterAdapter = NdisEnum1394Characteristcis->DeregisterAdapterHandler;
Nic1394RegisterAdapters();
return STATUS_SUCCESS;
}
VOID NicDeregisterEnum1394( VOID ) { PADAPTERCB pAdapter; LIST_ENTRY *pAdapterListEntry;
//
// go through all the adapters and Deregister them if necessary
//
NdisAcquireSpinLock (&g_DriverLock);
for (pAdapterListEntry = g_AdapterList.Flink; pAdapterListEntry != &g_AdapterList; pAdapterListEntry = pAdapterListEntry->Flink) { pAdapter = CONTAINING_RECORD(pAdapterListEntry, ADAPTERCB, linkAdapter); if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator)) { nicReferenceAdapter(pAdapter,"NicDeregisterEnum1394"); NdisReleaseSpinLock(&g_DriverLock);
NdisEnum1394DeregisterAdapter((PVOID)pAdapter->EnumAdapterHandle); NdisAcquireSpinLock( &g_DriverLock); nicDereferenceAdapter(pAdapter, "NicDeregisterEnum1394"); } ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator | fADAPTER_FailedRegisteration); } NdisReleaseSpinLock(&g_DriverLock);
NdisEnum1394RegisterDriver = NULL; NdisEnum1394DeregisterDriver = NULL; NdisEnum1394RegisterAdapter = NULL; NdisEnum1394DeregisterAdapter = NULL; }
VOID Nic1394Callback( PVOID CallBackContext, PVOID Source, PVOID Characteristics ) { NTSTATUS Status; //
// if we are the one issuing this notification, just return
//
if (Source == (PVOID)NDIS1394_CALLBACK_SOURCE_NIC1394) return;
//
// notification is coming from Nic1394. grab the entry points. call it and
// let it know that you are here
//
ASSERT(Source == (PVOID)NDIS1394_CALLBACK_SOURCE_ENUM1394);
if (Source != (PVOID)NDIS1394_CALLBACK_SOURCE_ENUM1394) { return; }
NdisEnum1394RegisterDriver = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->RegisterDriverHandler;
ASSERT(NdisEnum1394RegisterDriver != NULL);
if (NdisEnum1394RegisterDriver == NULL) { //
// invalid characteristics
//
return; }
Status = NdisEnum1394RegisterDriver(&Nic1394Characteristics); if (Status == STATUS_SUCCESS) { NdisEnum1394DeregisterDriver = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->DeregisterDriverHandler; NdisEnum1394RegisterAdapter = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->RegisterAdapterHandler; NdisEnum1394DeregisterAdapter = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->DeregisterAdapterHandler; Nic1394RegisterAdapters(); } else { NdisEnum1394RegisterDriver = NULL; } }
//
// This function walks the global list of the adapters and
// will register those that have not been registered with enum1394
//
VOID Nic1394RegisterAdapters( VOID ) { PADAPTERCB pAdapter; LIST_ENTRY *pAdapterListEntry; LARGE_INTEGER LocalHostUniqueId; NTSTATUS NtStatus; //
// go through all the adapters and register them if necessary. if there are
// any remote nodes connected to these adapters, they will be indicated back
// in the context of registering the adapter
//
NdisAcquireSpinLock(&g_DriverLock);
for (pAdapterListEntry = g_AdapterList.Flink; pAdapterListEntry != &g_AdapterList; pAdapterListEntry = pAdapterListEntry->Flink) { pAdapter = CONTAINING_RECORD(pAdapterListEntry, ADAPTERCB, linkAdapter); if (!ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator | fADAPTER_FailedRegisteration)) { nicReferenceAdapter (pAdapter, "Nic1394RegisterAdapters"); NdisReleaseSpinLock (&g_DriverLock);
NtStatus = NdisEnum1394RegisterAdapter((PVOID)pAdapter, pAdapter->pNdisDeviceObject, &pAdapter->EnumAdapterHandle, &LocalHostUniqueId); NdisAcquireSpinLock(&g_DriverLock); nicDereferenceAdapter(pAdapter, "Nic1394RegisterAdapters"); if (NtStatus == STATUS_SUCCESS) { ADAPTER_SET_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator); } else { ADAPTER_SET_FLAG(pAdapter, fADAPTER_FailedRegisteration); TRACE(TL_A, TM_All, ("Nic1394RegisterAdapters: failed to register Adapter %lx with enum1394. Status %lx\n", pAdapter, NtStatus)); } } } NdisReleaseSpinLock(&g_DriverLock);
return; }
|