1318 lines
27 KiB
C
1318 lines
27 KiB
C
/*++
|
||
Copyright (c) 1989-1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
packet.c
|
||
|
||
Abstract:
|
||
|
||
This module contains code that implements the SEND_PACKET and
|
||
RECEIVE_PACKET objects, which describe NDIS packets used
|
||
by the transport.
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
Sanjay Anand (SanjayAn) - 22-Sept-1995
|
||
BackFill optimization changes added under #if BACK_FILL
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
|
||
NTSTATUS
|
||
IpxInitializeSendPacket(
|
||
IN PDEVICE Device,
|
||
IN PIPX_SEND_PACKET Packet,
|
||
IN PUCHAR Header
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes a send packet by chaining the
|
||
buffer for the header on it.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Packet - The packet to initialize.
|
||
|
||
Header - Points to storage for the header.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NDIS_STATUS NdisStatus;
|
||
NTSTATUS Status;
|
||
PNDIS_BUFFER NdisMacBuffer;
|
||
PNDIS_BUFFER NdisIpxBuffer;
|
||
PIPX_SEND_RESERVED Reserved;
|
||
|
||
IpxAllocateSendPacket (Device, Packet, &Status);
|
||
|
||
if (Status != STATUS_SUCCESS) {
|
||
// ERROR LOG
|
||
return Status;
|
||
}
|
||
|
||
NdisAllocateBuffer(
|
||
&NdisStatus,
|
||
&NdisMacBuffer,
|
||
Device->NdisBufferPoolHandle,
|
||
Header,
|
||
MAC_HEADER_SIZE);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
IpxFreeSendPacket (Device, Packet);
|
||
// ERROR LOG
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
NdisAllocateBuffer(
|
||
&NdisStatus,
|
||
&NdisIpxBuffer,
|
||
Device->NdisBufferPoolHandle,
|
||
Header + MAC_HEADER_SIZE,
|
||
IPX_HEADER_SIZE + RIP_PACKET_SIZE);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
IpxFreeSendPacket (Device, Packet);
|
||
// ERROR LOG
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
NdisChainBufferAtFront (PACKET(Packet), NdisMacBuffer);
|
||
NdisChainBufferAtBack (PACKET(Packet), NdisIpxBuffer);
|
||
|
||
//
|
||
// This flag optimizes the virtual to physical address X-ln
|
||
// in the MAC drivers on x86
|
||
//
|
||
NdisMacBuffer->MdlFlags|=MDL_NETWORK_HEADER;
|
||
NdisIpxBuffer->MdlFlags|=MDL_NETWORK_HEADER;
|
||
|
||
Reserved = SEND_RESERVED(Packet);
|
||
Reserved->Identifier = IDENTIFIER_IPX;
|
||
Reserved->SendInProgress = FALSE;
|
||
Reserved->Header = Header;
|
||
Reserved->HeaderBuffer = NdisMacBuffer;
|
||
Reserved->PaddingBuffer = NULL;
|
||
#if BACK_FILL
|
||
Reserved->BackFill = FALSE;
|
||
#endif
|
||
|
||
ExInterlockedInsertHeadList(
|
||
&Device->GlobalSendPacketList,
|
||
&Reserved->GlobalLinkage,
|
||
&Device->Lock);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* IpxInitializeSendPacket */
|
||
|
||
#if BACK_FILL
|
||
NTSTATUS
|
||
IpxInitializeBackFillPacket(
|
||
IN PDEVICE Device,
|
||
IN PIPX_SEND_PACKET Packet,
|
||
IN PUCHAR Header
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes a send packet by chaining the
|
||
buffer for the header on it.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Packet - The packet to initialize.
|
||
|
||
Header - Points to storage for the header.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NDIS_STATUS NdisStatus;
|
||
NTSTATUS Status;
|
||
PNDIS_BUFFER NdisMacBuffer;
|
||
PNDIS_BUFFER NdisIpxBuffer;
|
||
PIPX_SEND_RESERVED Reserved;
|
||
|
||
|
||
IPX_DEBUG (PACKET, ("Initializing backfill packet\n"));
|
||
IpxAllocateSendPacket (Device, Packet, &Status);
|
||
|
||
if (Status != STATUS_SUCCESS) {
|
||
// ERROR LOG
|
||
return Status;
|
||
}
|
||
|
||
|
||
Reserved = SEND_RESERVED(Packet);
|
||
Reserved->Identifier = IDENTIFIER_IPX;
|
||
Reserved->SendInProgress = FALSE;
|
||
Reserved->Header = NULL;
|
||
Reserved->HeaderBuffer = NULL;
|
||
Reserved->PaddingBuffer = NULL;
|
||
Reserved->BackFill = TRUE;
|
||
|
||
ExInterlockedInsertHeadList(
|
||
&Device->GlobalBackFillPacketList,
|
||
&Reserved->GlobalLinkage,
|
||
&Device->Lock);
|
||
|
||
IPX_DEBUG (PACKET, ("Initializing backfill packet Done\n"));
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* IpxInitializeBackFillPacket */
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
IpxInitializeReceivePacket(
|
||
IN PDEVICE Device,
|
||
IN PIPX_RECEIVE_PACKET Packet
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes a receive packet.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Packet - The packet to initialize.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
PIPX_RECEIVE_RESERVED Reserved;
|
||
|
||
IpxAllocateReceivePacket (Device, Packet, &Status);
|
||
|
||
if (Status != STATUS_SUCCESS) {
|
||
// ERROR LOG
|
||
return Status;
|
||
}
|
||
|
||
Reserved = RECEIVE_RESERVED(Packet);
|
||
Reserved->Identifier = IDENTIFIER_IPX;
|
||
Reserved->TransferInProgress = FALSE;
|
||
Reserved->SingleRequest = NULL;
|
||
Reserved->ReceiveBuffer = NULL;
|
||
InitializeListHead (&Reserved->Requests);
|
||
|
||
ExInterlockedInsertHeadList(
|
||
&Device->GlobalReceivePacketList,
|
||
&Reserved->GlobalLinkage,
|
||
&Device->Lock);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* IpxInitializeReceivePacket */
|
||
|
||
|
||
NTSTATUS
|
||
IpxInitializeReceiveBuffer(
|
||
IN PADAPTER Adapter,
|
||
IN PIPX_RECEIVE_BUFFER ReceiveBuffer,
|
||
IN PUCHAR DataBuffer,
|
||
IN ULONG DataBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes a receive buffer by allocating
|
||
an NDIS_BUFFER to describe the data buffer.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter.
|
||
|
||
ReceiveBuffer - The receive buffer to initialize.
|
||
|
||
DataBuffer - The data buffer.
|
||
|
||
DataBufferLength - The length of the data buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NDIS_STATUS NdisStatus;
|
||
PNDIS_BUFFER NdisBuffer;
|
||
PDEVICE Device = Adapter->Device;
|
||
|
||
|
||
NdisAllocateBuffer(
|
||
&NdisStatus,
|
||
&NdisBuffer,
|
||
Device->NdisBufferPoolHandle,
|
||
DataBuffer,
|
||
DataBufferLength);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
// ERROR LOG
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
ReceiveBuffer->NdisBuffer = NdisBuffer;
|
||
ReceiveBuffer->Data = DataBuffer;
|
||
ReceiveBuffer->DataLength = 0;
|
||
|
||
ExInterlockedInsertHeadList(
|
||
&Device->GlobalReceiveBufferList,
|
||
&ReceiveBuffer->GlobalLinkage,
|
||
&Device->Lock);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* IpxInitializeReceiveBuffer */
|
||
|
||
|
||
NTSTATUS
|
||
IpxInitializePaddingBuffer(
|
||
IN PDEVICE Device,
|
||
IN PIPX_PADDING_BUFFER PaddingBuffer,
|
||
IN ULONG DataBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes a padding buffer by allocating
|
||
an NDIS_BUFFER to describe the data buffer.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter.
|
||
|
||
PaddingBuffer - The receive buffer to initialize.
|
||
|
||
DataBufferLength - The length of the data buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NDIS_STATUS NdisStatus;
|
||
PNDIS_BUFFER NdisBuffer;
|
||
|
||
NdisAllocateBuffer(
|
||
&NdisStatus,
|
||
&NdisBuffer,
|
||
Device->NdisBufferPoolHandle,
|
||
PaddingBuffer->Data,
|
||
DataBufferLength);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
// ERROR LOG
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
NDIS_BUFFER_LINKAGE(NdisBuffer) = (PNDIS_BUFFER)NULL;
|
||
PaddingBuffer->NdisBuffer = NdisBuffer;
|
||
PaddingBuffer->DataLength = DataBufferLength;
|
||
RtlZeroMemory (PaddingBuffer->Data, DataBufferLength);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* IpxInitializePaddingBuffer */
|
||
|
||
|
||
VOID
|
||
IpxDeinitializeSendPacket(
|
||
IN PDEVICE Device,
|
||
IN PIPX_SEND_PACKET Packet
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deinitializes a send packet.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Packet - The packet to deinitialize.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PNDIS_BUFFER NdisBuffer;
|
||
PNDIS_BUFFER NdisIpxBuffer;
|
||
PIPX_SEND_RESERVED Reserved;
|
||
CTELockHandle LockHandle;
|
||
|
||
|
||
Reserved = SEND_RESERVED(Packet);
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
RemoveEntryList (&Reserved->GlobalLinkage);
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
|
||
//
|
||
// Free the packet in a slightly unconventional way; this
|
||
// allows us to not have to NULL out HeaderBuffer's linkage
|
||
// field during normal operations when we put it back in
|
||
// the free pool.
|
||
//
|
||
|
||
NdisBuffer = Reserved->HeaderBuffer;
|
||
NdisIpxBuffer = NDIS_BUFFER_LINKAGE(NdisBuffer);
|
||
NDIS_BUFFER_LINKAGE (NdisBuffer) = NULL;
|
||
NDIS_BUFFER_LINKAGE (NdisIpxBuffer) = NULL;
|
||
|
||
#if 0
|
||
NdisAdjustBufferLength (NdisBuffer, PACKET_HEADER_SIZE);
|
||
#endif
|
||
NdisAdjustBufferLength (NdisBuffer, MAC_HEADER_SIZE);
|
||
NdisAdjustBufferLength (NdisIpxBuffer, IPX_HEADER_SIZE + RIP_PACKET_SIZE);
|
||
|
||
NdisFreeBuffer (NdisBuffer);
|
||
NdisFreeBuffer (NdisIpxBuffer);
|
||
|
||
NdisReinitializePacket (PACKET(Packet));
|
||
IpxFreeSendPacket (Device, Packet);
|
||
|
||
} /* IpxDeinitializeSendPacket */
|
||
|
||
#if BACK_FILL
|
||
VOID
|
||
IpxDeinitializeBackFillPacket(
|
||
IN PDEVICE Device,
|
||
IN PIPX_SEND_PACKET Packet
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deinitializes a back fill packet.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Packet - The packet to deinitialize.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PNDIS_BUFFER NdisBuffer;
|
||
PNDIS_BUFFER NdisIpxBuffer;
|
||
PIPX_SEND_RESERVED Reserved;
|
||
CTELockHandle LockHandle;
|
||
|
||
IPX_DEBUG (PACKET, ("DeInitializing backfill packet\n"));
|
||
|
||
Reserved = SEND_RESERVED(Packet);
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
RemoveEntryList (&Reserved->GlobalLinkage);
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
|
||
|
||
|
||
NdisReinitializePacket (PACKET(Packet));
|
||
IpxFreeSendPacket (Device, Packet);
|
||
IPX_DEBUG (PACKET, ("DeInitializing backfill packet Done\n"));
|
||
|
||
|
||
} /* IpxDeinitializeBackFillPacket */
|
||
#endif
|
||
|
||
|
||
VOID
|
||
IpxDeinitializeReceivePacket(
|
||
IN PDEVICE Device,
|
||
IN PIPX_RECEIVE_PACKET Packet
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes a receive packet.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Packet - The packet to initialize.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PIPX_RECEIVE_RESERVED Reserved;
|
||
CTELockHandle LockHandle;
|
||
|
||
Reserved = RECEIVE_RESERVED(Packet);
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
RemoveEntryList (&Reserved->GlobalLinkage);
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
|
||
IpxFreeReceivePacket (Device, Packet);
|
||
|
||
} /* IpxDeinitializeReceivePacket */
|
||
|
||
|
||
VOID
|
||
IpxDeinitializeReceiveBuffer(
|
||
IN PADAPTER Adapter,
|
||
IN PIPX_RECEIVE_BUFFER ReceiveBuffer,
|
||
IN ULONG DataBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deinitializes a receive buffer.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
ReceiveBuffer - The receive buffer.
|
||
|
||
DataBufferLength - The allocated length of the receive buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
CTELockHandle LockHandle;
|
||
PDEVICE Device = Adapter->Device;
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
RemoveEntryList (&ReceiveBuffer->GlobalLinkage);
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
|
||
NdisAdjustBufferLength (ReceiveBuffer->NdisBuffer, DataBufferLength);
|
||
NdisFreeBuffer (ReceiveBuffer->NdisBuffer);
|
||
|
||
} /* IpxDeinitializeReceiveBuffer */
|
||
|
||
|
||
VOID
|
||
IpxDeinitializePaddingBuffer(
|
||
IN PDEVICE Device,
|
||
IN PIPX_PADDING_BUFFER PaddingBuffer,
|
||
IN ULONG DataBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deinitializes a padding buffer.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
PaddingBuffer - The padding buffer.
|
||
|
||
DataBufferLength - The allocated length of the padding buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NdisAdjustBufferLength (PaddingBuffer->NdisBuffer, DataBufferLength);
|
||
NdisFreeBuffer (PaddingBuffer->NdisBuffer);
|
||
|
||
} /* IpxDeinitializePaddingBuffer */
|
||
|
||
|
||
VOID
|
||
IpxAllocateSendPool(
|
||
IN PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine adds 10 packets to the pool for this device.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PIPX_SEND_POOL SendPool;
|
||
UINT HeaderSize;
|
||
UINT PacketNum;
|
||
IPX_SEND_PACKET Packet;
|
||
PIPX_SEND_RESERVED Reserved;
|
||
PUCHAR Header;
|
||
NDIS_STATUS Status;
|
||
|
||
CTELockHandle LockHandle;
|
||
|
||
SendPool = (PIPX_SEND_POOL)IpxAllocateMemory (sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
|
||
|
||
if (SendPool == NULL) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate send pool memory\n"));
|
||
return;
|
||
}
|
||
|
||
HeaderSize = PACKET_HEADER_SIZE * Device->InitDatagrams;
|
||
|
||
Header = (PUCHAR)IpxAllocateMemory (HeaderSize, MEMORY_PACKET, "SendPool");
|
||
|
||
if (Header == NULL) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate header memory\n"));
|
||
//290901
|
||
IpxFreeMemory(SendPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
|
||
return;
|
||
}
|
||
|
||
SendPool->PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_NWLNKIPX;
|
||
|
||
NdisAllocatePacketPoolEx(
|
||
&Status,
|
||
&SendPool->PoolHandle,
|
||
Device->InitDatagrams,
|
||
0,
|
||
sizeof(IPX_SEND_RESERVED)
|
||
);
|
||
|
||
if (Status == NDIS_STATUS_RESOURCES) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n"));
|
||
//290901
|
||
IpxFreeMemory(SendPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
|
||
IpxFreeMemory(Header, HeaderSize, MEMORY_PACKET, "SendPool");
|
||
return;
|
||
}
|
||
|
||
NdisSetPacketPoolProtocolId(SendPool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
|
||
|
||
Device->MemoryUsage += Device->InitDatagrams * sizeof(IPX_SEND_RESERVED);
|
||
|
||
IPX_DEBUG (PACKET, ("Initializing send pool %lx, %d packets\n",
|
||
SendPool, Device->InitDatagrams));
|
||
|
||
SendPool->Header = Header;
|
||
|
||
for (PacketNum = 0; PacketNum < Device->InitDatagrams; PacketNum++) {
|
||
|
||
NdisAllocatePacket(&Status, &PACKET(&Packet), SendPool->PoolHandle);
|
||
|
||
if (IpxInitializeSendPacket (Device, &Packet, Header) != STATUS_SUCCESS) {
|
||
IPX_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
|
||
break;
|
||
}
|
||
|
||
Reserved = SEND_RESERVED(&Packet);
|
||
Reserved->Address = NULL;
|
||
Reserved->OwnedByAddress = FALSE;
|
||
#ifdef IPX_TRACK_POOL
|
||
Reserved->Pool = SendPool;
|
||
#endif
|
||
|
||
IPX_PUSH_ENTRY_LIST (&Device->SendPacketList, &Reserved->PoolLinkage, &Device->SListsLock);
|
||
|
||
Header += PACKET_HEADER_SIZE;
|
||
|
||
}
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
|
||
Device->AllocatedDatagrams += PacketNum;
|
||
InsertTailList (&Device->SendPoolList, &SendPool->Linkage);
|
||
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
} /* IpxAllocateSendPool */
|
||
|
||
|
||
#if BACK_FILL
|
||
|
||
VOID
|
||
IpxAllocateBackFillPool(
|
||
IN PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine adds 10 packets to the pool for this device.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT PacketNum;
|
||
IPX_SEND_PACKET Packet;
|
||
PIPX_SEND_RESERVED Reserved;
|
||
CTELockHandle LockHandle;
|
||
PIPX_SEND_POOL BackFillPool;
|
||
NDIS_STATUS Status;
|
||
|
||
IPX_DEBUG (PACKET, ("Allocating backfill pool\n"));
|
||
|
||
// Allocate pool for back fillable packets
|
||
|
||
BackFillPool = (PIPX_SEND_POOL)IpxAllocateMemory (sizeof(IPX_SEND_POOL), MEMORY_PACKET, "BafiPool");
|
||
|
||
if (BackFillPool == NULL) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate backfill pool memory\n"));
|
||
return;
|
||
}
|
||
|
||
BackFillPool->PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_NWLNKIPX;
|
||
|
||
NdisAllocatePacketPoolEx(
|
||
&Status,
|
||
&BackFillPool->PoolHandle,
|
||
Device->InitDatagrams,
|
||
0,
|
||
sizeof(IPX_SEND_RESERVED)
|
||
);
|
||
|
||
if (Status == NDIS_STATUS_RESOURCES) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n"));
|
||
return;
|
||
}
|
||
|
||
NdisSetPacketPoolProtocolId(BackFillPool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
|
||
|
||
Device->MemoryUsage += Device->InitDatagrams * sizeof(IPX_SEND_RESERVED);
|
||
|
||
for (PacketNum = 0; PacketNum < Device->InitDatagrams; PacketNum++) {
|
||
|
||
NdisAllocatePacket(&Status, &PACKET(&Packet), BackFillPool->PoolHandle);
|
||
|
||
if (IpxInitializeBackFillPacket (Device, &Packet, NULL) != STATUS_SUCCESS) {
|
||
IPX_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
|
||
break;
|
||
}
|
||
|
||
Reserved = SEND_RESERVED(&Packet);
|
||
Reserved->Address = NULL;
|
||
Reserved->OwnedByAddress = FALSE;
|
||
#ifdef IPX_TRACK_POOL
|
||
Reserved->Pool = BackFillPool;
|
||
#endif
|
||
|
||
IPX_PUSH_ENTRY_LIST (&Device->BackFillPacketList, &Reserved->PoolLinkage, &Device->SListsLock);
|
||
}
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
|
||
InsertTailList (&Device->BackFillPoolList, &BackFillPool->Linkage);
|
||
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
} /* IpxAllocateBackFillPool */
|
||
|
||
#endif
|
||
|
||
|
||
VOID
|
||
IpxAllocateReceivePool(
|
||
IN PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine adds receive packets to the pool for this device.
|
||
|
||
Arguments:
|
||
|
||
Device - The device.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PIPX_RECEIVE_POOL ReceivePool;
|
||
UINT PacketNum;
|
||
IPX_RECEIVE_PACKET Packet;
|
||
PIPX_RECEIVE_RESERVED Reserved;
|
||
CTELockHandle LockHandle;
|
||
NDIS_STATUS Status;
|
||
|
||
ReceivePool = (PIPX_SEND_POOL)IpxAllocateMemory (sizeof(IPX_RECEIVE_POOL), MEMORY_PACKET, "ReceivePool");
|
||
|
||
if (ReceivePool == NULL) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate receive pool memory\n"));
|
||
return;
|
||
}
|
||
|
||
ReceivePool->PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_NWLNKIPX;
|
||
|
||
NdisAllocatePacketPoolEx(
|
||
&Status,
|
||
&ReceivePool->PoolHandle,
|
||
Device->InitDatagrams,
|
||
0,
|
||
sizeof(IPX_SEND_RESERVED)
|
||
);
|
||
|
||
if (Status == NDIS_STATUS_RESOURCES) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate receive pool memory\n"));
|
||
return;
|
||
}
|
||
|
||
NdisSetPacketPoolProtocolId(ReceivePool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
|
||
|
||
IPX_DEBUG (PACKET, ("Initializing receive pool %lx, %d packets\n",
|
||
ReceivePool, Device->InitReceivePackets));
|
||
|
||
Device->MemoryUsage += Device->InitDatagrams * sizeof(IPX_SEND_RESERVED);
|
||
|
||
for (PacketNum = 0; PacketNum < Device->InitReceivePackets; PacketNum++) {
|
||
|
||
NdisAllocatePacket(&Status, &PACKET(&Packet), ReceivePool->PoolHandle);
|
||
|
||
if (IpxInitializeReceivePacket (Device, &Packet) != STATUS_SUCCESS) {
|
||
IPX_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
|
||
break;
|
||
}
|
||
|
||
Reserved = RECEIVE_RESERVED(&Packet);
|
||
Reserved->Address = NULL;
|
||
Reserved->OwnedByAddress = FALSE;
|
||
#ifdef IPX_TRACK_POOL
|
||
Reserved->Pool = ReceivePool;
|
||
#endif
|
||
|
||
IPX_PUSH_ENTRY_LIST (&Device->ReceivePacketList, &Reserved->PoolLinkage, &Device->SListsLock);
|
||
|
||
}
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
|
||
Device->AllocatedReceivePackets += PacketNum;
|
||
|
||
InsertTailList (&Device->ReceivePoolList, &ReceivePool->Linkage);
|
||
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
} /* IpxAllocateReceivePool */
|
||
|
||
VOID
|
||
IpxAllocateReceiveBufferPool(
|
||
IN PADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine adds receive buffers to the pool for this adapter.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PIPX_RECEIVE_BUFFER ReceiveBuffer;
|
||
UINT ReceiveBufferPoolSize;
|
||
UINT BufferNum;
|
||
PIPX_RECEIVE_BUFFER_POOL ReceiveBufferPool;
|
||
PDEVICE Device = Adapter->Device;
|
||
UINT DataLength;
|
||
PUCHAR Data;
|
||
CTELockHandle LockHandle;
|
||
|
||
DataLength = Adapter->MaxReceivePacketSize;
|
||
|
||
ReceiveBufferPoolSize = FIELD_OFFSET (IPX_RECEIVE_BUFFER_POOL, Buffers[0]) +
|
||
(sizeof(IPX_RECEIVE_BUFFER) * Device->InitReceiveBuffers) +
|
||
(DataLength * Device->InitReceiveBuffers);
|
||
|
||
ReceiveBufferPool = (PIPX_RECEIVE_BUFFER_POOL)IpxAllocateMemory (ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
|
||
if (ReceiveBufferPool == NULL) {
|
||
IPX_DEBUG (PACKET, ("Could not allocate receive buffer pool memory\n"));
|
||
return;
|
||
}
|
||
|
||
IPX_DEBUG (PACKET, ("Init recv buffer pool %lx, %d buffers, data %d\n",
|
||
ReceiveBufferPool, Device->InitReceiveBuffers, DataLength));
|
||
|
||
Data = (PUCHAR)(&ReceiveBufferPool->Buffers[Device->InitReceiveBuffers]);
|
||
|
||
|
||
for (BufferNum = 0; BufferNum < Device->InitReceiveBuffers; BufferNum++) {
|
||
|
||
ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
|
||
|
||
if (IpxInitializeReceiveBuffer (Adapter, ReceiveBuffer, Data, DataLength) != STATUS_SUCCESS) {
|
||
IPX_DEBUG (PACKET, ("Could not initialize buffer %lx\n", ReceiveBuffer));
|
||
break;
|
||
}
|
||
|
||
#ifdef IPX_TRACK_POOL
|
||
ReceiveBuffer->Pool = ReceiveBufferPool;
|
||
#endif
|
||
|
||
Data += DataLength;
|
||
|
||
}
|
||
|
||
ReceiveBufferPool->BufferCount = BufferNum;
|
||
ReceiveBufferPool->BufferFree = BufferNum;
|
||
|
||
CTEGetLock (&Device->Lock, &LockHandle);
|
||
|
||
for (BufferNum = 0; BufferNum < ReceiveBufferPool->BufferCount; BufferNum++) {
|
||
|
||
ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
|
||
IPX_PUSH_ENTRY_LIST (&Adapter->ReceiveBufferList, &ReceiveBuffer->PoolLinkage, &Device->SListsLock);
|
||
|
||
}
|
||
|
||
InsertTailList (&Adapter->ReceiveBufferPoolList, &ReceiveBufferPool->Linkage);
|
||
|
||
Adapter->AllocatedReceiveBuffers += ReceiveBufferPool->BufferCount;
|
||
|
||
CTEFreeLock (&Device->Lock, LockHandle);
|
||
|
||
} /* IpxAllocateReceiveBufferPool */
|
||
|
||
|
||
PSINGLE_LIST_ENTRY
|
||
IpxPopSendPacket(
|
||
PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates a packet from the device context's pool.
|
||
If there are no packets in the pool, it allocates one up to
|
||
the configured limit.
|
||
|
||
Arguments:
|
||
|
||
Device - Pointer to our device to charge the packet to.
|
||
|
||
Return Value:
|
||
|
||
The pointer to the Linkage field in the allocated packet.
|
||
|
||
--*/
|
||
|
||
{
|
||
PSINGLE_LIST_ENTRY s;
|
||
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Device->SendPacketList,
|
||
&Device->SListsLock);
|
||
|
||
if (s != NULL) {
|
||
return s;
|
||
}
|
||
|
||
//
|
||
// No packets in the pool, see if we can allocate more.
|
||
//
|
||
|
||
if (Device->AllocatedDatagrams < Device->MaxDatagrams) {
|
||
|
||
//
|
||
// Allocate a pool and try again.
|
||
//
|
||
|
||
IpxAllocateSendPool (Device);
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Device->SendPacketList,
|
||
&Device->SListsLock);
|
||
|
||
return s;
|
||
|
||
} else {
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
} /* IpxPopSendPacket */
|
||
|
||
#if BACK_FILL
|
||
|
||
PSINGLE_LIST_ENTRY
|
||
IpxPopBackFillPacket(
|
||
PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates a packet from the device context's pool.
|
||
If there are no packets in the pool, it allocates one up to
|
||
the configured limit.
|
||
|
||
Arguments:
|
||
|
||
Device - Pointer to our device to charge the packet to.
|
||
|
||
Return Value:
|
||
|
||
The pointer to the Linkage field in the allocated packet.
|
||
|
||
--*/
|
||
|
||
{
|
||
PSINGLE_LIST_ENTRY s;
|
||
|
||
IPX_DEBUG (PACKET, ("Popping backfill packet\n"));
|
||
|
||
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Device->BackFillPacketList,
|
||
&Device->SListsLock);
|
||
|
||
if (s != NULL) {
|
||
return s;
|
||
}
|
||
|
||
//
|
||
// No packets in the pool, see if we can allocate more.
|
||
//
|
||
|
||
if (Device->AllocatedDatagrams < Device->MaxDatagrams) {
|
||
|
||
//
|
||
// Allocate a pool and try again.
|
||
//
|
||
|
||
IpxAllocateBackFillPool (Device);
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Device->BackFillPacketList,
|
||
&Device->SListsLock);
|
||
|
||
|
||
IPX_DEBUG (PACKET, ("Popping backfill packet done\n"));
|
||
return s;
|
||
|
||
} else {
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
} /* IpxPopBackFillPacket */
|
||
#endif //BackFill
|
||
|
||
|
||
PSINGLE_LIST_ENTRY
|
||
IpxPopReceivePacket(
|
||
IN PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates a packet from the device context's pool.
|
||
If there are no packets in the pool, it allocates one up to
|
||
the configured limit.
|
||
|
||
Arguments:
|
||
|
||
Device - Pointer to our device to charge the packet to.
|
||
|
||
Return Value:
|
||
|
||
The pointer to the Linkage field in the allocated packet.
|
||
|
||
--*/
|
||
|
||
{
|
||
PSINGLE_LIST_ENTRY s;
|
||
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Device->ReceivePacketList,
|
||
&Device->SListsLock);
|
||
|
||
if (s != NULL) {
|
||
return s;
|
||
}
|
||
|
||
//
|
||
// No packets in the pool, see if we can allocate more.
|
||
//
|
||
|
||
if (Device->AllocatedReceivePackets < Device->MaxReceivePackets) {
|
||
|
||
//
|
||
// Allocate a pool and try again.
|
||
//
|
||
|
||
IpxAllocateReceivePool (Device);
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Device->ReceivePacketList,
|
||
&Device->SListsLock);
|
||
|
||
return s;
|
||
|
||
} else {
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
} /* IpxPopReceivePacket */
|
||
|
||
|
||
PSINGLE_LIST_ENTRY
|
||
IpxPopReceiveBuffer(
|
||
IN PADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates a receive buffer from the adapter's pool.
|
||
If there are no buffers in the pool, it allocates one up to
|
||
the configured limit.
|
||
|
||
Arguments:
|
||
|
||
Adapter - Pointer to our adapter to charge the buffer to.
|
||
|
||
Return Value:
|
||
|
||
The pointer to the Linkage field in the allocated receive buffer.
|
||
|
||
--*/
|
||
|
||
{
|
||
PSINGLE_LIST_ENTRY s;
|
||
PDEVICE Device = Adapter->Device;
|
||
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Adapter->ReceiveBufferList,
|
||
&Device->SListsLock);
|
||
|
||
if (s != NULL) {
|
||
return s;
|
||
}
|
||
|
||
//
|
||
// No buffer in the pool, see if we can allocate more.
|
||
//
|
||
|
||
if (Adapter->AllocatedReceiveBuffers < Device->MaxReceiveBuffers) {
|
||
|
||
//
|
||
// Allocate a pool and try again.
|
||
//
|
||
|
||
IpxAllocateReceiveBufferPool (Adapter);
|
||
s = IPX_POP_ENTRY_LIST(
|
||
&Adapter->ReceiveBufferList,
|
||
&Device->SListsLock);
|
||
|
||
return s;
|
||
|
||
} else {
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
} /* IpxPopReceiveBuffer */
|
||
|
||
|
||
PIPX_PADDING_BUFFER
|
||
IpxAllocatePaddingBuffer(
|
||
IN PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates a padding buffer for use by all devices.
|
||
|
||
Arguments:
|
||
|
||
Device - Pointer to our device to charge the packet to.
|
||
|
||
Return Value:
|
||
|
||
The pointer to the allocated padding buffer.
|
||
|
||
--*/
|
||
|
||
{
|
||
PIPX_PADDING_BUFFER PaddingBuffer;
|
||
ULONG PaddingBufferSize;
|
||
|
||
//
|
||
// We are assuming that we can use 1 global padding buffer for ALL
|
||
// transmits! We must therefore test to make sure that EthernetExtraPadding
|
||
// is not greater than 1. Otherwise, we must assume that the extra padding
|
||
// is being used for something and we therefore cannot share across all
|
||
// transmit requests.
|
||
//
|
||
|
||
//
|
||
// We cannot support more than 1 byte padding space, since we allocate only
|
||
// one buffer for all transmit requests.
|
||
//
|
||
|
||
if ( Device->EthernetExtraPadding > 1 ) {
|
||
IPX_DEBUG (PACKET, ("Padding buffer cannot be more than 1 byte\n"));
|
||
DbgBreakPoint();
|
||
}
|
||
|
||
//
|
||
// Allocate a padding buffer if possible.
|
||
//
|
||
|
||
PaddingBufferSize = FIELD_OFFSET (IPX_PADDING_BUFFER, Data[0]) + Device->EthernetExtraPadding;
|
||
|
||
PaddingBuffer = IpxAllocateMemory (PaddingBufferSize, MEMORY_PACKET, "PaddingBuffer");
|
||
|
||
if (PaddingBuffer != NULL) {
|
||
|
||
if (IpxInitializePaddingBuffer (Device, PaddingBuffer, Device->EthernetExtraPadding) !=
|
||
STATUS_SUCCESS) {
|
||
IpxFreeMemory (PaddingBuffer, PaddingBufferSize, MEMORY_PACKET, "Padding Buffer");
|
||
} else {
|
||
IPX_DEBUG (PACKET, ("Allocate padding buffer %lx\n", PaddingBuffer));
|
||
return PaddingBuffer;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
|
||
} /* IpxAllocatePaddingBuffer */
|
||
|
||
|
||
VOID
|
||
IpxFreePaddingBuffer(
|
||
IN PDEVICE Device
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deallocates the padding buffer.
|
||
|
||
Arguments:
|
||
|
||
Device - Pointer to our device to charge the packet to.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG PaddingBufferSize;
|
||
|
||
if ( IpxPaddingBuffer == (PIPX_PADDING_BUFFER)NULL ) {
|
||
return;
|
||
}
|
||
|
||
PaddingBufferSize = FIELD_OFFSET (IPX_PADDING_BUFFER, Data[0]) + Device->EthernetExtraPadding;
|
||
IpxFreeMemory( IpxPaddingBuffer, PaddingBufferSize, MEMORY_PACKET, "Padding Buffer" );
|
||
IpxPaddingBuffer = (PIPX_PADDING_BUFFER)NULL;
|
||
|
||
} /* IpxFreePaddingBuffer */
|
||
|
||
|