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

📄 send.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
--*/
{
   PNDIS_PACKET        tmpPacket;
   PPACKET_RESERVED    Reserved;
   NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;
   PSAR_INFO           pSar = pXmitSegInfo->Adapter->HardwareInfo->SarInfo;
   PXMIT_DMA_QUEUE     pXmitDmaQ = &pSar->XmitDmaQ;


   NdisAcquireSpinLock(&pXmitSegInfo->lock);

   //
   //	Are they trying to send a specific packet?
   //
   if (ARGUMENT_PRESENT(Packet))
   {
       Reserved = PACKET_RESERVED_FROM_PACKET(Packet);

       //
       //	1. If there is segmentation memory available? 
       //	2. If there is FreePadTrailerBuffers available? 
       //
       if ((pXmitDmaQ->RemainingTransmitSlots < Reserved->PhysicalBufferCount) ||
           (pXmitSegInfo->BeOrBeingUsedPadTrailerBufs >= TBATM155_MAX_PADTRAILER_BUFFERS))
       {

           // 
           //  Insert the packet to DmaWait queue if
           //  1. there is allocated FreePadTrailerBuffers available,
           //  2. AAL5 packet, and
           //  3. SegWait queue of the VC is empty.
           //
           if ((pXmitSegInfo->BeOrBeingUsedPadTrailerBufs < TBATM155_MAX_PADTRAILER_BUFFERS) &&
	            (AAL_TYPE_AAL5 == Reserved->pVc->AALType) &&
               (PACKET_QUEUE_EMPTY(&pXmitSegInfo->SegWait)))
           {
               //
               // If we come to this point, it means there is no packets
               // of this VC have been sent out. So we queue to DmaWait
               // to make sure this packet will be sent out when there
               // are resources available.
               //
               InsertPacketAtTailDpc(&pXmitDmaQ->DmaWait, Packet);
               pXmitSegInfo->BeOrBeingUsedPadTrailerBufs++;

               NdisReleaseSpinLock(&pXmitSegInfo->lock);

               DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
                   ("<==tbAtm155ProcessSegmentQueue(NDIS_STATUS_PENDING_1)\n"));

               return(NDIS_STATUS_PENDING);
           }

           if ((pXmitSegInfo->BeOrBeingUsedPadTrailerBufs >= TBATM155_MAX_PADTRAILER_BUFFERS) ||
               (pXmitDmaQ->RemainingTransmitSlots < MIN_SLOTS_REQUIED_PER_PACKET))
           {
               //
               //	No room available in the SAR. We need to queue this
               //	and do it later.
               //
               dbgLogSendPacket(
                   PACKET_RESERVED_FROM_PACKET(Packet)->pVc->DebugInfo,
                   Packet,
                   2,
                   0,
                   ' wsQ');

               InsertPacketAtTailDpc(&pXmitSegInfo->SegWait, Packet);
               NdisReleaseSpinLock(&pXmitSegInfo->lock);

               DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
                   ("<==tbAtm155ProcessSegmentQueue(NDIS_STATUS_PENDING)\n"));

               return(NDIS_STATUS_PENDING);
           }
       }

       //
       //	Are there any other packets that might be waiting for these
       //	resources?
       //
       if (PACKET_QUEUE_EMPTY(&pXmitSegInfo->SegWait) &&
           (pXmitSegInfo->BeOrBeingUsedPadTrailerBufs < TBATM155_MAX_PADTRAILER_BUFFERS))
       {
           //
           //	Packet queue is empty so we can try and send this packet to
           //	the transmit DMA engine.
           //             
           NdisReleaseSpinLock(&pXmitSegInfo->lock);

           dbgLogSendPacket(Reserved->pVc->DebugInfo, Packet, 0, 0, 'qwdp');

           tbAtm155ProcessTransmitDmaWaitQueue(
               pXmitSegInfo->Adapter,
               Packet,
               FALSE);

           dbgLogSendPacket( Reserved->pVc->DebugInfo, Packet, 0, 0, 'QWDP');

           NdisAcquireSpinLock(&pXmitSegInfo->lock);
           Status = NDIS_STATUS_SUCCESS;
       }
       else
       {
           //
           //	Packet queue is not empty so we need to place this packet at
           //	the end of the queue then we can process the packet queue from
           //	the beginning (remember we have already determined that we have
           //	resources in the segmentation memory).
           //
           dbgLogSendPacket(
               PACKET_RESERVED_FROM_PACKET(Packet)->pVc->DebugInfo,
               Packet,
               3,
               0,
               ' wsQ');

           InsertPacketAtTailDpc(&pXmitSegInfo->SegWait, Packet);
           Status = NDIS_STATUS_PENDING;
       }
   }
   else
   {
       //
       //	Are there any packets to process?
       //
       if (PACKET_QUEUE_EMPTY(&pXmitSegInfo->SegWait))
       {
           // No, the queue is empty.
           NdisReleaseSpinLock(&pXmitSegInfo->lock);

           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
               ("<==tbAtm155ProcessSegmentQueue(NDIS_STATUS_SUCCESS)\n"));

           return(NDIS_STATUS_SUCCESS);
       }
   }

   //
   //	Process the segmentation wait queue.
   //
   while(!PACKET_QUEUE_EMPTY(&pXmitSegInfo->SegWait))
   {
       //
       //	Determine if we have the segmentation resources necessary
       //	to process the packet.
       //
       Reserved = PACKET_RESERVED_FROM_PACKET(pXmitSegInfo->SegWait.Head);

       if (pXmitDmaQ->RemainingTransmitSlots < Reserved->PhysicalBufferCount)
       {
           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR, ("Not enough resources.\n"));
           break;
       }

       if ((AAL_TYPE_AAL5 == Reserved->pVc->AALType) &&
           (pXmitSegInfo->BeOrBeingUsedPadTrailerBufs >= TBATM155_MAX_PADTRAILER_BUFFERS))
       {
           //
           // All of padtrailerbuffer have been reserved.
           // Don't dequeue this packet from the Segwait queue.
           //
           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("no PadTrailerBuffers.\n"));
           break;
       }
		
       //
       //	We have enough resources, remove the packet from the waiting
       //	queue and note the resources that it will need.
       //
       dbgLogSendPacket(Reserved->pVc->DebugInfo, Packet, 1, 0, 'wsQD');

       RemovePacketFromHead(&pXmitSegInfo->SegWait, &tmpPacket);

       NdisReleaseSpinLock(&pXmitSegInfo->lock);

       dbgLogSendPacket(Reserved->pVc->DebugInfo, tmpPacket, 0, 0, 'qwdp');

       tbAtm155ProcessTransmitDmaWaitQueue(
           pXmitSegInfo->Adapter,
           tmpPacket,
           FALSE);

       dbgLogSendPacket(Reserved->pVc->DebugInfo, tmpPacket, 0, 0, 'QWDP');

       NdisAcquireSpinLock(&pXmitSegInfo->lock);
   }

   NdisReleaseSpinLock(&pXmitSegInfo->lock);

   return(Status);
}


VOID
tbAtm155QueuePacketsToDmaWaitQueue(
   IN  PXMIT_SEG_INFO      pXmitSegInfo
	)

/*++

Routine Description:

   This routine will determine if there are enough resources to transmit
   the waiting queue of this VC.
   If there are enough resources, packets are moved from SegWait queue
   and insert to DmaWait queue to wait to be transmitted later.
   This routine only queues waiting packets to DmaWait queue.


Arguments:

   pXmitSegInfo    -   Pointer to the segmentation information to process
                       packets for.

Return Value:

--*/
{
   PSAR_INFO           pSar = pXmitSegInfo->Adapter->HardwareInfo->SarInfo;
   PXMIT_DMA_QUEUE     pXmitDmaQ = &pSar->XmitDmaQ;
   PPACKET_RESERVED    Reserved;
	PNDIS_PACKET		tmpPacket;
   ULONG               CurrentRemainingTxSlots;


   NdisAcquireSpinLock(&pXmitSegInfo->lock);

   CurrentRemainingTxSlots = pSar->XmitDmaQ.RemainingTransmitSlots;

   //
   //	Process the segmentation wait queue.
   //
   while (!PACKET_QUEUE_EMPTY(&pXmitSegInfo->SegWait))
   {
       //
       //	Determine if we have the segmentation resources necessary
       //	to process the packet.
       //
       Reserved = PACKET_RESERVED_FROM_PACKET(pXmitSegInfo->SegWait.Head);

       if (CurrentRemainingTxSlots < (ULONG)Reserved->PhysicalBufferCount)
       {
           // we don't have enough resources to process the packet.
           break;
       }
		
       dbgLogSendPacket(Reserved->pVc->DebugInfo, tmpPacket, 0, 0, 'qptd');

       //
       //	Are there available FreePadTrailerBuffers for padding & trailer?
       //
       if (pXmitSegInfo->BeOrBeingUsedPadTrailerBufs >= TBATM155_MAX_PADTRAILER_BUFFERS)
       {
           //
           //  Too bad, there is no resources available for this Vc.
           //
	        break;
       }

       //
       //  Remove from SegWait queue.
       //
       RemovePacketFromHead(&pXmitSegInfo->SegWait, &tmpPacket);

       //
       //  Insert into DmaWait queue to be transmitted.
       //
       InsertPacketAtTail(&pXmitDmaQ->DmaWait, tmpPacket);

       CurrentRemainingTxSlots -= (ULONG)Reserved->PhysicalBufferCount;
       pXmitSegInfo->BeOrBeingUsedPadTrailerBufs++;

       dbgLogSendPacket(Reserved->pVc->DebugInfo, tmpPacket, 0, 0, 'qptd');

   }   // end of while loop

   NdisReleaseSpinLock(&pXmitSegInfo->lock);
}


VOID
tbAtm155TxInterruptOnCompletion(
   IN  PADAPTER_BLOCK		pAdapter
	)
/*++

Routine Description:

   This routine will process the Transmit Interrupt On Completion
   for the different transmit buffers.  This interrupt will be generated
   when a packet has been sent out from a Tx Active Slot list of a VC.

Arguments:

pAdapter   -   Pointer to the adapter block.

Return Value:

   None.

--*/
{
   PHARDWARE_INFO          pHwInfo = pAdapter->HardwareInfo;
   PSAR_INFO               pSar = pHwInfo->SarInfo;
   PXMIT_DMA_QUEUE         pXmitDmaQ = &pSar->XmitDmaQ;
   PPACKET_RESERVED        Reserved;
   PNDIS_PACKET            Packet;
   PVC_BLOCK               pVc;
   PTX_REPORT_QUEUE        pTxReportQ = &pAdapter->TxReportQueue;
   TX_REPORT_PTR           TxReportPtrReg;
   ULONG                   CurrentTxReportPtrPa;
   UINT                    CurrentTxReportQIdx;
   UINT                    i;
   PTX_REPORT_QUEUE_ENTRY  TxReportQueue;
	ULONG					Vci;
   PXMIT_SEG_INFO          pXmitSegInfo;


   DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
       ("==>TbAtm155TxInterruptOnCompletion\n"));

   NdisDprAcquireSpinLock(&pXmitDmaQ->lock);

   TBATM155_READ_PORT(
       &pHwInfo->TbAtm155_SAR->Tx_Report_Ptr,
       &TxReportPtrReg.reg);

   //
   //  Got the position of 155 PCI SAR's internal Tx report queue.
   //  This pointer indicates the address in host memory to whcih 155 SAR
   //  will write the next Tx report. So we always move the pointer
   //  (or index) to the previous entry to make sure the entry in the
   //  report queue is valid.
   //
   CurrentTxReportPtrPa = TxReportPtrReg.reg & ~0x3;

   //
   //  Calcuate the index of Tx Report Queue which is pointed by controller.
   //  Save the index to database for XmitDmaQ.
   //  Handling Rules:
   //      1. Only handle up to the entry before this one.
   //      2. Each entry of report queue indicates of a transmitted packet.
   //
   CurrentTxReportQIdx =
           (CurrentTxReportPtrPa - 
           NdisGetPhysicalAddressLow(pTxReportQ->TxReportQptrPa)) /
           sizeof(TX_REPORT_QUEUE_ENTRY);

   //
   //  Get the index handled last time.
   //
   TxReportQueue = (PTX_REPORT_QUEUE_ENTRY)pTxReportQ->TxReportQptrVa;

   DBGPRINT(DBG_COMP_TXIOC, DBG_LEVEL_ERR, 
            ("TxIOC CurTxRQIdx(%x), PrevTxRQIdx(%x)\n", 
            CurrentTxReportQIdx, pXmitDmaQ->PrevTxReportQIndex));

   for (i = pXmitDmaQ->PrevTxReportQIndex; 
        i != CurrentTxReportQIdx;
        i = (i == pHwInfo->MaxIdxOfTxReportQ)? 0 : ++i)
   {
       //
       //  Get the VC of the packet been sent out.
       //
       Vci = (ULONG) TxReportQueue[i].TxReportQDWord.VC;

       //
       //  There are more packets have been sent out.
       //  Let's get information from the queue.
       //
       pVc = tbAtm155UnHashVc(pAdapter, Vci);
       if ((NULL == pVc) || (NULL == pVc->XmitSegInfo))
       {
           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
               ("There is no VC activated for: %u\n", Vci));

           continue;
       }

       if (!VC_TEST_FLAG(pVc, fVC_ACTIVE) && !VC_TEST_FLAG(pVc, fVC_DEACTIVATING))
       {
           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
               ("The VC is activated for: %u\n", Vci));

           continue;
       }
       
       pXmitSegInfo = pVc->XmitSegInfo;

       NdisDprAcquireSpinLock(&pXmitSegInfo->lock);

       //
       //	Are there any packets to complete?
       //
       if (PACKET_QUEUE_EMPTY(&pXmitSegInfo->DmaCompleting))
       {
           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
           ("There is no any packets to complete of VC: %lx\n", Vci));

           NdisDprReleaseSpinLock(&pXmitSegInfo->lock);
           continue;
       }

       //
       //  Get VC information from VcHashTable based on the VC reported
       //
       Reserved = PACKET_RESERVED_FROM_PACKET(pVc->XmitSegInfo->DmaCompleting.Head);

       //
       // A packet has been sent out.
       //
       RemovePacketFromHead(&pXmitSegInfo->DmaCompleting, &Packet);



       if (Reserved->PadTrailerBufIndexInUse != 0x0FF)
       {
           pXmitSegInfo->FreePadTrailerBuffers++;

           //
           // Update the number of padtrailerbuffers to allow queuing 
           // more packets of this VC to the "dmawait" queue later.
           //
           pXmitSegInfo->BeOrBeingUsedPadTrailerBufs--;

       }

       NdisDprReleaseSpinLock(&pXmitSegInfo->lock);  

       pXmitDmaQ->RemainingTransmitSlots += (ULONG) Reserved->PhysicalBufferCount;

       dbgLogSendPacket(
           pVc->DebugInfo,
           Packet,
           0,
           0,
           'pmoc');

       //
       //	Complete the packet back to the protocol.
       //  Since we always return STATUS_PENDING to the protocol's
       //  send request, this function need to be called here.
       //

       //
       // Release spinlock before calling NdisMCoSendComplete to avoid a 
       // deadlock problem. After NdisMCoSendComplete is finished, 

⌨️ 快捷键说明

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