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

📄 send.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
       // re-aquire spinlock.
       //

       NdisDprReleaseSpinLock(&pXmitDmaQ->lock);

       NdisMCoSendComplete(
           NDIS_STATUS_SUCCESS,
           pVc->NdisVcHandle,
           Packet);

	    DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
		    ("TbAtm155TxInterruptOnCompletion: Pkt %x\n", Packet));

	    DBGPRINT(DBG_COMP_TXIOC, DBG_LEVEL_INFO,
		    ("TbAtm155TxIOC: Pkt %x VC:%lx(OK)\n", Packet, pVc->VpiVci.Vci));

       NdisDprAcquireSpinLock(&pXmitDmaQ->lock);

       //
       //  Check if any packets are waiting in the
       //  waiting segment queue, SegWait, of the VC.
       //
       tbAtm155QueuePacketsToDmaWaitQueue(pXmitSegInfo);
       NdisDprAcquireSpinLock(&pVc->lock);
       NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.XmitPdusOk);
       pVc->StatInfo.XmitPdusOk++;

       //
       //	Dereference the VC's reference count.
       //
       //	If we only have the creation reference and the VC
       //	is waiting to be deactivated then we are done here....
       //
       tbAtm155DereferenceVc(pVc);

       if ((1 == pVc->References) && (VC_TEST_FLAG(pVc, fVC_DEACTIVATING)))
       {
           NdisDprReleaseSpinLock(&pVc->lock);
           NdisDprReleaseSpinLock(&pXmitDmaQ->lock);

           //
           //	This VC is finished.
           //
           TbAtm155DeactivateVcComplete(pVc->Adapter, pVc);
           NdisDprAcquireSpinLock(&pXmitDmaQ->lock);
		}
       else
       {
           NdisDprReleaseSpinLock(&pVc->lock);
       }

   } // end of FOR

   //
   //  Update to handled index of Tx report queue.
   //
   pXmitDmaQ->PrevTxReportQIndex = CurrentTxReportQIdx;

   DBGPRINT(DBG_COMP_SEND_ERR, DBG_LEVEL_ERR,
       ("RemainingXmitSlots 0x%lx\n", pXmitDmaQ->RemainingTransmitSlots));

   NdisDprReleaseSpinLock(&pXmitDmaQ->lock);

   //
   //	Send packets out from DmaWait queues.
   //
   tbAtm155ProcessTransmitDmaWaitQueue(pAdapter, NULL, TRUE);

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

}


VOID
TbAtm155SendPackets(
   IN  NDIS_HANDLE     MiniportVcContext,
   IN  PPNDIS_PACKET   PacketArray,
   IN  UINT            NumberOfPackets
   )
/*++

Routine Description:

   This routine is the entry point to send packets on this miniport.

Arguments:

   MiniportVcContext   -   This is the pointer to our VC_BLOCK.
   PacketArray         -   Array of PNDIS_PACKETS to send on a given VC.
   NumberOfPackets     -   Number of packets in the PacketArray.

Return Value:

   Status is set for each packet in the PacketArray.

--*/
{
   PVC_BLOCK           pVc = (PVC_BLOCK)MiniportVcContext;
   UINT                c;
   PPNDIS_PACKET       CurrentPkt;
   NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;
   ULONG               VcReferences;
   PNDIS_PACKET        pErrorPacket = NULL;
   PNDIS_PACKET        pNextErrorPacket = NULL;
   BOOLEAN             fDeactivationComplete = FALSE;
   NDIS_HANDLE         NdisVcHandle;
   PADAPTER_BLOCK      pAdapter = pVc->Adapter;
#if DBG
   ULONG               dbgVcFlags;
#endif // end of DBG   


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

   DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
       ("PacketArray: 0x%lx, NumberOfPackets: %ld\n", PacketArray, NumberOfPackets));

   do {

       NdisAcquireSpinLock(&pAdapter->lock);
       //
       // Set this flag to prevent handling reset while we are processing send packets. 
       //
       ADAPTER_SET_FLAG(pAdapter, fADAPTER_PROCESSING_SENDPACKETS);
       NdisReleaseSpinLock(&pAdapter->lock);


       NdisAcquireSpinLock(&pVc->lock);
       NdisVcHandle = pVc->NdisVcHandle;

       //
       //	Is the adapter resetting?
       //
#if DBG
       dbgVcFlags = pVc->Flags;
#endif // end of DBG   


       if (VC_TEST_FLAG(pVc, fVC_RESET_IN_PROGRESS) ||
           !VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_TRANSMIT)) ||
           ADAPTER_TEST_FLAG(pAdapter, fADAPTER_HARDWARE_FAILURE))
       {
#if DBG
           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR, ("pVc(%lx), Flags(%lx), dbgVcFlags(%lx)\n", 
                    pVc->VpiVci.Vci, pVc->Flags, dbgVcFlags));
#endif // end of DBG   

           //
           //	What status should we complete the packet with?
           //
#if TB_CHK4HANG
           
           Status = NDIS_STATUS_RESET_IN_PROGRESS;
           if (!VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_TRANSMIT)))
           {
               Status = NDIS_STATUS_FAILURE;
           }
#else
           Status = VC_TEST_FLAG(pVc, fVC_RESET_IN_PROGRESS) ?
                       NDIS_STATUS_RESET_IN_PROGRESS : NDIS_STATUS_FAILURE;
#endif // end of TB_CHK4HANG

           NdisReleaseSpinLock(&pVc->lock);

			//
			//	Complete the packets.
			//
			for (c = 0, CurrentPkt = PacketArray;
			    (c < NumberOfPackets);
			    c++, CurrentPkt++)
			{
			    NDIS_SET_PACKET_STATUS(PacketArray[c], Status);

			    //
			    //  Place the packet on the error list. If pErrorPacket is NULL
			    //  it will initialize the Tail of the Linked list.
			    //	
			    PACKET_RESERVED_FROM_PACKET(*CurrentPkt)->Next = pErrorPacket;
				
			    pErrorPacket = *CurrentPkt;
			}
	
			DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
			    ("tbAtm155SendPackets: Failing due to invalid VC(%lx) state.\n",
			    pVc->VpiVci.Vci));

			DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
			    ("<==TbAtm155SendPackets\n"));
	
			break;
       }

       //
       //	Reference the VC so that it doesn't go away while we are sending.
       //	We don't need the VC_BLOCK lock acquired for this whole routine.
       //
       tbAtm155ReferenceVc(pVc);

       //
       //	Add references for all submitted packets. In case we fail one or more
       //	packets, we'll dereference those later.
       //
       //	We must add these references right here, because we may encounter
       //	send completion interrupts before this routine finishes, and those
       //	can cause the VC to be dereferenced away.
       //
       pVc->References += NumberOfPackets;
	
       NdisReleaseSpinLock(&pVc->lock);

       //
       //	We reference the VC block for every packet that gets queued.
       //
       VcReferences = 0;

       //
       //	Start processing the packet array.
       //
       for (c = 0, CurrentPkt = PacketArray;
            c < NumberOfPackets;
            c++, CurrentPkt++)
       {
           PNDIS_BUFFER                Buffer;
           UINT                        PacketLength;
           UINT                        PhysicalBufferCount;
           UINT                        BufferCount;
           USHORT                      DataSize;
		    USHORT						DataSizeMod;
           UCHAR                       NumOfPaddingBytes;
           PPACKET_RESERVED            Reserved;
           PMEDIA_SPECIFIC_INFORMATION pMediaInfo;
           ULONG                       SizeMediaInfo;
           PATM_AAL_OOB_INFO           pAtmOob;

			Reserved = PACKET_RESERVED_FROM_PACKET(*CurrentPkt);
			Reserved->Next = NULL;

           //
           //	If there is any OOB data then it had better be correct.
           //
           NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(*CurrentPkt, &pMediaInfo, &SizeMediaInfo);
           if ((0 != SizeMediaInfo) && (NULL != pMediaInfo))
           {
               pAtmOob = (PATM_AAL_OOB_INFO)pMediaInfo->ClassInformation;

               //
               //	We have media specific information.
               //	verify the type, size, and AAL type it is for.
               //
               if ((NdisClassAtmAALInfo != pMediaInfo->ClassId) ||
                   (sizeof(ATM_AAL_OOB_INFO) != pMediaInfo->Size) ||
                   (pVc->AALType != ((PATM_AAL_OOB_INFO)pMediaInfo->ClassInformation)->AalType))
               {
                   DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
                       ("Packet contains OOB data that is invalid!\n"));

                   NDIS_SET_PACKET_STATUS(*CurrentPkt, NDIS_STATUS_FAILURE);

                   //
                   //	Place the packet on the error list.
                   //
                   if (NULL != pErrorPacket)
                   {
                       Reserved->Next = pErrorPacket;
                   }

                   pErrorPacket = *CurrentPkt;

                   continue;
               }
           }

           //
           //	Get the information that we need from the packet.
           //
           NdisQueryPacket(
               *CurrentPkt,
               &PhysicalBufferCount,
               &BufferCount,
               &Buffer,
               &PacketLength);

           //
           //	If this is an AAL5 transmission then we need to
           //	determine if any padding is needed.  This must be on a
           //	cell granularity.
           //
           if (AAL_TYPE_AAL5 == pVc->AALType)
           {
               if (MAX_AAL5_PDU_SIZE < (ULONG)PacketLength)
               {
                   DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
                       ("PacketLength is larger than SegmentSize.\n"));

                   NDIS_SET_PACKET_STATUS(*CurrentPkt, NDIS_STATUS_FAILURE);
                   //
                   //	Place the packet on the error list.
                   //
                   if (NULL != pErrorPacket)
                   {
                       Reserved->Next = pErrorPacket;
                   }

                   pErrorPacket = *CurrentPkt;
				    continue;
               }

               //
               //  For AAL5, we need to calculate the padding bytes.
               //
               DataSize = (USHORT)PacketLength;
               DataSizeMod = DataSize % CELL_PAYLOAD_SIZE;

               if (DataSizeMod > 40)
               {
                   NumOfPaddingBytes  = (UCHAR)(96 - DataSizeMod);
               }
               else
               {
                   NumOfPaddingBytes  = (UCHAR)(48 - DataSizeMod);
               }

               //
               //  Save the padding bytes for this AAL5 packet.
               //
               NumOfPaddingBytes -= sizeof(AAL5_PDU_TRAILER);

               DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
                   ("NumOfPaddingBytes: 0x%lx, PacketLength: 0x%lx\n",
                   NumOfPaddingBytes, PacketLength));

               //
               //	We also need an extra buffer for the AAL5 PDU trailer.
               //
               PhysicalBufferCount++;

           }
           else
           {
               // 
               //  There is no padding byte needed for AAL5 packet.
               //
               NumOfPaddingBytes = 0;
           }

           //
           //	Save the amount of segmentation room, number of physical buffers,
           //	and the pointer to the VC_BLOCK that is need for the transmit of
           //	the current packet in our packet reserved section.
           //
           //  Initialize the database of chained reserved packet.
           //
           Reserved->PaddingBytesNeeded = NumOfPaddingBytes;
           Reserved->PhysicalBufferCount = (UCHAR)PhysicalBufferCount;
           Reserved->PadTrailerBufIndexInUse = 0x0FF;  // the buffer is not used.
           Reserved->pVc = pVc;
	
           //
           //	The packet is always pending.
           //
           NDIS_SET_PACKET_STATUS(*CurrentPkt, NDIS_STATUS_PENDING);

    	    DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
		        ("TbAtm155SendPacketPending: Pkt %x\n", *CurrentPkt));
           //
           //	We are going to keep the packet so we can increment the reference
           //	count on the VC.
           //
           VcReferences++;

           //
           //	Send the packet to the segmentation engine.  This routine will
           //	continue sending the packet on if there are card resources
           //	available.
           //
           dbgLogSendPacket(pVc->DebugInfo, *CurrentPkt, 0, 0, ' qsp');
           tbAtm155ProcessSegmentQueue(pVc->XmitSegInfo, *CurrentPkt);
       }

       //
       //	Add references to the VC_BLOCK for every packet that was queued.
       //
       NdisAcquireSpinLock(&pVc->lock);

       //
       //	Fix the references to reflect the packets that we did not
       //	queue for sending.
       //
       ASSERT(VcReferences <= NumberOfPackets);
       pVc->References -= (NumberOfPackets - VcReferences);

		//
		//	Remove the reference for the send path.
		//
       tbAtm155DereferenceVc(pVc);
       if ((1 == pVc->References) && (VC_TEST_FLAG(pVc, fVC_DEACTIVATING)))
       {
           //
           //	This VC is finished. Don't complete deactivation right now,
           //	but set a flag and do it below. This is so that we complete
           //	any errored packets before the deactivate-complete.
           //
           fDeactivationComplete = TRUE;
       }

       NdisReleaseSpinLock(&pVc->lock);

	} while (FALSE);

	//
	//	Did any packets error out?
	//
	while (NULL != pErrorPacket)
	{
		pNextErrorPacket = PACKET_RESERVED_FROM_PACKET(pErrorPacket)->Next;

		NdisInterlockedIncrement((PLONG)&pVc->Adapter->StatInfo.XmitPdusError);
		NdisInterlockedIncrement((PLONG)&pVc->StatInfo.XmitPdusError);

       NdisMCoSendComplete(
           NDIS_GET_PACKET_STATUS(pErrorPacket),
           NdisVcHandle,
           pErrorPacket);

	    DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
		    ("TbAtm155SendPacketError: Pkt %x\n", pErrorPacket));

		pErrorPacket = pNextErrorPacket;
	}

	if (fDeactivationComplete)
	{
       TbAtm155DeactivateVcComplete(pVc->Adapter, pVc);
	}


   NdisAcquireSpinLock(&pAdapter->lock);

   ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_PROCESSING_SENDPACKETS);

   if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RESET_REQUESTED) && !ADAPTER_TEST_FLAG(pAdapter, fADAPTER_PROCESSING_INTERRUPTS))
   {
       ADAPTER_SET_FLAG(pAdapter, fADAPTER_RESET_IN_PROGRESS);
       ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_RESET_REQUESTED);

       NdisReleaseSpinLock(&pAdapter->lock);

⌨️ 快捷键说明

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