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

📄 receive.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
       // 
       //  Let's link to the "Small" buffer pool.
       // 
       pFreeBufQ = pRecvSegInfo->FreeSmallBufQ;
       pRecvPoolTail = pSar->SmallRecvPoolTail;
       pRecvPoolQ = pSar->SmallRecvPoolQ;
       pAllocatedRecvBuffers = &pSar->AllocatedSmallRecvBuffers;
   }
   else
   {
       // 
       //  Let's link to the "Big" buffer pool.
       // 
       pFreeBufQ = pRecvSegInfo->FreeBigBufQ;
       pRecvPoolTail = pSar->BigRecvPoolTail;
       pRecvPoolQ = pSar->BigRecvPoolQ;
       pAllocatedRecvBuffers = &pSar->AllocatedBigRecvBuffers;
   }

   //
   //	Walk the list of receive buffers on the pool and add them
   //	to the free list.
   //
   for (pRecvHeader = pRecvPool->FreeBuffersHead;
        pRecvHeader != NULL;
        pRecvHeader = pNextRecvHeader)
   {
       //
       //	Save the real next pointer.
       //
       pNextRecvHeader = pRecvHeader->Next;

       //
       //  Queue the buffer to the end of queue.
       //
       tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvHeader, TRUE);
   }

   //
   //	There are no more receive buffers in the pool.	
   //	They all have been allocated for use and placed in the
   //	receive buffer information's free list.
   //

   //
   //  Queue pRecvPool to the (Big or Small) Recv_Buffer_Pool Queue.
   //
   if (NULL == pRecvPoolQ)
   {
       // 
       // Queue is empty
       // 
       pRecvPoolQ = pRecvPool;
       pRecvPoolTail = pRecvPool;
   }
   else
   {
       pRecvPoolTail->Next = pRecvPool;
       pRecvPoolTail = pRecvPool;
   }
   *pAllocatedRecvBuffers += (USHORT) (pRecvPool->BuffersFreed);

   pRecvPool->FreeBuffersHead = NULL;
   pRecvPool->BuffersFreed = 0;

   //
   // Reset to NULL to dettach from pVc and its data structures.
   //
   pRecvPool->RecvBufferInfo = NULL;

   NdisReleaseSpinLock(&pRecvInfo->lock);
}



NDIS_STATUS
tbAtm155AllocateReceiveBufferPool(
   IN  PADAPTER_BLOCK      pAdapter,
   IN  PRECV_BUFFER_INFO   pRecvInfo,
   IN  ULONG               NumberOfReceiveBuffers,
   IN  ULONG               SizeOfReceiveBuffer
   )
/*++

Routine Description:

   This routine will allocate a pool of receive buffers, NDIS_BUFFERs
   to identify them and packets to package them.

Arguments:

   pAdapter                -   Pointer to the adapter block.
   pRecvInfo               -   Pointer to the receive buffer information that
                               will keep track of the buffer pool that we
                               allocate.
   NumberOfReceiveBuffers  -   Number of buffers to allocate.
   SizeOfReceiveBuffers    -   Size of each receive buffer.

Return Value:

   NDIS_STATUS_SUCCESS     if the allocation was successful.
   NDIS_STATUS_RESOURCES   if the allocation failed due to memory constraints.

--*/
{
   NDIS_STATUS         Status;
   PRECV_BUFFER_POOL   pRecvPool = NULL;
   ULONG               TotalBufferSize;

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

   ASSERT(RECV_BUFFER_INFO_SIG == pRecvInfo->Signature);

   do
   {
       //
       //	Allocate storage for the buffer pool.
       //
       ALLOCATE_MEMORY(
           &Status,
           &pRecvPool,
           sizeof(RECV_BUFFER_POOL),
           '80DA');
       if (NDIS_STATUS_SUCCESS != Status)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("Unable to allocate a buffer pool\n"));

           break;
       }

       ZERO_MEMORY(pRecvPool, sizeof(RECV_BUFFER_POOL));

       pRecvPool->Signature = RECV_BUFFER_POOL_SIG;

       //
       //	Save a back pointer to the owning receive buffer information
       //	structure.
       //
       pRecvPool->RecvBufferInfo = pRecvInfo;

       //
       //	Allocate the packet pool.
       //
       NdisAllocatePacketPool(
           &Status,
           &pRecvPool->hNdisPacketPool,
           NumberOfReceiveBuffers,
           PROTOCOL_RESERVED_SIZE_IN_PACKET + TBATM155_PROTOCOL_RESERVED);
       if (Status != NDIS_STATUS_SUCCESS)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("Unable to allocate NDIS packet pool\n"));

           break;
       }

       //
       //	Allocate a buffer pool.
       //
       NdisAllocateBufferPool(
           &Status,
           &pRecvPool->hFlushBufferPool,
           NumberOfReceiveBuffers);
       if (Status != NDIS_STATUS_SUCCESS)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("Unable to allocate a NDIS_BUFFER pool for flush buffers.\n"));

           break;
       }

       //
       //	Allocate a buffer pool.
       //
       NdisAllocateBufferPool(
           &Status,
           &pRecvPool->hNdisBufferPool,
           NumberOfReceiveBuffers);
       if (Status != NDIS_STATUS_SUCCESS)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("Unable to allocate a NDIS_BUFFER pool for receive buffers.\n"));

           break;
       }

       //
       //	Save the number of buffers needed and the size for each buffer
       //	with the pool.
       //
       pRecvPool->ReceiveBufferCount = NumberOfReceiveBuffers;

       pRecvPool->ReceiveBufferSize = 
			(((SizeOfReceiveBuffer + gDmaAlignmentRequired - 1) /
			gDmaAlignmentRequired) * gDmaAlignmentRequired);


       //
       //	Using the alignment determine the size of the header
       //	for the receive buffers.
       //
       pRecvPool->ReceiveHeaderSize =
               (((sizeof(RECV_BUFFER_HEADER) + gDmaAlignmentRequired - 1) /
               gDmaAlignmentRequired) * gDmaAlignmentRequired);

       //
       //	Determine the total size needed for each buffer.
       //
       TotalBufferSize = pRecvPool->ReceiveHeaderSize + SizeOfReceiveBuffer;

       //
       //	We are going to first attempt to allocate this in one
       //	large chunk.
       //
       pRecvPool->Size = (NumberOfReceiveBuffers * TotalBufferSize) +
                          gDmaAlignmentRequired;

       //
       //	If we are doing this from the tbAtm155ActivateVc handler then
       //	we need to call async allocate to get our shared memory.
       //
       if (!ADAPTER_TEST_FLAG(pAdapter, fADAPTER_INITIALIZING))
       {
           ASSERT(NULL != pRecvInfo->pVc);

           //
           //	Setup for the staged allocation.
           //
           RECV_POOL_SET_FLAG(pRecvPool, fRECV_POOL_ALLOCATING_BLOCK);

           //
           //	Attempt to allocate the shared memory.
           //
           Status = NdisMAllocateSharedMemoryAsync(
                           pAdapter->MiniportAdapterHandle,
                           pRecvPool->Size,
                           TRUE,
                           pRecvPool);

           //
           //	The call above will either return pending or some error code.
           //
           break;
       }

       //
       //	Allocate a chunk of shared ram for the receive buffers.
       //
       NdisMAllocateSharedMemory(
           pAdapter->MiniportAdapterHandle,
           pRecvPool->Size,
           TRUE,
           &pRecvPool->VirtualAddress,
           &pRecvPool->PhysicalAddress);
       if (NULL != pRecvPool->VirtualAddress)
       {
           //
           //	Initialize the receive pool.
           //
           Status = tbAtm155InitializeBlockReceivePool(pRecvPool);
           if (NDIS_STATUS_SUCCESS != Status)
           {
               DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                   ("Unable to initialize the receive block\n"));

               break;
           }
       }
       else
       {
           //
           //	Do the individual buffer allocations.
           //
           Status = tbAtm155AllocateIndividualReceiveBuffers(
                       pAdapter,
                       pRecvPool);
           if (NDIS_STATUS_SUCCESS != Status)
           {
               DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                   ("Unable to allocate individual receive buffers\n"));

               break;
           }
       }

       //
       //	Did we successfully set up our receive packets and
       //	buffers?
       //
       if (NDIS_STATUS_SUCCESS == Status)
       {
           //
           //	Place the receive pool's buffers onto the receive info's
           //	free buffer list.
           //
           tbAtm155QueueReceivePoolToSarInfo(pRecvInfo, pRecvPool);

       }

   } while (FALSE);			

   //
   //	If we failed the routine then we need to free the resources
   //	that were allocated.
   //
   if ((NDIS_STATUS_SUCCESS != Status) && (NDIS_STATUS_PENDING != Status))
   {
       if (NULL != pRecvPool)
       {
           tbAtm155FreeReceiveBufferPool(pAdapter, pRecvPool);
       }
   }

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

   return(Status);
}


BOOLEAN
tbAtm155RxInterruptOnCompletion(
   IN  PADAPTER_BLOCK      pAdapter
	)
/*++

Routine Description:

   This routine will process the Receive Interrupt On Completion
   for the different receive buffers.  This interrupt will be generated
   when a packet has been received from a Rx Active Slot list of a VC.
   If the packet(s) have been receive without error, pass up to NDIS.
   Otherwise, discard the packet and return the buffers into free pool
   for the next receiving.


Arguments:

   pAdapter    -   Pointer to the adapter block.

Return Value:

   None.

--*/
{
   PHARDWARE_INFO              pHwInfo = pAdapter->HardwareInfo;
   PSAR_INFO                   pSar = pHwInfo->SarInfo;
   PRECV_DMA_QUEUE             pRecvDmaQ = &pSar->RecvDmaQ;
   AAL5_PDU_TRAILER            Trailer;
   PNDIS_PACKET                Packet;
   PVC_BLOCK                   pVc;
   PRX_REPORT_QUEUE            pRxReportQ = &pAdapter->RxReportQueue;
   PRX_REPORT_QUEUE_ENTRY      RxReportQueue;
   RX_REPORT_PTR               RxReportPtrReg;
   ULONG                       CurrentRxReportPtrPa;
   UINT                        CurrentRxReportQIdx;
   UINT                        i;
   ULONG                       Vci;
   PRECV_SEG_INFO              pRecvSegInfo;
   PRECV_BUFFER_HEADER         pRecvBufHead;
   PRECV_BUFFER_QUEUE          pFreeBufQ;

   PRECV_BUFFER_QUEUE          pSegCompleting;

   PNDIS_BUFFER                LastBuffer;
   PUCHAR                      LastBufferVa;
   UINT                        LastBufferLength;

   PNDIS_BUFFER                prevLastBuffer;
   PUCHAR                      prevLastBufferVa;
   UINT                        prevLastBufferLength;
   ULONG                       TrimAmount;
   UINT                        PacketLength;
   UINT                        PhysicalBufferCount;

   PMEDIA_SPECIFIC_INFORMATION pMediaSpecificInfo;
   ULONG                       MediaSpecificInfoSize;
   PATM_AAL_OOB_INFO           pAtmOobInfo;
   LONG                        tmpBufferType;
   BOOLEAN                     fReturnStatus = FALSE;
   BOOLEAN                     fRxSlotsLowOrNone;
   PRX_REPORT_QUEUE_ENTRY      pEntryOfRxReportQ;

   NDIS_STATUS                 Status;
   ULONG                       Dest;
   PULONG                      pTmpFreeSlots;
   PRECV_PACKET_RESERVED       Reserved;
   BOOLEAN                     fCorruptedPacket = FALSE;
   BOOLEAN                     fQueryBufferFail = FALSE;
#if    DBG
   PULONG                      pdbgTotalUsedRxSlots;
#endif // end of DBG


   TBATM155_READ_PORT(
       &pHwInfo->TbAtm155_SAR->Rx_Report_Ptr,
       &RxReportPtrReg.reg);

   //
   //  Got the position of 155 PCI SAR's internal Rx report queue.
   //  This pointer indicates the address in host memory to whcih 155 SAR
   //  will write the next Rx report. So we will only process up to the
   //  previous entry to make sure the status is valid
   //
   CurrentRxReportPtrPa = RxReportPtrReg.reg & ~0x3;

   //
   //  Calcuate the index of Rx Report Queue which is pointed by controller.
   //  HANDLING RULE:
   //      We only handle up to the entry before this one.
   //
   CurrentRxReportQIdx =
           (CurrentRxReportPtrPa - 
           NdisGetPhysicalAddressLow(pRxReportQ->RxReportQptrPa)) /
           sizeof(RX_REPORT_QUEUE_ENTRY);

   //
   //  Get the starting point where the entry of Rx report queue 
   //  needs to be handled.
   //
   RxReportQueue = (PRX_REPORT_QUEUE_ENTRY)pRxReportQ->RxReportQptrVa;

⌨️ 快捷键说明

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