672 lines
13 KiB
C
672 lines
13 KiB
C
|
|
//--------------------------------------------------------//
|
|
// //
|
|
// //
|
|
// ZwLoadDriver is locally declared because if I try //
|
|
// and include ZwApi.h there are conflicts with //
|
|
// structures defined in wdm.h //
|
|
// //
|
|
// //
|
|
//--------------------------------------------------------//
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
NDIS_STRING ArpName = NDIS_STRING_CONST("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ARP1394");
|
|
|
|
//----------------------------------------------------------//
|
|
// Local Prototypes //
|
|
//----------------------------------------------------------//
|
|
|
|
NTSYSAPI
|
|
NTSTATUS
|
|
NTAPI
|
|
ZwLoadDriver(
|
|
IN PUNICODE_STRING DriverServiceName
|
|
);
|
|
|
|
NTSYSAPI
|
|
NTSTATUS
|
|
NTAPI
|
|
ZwUnloadDriver(
|
|
IN PUNICODE_STRING DriverServiceName
|
|
);
|
|
|
|
VOID
|
|
nicEthStartArpWorkItem (
|
|
PNDIS_WORK_ITEM pWorkItem,
|
|
IN PVOID Context
|
|
);
|
|
|
|
NTSYSAPI
|
|
NTSTATUS
|
|
NTAPI
|
|
ZwDeviceIoControlFile(
|
|
IN HANDLE FileHandle,
|
|
IN HANDLE Event OPTIONAL,
|
|
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
|
IN PVOID ApcContext OPTIONAL,
|
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
IN ULONG IoControlCode,
|
|
IN PVOID InputBuffer OPTIONAL,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer OPTIONAL,
|
|
IN ULONG OutputBufferLength
|
|
);
|
|
|
|
VOID
|
|
nicSetupIoctlToLoadArp (
|
|
IN PADAPTERCB pAdapter,
|
|
IN PARP_INFO pArpInfo
|
|
);
|
|
|
|
VOID
|
|
nicSetupAndSendIoctlToArp (
|
|
IN PADAPTERCB pAdapter,
|
|
IN PARP_INFO pArpInfo
|
|
);
|
|
|
|
//----------------------------------------------------------//
|
|
// Functions //
|
|
//----------------------------------------------------------//
|
|
|
|
|
|
|
|
VOID
|
|
nicSendIoctlToArp(
|
|
PARP1394_IOCTL_COMMAND pCmd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send the start Ioctl to the ARp module
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN fRet = FALSE;
|
|
PUCHAR pc;
|
|
HANDLE DeviceHandle;
|
|
ULONG BytesReturned;
|
|
OBJECT_ATTRIBUTES Atts;
|
|
NDIS_STRING strArp1394 = NDIS_STRING_CONST ("\\Device\\Arp1394");
|
|
HANDLE Handle;
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
|
|
do
|
|
{
|
|
|
|
InitializeObjectAttributes(&Atts,
|
|
&strArp1394,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
|
|
status = ZwCreateFile(&Handle,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&Atts,
|
|
&ioStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
Handle = NULL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Submit the request to the forwarder
|
|
//
|
|
|
|
|
|
status = ZwDeviceIoControlFile(
|
|
Handle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ioStatusBlock,
|
|
ARP_IOCTL_CLIENT_OPERATION,
|
|
pCmd,
|
|
sizeof(*pCmd),
|
|
pCmd,
|
|
sizeof(*pCmd));
|
|
|
|
|
|
|
|
//
|
|
// Close the device.
|
|
//
|
|
|
|
ZwClose(Handle);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
ASSERT (status == STATUS_SUCCESS);
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
nicLoadArpDriver ()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Load the arp module
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
ZwLoadDriver(&ArpName);
|
|
|
|
TRACE (TL_T, TM_Mp,("Loaded the Arp Module %p\n", &ArpName));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
nicGetAdapterName (
|
|
IN PADAPTERCB pAdapter,
|
|
IN WCHAR* pAdapterName,
|
|
IN ULONG BufferSize,
|
|
IN PULONG pSizeReturned
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the Adapter Name From NDIS
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// The BufferSize always has to be greater than SizeReturned
|
|
//
|
|
|
|
NdisMoveMemory (pAdapterName,
|
|
&pAdapter->AdapterName[0],
|
|
pAdapter->AdapterNameSize * sizeof (WCHAR));
|
|
|
|
|
|
if (pSizeReturned != NULL)
|
|
{
|
|
|
|
*pSizeReturned = pAdapter->AdapterNameSize ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
nicSetupIoctlToArp (
|
|
IN PADAPTERCB pAdapter,
|
|
IN PARP_INFO pArpInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets up the Ioctl to be sent to the Arp module
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PARP1394_IOCTL_ETHERNET_NOTIFICATION pEthCmd = &pAdapter->ArpIoctl.EthernetNotification;
|
|
|
|
|
|
ADAPTER_ACQUIRE_LOCK(pAdapter);
|
|
|
|
if (BindArp == pArpInfo->Action || LoadArp == pArpInfo->Action)
|
|
{
|
|
// BRIDGE START
|
|
pEthCmd->Hdr.Op = ARP1394_IOCTL_OP_ETHERNET_START_EMULATION;
|
|
pAdapter->fIsArpStarted = TRUE;
|
|
ADAPTER_SET_FLAG(pAdapter,fADAPTER_BridgeMode);
|
|
}
|
|
|
|
|
|
if (UnloadArp == pArpInfo->Action || UnloadArpNoRequest== pArpInfo->Action)
|
|
{
|
|
// BRIDGE STOP
|
|
pEthCmd->Hdr.Op = ARP1394_IOCTL_OP_ETHERNET_STOP_EMULATION;
|
|
pAdapter->fIsArpStarted = FALSE;
|
|
ADAPTER_CLEAR_FLAG(pAdapter,fADAPTER_BridgeMode);
|
|
|
|
}
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK(pAdapter);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
nicSetupAndSendIoctlToArp (
|
|
IN PADAPTERCB pAdapter,
|
|
PARP_INFO pArpInfo )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets up an Ioctl and Sends it to the Arp module
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
|
|
nicSetupIoctlToArp (pAdapter, pArpInfo);
|
|
|
|
|
|
nicSendIoctlToArp(&pAdapter->ArpIoctl);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
nicSendNotificationToArp(
|
|
IN PADAPTERCB pAdapter,
|
|
IN PARP_INFO pArpInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send the notification to the arp module
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_REQUEST pRequest = NULL;
|
|
ULONG Start = FALSE;
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
ARP1394_IOCTL_COMMAND ArpIoctl;
|
|
|
|
//
|
|
// Extract our variables from the workitem
|
|
//
|
|
|
|
TRACE (TL_T, TM_Mp, ("==>nicEthStartArpWorkItem Start %x", Start ));
|
|
|
|
|
|
|
|
do
|
|
{
|
|
//
|
|
// First complete the request, so that protocols can start sending new
|
|
// requests . Notes 11/30/00
|
|
//
|
|
if (pArpInfo->Action == LoadArp || pArpInfo->Action == UnloadArp)
|
|
{
|
|
//
|
|
// in either of these cases, it is a request that has initiated the action.
|
|
//
|
|
//
|
|
if (pRequest == NULL)
|
|
{
|
|
//
|
|
// This came in through our CL SetInformation Handler
|
|
//
|
|
NdisMSetInformationComplete (pAdapter->MiniportAdapterHandle, NdisStatus );
|
|
}
|
|
else
|
|
{
|
|
NdisMCoRequestComplete ( NdisStatus ,
|
|
pAdapter->MiniportAdapterHandle,
|
|
pRequest);
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// "arp13 -bstart adapter"
|
|
// If we are asked to Load Arp, we verify that the arp hasn't
|
|
// already been started
|
|
//
|
|
|
|
|
|
if (pArpInfo->Action == LoadArp && pAdapter->fIsArpStarted == FALSE)// we are turning ON
|
|
{
|
|
//
|
|
// Load the driver
|
|
//
|
|
nicLoadArpDriver ();
|
|
//
|
|
// Send it an IOCTL to open the nic1394 adapter
|
|
//
|
|
|
|
}
|
|
|
|
|
|
if (pArpInfo->Action == BindArp && pAdapter->fIsArpStarted == FALSE)
|
|
{
|
|
//
|
|
// if the arp module has not been started and we are asking to bind,
|
|
// then it means that an unload was ahead of us in the queue and
|
|
// unbound nic1394 from arp1394. This thread can exit.
|
|
//
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Send the Ioctl to the Arp module
|
|
//
|
|
|
|
nicSetupAndSendIoctlToArp (pAdapter, pArpInfo);
|
|
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
//
|
|
// end of function
|
|
//
|
|
FREE_NONPAGED (pArpInfo);
|
|
|
|
TRACE (TL_T, TM_Mp, ("<==nicEthStartArpWorkItem fLoadArp %x", pArpInfo->Action));
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
nicProcessNotificationForArp(
|
|
IN PNDIS_WORK_ITEM pWorkItem,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function extracts the notification from the workitem and
|
|
sends the Load/Unload/ BInd notfication to ARp 1394
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
PADAPTERCB pAdapter = (PADAPTERCB) Context;
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
|
|
//
|
|
// Empty the Queue indicating as many packets as possible
|
|
//
|
|
while (IsListEmpty(&pAdapter->LoadArp.Queue)==FALSE)
|
|
{
|
|
PARP_INFO pArpInfo;
|
|
PLIST_ENTRY pLink;
|
|
NDIS_STATUS NdisStatus;
|
|
|
|
pAdapter->LoadArp.PktsInQueue--;
|
|
|
|
pLink = RemoveHeadList(&pAdapter->LoadArp.Queue);
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
//
|
|
// Extract the send context
|
|
//
|
|
if (pLink != NULL)
|
|
{
|
|
pArpInfo = CONTAINING_RECORD(
|
|
pLink,
|
|
ARP_INFO,
|
|
Link);
|
|
|
|
nicSendNotificationToArp(pAdapter, pArpInfo);
|
|
}
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
}
|
|
|
|
//
|
|
// clear the flag
|
|
//
|
|
|
|
ASSERT (pAdapter->LoadArp.PktsInQueue==0);
|
|
ASSERT (IsListEmpty(&pAdapter->LoadArp.Queue));
|
|
|
|
pAdapter->LoadArp.bTimerAlreadySet = FALSE;
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
NdisInterlockedDecrement (&pAdapter->OutstandingWorkItems);
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
nicInitializeLoadArpStruct(
|
|
PADAPTERCB pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes the LoadArp struct in _ADAPTERCB
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
if (pAdapter->LoadArp.bInitialized == FALSE)
|
|
{
|
|
|
|
PARP1394_IOCTL_ETHERNET_NOTIFICATION pEthCmd = &pAdapter->ArpIoctl.EthernetNotification;
|
|
ULONG Size;
|
|
|
|
NdisZeroMemory (&pAdapter->LoadArp, sizeof(pAdapter->LoadArp));
|
|
InitializeListHead(&pAdapter->LoadArp.Queue);
|
|
pAdapter->LoadArp.bInitialized = TRUE;
|
|
|
|
NdisInitializeWorkItem (&pAdapter->LoadArp.WorkItem,
|
|
nicProcessNotificationForArp,
|
|
pAdapter);
|
|
|
|
|
|
|
|
nicGetAdapterName (pAdapter,
|
|
pEthCmd->AdapterName,
|
|
sizeof(pEthCmd->AdapterName)-sizeof(WCHAR),
|
|
&Size );
|
|
|
|
pEthCmd->AdapterName[Size/2]=0;
|
|
|
|
|
|
pEthCmd->Hdr.Version = ARP1394_IOCTL_VERSION;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicQueueRequestToArp(
|
|
PADAPTERCB pAdapter,
|
|
ARP_ACTION Action,
|
|
PNDIS_REQUEST pRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function inserts a request to load/unload or bind the Arp module
|
|
If there is no timer servicing the queue
|
|
then it queues a timer to dequeue the packet in Global Event's context
|
|
|
|
|
|
Arguments:
|
|
|
|
Self explanatory
|
|
|
|
Return Value:
|
|
Success - if inserted into the the queue
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
|
|
BOOLEAN fSetWorkItem = FALSE;
|
|
PARP_INFO pArpInfo;
|
|
|
|
do
|
|
{
|
|
|
|
pArpInfo = ALLOC_NONPAGED(sizeof (ARP_INFO), MTAG_DEFAULT);
|
|
|
|
if (pArpInfo == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
//
|
|
// Find out if this thread needs to fire the timer
|
|
//
|
|
|
|
pArpInfo->Action = Action;
|
|
pArpInfo->pRequest = pRequest;
|
|
|
|
if (pAdapter->LoadArp.bTimerAlreadySet == FALSE)
|
|
{
|
|
fSetWorkItem = TRUE;
|
|
pAdapter->LoadArp.bTimerAlreadySet = TRUE;
|
|
|
|
}
|
|
|
|
InsertTailList(
|
|
&pAdapter->LoadArp.Queue,
|
|
&pArpInfo->Link
|
|
);
|
|
pAdapter->LoadArp.PktsInQueue++;
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
//
|
|
// Now queue the timer
|
|
//
|
|
|
|
if (fSetWorkItem== TRUE)
|
|
{
|
|
PNDIS_WORK_ITEM pWorkItem;
|
|
//
|
|
// Initialize the timer
|
|
//
|
|
pWorkItem = &pAdapter->LoadArp.WorkItem;
|
|
|
|
|
|
TRACE( TL_V, TM_Recv, ( " Set Timer "));
|
|
|
|
|
|
NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
|
|
|
|
NdisScheduleWorkItem (pWorkItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
} while (FALSE);
|
|
|
|
ASSERT (Status == NDIS_STATUS_SUCCESS);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|