windows-nt/Source/XPSP1/NT/net/1394/nic/sys/nt.c

551 lines
14 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// 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;
}