⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 receive.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:

       //
       //	Save the pointer to the media specific information in
       //	the packets OOB information.
       //
       NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(
           pRecvHeader->Packet,
           pMediaSpecificInfo,
			sizeof(MEDIA_SPECIFIC_INFORMATION) + sizeof(ATM_AAL_OOB_INFO));

       //
       //	Save the pool with the receive buffer.
       //
       pRecvHeader->Pool = pRecvPool;

       //
       //	Chain the buffer to the owning pool.
       //
       pRecvHeader->Next = pRecvPool->FreeBuffersHead;
		pRecvHeader->Prev = NULL;
       pRecvPool->FreeBuffersHead = pRecvHeader;
       pRecvPool->BuffersFreed++;
   }
   else
   {

       DBGPRINT(DBG_COMP_SPECIAL, DBG_LEVEL_ERR,
           ("tbAtm155InitializeReceiveBuffer: failed, freed up allcated buffers.\n"));

       if (NULL != pRecvHeader->FlushBuffer)
       {
           NdisFreeBuffer(pRecvHeader->FlushBuffer);
           pRecvHeader->FlushBuffer = NULL;
       }

       //
       //	Free the NDIS buffer.
       //
       if (NULL != pRecvHeader->NdisBuffer)
       {
           NdisFreeBuffer(pRecvHeader->NdisBuffer);
           pRecvHeader->NdisBuffer = NULL;
       }

       //
       //	Free the NDIS packet.
       //
       if (NULL != pRecvHeader->Packet)
       {
           NdisFreePacket(pRecvHeader->Packet);
           pRecvHeader->Packet = NULL;
       }
   }

   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
       ("<==tbAtm155InitializeReceiveBuffer\n"));

   return(Status);
}


NDIS_STATUS
tbAtm155InitializeBlockReceivePool(
   IN  PRECV_BUFFER_POOL   pRecvPool
	)
/*++

Routine Description:

   This routine will initialize receive buffers from a receive buffer pool
   that was allocated in a single chunk of shared memory.

Arguments:

   pRecvPool   -   Pointer to the receive pool to initialize.

Return Value:

   NDIS_STATUS_SUCCESS     if the receive pool is successfully initialized.

--*/
{
   ULONG                   Offset;
   PUCHAR                  StartVa;
   NDIS_PHYSICAL_ADDRESS   StartPa;
   PUCHAR                  AlignedVa;
   NDIS_PHYSICAL_ADDRESS   AlignedPa;
   ULONG                   BufferSize;
   PRECV_BUFFER_HEADER     pRecvHeader;
   UINT                    c;
   NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;


   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
       ("==>tbAtm155InitializeBlockReceivePool\n"));

   ASSERT(RECV_BUFFER_POOL_SIG == pRecvPool->Signature);

   //
   //	Determine the buffer size including header.
   //
   BufferSize = pRecvPool->ReceiveHeaderSize + pRecvPool->ReceiveBufferSize;

   //
   //	Align the block.
   //
   Offset = (ULONG)((ULONG_PTR)pRecvPool->VirtualAddress % gDmaAlignmentRequired);
   if (Offset != 0)
   {
       Offset = gDmaAlignmentRequired - Offset;
   }

   //
   //	Get pointers to the aligned block.
   //
   StartVa = ((PUCHAR)pRecvPool->VirtualAddress + Offset);

   NdisSetPhysicalAddressHigh(StartPa, 0);
   NdisSetPhysicalAddressLow(
       StartPa,
       NdisGetPhysicalAddressLow(pRecvPool->PhysicalAddress) + Offset);

   RECV_POOL_SET_FLAG(pRecvPool, fRECV_POOL_BLOCK_ALLOC);

   //
   //	Initialize the temporary physical address.
   //
   AlignedPa = StartPa;

   for (c = 0, Offset = 0; c < pRecvPool->ReceiveBufferCount; c++)
   {
       //
       //	Determine the virtual address for the receive buffer within
       //	the block.
       //
       AlignedVa = (PUCHAR)StartVa + Offset;

       //
       //	Determine the physical address for the receive buffer within
       //	the block.
       //
       NdisSetPhysicalAddressLow(
           AlignedPa,
           NdisGetPhysicalAddressLow(StartPa) + Offset);

       //
       //	Get the offset for the next buffer within the block.
       //
       Offset += BufferSize;

       //
       //	Get a pointer to the receive header.
       //
       pRecvHeader = (PRECV_BUFFER_HEADER)AlignedVa;

       //
       //	Initialize the header.
       //
       ZERO_MEMORY(pRecvHeader, sizeof(RECV_BUFFER_HEADER));

       //
       //	Pass the receive buffer to a common initialization routine.
       //
       Status = tbAtm155InitializeReceiveBuffer(
                   pRecvPool,
                   pRecvHeader,
                   AlignedVa,
                   AlignedPa,
                   pRecvPool->ReceiveBufferSize);
       if (NDIS_STATUS_SUCCESS != Status)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("tbAtm155InitializeReceiveBuffer failed\n"));

           break;
       }
   }

   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
       ("<==tbAtm155InitializeBlockReceivePool\n"));

   return(Status);
}

VOID
tbAtm155BuildIndividualReceiveHeader(
   OUT PRECV_BUFFER_HEADER     *ppRecvHeader,
   OUT PUCHAR                  *pAlignedVa,
   OUT NDIS_PHYSICAL_ADDRESS   *pAlignedPa,
   IN  PUCHAR                  VirtualAddress,
   IN  NDIS_PHYSICAL_ADDRESS   PhysicalAddress,
   IN  ULONG                   TotalBufferSize
)
/*++

Routine Description:

   This routine simply aligns the virutal address to get the receive header
   and saves the original virutal address, physical address, and size with it.
   The reason it's in a routine is that it's called from different places
   in the driver.

Arguments:

   ppRecvHeader    -   Pointer to the storage for the PRECV_BUFFER_HEADER.
   pAlignedVa      -   Pointer to the storage for the aligned virtual address.
   pAlignedPa      -   Pointer to the storage for the aligned physical address.
   VirtualAddress  -   Unaligned virtual address for the receive buffer.
   PhysicalAddress -   Unaligned physical address for the receive buffer.
   TotalBufferSize -   Size of the receive buffer and header.

Return Value:

   None.

--*/
{
   ULONG               Offset;
   PRECV_BUFFER_HEADER pRecvHeader;

   //
   //	Determine the offset into the allocated buffer so that it would
   //	be correctly aligned.
   //
   Offset = (ULONG)((ULONG_PTR)VirtualAddress % gDmaAlignmentRequired);
   if (Offset != 0)
   {
       Offset = gDmaAlignmentRequired - Offset;
   }
   *pAlignedVa = (PUCHAR)VirtualAddress + Offset;

   NdisSetPhysicalAddressLow(
       *pAlignedPa,
       NdisGetPhysicalAddressLow(PhysicalAddress) + Offset);

   //
   //	Get a pointer to the receive buffer header.
   //
   pRecvHeader = (PRECV_BUFFER_HEADER)*pAlignedVa;

   //
   //	Initialize the receive header.
   //
   ZERO_MEMORY(pRecvHeader, sizeof(RECV_BUFFER_HEADER));

   //
   //	Save the original virtual address, physical address, and size
   //	of the shared memory allocation for deletion at a later time.
   //
   pRecvHeader->Alloc[RECV_BUFFER_ORIGINAL].VirtualAddress = VirtualAddress;
   pRecvHeader->Alloc[RECV_BUFFER_ORIGINAL].PhysicalAddress = PhysicalAddress;
   pRecvHeader->Alloc[RECV_BUFFER_ORIGINAL].Size = TotalBufferSize;

   *ppRecvHeader = pRecvHeader;
}


NDIS_STATUS
tbAtm155AllocateIndividualReceiveBuffers(
   IN  PADAPTER_BLOCK      pAdapter,
   IN  PRECV_BUFFER_POOL   pRecvPool
   )
/*++

Routine Description:

   This routine will attempt to allocate individual shared memory chunks
   for the receive buffers.

Arguments:

   pAdapter    -   Pointer to the ADAPTER_BLOCK.
   pRecvPool   -   Pointer to the RECV_BUFFER_POOL that will manage the
                   receive buffers.

Return Value:

   NDIS_STATUS_SUCCESS     if we were able to allocate the receive buffers.

--*/
{
   ULONG                   TotalBufferSize;
   UINT                    c;
   PUCHAR                  VirtualAddress;
   NDIS_PHYSICAL_ADDRESS   PhysicalAddress;
   PUCHAR                  AlignedVa;
   NDIS_PHYSICAL_ADDRESS   AlignedPa;
   PRECV_BUFFER_HEADER     pRecvHeader;
   NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;

   ASSERT(RECV_BUFFER_POOL_SIG == pRecvPool->Signature);


   //
   //	We need to readjust the size of the recieve header, with
   //	respect to the alignment, to take into consideration another
   //	ALLOCATION_INFO struct.  this structure will hold the original
   //	virtual address, physical address and size that is returned for
   //	each, individual buffer allocation.
   //
   pRecvPool->ReceiveHeaderSize =
       (((sizeof(RECV_BUFFER_HEADER) + sizeof(ALLOCATION_INFO) +
        gDmaAlignmentRequired - 1) / gDmaAlignmentRequired) *
        gDmaAlignmentRequired);

   //
   //	Determine the actual size for each shared memory allocation.
   //
   TotalBufferSize = pRecvPool->ReceiveHeaderSize +
                       pRecvPool->ReceiveBufferSize;


   //
   //	Loop allocating the buffers.
   //
   for (c = 0; c < pRecvPool->ReceiveBufferCount; c++)
   {
       //
       //	Attempt to allocate the shared memory.
       //
       NdisMAllocateSharedMemory(
           pAdapter->MiniportAdapterHandle,
           TotalBufferSize,
           TRUE,
           &VirtualAddress,
           &PhysicalAddress);
       if (NULL == VirtualAddress)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("Unable to allocate an individual shared memory receive buffer\n"));

           Status = NDIS_STATUS_RESOURCES;
           break;
       }

       //
       //	Build the individual receive header.
       //
       tbAtm155BuildIndividualReceiveHeader(
               &pRecvHeader,
               &AlignedVa,
               &AlignedPa,
               VirtualAddress,
               PhysicalAddress,
               TotalBufferSize);

       //
       //	Finish the common buffer initialization.
       //
       Status = tbAtm155InitializeReceiveBuffer(
                       pRecvPool,
                       pRecvHeader,
                       AlignedVa,
                       AlignedPa,
                       pRecvPool->ReceiveBufferSize);
       if (NDIS_STATUS_SUCCESS != Status)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("tbAtm155InitializeReceiveBuffer failed for individual allocation\n"));

           //
           //	Deallocate the last shared memory allocation now.
           //	If any other individual buffers were allocted they are already
           //	queued to the receive pool and will be cleaned up when we
           //	deallocate the receive pool.
           //
           NdisMFreeSharedMemory(
               pAdapter->MiniportAdapterHandle,
               TotalBufferSize,
               TRUE,
               VirtualAddress,
               PhysicalAddress);

           break;
       }
   }

   return(Status);
}


VOID
tbAtm155QueueReceivePoolToSarInfo(
   IN  PRECV_BUFFER_INFO   pRecvInfo,
   IN  PRECV_BUFFER_POOL   pRecvPool
   )
/*++

Routine Description:

   This routine will walk through the receive pool's buffer list, remove the
   receive buffers from it and place them on either "BIG" or "SMALL" 
   free buffer list in the Sar information database.

Arguments:

   pRecvInfo   -   Pointer to the PRECV_BUFFER_INFO that owns the pool.
   pRecvPool   -   Pointer to the PRECV_BUFFER_POOL whose packets we are going
                   to allocate.
Return Value:

   None.

--*/
{
   PRECV_BUFFER_HEADER	    pRecvHeader;
   PRECV_BUFFER_HEADER	    pNextRecvHeader;
   PRECV_SEG_INFO          pRecvSegInfo = pRecvInfo->pVc->RecvSegInfo;
   PRECV_BUFFER_QUEUE      pFreeBufQ;
   PSAR_INFO               pSar = pRecvInfo->pVc->Sar;
   PRECV_BUFFER_POOL       pRecvPoolTail;
   PRECV_BUFFER_POOL       pRecvPoolQ;
   PUSHORT                 pAllocatedRecvBuffers;

   ASSERT(RECV_BUFFER_INFO_SIG == pRecvInfo->Signature);
   ASSERT(RECV_BUFFER_POOL_SIG == pRecvPool->Signature);

   //
   //	Add the new receive buffer to the Sar buffer info.
   //
   NdisAcquireSpinLock(&pRecvInfo->lock);

   if (pRecvInfo->pVc->RecvBufType == RECV_SMALL_BUFFER)
   {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -