|
|
/*++
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); }
|