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

📄 receive.c

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

   NdisDprAcquireSpinLock(&pRecvDmaQ->lock);

   DBGPRINT(DBG_COMP_RXIOC, DBG_LEVEL_ERR, 
           ("RxIOC CurRxRQIdx(%x), PrevRxRQIdx(%x)\n", 
           CurrentRxReportQIdx, pRecvDmaQ->PrevRxReportQIndex));

   for (i = pRecvDmaQ->PrevRxReportQIndex;
        i != CurrentRxReportQIdx;
        i = (i == pHwInfo->MaxIdxOfRxReportQ)? 0 : ++i)
   {
       //
       //  Get the VC from report queue.
       //
       pEntryOfRxReportQ = &RxReportQueue[i];
       Vci = (ULONG) pEntryOfRxReportQ->RxReportQDWord1.VC;

       //       
       //  Get the physical address of reported buffer to search
       //  the buffer from CompletingXXXBufQ accordingly.
       //       
       Dest = pEntryOfRxReportQ->RxReportQDWord0.Index;

       tmpBufferType = (pEntryOfRxReportQ->RxReportQDWord0.rqSlotType == 1)?
                       RECV_BIG_BUFFER :
                       RECV_SMALL_BUFFER;

       //
       //  Search reported buffer queue first. 
       //  if not find the buffer then search another buffer queue.
       //
       if (RECV_BIG_BUFFER == tmpBufferType)
       {

#if    DBG
           pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedBigRxSlots;
#endif // end of DBG

           tbAtm155SearchRecvBufferFromQueue(
               &pRecvDmaQ->CompletingBigBufQ,
               Dest,
               &pRecvBufHead);

           if (NULL == pRecvBufHead)
           {
               tmpBufferType = RECV_SMALL_BUFFER;

#if    DBG
               pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedSmallRxSlots;
#endif // end of DBG

               //           
               //  Try from "Small" buffer pool.           
               //           
               tbAtm155SearchRecvBufferFromQueue(
                   &pRecvDmaQ->CompletingSmallBufQ,
                   Dest,
                   &pRecvBufHead);
           }
       }
       else
       {

#if    DBG
           pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedSmallRxSlots;
#endif // end of DBG

           tbAtm155SearchRecvBufferFromQueue(
               &pRecvDmaQ->CompletingSmallBufQ,
               Dest,
               &pRecvBufHead);

           if (NULL == pRecvBufHead)
           {
               tmpBufferType = RECV_BIG_BUFFER;

#if    DBG
               pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedBigRxSlots;
#endif // end of DBG

               //           
               //  Try from "Big" buffer pool.           
               //           
               tbAtm155SearchRecvBufferFromQueue(
                   &pRecvDmaQ->CompletingBigBufQ,
                   Dest,
                   &pRecvBufHead);
           }
       }

       if (NULL == pRecvBufHead)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("Can NOT find from either pool.(Dest=%lx)\n", Dest));
           
           DBGPRINT(DBG_COMP_NRXBUFFOUND, DBG_LEVEL_ERR, 
                   ("RxIOC CurRxRQIdx(%x), PrevRxRQIdx(%x)\n", 
                   CurrentRxReportQIdx, pRecvDmaQ->PrevRxReportQIndex));

           DBGPRINT(DBG_COMP_NRXBUFFOUND, DBG_LEVEL_ERR, 
                   ("RxIOC RxReportEntryW0(%lx), RxReportEntryW1(%lx)\n", 
                   pEntryOfRxReportQ->RxReportQueueDword0, 
                   pEntryOfRxReportQ->RxReportQueueDword1));

           continue;       
       }

       if (RECV_BIG_BUFFER == tmpBufferType)
       {
           //           
           //  Make sure return to the corresponding queue.
           //           
           pFreeBufQ = &pSar->FreeBigBufferQ;
           pTmpFreeSlots = &pRecvDmaQ->RemainingReceiveBigSlots;
           fRxSlotsLowOrNone = pSar->fBigllSlotsLowOrNone;
       }
       else
       {
           //           
           //  Make sure return to the corresponding queue.
           //           
           pFreeBufQ = &pSar->FreeSmallBufferQ;
           pTmpFreeSlots = &pRecvDmaQ->RemainingReceiveSmallSlots;
           fRxSlotsLowOrNone = pSar->fSmallSlotsLowOrNone;
       }

       //
       //  Update the remaining free slot count for the buffer queue.
       //
       (*pTmpFreeSlots)++;

       //
       //	flush the cache.
       //
       NdisFlushBuffer(pRecvBufHead->FlushBuffer, FALSE);

       NdisMUpdateSharedMemory(
           pAdapter->MiniportAdapterHandle,
           pRecvBufHead->Alloc[RECV_BUFFER_ALIGNED].Size,
           pRecvBufHead->Alloc[RECV_BUFFER_ALIGNED].VirtualAddress,
           pRecvBufHead->Alloc[RECV_BUFFER_ALIGNED].PhysicalAddress);


#if    DBG
       (*pdbgTotalUsedRxSlots)++;
#endif // end of DBG


       //
       //  Check if the Vc is valid.
       //
       NdisDprReleaseSpinLock(&pRecvDmaQ->lock);
       pVc = tbAtm155UnHashVc(pAdapter, Vci);
       NdisDprAcquireSpinLock(&pRecvDmaQ->lock);

       if (NULL == pVc)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("There is not a valid VC for %u\n", Vci));

           NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvInvalidVpiVci);

           //
           //  Return the receive buffer to the free pool.
           //
           tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);

           continue;
       }

       //
       //  BUGFIX 158842
       //
       if (!VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_RECEIVE)))
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
				("We don't have a valid VC_BLOCK: 0x%x for VCI: %u\n", pVc, Vci));

           //
           //  Return the receive buffer to the free pool.
           //
           tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);

           continue;
       }

       pRecvSegInfo = pVc->RecvSegInfo;

       if (pVc->RecvBufType != tmpBufferType)
       {
           DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
               ("Buffer types are not matched with the VC's.\n"));

           //
           //
           //  The buffer type is not matched with the type reported
           //  from Rx report queue, return the receive buffer to the
           //  free pool, then go to handle the next report entry.
           //
           tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
           
           continue;
       }

       //
       //  Point to the list which queues the receive buffers until
       //  a whole packet is in (indicates by EOP flag in Rx report queue.)
       //
       pSegCompleting = &pRecvSegInfo->SegCompleting;

       //
       //  Let's check if the data in the receive buffer is healthy.
       //
       if (pEntryOfRxReportQ->RxReportQDWord1.Bad)
       {
           //
           //  Data in the buffer is bad.
           //
           //  1. Release any chained buffers in the VC.
           //  2. Return the current receive buffer back to the buffer pool.
           //
           if (NULL != pSegCompleting->BufListHead)
           {
               NdisDprReleaseSpinLock(&pRecvDmaQ->lock);

               // 
               //  It is possible that receive congestion happened.
               //  Abort the receive buffers, which contain the packet,
               //  into the list.
               // 

               tbAtm155ProcessReturnPacket(
                       pAdapter,
                       pSegCompleting->BufListHead->Packet,
                       pSegCompleting->BufListHead,
                       FALSE);
  
               NdisDprAcquireSpinLock(&pRecvDmaQ->lock);
               //
               //  Check if the buffer has been freed in tbAtm155ProcessReturnPacket()
               //
               if (NULL != pRecvSegInfo)
               {
                   pSegCompleting->BufListHead = NULL;
                   pSegCompleting->BufListTail = NULL;
                   pSegCompleting->BufferCount = 0;
               }

               DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR, ("Recved a bad packet.\n"));
           }

           //
           //  Return the receive buffer to the free pool.
           //
           tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);

           //
           //      There are for
           //          1. Adapters in ADAPTER_BLOCK
           //          2. VC in VC_BLOCK
           //
           switch (pEntryOfRxReportQ->RxReportQDWord1.Status)
           {
               case Crc32ErrDiscard:
                   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                       ("CRC32 Error detected, discard packet.\n"));
                   NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvCrcError);
                   NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvCrcError);
                   break;

               case LengthErrDiscard:
                   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                       ("Packet Length Error detected, discard packet.\n"));
                   NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusError);
                   NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusError);
				    break;

               case AbortedPktDiscard:
                   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                       ("Aborted Packet detected, discard packet.\n"));
                   NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusError);
                   NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusError);
				    break;

               case SlotCongDiscard:
                   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                       ("Slot Congestion detected, discard packet.\n"));
                   NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvCellsDropped);
                   NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvCellsDropped);
				    break;

               case OtherCellErrDiscard:
                   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                       ("Other Cell Error detected, discard packet.\n"));
                   NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusNoBuffer);
                   NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusNoBuffer);
				    break;

               case ReassemblyTimeout:
                   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                       ("Reassembly Timeout detected, discard packet.\n"));
                   NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvReassemblyErr);
                   NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvReassemblyErr);
				    break;

               case PktTooLongErr:
                   DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
                       ("Packet Too Long detected, discard packet.\n"));
                   NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusError);
                   NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusError);
				    break;

           }

           continue;
       }

       //
       //	Save Vc info to this receive buffer.
       //
       pRecvBufHead->pVc = pVc;

       if ((pEntryOfRxReportQ->RxReportQDWord1.Sop == 0) &&
           (NULL == pSegCompleting->BufListHead))
       {
           // 
           // The SOP of the packet is lost. 
           // Return this receive buffer to the free pool.
           //
           DBGPRINT(DBG_COMP_SPECIAL, DBG_LEVEL_ERR,
                   ("Lost the SOP of the packet, discard packet.\n"));
           tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
           continue;
       }

       if (pEntryOfRxReportQ->RxReportQDWord1.Sop)
       {
           if ((pEntryOfRxReportQ->RxReportQDWord1.Eop) && 
               (1 == pEntryOfRxReportQ->RxReportQDWord1.Status))
           {
               // 
               //  AAL5 Reassembly Timeout.
               //  Return this receive buffer to the free pool.
               //
               DBGPRINT(DBG_COMP_SPECIAL, DBG_LEVEL_ERR,
                       ("Experienced reassembly timeout. discard packet.\n"));
               tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
               continue;
           }

       	   NdisDprReleaseSpinLock(&pRecvDmaQ->lock);
           NdisDprAcquireSpinLock(&pVc->lock);

           //
           //  Verify if the VC is still active again for just in case.
           //
           if (!VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_RECEIVE)))
           {
               DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
				         ("We don't have a valid VC_BLOCK now: 0x%x for VCI: %u\n", pVc, Vci));

               NdisDprReleaseSpinLock(&pVc->lock);
               NdisDprAcquireSpinLock(&pRecvDmaQ->lock);

               //
               //  Return the receive buffer to the free pool.
               //
               tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
               continue;
           }

           //
           //	Reference the VC
           //
           tbAtm155ReferenceVc(pVc);

           NdisDprReleaseSpinLock(&pVc->lock);
           NdisDprAcquireSpinLock(&pRecvDmaQ->lock);

           //
           //  This flag indicates if the slot being reported contains
           //  the first byte of an AAL5 packet.
           //  Also, it may be used by the driver to detect error conditions
           //  which may not have been reported due to lack of slots
           //  (receive congestion).
           //
           if (NULL != pSegCompleting->BufListHead)
           {
               NdisDprReleaseSpinLock(&pRecvDmaQ->lock);

               // 
               //  It is possible that receive congestion happened.
               //  Abort the receive buffers in the list.
               // 
               tbAtm155ProcessReturnPacket(
                   pAdapter,
                   pSegCompleting->BufListHead->Packet,
                   pSegCompleting->BufListHead,
                   FALSE);

               NdisDprAcquireSpinLock(&pRecvDmaQ->lock);

               //
               //  Check if the buffer has been freed in tbAtm155ProcessReturnPacket()
               //
               if (NULL != pRecvSegInfo)
               {
                   pSegCompleting->BufListHead = NULL;
                   pSegCompleting->BufListTail = NULL;
                   pSegCompleting->BufferCount = 0;
               }

               NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvCellsDropped);
               NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvCellsDropped);
           }

           //
           //	Grab a packet for the receive.
           //
           Packet = pRecvBufHead->Packet;

           //
           //	Save the first receive buffer to be used with the packet.
           //

⌨️ 快捷键说明

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