/*++ 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 */ #ifdef IPX_OWN_PACKETS 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 SendPoolSize; UINT PacketNum; PIPX_SEND_PACKET Packet; PIPX_SEND_RESERVED Reserved; PUCHAR Header; CTELockHandle LockHandle; SendPoolSize = FIELD_OFFSET (IPX_SEND_POOL, Packets[0]) + (sizeof(IPX_SEND_PACKET) * Device->InitDatagrams) + (PACKET_HEADER_SIZE * Device->InitDatagrams); SendPool = (PIPX_SEND_POOL)IpxAllocateMemory (SendPoolSize, MEMORY_PACKET, "SendPool"); if (SendPool == NULL) { IPX_DEBUG (PACKET, ("Could not allocate send pool memory\n")); return; } IPX_DEBUG (PACKET, ("Initializing send pool %lx, %d packets\n", SendPool, Device->InitDatagrams)); Header = (PUCHAR)(&SendPool->Packets[Device->InitDatagrams]); for (PacketNum = 0; PacketNum < Device->InitDatagrams; PacketNum++) { Packet = &SendPool->Packets[PacketNum]; 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 Header += PACKET_HEADER_SIZE; } SendPool->PacketCount = PacketNum; SendPool->PacketFree = PacketNum; CTEGetLock (&Device->Lock, &LockHandle); for (PacketNum = 0; PacketNum < SendPool->PacketCount; PacketNum++) { Packet = &SendPool->Packets[PacketNum]; Reserved = SEND_RESERVED(Packet); IPX_PUSH_ENTRY_LIST (&Device->SendPacketList, &Reserved->PoolLinkage, &Device->SListsLock); } InsertTailList (&Device->SendPoolList, &SendPool->Linkage); Device->AllocatedDatagrams += SendPool->PacketCount; 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. --*/ { PIPX_SEND_POOL SendPool; UINT SendPoolSize; UINT PacketNum; PIPX_SEND_PACKET Packet; PIPX_SEND_RESERVED Reserved; PUCHAR Header; CTELockHandle LockHandle; PIPX_SEND_POOL BackFillPool; UINT BackFillPoolSize; IPX_DEBUG (PACKET, ("Allocating backfill pool\n")); BackFillPoolSize = FIELD_OFFSET (IPX_SEND_POOL, Packets[0]) + (sizeof(IPX_SEND_PACKET) * Device->InitDatagrams); // Allocate pool for back fillable packets BackFillPool = (PIPX_SEND_POOL)IpxAllocateMemory (BackFillPoolSize, MEMORY_PACKET, "BafiPool"); if (BackFillPool == NULL) { IPX_DEBUG (PACKET, ("Could not allocate BackFill pool memory\n")); return; } for (PacketNum = 0; PacketNum < Device->InitDatagrams; PacketNum++) { Packet = &BackFillPool->Packets[PacketNum]; 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 } BackFillPool->PacketCount = PacketNum; BackFillPool->PacketFree = PacketNum; CTEGetLock (&Device->Lock, &LockHandle); for (PacketNum = 0; PacketNum < BackFillPool->PacketCount; PacketNum++) { Packet = &BackFillPool->Packets[PacketNum]; Reserved = SEND_RESERVED(Packet); IPX_PUSH_ENTRY_LIST (&Device->BackFillPacketList, &Reserved->PoolLinkage, &Device->SListsLock); } InsertTailList (&Device->BackFillPoolList, &BackFillPool->Linkage); IPX_DEBUG (PACKET, ("Allocation of backfill pool done\n")); 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 ReceivePoolSize; UINT PacketNum; PIPX_RECEIVE_PACKET Packet; PIPX_RECEIVE_RESERVED Reserved; CTELockHandle LockHandle; ReceivePoolSize = FIELD_OFFSET (IPX_RECEIVE_POOL, Packets[0]) + (sizeof(IPX_RECEIVE_PACKET) * Device->InitReceivePackets); ReceivePool = (PIPX_RECEIVE_POOL)IpxAllocateMemory (ReceivePoolSize, MEMORY_PACKET, "ReceivePool"); if (ReceivePool == NULL) { IPX_DEBUG (PACKET, ("Could not allocate receive pool memory\n")); return; } IPX_DEBUG (PACKET, ("Initializing receive pool %lx, %d packets\n", ReceivePool, Device->InitReceivePackets)); for (PacketNum = 0; PacketNum < Device->InitReceivePackets; PacketNum++) { Packet = &ReceivePool->Packets[PacketNum]; 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 } ReceivePool->PacketCount = PacketNum; ReceivePool->PacketFree = PacketNum; CTEGetLock (&Device->Lock, &LockHandle); for (PacketNum = 0; PacketNum < ReceivePool->PacketCount; PacketNum++) { Packet = &ReceivePool->Packets[PacketNum]; Reserved = RECEIVE_RESERVED(Packet); IPX_PUSH_ENTRY_LIST (&Device->ReceivePacketList, &Reserved->PoolLinkage, &Device->SListsLock); } InsertTailList (&Device->ReceivePoolList, &ReceivePool->Linkage); Device->AllocatedReceivePackets += ReceivePool->PacketCount; CTEFreeLock (&Device->Lock, LockHandle); } /* IpxAllocateReceivePool */ #else // IPX_OWN_PACKETS 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")); return; } NdisAllocatePacketPool(&Status, &SendPool->PoolHandle, Device->InitDatagrams, sizeof(IPX_SEND_RESERVED)); if (Status == NDIS_STATUS_RESOURCES) { IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n")); return; } Device->MemoryUsage += (FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0]) + Device->InitDatagrams * (FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0]) + 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; } NdisAllocatePacketPool(&Status, &BackFillPool->PoolHandle, Device->InitDatagrams, sizeof(IPX_SEND_RESERVED)); if (Status == NDIS_STATUS_RESOURCES) { IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n")); return; } Device->MemoryUsage += (FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0]) + Device->InitDatagrams * (FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0]) + 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; } NdisAllocatePacketPool(&Status, &ReceivePool->PoolHandle, Device->InitDatagrams, sizeof(IPX_SEND_RESERVED)); if (Status == NDIS_STATUS_RESOURCES) { IPX_DEBUG (PACKET, ("Could not allocate receive pool memory\n")); return; } IPX_DEBUG (PACKET, ("Initializing receive pool %lx, %d packets\n", ReceivePool, Device->InitReceivePackets)); Device->MemoryUsage += (FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0]) + Device->InitReceivePackets * (FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0]) + sizeof(IPX_RECEIVE_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 */ #endif // IPX_OWN_PACKETS 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 */