Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1236 lines
31 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
testmac.c
Abstract:
simple MAC to test the NDIS wrapper.
Mostly taken from the Elnkii code spec.
Author:
Adam Barr (adamba) 14-Jul-1990
Environment:
Kernel mode, FSD
Revision History:
--*/
#include <ntos.h>
#include <ndis.h>
#include "testmac.h"
/*++
Routine Description:
This is the initialization routine for the driver. It is invoked once
when the driver is loaded into the system. Its job is to initialize all
the structures which will be used by the FSD.
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
None.
--*/
static
NTSTATUS
TestMacDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the main dispatch routine for the FSD. This routine
accepts an I/O Request Packet (IRP) and either performs the request
itself, or it passes it to the FSP for processing.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
The function value is the status of the operation.
--*/
{
KIRQL oldIrql;
DeviceObject;
KeRaiseIrql( DISPATCH_LEVEL, &oldIrql );
IoCompleteRequest( Irp, 0 );
KeLowerIrql( oldIrql );
return STATUS_NOT_IMPLEMENTED;
}
MAC_BLOCK GlobalMacBlock;
UCHAR * AdapterNames[] = {
"\\Device\\TestMac0",
"\\Device\\TestMac1",
"\\Device\\TestMac2"
};
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject
)
{
PMAC_BLOCK NewMacP = &GlobalMacBlock;
NDIS_STATUS Status;
CLONG i;
STRING AdapterName;
// Initialize the driver object with this driver's entry points.
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = TestMacDispatch;
}
// Initialize the wrapper
NdisInitializeWrapper( (PVOID)DriverObject, NULL, NULL);
NewMacP->Debug = FALSE;
// set up driver object, etc.
NewMacP->DriverObject = DriverObject;
KeInitializePowerStatus(&NewMacP->PowerStatus);
NewMacP->PowerBoolean = FALSE;
KeInsertQueuePowerStatus(&NewMacP->PowerStatus, &NewMacP->PowerBoolean);
NdisAllocateSpinLock(&NewMacP->SpinLock);
NewMacP->NumAdapters = 0;
NewMacP->AdapterQueue = (PADAPTER_BLOCK)NULL;
// get ready to call NdisRegisterMac
NewMacP->MacCharacteristics.MajorNdisVersion = 3;
NewMacP->MacCharacteristics.MinorNdisVersion = 0;
NewMacP->MacCharacteristics.Reserved = 0;
NewMacP->MacCharacteristics.OpenAdapterHandler = TestMacOpenAdapter;
NewMacP->MacCharacteristics.CloseAdapterHandler = TestMacCloseAdapter;
NewMacP->MacCharacteristics.SetPacketFilterHandler = TestMacSetPacketFilter;
NewMacP->MacCharacteristics.AddMulticastAddressHandler =
TestMacAddMulticastAddress;
NewMacP->MacCharacteristics.DeleteMulticastAddressHandler =
TestMacDeleteMulticastAddress;
NewMacP->MacCharacteristics.SendHandler = TestMacSend;
NewMacP->MacCharacteristics.TransferDataHandler = TestMacTransferData;
NewMacP->MacCharacteristics.QueryInformationHandler =
TestMacQueryInformation;
NewMacP->MacCharacteristics.SetInformationHandler = TestMacSetInformation;
NewMacP->MacCharacteristics.ResetHandler = TestMacReset;
NewMacP->MacCharacteristics.TestHandler = TestMacTest;
NewMacP->MacCharacteristics.NameLength = sizeof("TESTMAC");
RtlMoveMemory(NewMacP->MacCharacteristics.Name, "TESTMAC", 8);
NdisRegisterMac(&Status,
&NewMacP->NdisMacHandle,
&NewMacP->MacCharacteristics,
sizeof(NewMacP->MacCharacteristics)+8);
if (Status != NDIS_STATUS_SUCCESS) {
// NdisRegisterMac failed
if (NewMacP->Debug)
DbgPrint(" [ RegisterMac FAILURE %d ] ", Status);
KeRemoveQueuePowerStatus(&NewMacP->PowerStatus);
NdisFreeSpinLock(&NewMacP->SpinLock);
return STATUS_UNSUCCESSFUL;
}
for (i=0; i<3; i++) {
RtlInitString(&AdapterName, AdapterNames[i]);
if (TestMacRegisterAdapter(&AdapterName, i) != NDIS_STATUS_SUCCESS)
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
//
// MacRegisterAdapter
//
// NT will call this function when a new adapter should be opened
//
// - allocates space for adapter block and open blocks
// - initializes the open block
// - calls NdisRegisterAdapter
//
static
NDIS_STATUS
TestMacRegisterAdapter(
IN PSTRING AdapterName,
IN UINT AdapterNumber
)
{
PADAPTER_BLOCK NewAdaptP;
NDIS_STATUS Status;
UINT i;
// OK to allocate memory now
NewAdaptP = (PADAPTER_BLOCK)AllocPhys(sizeof(ADAPTER_BLOCK));
if (NewAdaptP == (PADAPTER_BLOCK)NULL)
return NDIS_STATUS_FAILURE;
NewAdaptP->AdapterName = AdapterName;
NewAdaptP->AdapterNumber = AdapterNumber;
NewAdaptP->MaxOpens = 4;
NewAdaptP->MulticastListMax = 8;
NewAdaptP->MulticastDontModify = FALSE;
// need to get this memory now
NewAdaptP->OpenBlocks =
(POPEN_BLOCK)AllocPhys(sizeof(OPEN_BLOCK) * NewAdaptP->MaxOpens);
if (NewAdaptP->OpenBlocks == (POPEN_BLOCK)NULL)
{
FreePhys((PVOID)NewAdaptP);
return NDIS_STATUS_FAILURE;
}
++(NewAdaptP->MulticastListMax); // to allow for broadcast address
// need to get this memory now
NewAdaptP->MulticastList = (PMULTICAST_ENTRY)
AllocPhys(sizeof(MULTICAST_ENTRY) * (NewAdaptP->MulticastListMax));
if (NewAdaptP->MulticastList == (PMULTICAST_ENTRY)NULL) {
FreePhys((PVOID)NewAdaptP->OpenBlocks);
FreePhys((PVOID)NewAdaptP);
return NDIS_STATUS_FAILURE;
}
NdisAllocateSpinLock(&NewAdaptP->MulticastSpinLock);
// set up the broadcast address as first multicast list entry
NewAdaptP->MulticastListSize = 1;
RtlMoveMemory(NewAdaptP->MulticastList->Address,
BroadcastAddress, ADDRESS_LEN);
NewAdaptP->MulticastList->ProtocolMask = ~(MASK)0; // not really needed
NewAdaptP->LoopbackQueue = (PNDIS_PACKET)NULL;
NdisAllocateSpinLock(&NewAdaptP->LoopbackSpinLock);
NewAdaptP->NumOpens = 0;
NewAdaptP->OpenQueue = (POPEN_BLOCK)NULL;
// set up free list of open blocks
NewAdaptP->FreeOpenQueue = NewAdaptP->OpenBlocks;
for (i = 0; i < NewAdaptP->MaxOpens-1; i++)
NewAdaptP->OpenBlocks[i].NextOpen = &(NewAdaptP->OpenBlocks[i+1]);
NewAdaptP->OpenBlocks[i].NextOpen = (POPEN_BLOCK)NULL;
NewAdaptP->MacBlock = &GlobalMacBlock;
NdisAcquireSpinLock(&GlobalMacBlock.SpinLock);
NewAdaptP->NextAdapter = GlobalMacBlock.AdapterQueue;
GlobalMacBlock.AdapterQueue = NewAdaptP;
NdisReleaseSpinLock(&GlobalMacBlock.SpinLock);
NewAdaptP->Debug = GlobalMacBlock.Debug;
Status = NdisRegisterAdapter(&NewAdaptP->NdisAdapterHandle,
GlobalMacBlock.NdisMacHandle,
(NDIS_HANDLE)NewAdaptP,
AdapterName);
if (Status != NDIS_STATUS_SUCCESS) {
if (NewAdaptP->Debug)
DbgPrint(" [ NdisRegisterAdapter FAILURE %d ] ", Status);
//*\\ take us out of GlobalMacBlock.AdapterQueue;
FreePhys((PVOID)NewAdaptP->OpenBlocks);
FreePhys((PVOID)NewAdaptP);
return NDIS_STATUS_FAILURE;
}
KeInitializeDpc(&NewAdaptP->IndicateDpc,
TestMacIndicateDpc, (PVOID)NewAdaptP);
NewAdaptP->DpcQueued = FALSE;
return NDIS_STATUS_SUCCESS;
}
//
// MacOpenAdapter
//
// NDIS function
//
static
NDIS_STATUS
TestMacOpenAdapter(
OUT NDIS_HANDLE * MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN NDIS_HANDLE NdisBindingContext,
IN NDIS_HANDLE MacAdapterContext,
IN PSTRING AddressingInformation OPTIONAL
)
{
#define AdaptP ((PADAPTER_BLOCK)MacAdapterContext)
POPEN_BLOCK NewOpenP;
RequestHandle;
// take care of linking us in to the appropriate lists
NdisAcquireSpinLock(&AdaptP->MacBlock->SpinLock);
if (AdaptP->NumOpens == AdaptP->MaxOpens) {
NdisReleaseSpinLock(&AdaptP->MacBlock->SpinLock);
return NDIS_STATUS_FAILURE;
}
// rearrange free list
NewOpenP = AdaptP->FreeOpenQueue;
AdaptP->FreeOpenQueue = NewOpenP->NextOpen;
// and link us on to active list
NewOpenP->NextOpen = AdaptP->OpenQueue;
AdaptP->OpenQueue = NewOpenP;
++(AdaptP->NumOpens);
NdisReleaseSpinLock(&AdaptP->MacBlock->SpinLock);
// set up the open block
NewOpenP->AdapterBlock = AdaptP;
NewOpenP->MacBlock = AdaptP->MacBlock;
NewOpenP->NdisBindingContext = NdisBindingContext;
NewOpenP->AddressingInformation = AddressingInformation;
// set nth bit of Multicast bit (where n is our index in AdaptP->OpenBlocks)
NewOpenP->MulticastBit = 1;
NewOpenP->MulticastBit <<= AdaptP->OpenBlocks - NewOpenP;
NewOpenP->Debug = AdaptP->Debug;
if (NewOpenP->Debug)
DbgPrint("--> TestMacOpenAdapter %d\n", AdaptP->AdapterNumber);
//*\\ initialize OpenData to zero
*MacBindingHandle = (NDIS_HANDLE)NewOpenP;
return NDIS_STATUS_SUCCESS;
#undef AdaptP
}
//
// MacCloseAdapter
//
// NDIS function
//
static
NDIS_STATUS
TestMacCloseAdapter(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
POPEN_BLOCK TmpOpenP;
RequestHandle;
if (OpenP->Debug)
DbgPrint("--> TestMacCloseAdapter %d\n", AdaptP->AdapterNumber);
// first zap us off the multicast address list
TestMacKillMulticastAddresses(AdaptP, OpenP->MulticastBit);
// now remove us from the list of opens for this adapter
NdisAcquireSpinLock(&AdaptP->MacBlock->SpinLock);
// take us off active list
if (OpenP == AdaptP->OpenQueue)
AdaptP->OpenQueue = OpenP->NextOpen;
else {
TmpOpenP = AdaptP->OpenQueue;
while (TmpOpenP->NextOpen != OpenP)
TmpOpenP = TmpOpenP->NextOpen;
TmpOpenP->NextOpen = OpenP->NextOpen;
}
// put us on free list
OpenP->NextOpen = AdaptP->FreeOpenQueue;
AdaptP->FreeOpenQueue = OpenP;
--(AdaptP->NumOpens);
NdisReleaseSpinLock(&AdaptP->MacBlock->SpinLock);
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
//
// MacSetPacketFilter
//
// NDIS function
//
// - set appropriate bits in the adapter filters
// - modify the card Receive Configuration Register if needed
//
static
NDIS_STATUS
TestMacSetPacketFilter(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN UINT PacketFilter
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
MASK BitOn = OpenP->MulticastBit;
MASK BitOff = ~(OpenP->MulticastBit);
RequestHandle;
if (OpenP->Debug)
DbgPrint("--> TestMacSetPacketFilter %d\n", AdaptP->AdapterNumber);
// acquire AdaptP->MulticastSpinLock
TestMacGetMulticastAccess(AdaptP);
if (PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
AdaptP->DirectedFilter |= BitOn;
else
AdaptP->DirectedFilter &= BitOff;
if (PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
AdaptP->MulticastFilter |= BitOn;
else
AdaptP->MulticastFilter &= BitOff;
if (PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
AdaptP->AllMulticastFilter |= BitOn;
else
AdaptP->AllMulticastFilter &= BitOff;
if (PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
AdaptP->BroadcastFilter |= BitOn;
else
AdaptP->BroadcastFilter &= BitOff;
if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
AdaptP->PromiscuousFilter |= BitOn;
else
AdaptP->PromiscuousFilter &= BitOff;
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
//
// MacAddMulticastAddress
//
// NDIS function
//
// - add the address to the list if needed
// - modify the card multicast registers if needed
//
static
NDIS_STATUS
TestMacAddMulticastAddress(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN PSTRING MulticastAddress
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
PMULTICAST_ENTRY MCSlot;
RequestHandle;
if (OpenP->Debug)
DbgPrint("--> TestMacAddMulticastAddress %d\n", AdaptP->AdapterNumber);
// acquire AdaptP->MulticastSpinLock
TestMacGetMulticastAccess(AdaptP);
// see if this address exists in our list
MCSlot = TestMacFindMulticastAddress(AdaptP->MulticastList,
AdaptP->MulticastListSize, MulticastAddress->Buffer);
if (MCSlot == (PMULTICAST_ENTRY)NULL) {
// see if our list is full
if (AdaptP->MulticastListSize == AdaptP->MulticastListMax) {
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
return NDIS_MULTICAST_LIST_FULL;
}
// add us at the end
MCSlot = &(AdaptP->MulticastList[AdaptP->MulticastListSize]);
++(AdaptP->MulticastListSize);
RtlMoveMemory(MCSlot->Address, MulticastAddress->Buffer, ADDRESS_LEN);
MCSlot->ProtocolMask = OpenP->MulticastBit; // so far, only us
} else {
if (MCSlot->ProtocolMask & OpenP->MulticastBit) {
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
return NDIS_MULTICAST_EXISTS;
}
MCSlot->ProtocolMask |= OpenP->MulticastBit;
}
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
//
// GetMulticastAccess
//
// - acquire AdaptP->MulticastSpinLock in a lazy fashion
//
static
VOID
TestMacGetMulticastAccess(
IN PADAPTER_BLOCK AdaptP
)
{
for (;;) {
NdisAcquireSpinLock(&AdaptP->MulticastSpinLock);
if (AdaptP->MulticastDontModify) {
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
// wait a little bit..
} else
return;
}
}
// just hack this in
static
UINT
ExCompareMemory(
PUCHAR s,
PUCHAR t,
UINT l
)
{
UINT i;
for (i=0; i<l; i++) {
if (s[i] != t[i])
return -1;
}
return 0;
}
//
// FindMulticastAddress
//
// finds a multicast address in a list
//
// - call this with a spin lock held
//
static
PMULTICAST_ENTRY
TestMacFindMulticastAddress(
IN PMULTICAST_ENTRY List,
IN UINT Size,
IN PUCHAR MulticastAddress
)
{
PMULTICAST_ENTRY End = &List[Size];
for ( ; List<End; ++List) {
// thanks to HenrySa for this idea...
if (MulticastAddress[4] != List->Address[4])
continue;
if (ExCompareMemory(MulticastAddress, List->Address, ADDRESS_LEN) == 0)
return List;
}
return (PMULTICAST_ENTRY)NULL;
}
//
// KillMulticastAddresses
//
// removes all multicast entries with MulticastBit on
//
// - called when an open is closed
// - if this is the last reference to an entry, remove it
//
static
VOID
TestMacKillMulticastAddresses(
IN PADAPTER_BLOCK AdaptP,
IN MASK MulticastBit
)
{
PMULTICAST_ENTRY List = AdaptP->MulticastList;
PMULTICAST_ENTRY End = &List[AdaptP->MulticastListSize];
PMULTICAST_ENTRY Dest;
// acquire AdaptP->MulticastSpinLock
TestMacGetMulticastAccess(AdaptP);
Dest = List;
while (List < End) {
List->ProtocolMask &= ~MulticastBit;
if (List->ProtocolMask != 0) {
if (Dest < List)
RtlMoveMemory(Dest, List, sizeof(MULTICAST_ENTRY));
++Dest;
}
++List;
}
AdaptP->MulticastListSize = Dest - AdaptP->MulticastList;
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
}
//
// MacDeleteMulticastAddress
//
// NDIS function
//
static
NDIS_STATUS
TestMacDeleteMulticastAddress(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN PSTRING MulticastAddress
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
PMULTICAST_ENTRY MCSlot;
RequestHandle;
if (OpenP->Debug)
DbgPrint("--> TestMacDeleteMulticastAddress %d\n", AdaptP->AdapterNumber);
// acquire AdaptP->MulticastSpinLock
TestMacGetMulticastAccess(AdaptP);
MCSlot = TestMacFindMulticastAddress(AdaptP->MulticastList,
AdaptP->MulticastListSize, MulticastAddress->Buffer);
if (MCSlot == (PMULTICAST_ENTRY)NULL) {
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
return NDIS_MULTICAST_NOT_FOUND;
} else {
if (!(MCSlot->ProtocolMask & OpenP->MulticastBit)) {
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
return NDIS_MULTICAST_NOT_FOUND;
} else {
MCSlot->ProtocolMask &= ~(OpenP->MulticastBit);
if (MCSlot->ProtocolMask == 0) { // nobody using it
// remove this entry from the list
--(AdaptP->MulticastListSize);
if (MCSlot != &AdaptP->MulticastList[AdaptP->MulticastListSize])
RtlMoveMemory(MCSlot,
&AdaptP->MulticastList[AdaptP->MulticastListSize],
sizeof(MULTICAST_ENTRY));
}
}
}
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
//
// MacSend
//
// NDIS function
//
static
NDIS_STATUS
TestMacSend(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN PNDIS_PACKET Packet
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = ((POPEN_BLOCK)MacBindingHandle)->AdapterBlock;
PMAC_RESERVED Reserved = RESERVED(Packet);
if (OpenP->Debug)
DbgPrint("--> TestMacSend %d\n", AdaptP->AdapterNumber);
if (OpenP->Debug) {
UCHAR Buf[80];
UINT Len;
Len = TestMacCopyOver(Buf, Packet, 0, 80);
DbgPrint("Message <%.*s>\n", Len, Buf);
}
Reserved->RequestHandle = RequestHandle;
Reserved->OpenBlock = (POPEN_BLOCK)MacBindingHandle;
Reserved->NextPacket = (PNDIS_PACKET)NULL;
TestMacSetLoopbackFlag(Packet);
if (Reserved->Loopback) {
Reserved->Status = 1;
NdisAcquireSpinLock(&AdaptP->LoopbackSpinLock);
TestMacLoopbackPacket(AdaptP, Packet);
NdisReleaseSpinLock(&AdaptP->LoopbackSpinLock);
}
return NDIS_STATUS_PENDING; // will complete when looped back
#undef OpenP
}
//
// SetLoopbackFlag
//
// sets the loopback flag in the reserved section of a packet
// if it has a multicast destination address
//
static
VOID
TestMacSetLoopbackFlag(
IN OUT PNDIS_PACKET Packet
)
{
UINT Dummy;
PNDIS_BUFFER FirstBuf;
PVOID BufVA;
PMAC_RESERVED Reserved = RESERVED(Packet);
#if 0
NdisQueryPacket(Packet, NULL, &Dummy, &FirstBuf, NULL);
NdisQueryBuffer(FirstBuf, NULL, &BufVA, &Dummy);
Reserved->Loopback = (BOOLEAN)((((PUCHAR)BufVA)[0] & 1) != 0);
#else
Dummy; FirstBuf; BufVA;
Reserved->Loopback = TRUE;
#endif
}
//
// LoopbackPacket
//
// put a packet on the loopback queue
//
// - call this with LoopbackSpinLock held
//
//
static
VOID
TestMacLoopbackPacket(
IN PADAPTER_BLOCK AdaptP,
IN OUT PNDIS_PACKET Packet
)
{
PMAC_RESERVED Reserved = RESERVED(Packet);
if (AdaptP->LoopbackQueue == (PNDIS_PACKET)NULL) {
AdaptP->LoopbackQueue = Packet;
AdaptP->LoopbackQTail = Packet;
} else {
PMAC_RESERVED Res2 = RESERVED(AdaptP->LoopbackQTail);
Res2->NextPacket = Packet;
AdaptP->LoopbackQTail = Packet;
}
Reserved->NextPacket = (PNDIS_PACKET)NULL;
if (!AdaptP->DpcQueued) {
AdaptP->DpcQueued = TRUE;
KeInsertQueueDpc(&AdaptP->IndicateDpc, NULL, NULL);
}
}
//
// IndicateLoopbackPacket
//
// indicates a loopback packet to the protocols
//
// - the protocol must want to receive multicast/broadcast packets
// - the address must be on his multicast list
//
static
VOID
TestMacIndicateLoopbackPacket(
IN PADAPTER_BLOCK AdaptP,
IN PNDIS_PACKET Packet
)
{
PMULTICAST_ENTRY MCSlot;
POPEN_BLOCK CurOpen;
MASK EffectiveMask;
UINT IndicateLen;
UINT PacketLen;
NDIS_STATUS Status;
// copy destination address of packet into AdaptP->Lookahead
if (TestMacCopyOver(AdaptP->Lookahead, Packet, 0, ADDRESS_LEN) < ADDRESS_LEN) {
return;
// error, runt packet
}
NdisAcquireSpinLock(&AdaptP->MulticastSpinLock);
AdaptP->MulticastDontModify = TRUE;
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
if (AdaptP->Lookahead[0] & 1) {
// if bit x in EffectiveMask is on, the protocol x wants this packet
MCSlot = TestMacFindMulticastAddress(AdaptP->MulticastList,
AdaptP->MulticastListSize, AdaptP->Lookahead);
if (MCSlot == (PMULTICAST_ENTRY)NULL)
EffectiveMask = AdaptP->MulticastFilter | AdaptP->PromiscuousFilter;
else if (MCSlot == &AdaptP->MulticastList[0]) // broadcast
EffectiveMask = AdaptP->BroadcastFilter | AdaptP->PromiscuousFilter;
else
EffectiveMask = MCSlot->ProtocolMask &
(AdaptP->MulticastFilter | AdaptP->AllMulticastFilter |
AdaptP->PromiscuousFilter);
} else {
EffectiveMask = AdaptP->DirectedFilter | AdaptP->PromiscuousFilter;
}
// as long as somebody wants it, indicate it
if (EffectiveMask != 0) {
PacketLen = TestMacPacketSize(Packet);
IndicateLen = (PacketLen > 256) ? 256 : PacketLen;
// copy the lookahead data into a contiguous buffer
TestMacCopyOver(AdaptP->Lookahead+ADDRESS_LEN,
Packet, ADDRESS_LEN, IndicateLen-ADDRESS_LEN);
CurOpen = AdaptP->OpenQueue;
while (CurOpen) {
if (CurOpen->MulticastBit & EffectiveMask) {
NdisIndicateReceive(&Status,
CurOpen->NdisBindingContext,
(NDIS_HANDLE)AdaptP,
AdaptP->Lookahead,
IndicateLen,
PacketLen);
}
CurOpen = CurOpen->NextOpen;
}
}
NdisAcquireSpinLock(&AdaptP->MulticastSpinLock);
AdaptP->MulticastDontModify = FALSE;
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
}
//
// PacketSize
//
// returns the number of bytes of data in a packet
//
static
UINT
TestMacPacketSize(
IN PNDIS_PACKET Packet
)
{
PNDIS_BUFFER CurBuffer;
UINT Dummy;
UINT BufLen;
UINT TotLen;
TotLen = 0;
NdisQueryPacket(Packet, NULL, &Dummy, &CurBuffer, NULL);
while (CurBuffer != (PNDIS_BUFFER)NULL) {
NdisQueryBuffer(CurBuffer, NULL, NULL, &BufLen);
TotLen += BufLen;
NdisGetNextBuffer(CurBuffer, &CurBuffer);
}
return TotLen;
}
//
// CopyOver
//
// copy bytes from a packet into a buffer
//
// - returns the actual number of bytes copied
//
static
UINT
TestMacCopyOver(
OUT PUCHAR Buf, // destination
IN PNDIS_PACKET Packet, // source packet
IN UINT Offset, // offset in packet
IN UINT Length // number of bytes to copy
)
{
PNDIS_BUFFER CurBuffer;
UINT Dummy;
UINT BytesCopied;
PUCHAR BufVA;
UINT BufLen;
UINT ToCopy;
UINT CurOffset;
BytesCopied = 0;
// first move to Offset bytes into the packet
CurOffset = 0;
NdisQueryPacket(Packet, NULL, &Dummy, &CurBuffer, NULL);
while (CurBuffer != (PNDIS_BUFFER)NULL) {
NdisQueryBuffer(CurBuffer, NULL, (PVOID *) &BufVA, &BufLen);
if (CurOffset + BufLen > Offset)
break;
CurOffset += BufLen;
NdisGetNextBuffer(CurBuffer, &CurBuffer);
}
// see if we went off the end of the packet
if (CurBuffer == (PNDIS_BUFFER)NULL)
return 0;
// now copy over Length bytes
BufVA += (Offset - CurOffset);
BufLen -= (Offset - CurOffset);
for (;;) {
ToCopy = (BytesCopied+BufLen > Length) ? Length - BytesCopied : BufLen;
RtlMoveMemory(Buf+BytesCopied, BufVA, ToCopy);
BytesCopied += ToCopy;
if (BytesCopied == Length)
return BytesCopied;
NdisGetNextBuffer(CurBuffer, &CurBuffer);
if (CurBuffer == (PNDIS_BUFFER)NULL)
break;
NdisQueryBuffer(CurBuffer, NULL, (PVOID *) &BufVA, &BufLen);
}
return BytesCopied;
}
//
// NdisTransferData
//
// NDIS function
//
// - AdaptP->LoopbackPacket will be FALSE if this is for a normal
// indication, otherwise it will point to a loopback packet
//
static
NDIS_STATUS
TestMacTransferData(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
#define AdaptP ((PADAPTER_BLOCK)MacReceiveContext)
RequestHandle; ByteOffset; BytesToTransfer; Packet; BytesTransferred;
if (OpenP->Debug)
DbgPrint("--> TestMacTransferData %d\n", AdaptP->AdapterNumber);
if (AdaptP->LoopbackPacket != (PNDIS_PACKET)NULL) {
PNDIS_BUFFER CurBuffer;
UINT Dummy;
PUCHAR BufVA;
UINT BufLen, Copied;
UINT CurOff;
// have to copy data from AdaptP->LoopbackPacket into Packet
NdisQueryPacket(Packet, NULL, &Dummy, &CurBuffer, NULL);
CurOff = ByteOffset;
while (CurBuffer != (PNDIS_BUFFER)NULL) {
NdisQueryBuffer(CurBuffer, NULL, (PVOID *) &BufVA, &BufLen);
Copied = TestMacCopyOver(BufVA, AdaptP->LoopbackPacket,
CurOff, BufLen);
CurOff += Copied;
if (Copied < BufLen)
break;
NdisGetNextBuffer(CurBuffer, &CurBuffer);
}
*BytesTransferred = CurOff - ByteOffset;
}
return NDIS_STATUS_SUCCESS;
#undef AdaptP
#undef OpenP
}
//
// MacQueryInformation
//
// NDIS function
//
static
NDIS_STATUS
TestMacQueryInformation(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN NDIS_INFORMATION_CLASS InformationClass,
OUT PVOID Buffer,
IN UINT BufferLength
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
UINT i;
static UCHAR StationAddress[] = { 0x00, 0x00, 0x00, 0x01, 0x02, 0x03 };
RequestHandle; InformationClass; Buffer; BufferLength;
if (OpenP->Debug)
DbgPrint("--> TestMacQueryInformation %d\n", AdaptP->AdapterNumber);
switch (InformationClass) {
case NdisInfoStationAddress:
RtlMoveMemory(Buffer, StationAddress, 6);
break;
}
#if 0
if ((UINT)InformationClass == 1) {
// show multicast list
PMULTICAST_ENTRY MCSlot, End;
POPEN_BLOCK CurOpen;
PUCHAR Tcp;
NdisAcquireSpinLock(&AdaptP->MulticastSpinLock);
AdaptP->MulticastDontModify = TRUE;
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
MCSlot = AdaptP->MulticastList;
End = &AdaptP->MulticastList[AdaptP->MulticastListSize];
while (MCSlot < End) {
Tcp = MCSlot->Address;
for (i=0; i<6; i++) {
if (Tcp[i] >= ' ' && Tcp[i] <= 'z')
DbgPrint(" %c ", Tcp[i]);
else
DbgPrint("%2x ", Tcp[i]);
}
CurOpen = AdaptP->OpenQueue;
while (CurOpen != (POPEN_BLOCK)NULL) {
if (CurOpen->MulticastBit & MCSlot->ProtocolMask)
DbgPrint(CurOpen == OpenP ? " X" : " x");
else
DbgPrint(" ");
CurOpen = CurOpen->NextOpen;
}
DbgPrint("\n");
++MCSlot;
}
NdisAcquireSpinLock(&AdaptP->MulticastSpinLock);
AdaptP->MulticastDontModify = FALSE;
NdisReleaseSpinLock(&AdaptP->MulticastSpinLock);
}
#else
i;
#endif
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
//
// MacSetInformation
//
// NDIS function
//
static
NDIS_STATUS
TestMacSetInformation(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle,
IN NDIS_INFORMATION_CLASS InformationClass,
IN PVOID Buffer,
IN UINT BufferLength
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
RequestHandle; InformationClass; Buffer; BufferLength;
if (OpenP->Debug)
DbgPrint("--> TestMacSetInformation %d\n", AdaptP->AdapterNumber);
// this will involve the OpenData and AdapterData structures
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
//
// MacReset
//
// NDIS function
//
static
NDIS_STATUS
TestMacReset(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
POPEN_BLOCK TmpOpenP;
RequestHandle;
if (OpenP->Debug)
DbgPrint("--> TestMacReset %d\n", AdaptP->AdapterNumber);
TmpOpenP = AdaptP->OpenQueue;
while (TmpOpenP != (POPEN_BLOCK)NULL) {
NdisIndicateStatus(TmpOpenP->NdisBindingContext, NDIS_STATUS_RESET, 0);
TmpOpenP = TmpOpenP->NextOpen;
}
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
//
// MacTest
//
// NDIS function
//
static
NDIS_STATUS
TestMacTest(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE RequestHandle
)
{
#define OpenP ((POPEN_BLOCK)MacBindingHandle)
PADAPTER_BLOCK AdaptP = OpenP->AdapterBlock;
RequestHandle;
if (OpenP->Debug)
DbgPrint("--> TestMacTest %d\n", AdaptP->AdapterNumber);
return NDIS_STATUS_SUCCESS;
#undef OpenP
}
static
VOID
TestMacIndicateDpc(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
#define AdaptP ((PADAPTER_BLOCK)DeferredContext)
PNDIS_PACKET LPacket;
PMAC_RESERVED Reserved;
POPEN_BLOCK CurOpen;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
// loopback any waiting packets
NdisAcquireSpinLock(&AdaptP->LoopbackSpinLock);
while (AdaptP->LoopbackQueue) {
// take the first packet off the queue
LPacket = AdaptP->LoopbackQueue;
Reserved = RESERVED(LPacket);
AdaptP->LoopbackQueue = RESERVED(AdaptP->LoopbackQueue)->NextPacket;
NdisReleaseSpinLock(&AdaptP->LoopbackSpinLock);
AdaptP->LoopbackPacket = LPacket;
// actually indicate it
TestMacIndicateLoopbackPacket(AdaptP, AdaptP->LoopbackPacket);
NdisAcquireSpinLock(&AdaptP->LoopbackSpinLock);
// complete the packet if needed
if (Reserved->RequestHandle != 0) {
NdisCompleteSend(
Reserved->OpenBlock->NdisBindingContext,
Reserved->RequestHandle,
NDIS_STATUS_SUCCESS);
}
}
AdaptP->DpcQueued = FALSE;
NdisReleaseSpinLock(&AdaptP->LoopbackSpinLock);
// indicate ReceiveComplete
CurOpen = AdaptP->OpenQueue;
while (CurOpen) {
NdisIndicateReceiveComplete(CurOpen->NdisBindingContext);
CurOpen = CurOpen->NextOpen;
}
#undef AdaptP
}