summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/nb/packet.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/tdi/isn/nb/packet.c1482
1 files changed, 1482 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/nb/packet.c b/private/ntos/tdi/isn/nb/packet.c
new file mode 100644
index 000000000..7e22534a8
--- /dev/null
+++ b/private/ntos/tdi/isn/nb/packet.c
@@ -0,0 +1,1482 @@
+/*++
+
+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:
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// Local Function Protos
+//
+#if defined(_PNP_POWER)
+#if !defined(DBG)
+__inline
+#endif
+VOID
+NbiFreeReceiveBufferPool (
+ IN PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool
+ );
+#endif _PNP_POWER
+
+
+NTSTATUS
+NbiInitializeSendPacket(
+ IN PDEVICE Device,
+ IN NDIS_HANDLE PoolHandle OPTIONAL,
+ IN PNB_SEND_PACKET Packet,
+ IN PUCHAR Header,
+ IN ULONG HeaderLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes a send packet by chaining the
+ buffer for the header on it.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD,
+ AND RETURNS WITH IT HELD.
+
+Arguments:
+
+ Device - The device.
+
+ PoolHandle - Ndis packet pool handle if !NB_OWN_PACKETS
+
+ Packet - The packet to initialize.
+
+ Header - Points to storage for the header.
+
+ HeaderLength - The length of the header.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ NDIS_STATUS NdisStatus;
+ NTSTATUS Status;
+ PNDIS_BUFFER NdisBuffer;
+ PNDIS_BUFFER NdisNbBuffer;
+ PNB_SEND_RESERVED Reserved;
+ ULONG MacHeaderNeeded = NbiDevice->Bind.MacHeaderNeeded;
+
+ NbiAllocateSendPacket (Device, PoolHandle, Packet, &Status);
+
+ if (Status != STATUS_SUCCESS) {
+ // ERROR LOG
+ return Status;
+ }
+// DbgPrint("NbiInitializeSendPacket: PACKET is (%x)\n", PACKET(Packet));
+
+ //
+ // allocate the mac header.
+ //
+ NdisAllocateBuffer(
+ &NdisStatus,
+ &NdisBuffer,
+ Device->NdisBufferPoolHandle,
+ Header,
+ MacHeaderNeeded);
+
+ if (NdisStatus != NDIS_STATUS_SUCCESS) {
+ NbiFreeSendPacket (Device, Packet);
+ // ERROR LOG
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ NdisChainBufferAtFront (PACKET(Packet), NdisBuffer);
+
+// DbgPrint("NbiInitializeSendPacket: MAC header address is (%x)\n", NdisBuffer);
+ //
+ // Allocate the nb header
+ //
+ NdisAllocateBuffer(
+ &NdisStatus,
+ &NdisNbBuffer,
+ Device->NdisBufferPoolHandle,
+ Header + MacHeaderNeeded,
+ HeaderLength - MacHeaderNeeded);
+
+ if (NdisStatus != NDIS_STATUS_SUCCESS) {
+ NdisUnchainBufferAtFront (PACKET(Packet), &NdisBuffer);
+ CTEAssert (NdisBuffer);
+
+ NdisAdjustBufferLength (NdisBuffer, MacHeaderNeeded);
+ NdisFreeBuffer (NdisBuffer);
+ NbiFreeSendPacket (Device, Packet);
+ // ERROR LOG
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // DbgPrint("NbiInitializeSendPacket: IPX header address is (%x)\n", NdisNbBuffer);
+ NdisChainBufferAtBack (PACKET(Packet), NdisNbBuffer);
+
+ Reserved = SEND_RESERVED(Packet);
+ Reserved->Identifier = IDENTIFIER_NB;
+ Reserved->SendInProgress = FALSE;
+ Reserved->OwnedByConnection = FALSE;
+ Reserved->Header = Header;
+ Reserved->HeaderBuffer = NdisBuffer;
+
+ Reserved->Reserved[0] = NULL;
+ Reserved->Reserved[1] = NULL;
+
+ InsertHeadList(
+ &Device->GlobalSendPacketList,
+ &Reserved->GlobalLinkage);
+
+ return STATUS_SUCCESS;
+
+} /* NbiInitializeSendPacket */
+
+
+NTSTATUS
+NbiInitializeReceivePacket(
+ IN PDEVICE Device,
+ IN NDIS_HANDLE PoolHandle OPTIONAL,
+ IN PNB_RECEIVE_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes a receive packet.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD,
+ AND RETURNS WITH IT HELD.
+
+Arguments:
+
+ Device - The device.
+
+ PoolHandle - Ndis packet pool handle if !NB_OWN_PACKETS
+
+ Packet - The packet to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ NTSTATUS Status;
+ PNB_RECEIVE_RESERVED Reserved;
+
+ NbiAllocateReceivePacket (Device, PoolHandle, Packet, &Status);
+
+ if (Status != STATUS_SUCCESS) {
+ // ERROR LOG
+ return Status;
+ }
+
+ Reserved = RECEIVE_RESERVED(Packet);
+ Reserved->Identifier = IDENTIFIER_NB;
+ Reserved->TransferInProgress = FALSE;
+
+ InsertHeadList(
+ &Device->GlobalReceivePacketList,
+ &Reserved->GlobalLinkage);
+
+ return STATUS_SUCCESS;
+
+} /* NbiInitializeReceivePacket */
+
+
+NTSTATUS
+NbiInitializeReceiveBuffer(
+ IN PDEVICE Device,
+ IN PNB_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.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD,
+ AND RETURNS WITH IT HELD.
+
+Arguments:
+
+ Device - The device.
+
+ 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;
+
+
+ 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;
+
+ InsertHeadList(
+ &Device->GlobalReceiveBufferList,
+ &ReceiveBuffer->GlobalLinkage);
+
+ return STATUS_SUCCESS;
+
+} /* NbiInitializeReceiveBuffer */
+
+
+
+VOID
+NbiDeinitializeSendPacket(
+ IN PDEVICE Device,
+ IN PNB_SEND_PACKET Packet,
+ IN ULONG HeaderLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine deinitializes a send packet.
+
+Arguments:
+
+ Device - The device.
+
+ Packet - The packet to deinitialize.
+
+ HeaderLength - The length of the first buffer on the packet.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PNDIS_BUFFER NdisBuffer;
+ PNB_SEND_RESERVED Reserved;
+ CTELockHandle LockHandle;
+ ULONG MacHeaderNeeded = NbiDevice->Bind.MacHeaderNeeded;
+
+ CTEAssert(HeaderLength > MacHeaderNeeded);
+ Reserved = SEND_RESERVED(Packet);
+
+ NB_GET_LOCK (&Device->Lock, &LockHandle);
+ RemoveEntryList (&Reserved->GlobalLinkage);
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+
+ //
+ // Free the mac header
+ //
+ // DbgPrint("NbiDeinitializeSendPacket: PACKET is (%x)\n", PACKET(Packet));
+ NdisUnchainBufferAtFront (PACKET(Packet), &NdisBuffer);
+ CTEAssert (NdisBuffer);
+ // DbgPrint("NbiDeinitializeSendPacket: MAC header address is (%x)\n", NdisBuffer);
+
+ NdisAdjustBufferLength (NdisBuffer, MacHeaderNeeded);
+ NdisFreeBuffer (NdisBuffer);
+
+ //
+ // Free the nb header
+ //
+ NdisUnchainBufferAtFront (PACKET(Packet), &NdisBuffer);
+ // DbgPrint("NbiDeinitializeSendPacket: IPX header address is (%x)\n", NdisBuffer);
+ CTEAssert (NdisBuffer);
+
+ NdisAdjustBufferLength (NdisBuffer, HeaderLength - MacHeaderNeeded);
+ NdisFreeBuffer (NdisBuffer);
+
+ //
+ // free the packet
+ //
+ NbiFreeSendPacket (Device, Packet);
+
+} /* NbiDeinitializeSendPacket */
+
+
+VOID
+NbiDeinitializeReceivePacket(
+ IN PDEVICE Device,
+ IN PNB_RECEIVE_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes a receive packet.
+
+Arguments:
+
+ Device - The device.
+
+ Packet - The packet to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PNB_RECEIVE_RESERVED Reserved;
+ CTELockHandle LockHandle;
+
+ Reserved = RECEIVE_RESERVED(Packet);
+
+ NB_GET_LOCK (&Device->Lock, &LockHandle);
+ RemoveEntryList (&Reserved->GlobalLinkage);
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+
+ NbiFreeReceivePacket (Device, Packet);
+
+} /* NbiDeinitializeReceivePacket */
+
+
+
+VOID
+NbiDeinitializeReceiveBuffer(
+ IN PDEVICE Device,
+ IN PNB_RECEIVE_BUFFER ReceiveBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine deinitializes a receive buffer.
+
+Arguments:
+
+ Device - The device.
+
+ ReceiveBuffer - The receive buffer.
+
+Return Value:
+
+ None.
+
+ THIS ROUTINE SHOULD BE CALLED WITH THE DEVICE LOCK HELD. If this
+ routine also called from the DestroyDevice routine, it is not
+ necessary to call this with the lock.
+
+--*/
+
+{
+#if defined(_PNP_POWER)
+ RemoveEntryList (&ReceiveBuffer->GlobalLinkage);
+#else
+ CTELockHandle LockHandle;
+
+ NB_GET_LOCK (&Device->Lock, &LockHandle);
+ RemoveEntryList (&ReceiveBuffer->GlobalLinkage);
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+#endif _PNP_POWER
+
+ NdisFreeBuffer (ReceiveBuffer->NdisBuffer);
+
+} /* NbiDeinitializeReceiveBuffer */
+
+
+
+VOID
+NbiAllocateSendPool(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds 10 packets to the pool for this device.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
+ RETURNS WITH IT HELD.
+
+Arguments:
+
+ Device - The device.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PNB_SEND_POOL SendPool;
+ UINT SendPoolSize;
+ UINT PacketNum;
+ PNB_SEND_PACKET Packet;
+ PNB_SEND_RESERVED Reserved;
+ PUCHAR Header;
+ ULONG HeaderLength;
+ NTSTATUS Status;
+
+ HeaderLength = Device->Bind.MacHeaderNeeded + sizeof(NB_CONNECTIONLESS);
+ SendPoolSize = FIELD_OFFSET (NB_SEND_POOL, Packets[0]) +
+ (sizeof(NB_SEND_PACKET) * Device->InitPackets) +
+ (HeaderLength * Device->InitPackets);
+
+ SendPool = (PNB_SEND_POOL)NbiAllocateMemory (SendPoolSize, MEMORY_PACKET, "SendPool");
+ if (SendPool == NULL) {
+ NB_DEBUG (PACKET, ("Could not allocate send pool memory\n"));
+ return;
+ }
+
+ RtlZeroMemory (SendPool, SendPoolSize);
+
+
+#if !defined(NB_OWN_PACKETS)
+ //
+ // Now allocate the ndis packet pool
+ //
+ NdisAllocatePacketPool( &Status, &SendPool->PoolHandle, Device->InitPackets, sizeof(NB_SEND_RESERVED));
+ if (!NT_SUCCESS(Status)){
+ NB_DEBUG (PACKET, ("Could not allocate Ndis Packet Pool memory\n"));
+ NbiFreeMemory( SendPool, SendPoolSize, MEMORY_PACKET, "Send Pool Freed");
+ return;
+ }
+#endif
+
+ NB_DEBUG2 (PACKET, ("Initializing send pool %lx, %d packets, header %d\n",
+ SendPool, Device->InitPackets, HeaderLength));
+
+ Header = (PUCHAR)(&SendPool->Packets[Device->InitPackets]);
+
+ for (PacketNum = 0; PacketNum < Device->InitPackets; PacketNum++) {
+
+ Packet = &SendPool->Packets[PacketNum];
+
+ if (NbiInitializeSendPacket (
+ Device,
+#ifdef NB_OWN_PACKETS
+ NULL,
+#else
+ SendPool->PoolHandle,
+#endif
+ Packet,
+ Header,
+ HeaderLength) != STATUS_SUCCESS) {
+ NB_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
+ break;
+ }
+
+ Reserved = SEND_RESERVED(Packet);
+ Reserved->u.SR_NF.Address = NULL;
+#ifdef NB_TRACK_POOL
+ Reserved->Pool = SendPool;
+#endif
+
+ Header += HeaderLength;
+
+ }
+
+ SendPool->PacketCount = PacketNum;
+ SendPool->PacketFree = PacketNum;
+
+ for (PacketNum = 0; PacketNum < SendPool->PacketCount; PacketNum++) {
+
+ Packet = &SendPool->Packets[PacketNum];
+ Reserved = SEND_RESERVED(Packet);
+ ExInterlockedPushEntrySList(
+ &Device->SendPacketList,
+ &Reserved->PoolLinkage,
+ &NbiGlobalPoolInterlock);
+
+ }
+
+ InsertTailList (&Device->SendPoolList, &SendPool->Linkage);
+
+ Device->AllocatedSendPackets += SendPool->PacketCount;
+
+} /* NbiAllocateSendPool */
+
+
+VOID
+NbiAllocateReceivePool(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds 5 receive packets to the pool for this device.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
+ RETURNS WITH IT HELD.
+
+Arguments:
+
+ Device - The device.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PNB_RECEIVE_POOL ReceivePool;
+ UINT ReceivePoolSize;
+ UINT PacketNum;
+ PNB_RECEIVE_PACKET Packet;
+ PNB_RECEIVE_RESERVED Reserved;
+ NTSTATUS Status;
+
+ ReceivePoolSize = FIELD_OFFSET (NB_RECEIVE_POOL, Packets[0]) +
+ (sizeof(NB_RECEIVE_PACKET) * Device->InitPackets);
+
+ ReceivePool = (PNB_RECEIVE_POOL)NbiAllocateMemory (ReceivePoolSize, MEMORY_PACKET, "ReceivePool");
+ if (ReceivePool == NULL) {
+ NB_DEBUG (PACKET, ("Could not allocate receive pool memory\n"));
+ return;
+ }
+
+ RtlZeroMemory (ReceivePool, ReceivePoolSize);
+
+#if !defined(NB_OWN_PACKETS)
+ //
+ // Now allocate the ndis packet pool
+ //
+ NdisAllocatePacketPool( &Status, &ReceivePool->PoolHandle, Device->InitPackets, sizeof(NB_RECEIVE_RESERVED));
+ if (!NT_SUCCESS(Status)){
+ NB_DEBUG (PACKET, ("Could not allocate Ndis Packet Pool memory\n"));
+ NbiFreeMemory( ReceivePool, ReceivePoolSize, MEMORY_PACKET, "Receive Pool Freed");
+ return;
+ }
+#endif NB_OWN_PACKETS
+
+ NB_DEBUG2 (PACKET, ("Initializing receive pool %lx, %d packets\n",
+ ReceivePool, Device->InitPackets));
+
+ for (PacketNum = 0; PacketNum < Device->InitPackets; PacketNum++) {
+
+ Packet = &ReceivePool->Packets[PacketNum];
+
+ if (NbiInitializeReceivePacket (
+ Device,
+#ifdef NB_OWN_PACKETS
+ NULL,
+#else
+ ReceivePool->PoolHandle,
+#endif
+ Packet) != STATUS_SUCCESS) {
+ NB_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
+ break;
+ }
+
+ Reserved = RECEIVE_RESERVED(Packet);
+#ifdef NB_TRACK_POOL
+ Reserved->Pool = ReceivePool;
+#endif
+
+ }
+
+ ReceivePool->PacketCount = PacketNum;
+ ReceivePool->PacketFree = PacketNum;
+
+ for (PacketNum = 0; PacketNum < ReceivePool->PacketCount; PacketNum++) {
+
+ Packet = &ReceivePool->Packets[PacketNum];
+ Reserved = RECEIVE_RESERVED(Packet);
+ ExInterlockedPushEntrySList(
+ &Device->ReceivePacketList,
+ &Reserved->PoolLinkage,
+ &NbiGlobalPoolInterlock);
+// PushEntryList (&Device->ReceivePacketList, &Reserved->PoolLinkage);
+
+ }
+
+ InsertTailList (&Device->ReceivePoolList, &ReceivePool->Linkage);
+
+ Device->AllocatedReceivePackets += ReceivePool->PacketCount;
+
+} /* NbiAllocateReceivePool */
+
+
+#if defined(_PNP_POWER)
+
+VOID
+NbiAllocateReceiveBufferPool(
+ IN PDEVICE Device,
+ IN UINT DataLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds receive buffers to the pool for this device.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
+ RETURNS WITH IT HELD.
+
+Arguments:
+
+ Device - The device.
+
+ DataLength - Max length of the data in each buffer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PNB_RECEIVE_BUFFER ReceiveBuffer;
+ UINT ReceiveBufferPoolSize;
+ UINT BufferNum;
+ PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
+ PUCHAR Data;
+
+
+ ReceiveBufferPoolSize = FIELD_OFFSET (NB_RECEIVE_BUFFER_POOL, Buffers[0]) +
+ (sizeof(NB_RECEIVE_BUFFER) * Device->InitPackets) +
+ (DataLength * Device->InitPackets);
+
+ ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)NbiAllocateMemory (ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
+ if (ReceiveBufferPool == NULL) {
+ NB_DEBUG (PACKET, ("Could not allocate receive buffer pool memory\n"));
+ return;
+ }
+
+ RtlZeroMemory (ReceiveBufferPool, ReceiveBufferPoolSize);
+
+ NB_DEBUG2 (PACKET, ("Initializing receive buffer pool %lx, %d buffers, data %d\n",
+ ReceiveBufferPool, Device->InitPackets, DataLength));
+
+ Data = (PUCHAR)(&ReceiveBufferPool->Buffers[Device->InitPackets]);
+
+ for (BufferNum = 0; BufferNum < Device->InitPackets; BufferNum++) {
+
+ ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
+
+ if (NbiInitializeReceiveBuffer (Device, ReceiveBuffer, Data, DataLength) != STATUS_SUCCESS) {
+ NB_DEBUG (PACKET, ("Could not initialize buffer %lx\n", ReceiveBuffer));
+ break;
+ }
+
+ ReceiveBuffer->Pool = ReceiveBufferPool;
+
+ Data += DataLength;
+
+ }
+
+ ReceiveBufferPool->BufferCount = BufferNum;
+ ReceiveBufferPool->BufferFree = BufferNum;
+ ReceiveBufferPool->BufferDataSize = DataLength;
+
+ for (BufferNum = 0; BufferNum < ReceiveBufferPool->BufferCount; BufferNum++) {
+
+ ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
+ PushEntryList (&Device->ReceiveBufferList, &ReceiveBuffer->PoolLinkage);
+
+ }
+
+ InsertTailList (&Device->ReceiveBufferPoolList, &ReceiveBufferPool->Linkage);
+
+ Device->AllocatedReceiveBuffers += ReceiveBufferPool->BufferCount;
+ Device->CurMaxReceiveBufferSize = DataLength;
+
+} /* NbiAllocateReceiveBufferPool */
+#else
+
+VOID
+NbiAllocateReceiveBufferPool(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds receive buffers to the pool for this device.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
+ RETURNS WITH IT HELD.
+
+Arguments:
+
+ Device - The device.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PNB_RECEIVE_BUFFER ReceiveBuffer;
+ UINT ReceiveBufferPoolSize;
+ UINT BufferNum;
+ PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
+ UINT DataLength;
+ PUCHAR Data;
+
+ DataLength = Device->Bind.LineInfo.MaximumPacketSize;
+
+ ReceiveBufferPoolSize = FIELD_OFFSET (NB_RECEIVE_BUFFER_POOL, Buffers[0]) +
+ (sizeof(NB_RECEIVE_BUFFER) * Device->InitPackets) +
+ (DataLength * Device->InitPackets);
+
+ ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)NbiAllocateMemory (ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
+ if (ReceiveBufferPool == NULL) {
+ NB_DEBUG (PACKET, ("Could not allocate receive buffer pool memory\n"));
+ return;
+ }
+
+ RtlZeroMemory (ReceiveBufferPool, ReceiveBufferPoolSize);
+
+ NB_DEBUG2 (PACKET, ("Initializing receive buffer pool %lx, %d buffers, data %d\n",
+ ReceiveBufferPool, Device->InitPackets, DataLength));
+
+ Data = (PUCHAR)(&ReceiveBufferPool->Buffers[Device->InitPackets]);
+
+ for (BufferNum = 0; BufferNum < Device->InitPackets; BufferNum++) {
+
+ ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
+
+ if (NbiInitializeReceiveBuffer (Device, ReceiveBuffer, Data, DataLength) != STATUS_SUCCESS) {
+ NB_DEBUG (PACKET, ("Could not initialize buffer %lx\n", ReceiveBuffer));
+ break;
+ }
+
+#ifdef NB_TRACK_POOL
+ ReceiveBuffer->Pool = ReceiveBufferPool;
+#endif
+
+ Data += DataLength;
+
+ }
+
+ ReceiveBufferPool->BufferCount = BufferNum;
+ ReceiveBufferPool->BufferFree = BufferNum;
+
+ for (BufferNum = 0; BufferNum < ReceiveBufferPool->BufferCount; BufferNum++) {
+
+ ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
+ PushEntryList (&Device->ReceiveBufferList, &ReceiveBuffer->PoolLinkage);
+
+ }
+
+ InsertTailList (&Device->ReceiveBufferPoolList, &ReceiveBufferPool->Linkage);
+
+ Device->AllocatedReceiveBuffers += ReceiveBufferPool->BufferCount;
+
+} /* NbiAllocateReceiveBufferPool */
+#endif _PNP_POWER
+
+#if defined(_PNP_POWER)
+
+VOID
+NbiReAllocateReceiveBufferPool(
+ IN PWORK_QUEUE_ITEM WorkItem
+ )
+
+/*++
+
+Routine Description:
+
+ This routines destroys all the existing Buffer Pools and creates
+ new one using the larger packet size given to us by IPX because
+ a new card was inserted with a larger packet size.
+
+Arguments:
+
+ WorkItem - The work item that was allocated for this.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE Device = NbiDevice;
+ CTELockHandle LockHandle;
+
+ NB_GET_LOCK ( &Device->Lock, &LockHandle );
+
+ if ( Device->Bind.LineInfo.MaximumPacketSize > Device->CurMaxReceiveBufferSize ) {
+
+#if DBG
+ DbgPrint("Reallocating new pools due to new maxpacketsize\n");
+#endif
+ NbiDestroyReceiveBufferPools( Device );
+ NbiAllocateReceiveBufferPool( Device, Device->Bind.LineInfo.MaximumPacketSize );
+
+ }
+
+ NB_FREE_LOCK( &Device->Lock, LockHandle );
+
+ NbiFreeMemory( WorkItem, sizeof(WORK_QUEUE_ITEM), MEMORY_WORK_ITEM, "Alloc Rcv Buff Work Item freed");
+}
+
+#if !defined(DBG)
+__inline
+#endif
+VOID
+NbiFreeReceiveBufferPool (
+ IN PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees the
+Arguments:
+
+ Device - Pointer to our device to charge the packet to.
+
+Return Value:
+
+ The pointer to the Linkage field in the allocated packet.
+
+--*/
+{
+ PDEVICE Device = NbiDevice;
+ PNB_RECEIVE_BUFFER ReceiveBuffer;
+ UINT ReceiveBufferPoolSize,i;
+
+ CTEAssert( ReceiveBufferPool->BufferDataSize );
+
+ ReceiveBufferPoolSize = FIELD_OFFSET (NB_RECEIVE_BUFFER_POOL, Buffers[0]) +
+ (sizeof(NB_RECEIVE_BUFFER) * Device->InitPackets) +
+ (ReceiveBufferPool->BufferDataSize * Device->InitPackets);
+
+ //
+ // Check if we can free this pool
+ //
+ CTEAssert(ReceiveBufferPool->BufferCount == ReceiveBufferPool->BufferFree );
+
+ for (i = 0; i < ReceiveBufferPool->BufferCount; i++) {
+
+ ReceiveBuffer = &ReceiveBufferPool->Buffers[i];
+ NbiDeinitializeReceiveBuffer (Device, ReceiveBuffer);
+
+ }
+
+ RemoveEntryList( &ReceiveBufferPool->Linkage );
+
+ NB_DEBUG2 (PACKET, ("Free buffer pool %lx\n", ReceiveBufferPool));
+
+ NbiFreeMemory (ReceiveBufferPool, ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
+
+}
+
+
+VOID
+NbiDestroyReceiveBufferPools(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routines walks the ReceiveBufferPoolList and destroys the
+ pool which does not have any buffer in use.
+
+Arguments:
+
+Return Value:
+
+ None.
+
+ THIS ROUTINE COULD BE CALLED WITH THE DEVICE LOCK HELD. If this
+ routine is also called from the DestroyDevice routine, it is not
+ necessary to call this with the lock.
+
+--*/
+{
+ PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
+ PLIST_ENTRY p;
+ PSINGLE_LIST_ENTRY Unused;
+
+
+ //
+ // Clean up this list before we call NbiFreeReceiveBufferPool bcoz that will
+ // simply destroy all the buffer which might be queue here on this list.
+ // At the end of this routine we must start with a fresh ReceiveBufferList.
+ //
+ do {
+ Unused = PopEntryList( &Device->ReceiveBufferList );
+ } while( Unused );
+
+ //
+ // Now destroy each individual ReceiveBufferPool.
+ //
+ for ( p = Device->ReceiveBufferPoolList.Flink;
+ p != &Device->ReceiveBufferPoolList;
+ ) {
+
+
+ ReceiveBufferPool = CONTAINING_RECORD (p, NB_RECEIVE_BUFFER_POOL, Linkage);
+ p = p->Flink;
+
+ //
+ // This will destroy and unlink this Pool if none of its buffer is
+ // in use currently.
+ //
+
+ if ( ReceiveBufferPool->BufferCount == ReceiveBufferPool->BufferFree ) {
+ NbiFreeReceiveBufferPool( ReceiveBufferPool );
+ } else {
+ //
+ // When the device is stopping we must succeed in freeing the pool.
+ CTEAssert( Device->State != DEVICE_STATE_STOPPING );
+ }
+
+ }
+
+}
+
+
+VOID
+NbiPushReceiveBuffer (
+ IN PNB_RECEIVE_BUFFER ReceiveBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the receive buffer back to the free list.
+ It checks the size of this buffer. If it is smaller than the
+ the CurMaxReceiveBufferSize, then it does not return this back
+ to the free list, instead it destroys it and possibly also
+ destroys the pool associated with it. O/w it simply returns this
+ to the free list.
+
+Arguments:
+
+ ReceiveBuffer - Pointer to the buffer to be returned to the free list.
+
+Return Value:
+
+ The pointer to the Linkage field in the allocated packet.
+
+--*/
+
+{
+
+ PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)ReceiveBuffer->Pool;
+ PDEVICE Device = NbiDevice;
+ CTELockHandle LockHandle;
+#if defined(DBG)
+ ULONG BufLen = 0;
+#endif
+
+ NB_GET_LOCK( &Device->Lock, &LockHandle );
+
+#if defined(DBG)
+ NdisQueryBuffer( ReceiveBuffer->NdisBuffer, NULL, &BufLen );
+ CTEAssert( BufLen == ReceiveBufferPool->BufferDataSize );
+#endif
+
+ //
+ // This is an old buffer which was in use when we changed
+ // the CurMaxReceiveBufferSize due to new adapter. We must not
+ // return this buffer back to free list. Infact, if the pool
+ // associated with this buffer does not have any other buffers
+ // in use, we should free the pool also.
+ CTEAssert( ReceiveBufferPool->BufferFree < ReceiveBufferPool->BufferCount );
+ ReceiveBufferPool->BufferFree++;
+
+ if ( ReceiveBufferPool->BufferDataSize < Device->CurMaxReceiveBufferSize ) {
+
+#if DBG
+ DbgPrint("ReceiveBuffer %lx, not returned to pool %lx( Free %d)\n", ReceiveBuffer, ReceiveBufferPool, ReceiveBufferPool->BufferFree);
+#endif
+
+
+ if ( ReceiveBufferPool->BufferFree == ReceiveBufferPool->BufferCount ) {
+ NbiFreeReceiveBufferPool( ReceiveBufferPool );
+ }
+ } else {
+
+ PushEntryList( &Device->ReceiveBufferList, &ReceiveBuffer->PoolLinkage );
+
+
+ }
+
+ NB_FREE_LOCK( &Device->Lock, LockHandle );
+}
+#endif _PNP_POWER
+
+
+PSINGLE_LIST_ENTRY
+NbiPopSendPacket(
+ IN PDEVICE Device,
+ IN BOOLEAN LockAcquired
+ )
+
+/*++
+
+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.
+
+ LockAcquired - TRUE if Device->Lock is acquired.
+
+Return Value:
+
+ The pointer to the Linkage field in the allocated packet.
+
+--*/
+
+{
+ PSINGLE_LIST_ENTRY s;
+ CTELockHandle LockHandle;
+
+ s = ExInterlockedPopEntrySList(
+ &Device->SendPacketList,
+ &NbiGlobalPoolInterlock);
+
+ if (s != NULL) {
+ return s;
+ }
+
+ //
+ // No packets in the pool, see if we can allocate more.
+ //
+
+ if (!LockAcquired) {
+ NB_GET_LOCK (&Device->Lock, &LockHandle);
+ }
+
+ if (Device->AllocatedSendPackets < Device->MaxPackets) {
+
+ //
+ // Allocate a pool and try again.
+ //
+
+
+ NbiAllocateSendPool (Device);
+
+
+ if (!LockAcquired) {
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+ }
+
+ s = ExInterlockedPopEntrySList(
+ &Device->SendPacketList,
+ &NbiGlobalPoolInterlock);
+
+ return s;
+ } else {
+
+ if (!LockAcquired) {
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+ }
+ return NULL;
+ }
+
+} /* NbiPopSendPacket */
+
+
+VOID
+NbiPushSendPacket(
+ IN PNB_SEND_RESERVED Reserved
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees a packet back to the device context's pool.
+ If there are connections waiting for packets, it removes
+ one from the list and inserts it on the packetize queue.
+
+Arguments:
+
+ Device - Pointer to our device to charge the packet to.
+
+Return Value:
+
+ The pointer to the Linkage field in the allocated packet.
+
+--*/
+
+{
+ PDEVICE Device = NbiDevice;
+ PLIST_ENTRY p;
+ PCONNECTION Connection;
+ NB_DEFINE_LOCK_HANDLE (LockHandle)
+ NB_DEFINE_LOCK_HANDLE (LockHandle1)
+
+
+ ExInterlockedPushEntrySList(
+ &Device->SendPacketList,
+ &Reserved->PoolLinkage,
+ &NbiGlobalPoolInterlock);
+
+ //
+ // BUGBUG: Make this a function. Optimize for
+ // UP by not doing two checks?
+ //
+
+ if (!IsListEmpty (&Device->WaitPacketConnections)) {
+
+ NB_SYNC_GET_LOCK (&Device->Lock, &LockHandle);
+
+ p = RemoveHeadList (&Device->WaitPacketConnections);
+
+ //
+ // Take a connection off the WaitPacketQueue and put it
+ // on the PacketizeQueue. We don't worry about if the
+ // connection has stopped, that will get checked when
+ // the PacketizeQueue is run down.
+ //
+ // Since this is in send completion, we may not get
+ // a receive complete. We guard against this by calling
+ // NbiReceiveComplete from the long timer timeout.
+ //
+
+ if (p != &Device->WaitPacketConnections) {
+
+ Connection = CONTAINING_RECORD (p, CONNECTION, WaitPacketLinkage);
+
+ CTEAssert (Connection->OnWaitPacketQueue);
+ Connection->OnWaitPacketQueue = FALSE;
+
+ NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle);
+
+ NB_SYNC_GET_LOCK (&Connection->Lock, &LockHandle1);
+
+
+ if (Connection->SubState == CONNECTION_SUBSTATE_A_W_PACKET) {
+
+ CTEAssert (!Connection->OnPacketizeQueue);
+ Connection->OnPacketizeQueue = TRUE;
+
+ NbiTransferReferenceConnection (Connection, CREF_W_PACKET, CREF_PACKETIZE);
+
+ NB_INSERT_TAIL_LIST(
+ &Device->PacketizeConnections,
+ &Connection->PacketizeLinkage,
+ &Device->Lock);
+
+ Connection->SubState = CONNECTION_SUBSTATE_A_PACKETIZE;
+
+ } else {
+
+ NbiDereferenceConnection (Connection, CREF_W_PACKET);
+
+ }
+
+ NB_SYNC_FREE_LOCK (&Connection->Lock, LockHandle1);
+
+ } else {
+
+ NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle);
+
+ }
+
+ }
+
+} /* NbiPushSendPacket */
+
+
+VOID
+NbiCheckForWaitPacket(
+ IN PCONNECTION Connection
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks if a connection is on the wait packet
+ queue and if so takes it off and queues it to be packetized.
+ It is meant to be called when the connection's packet has
+ been freed.
+
+Arguments:
+
+ Connection - The connection to check.
+
+Return Value:
+
+ The pointer to the Linkage field in the allocated packet.
+
+--*/
+
+{
+ PDEVICE Device = NbiDevice;
+ NB_DEFINE_LOCK_HANDLE (LockHandle)
+ NB_DEFINE_LOCK_HANDLE (LockHandle1)
+
+ NB_SYNC_GET_LOCK (&Connection->Lock, &LockHandle);
+ NB_SYNC_GET_LOCK (&Device->Lock, &LockHandle1);
+
+ if (Connection->OnWaitPacketQueue) {
+
+ Connection->OnWaitPacketQueue = FALSE;
+ RemoveEntryList (&Connection->WaitPacketLinkage);
+
+ if (Connection->SubState == CONNECTION_SUBSTATE_A_W_PACKET) {
+
+ CTEAssert (!Connection->OnPacketizeQueue);
+ Connection->OnPacketizeQueue = TRUE;
+
+ NbiTransferReferenceConnection (Connection, CREF_W_PACKET, CREF_PACKETIZE);
+
+ InsertTailList(
+ &Device->PacketizeConnections,
+ &Connection->PacketizeLinkage);
+ Connection->SubState = CONNECTION_SUBSTATE_A_PACKETIZE;
+
+ } else {
+
+ NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle1);
+ NB_SYNC_FREE_LOCK (&Connection->Lock, LockHandle);
+
+ NbiDereferenceConnection (Connection, CREF_W_PACKET);
+
+ return;
+ }
+ }
+
+ NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle1);
+ NB_SYNC_FREE_LOCK (&Connection->Lock, LockHandle);
+
+} /* NbiCheckForWaitPacket */
+
+
+PSINGLE_LIST_ENTRY
+NbiPopReceivePacket(
+ 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;
+ CTELockHandle LockHandle;
+
+ s = ExInterlockedPopEntrySList(
+ &Device->ReceivePacketList,
+ &NbiGlobalPoolInterlock);
+
+ if (s != NULL) {
+ return s;
+ }
+
+ //
+ // No packets in the pool, see if we can allocate more.
+ //
+
+ if (Device->AllocatedReceivePackets < Device->MaxPackets) {
+
+ //
+ // Allocate a pool and try again.
+ //
+
+ NB_GET_LOCK (&Device->Lock, &LockHandle);
+
+ NbiAllocateReceivePool (Device);
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+ s = ExInterlockedPopEntrySList(
+ &Device->ReceivePacketList,
+ &NbiGlobalPoolInterlock);
+
+
+ return s;
+
+ } else {
+
+ return NULL;
+
+ }
+
+} /* NbiPopReceivePacket */
+
+
+PSINGLE_LIST_ENTRY
+NbiPopReceiveBuffer(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates a receive buffer from the device context's pool.
+ If there are no buffers in the pool, it allocates one up to
+ the configured limit.
+
+Arguments:
+
+ Device - Pointer to our device to charge the buffer to.
+
+Return Value:
+
+ The pointer to the Linkage field in the allocated receive buffer.
+
+--*/
+
+{
+#if defined(_PNP_POWER)
+ PSINGLE_LIST_ENTRY s;
+ PNB_RECEIVE_BUFFER ReceiveBuffer;
+ PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
+ CTELockHandle LockHandle;
+
+ NB_GET_LOCK( &Device->Lock, &LockHandle );
+
+ s = PopEntryList( &Device->ReceiveBufferList );
+
+
+ if ( !s ) {
+
+ //
+ // No buffer in the pool, see if we can allocate more.
+ //
+ if (Device->AllocatedReceiveBuffers < Device->MaxReceiveBuffers) {
+
+ //
+ // Allocate a pool and try again.
+ //
+
+
+ NbiAllocateReceiveBufferPool (Device, Device->CurMaxReceiveBufferSize );
+ s = PopEntryList(&Device->ReceiveBufferList);
+ }
+ }
+
+ if ( s ) {
+
+
+ //
+ // Decrement the BufferFree count on the corresponding ReceiveBufferPool.
+ // so that we know that
+ ReceiveBuffer = CONTAINING_RECORD( s, NB_RECEIVE_BUFFER, PoolLinkage );
+
+
+ ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)ReceiveBuffer->Pool;
+
+ CTEAssert( ReceiveBufferPool->BufferFree && ( ReceiveBufferPool->BufferFree <= ReceiveBufferPool->BufferCount ) );
+ CTEAssert( ReceiveBufferPool->BufferDataSize == Device->CurMaxReceiveBufferSize );
+
+ ReceiveBufferPool->BufferFree--;
+
+ }
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+
+ return s;
+#else
+ PSINGLE_LIST_ENTRY s;
+ CTELockHandle LockHandle;
+
+ s = ExInterlockedPopEntryList(
+ &Device->ReceiveBufferList,
+ &Device->Lock.Lock);
+
+ if (s != NULL) {
+ return s;
+ }
+
+ //
+ // No buffer in the pool, see if we can allocate more.
+ //
+
+ if (Device->AllocatedReceiveBuffers < Device->MaxReceiveBuffers) {
+
+ //
+ // Allocate a pool and try again.
+ //
+
+ NB_GET_LOCK (&Device->Lock, &LockHandle);
+
+ NbiAllocateReceiveBufferPool (Device);
+ s = PopEntryList(&Device->ReceiveBufferList);
+
+ NB_FREE_LOCK (&Device->Lock, LockHandle);
+
+ return s;
+
+ } else {
+
+ return NULL;
+
+ }
+#endif _PNP_POWER
+} /* NbiPopReceiveBuffer */
+