551 lines
14 KiB
C
551 lines
14 KiB
C
//
|
|
// 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;
|
|
}
|
|
|
|
|