601 lines
15 KiB
C
601 lines
15 KiB
C
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pkt.c
|
|
|
|
Abstract:
|
|
|
|
ARP1394 ARP control packet management.
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
josephj 07-01-99 Created
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
#include <precomp.h>
|
|
|
|
//
|
|
// File-specific debugging defaults.
|
|
//
|
|
#define TM_CURRENT TM_PKT
|
|
|
|
//=========================================================================
|
|
// L O C A L P R O T O T Y P E S
|
|
//=========================================================================
|
|
|
|
NDIS_STATUS
|
|
arpAllocateControlPacketPool(
|
|
PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
|
|
UINT MaxBufferSize,
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Allocate & initialize the packet pool used for allocating control packets.
|
|
Control packets are used for ARP and MCAP. This routine MUST be called
|
|
BEFORE the first call to arpAllocateControlPacket.
|
|
|
|
Arguments:
|
|
|
|
pIF - The interface in which to allocate the pool. Only one such pool
|
|
is allocated per interface and it occupies a specific field of
|
|
pIF.
|
|
MaxBufferSize - Maximum data size of packets to be allocated using this
|
|
pool. Attempts to allocate a packet
|
|
(using arpAllocateControlPacket) with a size larger than
|
|
MaxBufferSize will fail.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS on success.
|
|
Ndis error code on failure.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE PacketPool=NULL;
|
|
NDIS_HANDLE BufferPool=NULL;
|
|
ENTER("arpAllocateControlPacketPool", 0x71579254)
|
|
|
|
RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR);
|
|
ASSERT(pIF->arp.PacketPool == NULL);
|
|
ASSERT(pIF->arp.BufferPool == NULL);
|
|
ASSERT(pIF->arp.NumOutstandingPackets == 0);
|
|
|
|
do
|
|
{
|
|
// Allocate the NDIS Packet Pool
|
|
//
|
|
NdisAllocatePacketPool(
|
|
&Status,
|
|
&PacketPool,
|
|
ARP1394_MAX_PROTOCOL_PKTS,
|
|
sizeof(struct PCCommon)
|
|
);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
PacketPool = NULL;
|
|
break;
|
|
}
|
|
|
|
// Allocate the NDIS Buffer Pool
|
|
//
|
|
NdisAllocateBufferPool(
|
|
&Status,
|
|
&BufferPool,
|
|
ARP1394_MAX_PROTOCOL_PKTS
|
|
);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
BufferPool = NULL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We could allocate a lookaside list for the Protocol data, but we
|
|
// choose to use NdisAllocateMemoryWithTag on demand instead. Protocol pkts
|
|
// are not high-frequency things; plus we don't have support for lookaside
|
|
// lists on win98 (although we could easily implement our own for
|
|
// win98, so that's not really an excuse).
|
|
//
|
|
pIF->arp.MaxBufferSize = MaxBufferSize;
|
|
|
|
// (DBG only) Add associations for the packet pool and buffer pool.
|
|
// These associations must be removed before the interface is deallocated.
|
|
//
|
|
DBG_ADDASSOC(
|
|
&pIF->Hdr, // pObject
|
|
PacketPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_PROTOPKTPOOL, // AssociationID
|
|
" Proto Packet Pool 0x%p\n",// szFormat
|
|
pSR
|
|
);
|
|
DBG_ADDASSOC(
|
|
&pIF->Hdr, // pObject
|
|
BufferPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_PROTOBUFPOOL, // AssociationID
|
|
" Proto Buffer Pool 0x%p\n",// szFormat
|
|
pSR
|
|
);
|
|
|
|
pIF->arp.PacketPool = PacketPool;
|
|
pIF->arp.BufferPool = BufferPool;
|
|
PacketPool = NULL;
|
|
BufferPool = NULL;
|
|
|
|
} while (FALSE);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
if (PacketPool != NULL)
|
|
{
|
|
NdisFreePacketPool(PacketPool);
|
|
}
|
|
|
|
if (BufferPool != NULL)
|
|
{
|
|
NdisFreeBufferPool(BufferPool);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(PacketPool == NULL && BufferPool == NULL);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
arpFreeControlPacketPool(
|
|
PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Free the previously allocated control packet pool. MUST be called AFTER the last
|
|
call to arpFreeControlPacket. See arpAllocateControlPacketPool for more details.
|
|
|
|
Arguments:
|
|
|
|
pIF - The interface in which to free the pool.
|
|
|
|
--*/
|
|
{
|
|
NDIS_HANDLE PacketPool;
|
|
NDIS_HANDLE BufferPool;
|
|
ENTER("arpFreeControlPacketPool", 0x3c3acf47)
|
|
|
|
// Make sure the IF is locked.
|
|
//
|
|
RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR);
|
|
|
|
// Make sure that there are no outstanding allocated packets.
|
|
//
|
|
ASSERT(pIF->arp.NumOutstandingPackets == 0);
|
|
|
|
PacketPool = pIF->arp.PacketPool;
|
|
BufferPool = pIF->arp.BufferPool;
|
|
pIF->arp.PacketPool = NULL;
|
|
pIF->arp.BufferPool = NULL;
|
|
|
|
// (DBG only) Remove associations for the control and packet pools.
|
|
//
|
|
DBG_DELASSOC(
|
|
&pIF->Hdr, // pObject
|
|
PacketPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_PROTOPKTPOOL, // AssociationID
|
|
pSR
|
|
);
|
|
DBG_DELASSOC(
|
|
&pIF->Hdr, // pObject
|
|
BufferPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_PROTOBUFPOOL, // AssociationID
|
|
pSR
|
|
);
|
|
|
|
// Free the buffer and packet pools
|
|
//
|
|
NdisFreeBufferPool(BufferPool);
|
|
NdisFreePacketPool(PacketPool);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
arpAllocateControlPacket(
|
|
IN PARP1394_INTERFACE pIF,
|
|
IN UINT cbBufferSize,
|
|
IN UINT PktFlags,
|
|
OUT PNDIS_PACKET *ppNdisPacket,
|
|
OUT PVOID *ppvData,
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Allocate a control packet from the interfaces control packet pool. Also
|
|
allocate and chain a SINGLE buffer of size cbBufferSize and return a pointer to
|
|
this buffer in *ppvData.
|
|
|
|
NOTE1: The packet and associated buffer MUST be freed
|
|
by a subsequent call to arpFreeControlPacket -- do not free the packet & buffer
|
|
by directly calling ndis apis.
|
|
|
|
NOTE2: cbBufferSize must be <= the max-buffer-size specified when
|
|
creating the pool (see arpAllocateControlPacketPool for details).
|
|
|
|
Arguments:
|
|
|
|
pIF - Interface whose control packet pool to use.
|
|
cbBufferSize - size of the control packet.
|
|
ppNdisPacket - Location to set to point to the allocated pkt.
|
|
ppvData - Location to set to point to the packet data (single buffer).
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS on success.
|
|
NDIS_STATUS_RESOURCES if buffers or pkts are currently not available.
|
|
Other ndis error on other kinds of failures.
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
PNDIS_PACKET pNdisPacket = NULL;
|
|
PNDIS_BUFFER pNdisBuffer = NULL;
|
|
PVOID pvData = NULL;
|
|
ENTER("arpAllocateControlPacket", 0x8ccce6ea)
|
|
|
|
//
|
|
// NOTE: we don't care if pIF is locked or not.
|
|
//
|
|
|
|
|
|
pNdisPacket = NULL;
|
|
pvData = NULL;
|
|
|
|
do
|
|
{
|
|
|
|
// Allocate space for the packet data.
|
|
// TODO: here is where we could use a lookaside list instead
|
|
// of NdisAllocateMemoryWithTag.
|
|
//
|
|
{
|
|
if (cbBufferSize > pIF->arp.MaxBufferSize)
|
|
{
|
|
ASSERT(FALSE);
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
NdisAllocateMemoryWithTag(
|
|
&pvData,
|
|
cbBufferSize,
|
|
MTAG_PKT
|
|
);
|
|
if (pvData == NULL)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Allocate a buffer.
|
|
//
|
|
NdisAllocateBuffer(
|
|
&Status,
|
|
&pNdisBuffer,
|
|
pIF->arp.BufferPool,
|
|
pvData,
|
|
cbBufferSize
|
|
);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
pNdisBuffer = NULL;
|
|
break;
|
|
}
|
|
|
|
// Allocate a packet
|
|
//
|
|
NdisAllocatePacket(
|
|
&Status,
|
|
&pNdisPacket,
|
|
pIF->arp.PacketPool
|
|
);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
pNdisPacket = NULL;
|
|
break;
|
|
}
|
|
|
|
// Identify the packet as belonging to us (ARP).
|
|
//
|
|
{
|
|
struct PacketContext *PC;
|
|
PC = (struct PacketContext *)pNdisPacket->ProtocolReserved;
|
|
PC->pc_common.pc_owner = PACKET_OWNER_LINK;
|
|
PC->pc_common.pc_flags = (UCHAR)PktFlags; // ARP1394_PACKET_FLAGS_CONTROL;
|
|
}
|
|
|
|
// Link the packet and buffer.
|
|
//
|
|
NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
|
|
|
|
InterlockedIncrement(&pIF->arp.NumOutstandingPackets);
|
|
*ppNdisPacket = pNdisPacket;
|
|
*ppvData = pvData;
|
|
|
|
pNdisPacket = NULL;
|
|
pNdisBuffer = NULL;
|
|
pvData = NULL;
|
|
|
|
} while (FALSE);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
if (pNdisPacket != NULL)
|
|
{
|
|
NdisFreePacket(pNdisPacket);
|
|
}
|
|
if (pNdisBuffer != NULL)
|
|
{
|
|
NdisFreeBuffer(pNdisBuffer);
|
|
}
|
|
if (pvData != NULL)
|
|
{
|
|
NdisFreeMemory(pvData, 0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(pNdisPacket == NULL
|
|
&& pNdisBuffer == NULL
|
|
&& pvData == NULL);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
arpFreeControlPacket(
|
|
PARP1394_INTERFACE pIF,
|
|
PNDIS_PACKET pNdisPacket,
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Free a packet previously allocated using arpAllocateControlPacket.
|
|
|
|
Arguments:
|
|
|
|
pIF - Interface whose control packet pool to use.
|
|
--*/
|
|
{
|
|
PNDIS_BUFFER pNdisBuffer = NULL;
|
|
PVOID pvData = NULL;
|
|
|
|
ENTER("arpFreeControlPacket", 0x01e7fbc7)
|
|
|
|
// (DBG only) Verify that this packet belongs to us.
|
|
//
|
|
#if DBG
|
|
{
|
|
struct PacketContext *PC;
|
|
PC = (struct PacketContext *)pNdisPacket->ProtocolReserved;
|
|
ASSERT(PC->pc_common.pc_owner == PACKET_OWNER_LINK);
|
|
}
|
|
#endif // DBG
|
|
|
|
// Decrement the allocated packet count.
|
|
//
|
|
{
|
|
LONG Count;
|
|
Count = InterlockedDecrement(&pIF->arp.NumOutstandingPackets);
|
|
ASSERT(Count >= 0);
|
|
}
|
|
|
|
// Extract the buffer and data
|
|
//
|
|
{
|
|
UINT TotalLength;
|
|
UINT BufferLength;
|
|
|
|
NdisQueryPacket(
|
|
pNdisPacket,
|
|
NULL,
|
|
NULL,
|
|
&pNdisBuffer,
|
|
&TotalLength
|
|
);
|
|
|
|
if (TotalLength > 0)
|
|
{
|
|
NdisQueryBuffer(
|
|
pNdisBuffer,
|
|
&pvData,
|
|
&BufferLength
|
|
);
|
|
}
|
|
else
|
|
{
|
|
BufferLength = 0;
|
|
}
|
|
|
|
// There should only be a single buffer!
|
|
//
|
|
ASSERT(TotalLength!=0 && TotalLength == BufferLength);
|
|
}
|
|
|
|
// Free the data
|
|
//
|
|
if (pvData != NULL)
|
|
{
|
|
NdisFreeMemory(pvData, 0, 0);
|
|
}
|
|
// Free the buffer
|
|
//
|
|
if (pNdisBuffer != NULL)
|
|
{
|
|
NdisFreeBuffer(pNdisBuffer);
|
|
}
|
|
// Free the packet
|
|
//
|
|
if (pNdisPacket != NULL)
|
|
{
|
|
NdisFreePacket(pNdisPacket);
|
|
}
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
arpAllocateEthernetPools(
|
|
IN PARP1394_INTERFACE pIF,
|
|
IN PRM_STACK_RECORD pSR
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE PacketPool=NULL;
|
|
NDIS_HANDLE BufferPool=NULL;
|
|
ENTER("arpAllocateEthernetPools", 0x9dc1d759)
|
|
|
|
RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR);
|
|
ASSERT(pIF->ethernet.PacketPool == NULL);
|
|
ASSERT(pIF->ethernet.BufferPool == NULL);
|
|
|
|
do
|
|
{
|
|
// Allocate the NDIS Packet Pool
|
|
//
|
|
NdisAllocatePacketPool(
|
|
&Status,
|
|
&PacketPool,
|
|
ARP1394_MAX_ETHERNET_PKTS,
|
|
sizeof(struct PCCommon)
|
|
);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
PacketPool = NULL;
|
|
break;
|
|
}
|
|
|
|
// Allocate the NDIS Buffer Pool
|
|
//
|
|
NdisAllocateBufferPool(
|
|
&Status,
|
|
&BufferPool,
|
|
2*ARP1394_MAX_ETHERNET_PKTS // two buffers per packet.
|
|
);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
BufferPool = NULL;
|
|
break;
|
|
}
|
|
|
|
// (DBG only) Add associations for the ethernet packet pool and buffer pool.
|
|
// These associations must be removed before the interface is deallocated.
|
|
//
|
|
DBG_ADDASSOC(
|
|
&pIF->Hdr, // pObject
|
|
PacketPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_ETHPKTPOOL, // AssociationID
|
|
" Eth Packet Pool 0x%p\n",// szFormat
|
|
pSR
|
|
);
|
|
DBG_ADDASSOC(
|
|
&pIF->Hdr, // pObject
|
|
BufferPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_ETHBUFPOOL, // AssociationID
|
|
" Eth Buffer Pool 0x%p\n",// szFormat
|
|
pSR
|
|
);
|
|
|
|
pIF->ethernet.PacketPool = PacketPool;
|
|
pIF->ethernet.BufferPool = BufferPool;
|
|
PacketPool = NULL;
|
|
BufferPool = NULL;
|
|
|
|
} while (FALSE);
|
|
|
|
if (FAIL(Status))
|
|
{
|
|
if (PacketPool != NULL)
|
|
{
|
|
NdisFreePacketPool(PacketPool);
|
|
}
|
|
|
|
if (BufferPool != NULL)
|
|
{
|
|
NdisFreeBufferPool(BufferPool);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(PacketPool == NULL && BufferPool == NULL);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
arpFreeEthernetPools(
|
|
IN PARP1394_INTERFACE pIF,
|
|
IN PRM_STACK_RECORD pSR
|
|
)
|
|
{
|
|
NDIS_HANDLE PacketPool;
|
|
NDIS_HANDLE BufferPool;
|
|
ENTER("arpFreeEthernetPools", 0x3e780760)
|
|
|
|
// Make sure the IF is locked.
|
|
//
|
|
RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR);
|
|
|
|
PacketPool = pIF->ethernet.PacketPool;
|
|
BufferPool = pIF->ethernet.BufferPool;
|
|
pIF->ethernet.PacketPool = NULL;
|
|
pIF->ethernet.BufferPool = NULL;
|
|
|
|
// (DBG only) Remove associations for the control and packet pools.
|
|
//
|
|
DBG_DELASSOC(
|
|
&pIF->Hdr, // pObject
|
|
PacketPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_ETHPKTPOOL, // AssociationID
|
|
pSR
|
|
);
|
|
DBG_DELASSOC(
|
|
&pIF->Hdr, // pObject
|
|
BufferPool, // Instance1
|
|
NULL, // Instance2
|
|
ARPASSOC_IF_ETHBUFPOOL, // AssociationID
|
|
pSR
|
|
);
|
|
|
|
// Free the buffer and packet pools
|
|
//
|
|
NdisFreeBufferPool(BufferPool);
|
|
NdisFreePacketPool(PacketPool);
|
|
}
|