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

📄 send.c

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

Copyright (c) 2000 Microsoft Corporation. All rights reserved.

   File:       send.c
 
               Developed for Toshiba by Elisa Research Inc., CA
               http://www.elisaresearch.com
               (510) 770-4920



Abstract:

Author:

   A. Wang

Environment:

   Kernel mode

Revision History:

   09/23/96        kyleb       Fix map register freeing bug
                               Fix Deactivate VC complete bug.
   01/07/97        awang       Initial of Toshiba ATM 155 Device Driver.
   02/16/99        hhan        Use synchronize mode to allocate xmit buffer.
   03/03/97        hhan        Added in 'ScatterGetherDMA'.
--*/

#include "precomp.h"
#pragma hdrstop

#define	MODULE_NUMBER	MODULE_SEND

VOID
tbAtm155TransmitPacket(
	IN	PVC_BLOCK       pVc,
  	IN  PNDIS_PACKET    Packet
   )
/*++

Routine Description:

   This routine will set up the DMA operation.

   Assume: FreePadTrailerBuffers > 0

   - There are two ways to send a packet
     1. post the tx buffer(s) from NDIS directly to SAR.
     2. if Remaining slot are running low, copy tx data in buffer(s) to
        pre-allocated tx buffer and then post the pre-allocate buffer
        to SAR.

   - After post Tx data of the packet, ALWAYS post a PadTrailerBuffers
     for AAL5 packets.

Arguments:

Return Value:

--*/
{                           	
   PADAPTER_BLOCK              pAdapter = pVc->Adapter;
   PHARDWARE_INFO              pHwInfo = pVc->HwInfo;
   PTBATM155_SAR               TbAtm155Sar = pHwInfo->TbAtm155_SAR;
   PSAR_INFO                   pSar = pHwInfo->SarInfo;
   PXMIT_SEG_INFO              pXmitSegInfo = pVc->XmitSegInfo;
   PXMIT_DMA_QUEUE             pXmitDmaQ = &pSar->XmitDmaQ;
   PPACKET_RESERVED            Reserved = PACKET_RESERVED_FROM_PACKET(Packet);
   UINT                        PacketLength;
   UINT                        c;
   PMEDIA_SPECIFIC_INFORMATION pMediaInfo;
   ULONG                       SizeMediaInfo;
   PATM_AAL_OOB_INFO           pAtmOob;
   AAL5_PDU_TRAILER            Trailer;
   ULONG                       Padding = 0;
	PSCATTER_GATHER_LIST		psgl;
   
   TX_PENDING_SLOTS_CTL        TxPendingSlotCtrlReg;
   ULONG                       TxSlotNum = 0;
   PALLOCATION_MAP             pPadTrailerBuffer;

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

   //
   //	Place the packet on the completing queue.
   //
   InsertPacketAtTail(&pXmitSegInfo->DmaCompleting, Packet);

   //
   //	Clear the trailer first.
   //
   ZERO_MEMORY(&Trailer, sizeof(AAL5_PDU_TRAILER));

   //
   //	Set defaults for the pdu trailer
   //
   Trailer.UserToUserIndication = 0;
   Trailer.CommonPartIndicator = 0;

   //
   //	Do we have any oob data in the packet?
   //
   NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &pMediaInfo, &SizeMediaInfo);

   //
   //	If there is OOB data then it's already been verified.	
   //
   if (0 != SizeMediaInfo)
   {
       pAtmOob = (PATM_AAL_OOB_INFO)pMediaInfo->ClassInformation;

       //
       //	The contents depends upon the AAL type.
       //
       if (AAL_TYPE_AAL5 == pAtmOob->AalType)
       {
           Trailer.UserToUserIndication = pAtmOob->ATM_AAL5_INFO.UserToUserIndication;
           Trailer.CommonPartIndicator = pAtmOob->ATM_AAL5_INFO.CommonPartIndicator;
       }
   }

   psgl = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo);

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

   //
   //  Copy the initial control register value of Tx_Pending_Slots
   //
   TxPendingSlotCtrlReg.reg = pXmitSegInfo->InitXmitSlotDesc.reg;

	for (c = 0; c < psgl->NumberOfElements; c++)
	{
       DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
           ("TbAtm155TransmitPacket: Pkt %x, elem %d, Length %d\n",
            Packet, c, psgl->Elements[c].Length));

       //
       //	Initialize the descriptor with the physical buffer info.
       //  and write to Tx_Pending_slots registers of 155 PCI SAR 
       //
       TxPendingSlotCtrlReg.Slot_Size = psgl->Elements[c].Length;

       TBATM155_WRITE_PORT(
               &TbAtm155Sar->Tx_Pending_Slots[TxSlotNum].Cntrl,
               TxPendingSlotCtrlReg.reg);

       TBATM155_WRITE_PORT(
               &TbAtm155Sar->Tx_Pending_Slots[TxSlotNum].Base_Addr,
               NdisGetPhysicalAddressLow(psgl->Elements[c].Address));

       //               
       //  Move to next slot registers for the next posting.
       //               
       TxSlotNum = (TxSlotNum + 1) % MAX_SLOTS_NUMBER;

   } // end of FOR

    //
    //	Update the total posted Tx pending slots.
    //
    Reserved->PhysicalBufferCount = (UCHAR)psgl->NumberOfElements;

    //
    //	Update the total remaining Tx free slots.
    //
    pXmitDmaQ->RemainingTransmitSlots -= psgl->NumberOfElements;



    //
	//	If this was an AAL5 packet then we need to
	//	copy out any padding and the AAL5 pdu trailer.
	//
	if (AAL_TYPE_AAL5 == pVc->AALType)
	{
		//
		//	Get the first packet buffer and the number of physical
		//	segments that comprise the packet.
		//
		NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);

       //
       //	Build the AAL5 trailer information.
       //
       Trailer.Length = TBATM155_SWAP_USHORT((USHORT)PacketLength);

       //
       //	Determine the amount of padding bytes.
       //
       pPadTrailerBuffer = &pXmitSegInfo->PadTrailerBuffers[pXmitSegInfo->PadTrailerBufferIndex];
                                                     
       DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("Va=0x%lX\n", pPadTrailerBuffer->Va));

       //
       // copy Trailer to the buffer.
       //

       Padding = (ULONG)Reserved->PaddingBytesNeeded;

       NdisMoveMemory(
           (PUCHAR)pPadTrailerBuffer->Va + Padding, 
           (PVOID)&Trailer,
           (ULONG)sizeof(AAL5_PDU_TRAILER));
		
       //
       //  Let's to write the last fragment out
       //
       //	Initialize the descriptor with the physical buffer info.
       //  and write to Tx_Pending_slots registers of 155 PCI SAR 
		//
       TxPendingSlotCtrlReg.Slot_Size = Padding + sizeof(AAL5_PDU_TRAILER);
       TxPendingSlotCtrlReg.EOP = 1;

       TBATM155_WRITE_PORT(
           &TbAtm155Sar->Tx_Pending_Slots[TxSlotNum].Cntrl,
           TxPendingSlotCtrlReg.reg);

       TBATM155_WRITE_PORT(
           &TbAtm155Sar->Tx_Pending_Slots[TxSlotNum].Base_Addr,
           pPadTrailerBuffer->Pa);

       //
       //	Flush it out.
       //
       NdisFlushBuffer(
           pPadTrailerBuffer->FlushBuffer, 
           TRUE
       );

       Reserved->PadTrailerBufIndexInUse = pXmitSegInfo->PadTrailerBufferIndex;
       pXmitSegInfo->FreePadTrailerBuffers--;
       pXmitSegInfo->PadTrailerBufferIndex++;

       if(pXmitSegInfo->PadTrailerBufferIndex == TBATM155_MAX_PADTRAILER_BUFFERS)
       {
           pXmitSegInfo->PadTrailerBufferIndex = 0;
       }

       //
       //  Update the total posted Tx pending slots.
       //
       Reserved->PhysicalBufferCount++;

       //
       //	Update the total remaining Tx free slots.
       //
       pXmitDmaQ->RemainingTransmitSlots--;

   }

#if TB_CHK4HANG
   ADAPTER_SET_FLAG(pAdapter, fADAPTER_EXPECT_TXIOC);
#endif // end of TB_CHK4HANG

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


NDIS_STATUS
tbAtm155ProcessTransmitDmaWaitQueue(
   IN  PADAPTER_BLOCK  pAdapter,
   IN  PNDIS_PACKET    Packet,
   IN  BOOLEAN         fLimitedNoPkts
   )
/*++

Routine Description:

   This routine will either queue a packet to the transmit DMA queue or
   DMA the packet.

Arguments:

   pAdapter    -   Pointer to the ADAPTER_BLOCK
   Packet      -   if equal to NULL, this routine is called in
                   the interrupt service routine 
                   tbAtm155TxInterruptOnCompletion().
                   Otherwise, this routine is called from foreground.

Return Value:

   NDIS_STATUS_SUCCESS if the packet was successfully sent to the
                       transmit DMA engine.
   NDIS_STATUS_PENDING if it was queued waiting for DMA resources.

--*/
{
   PSAR_INFO           pSar = pAdapter->HardwareInfo->SarInfo;
   PXMIT_DMA_QUEUE     pXmitDmaQ = &pSar->XmitDmaQ;
   PNDIS_PACKET        tmpPacket;
   PPACKET_RESERVED    Reserved;
   NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;
   PXMIT_SEG_INFO      pXmitSegInfo;
   PVC_BLOCK           pVc;
   PHARDWARE_INFO      pHwInfo = pAdapter->HardwareInfo;

   //
   //	If a packet was not passed in to transmit then we need to
   //	grab them off of the pending queue.
   //
   NdisAcquireSpinLock(&pXmitDmaQ->lock);

   if (ARGUMENT_PRESENT(Packet))
   {
       Reserved = PACKET_RESERVED_FROM_PACKET(Packet);
       pVc = Reserved->pVc;
       pXmitSegInfo = pVc->XmitSegInfo;

	    if (AAL_TYPE_AAL5 == pVc->AALType)
       {
           NdisAcquireSpinLock(&pXmitSegInfo->lock);
           pXmitSegInfo->BeOrBeingUsedPadTrailerBufs++;
           NdisReleaseSpinLock(&pXmitSegInfo->lock);
       }

       //
       //	Are there transmit DMA resources available?
       //
       if (pXmitDmaQ->RemainingTransmitSlots < Reserved->PhysicalBufferCount)
       {
           //
           //  Too bad, there is no resources available.
           //  Queue to DmaWait list to handle later.
           //
           dbgLogSendPacket(pVc->DebugInfo, Packet, 1, 0, ' wdq');

           InsertPacketAtTail(&pXmitDmaQ->DmaWait, Packet);

           NdisReleaseSpinLock(&pXmitDmaQ->lock);

           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
               ("<==tbAtm155ProcessTransmitDmaWaitQueue(NDIS_STATUS_PENDING)\n"));

           return(NDIS_STATUS_PENDING);
           
       }

       //
       //	Are there any other packets waiting for the DMA engine?
       //
       if (!PACKET_QUEUE_EMPTY(&pXmitDmaQ->DmaWait))
       {
           //
           //	There are other packets waiting for the available DMA
           //	resources so this guy goes to the end of the list.
           //
           dbgLogSendPacket(pVc->DebugInfo, Packet, 2, 0, ' wdq');
           InsertPacketAtTail(&pXmitDmaQ->DmaWait, Packet);
           Status = NDIS_STATUS_PENDING;
       }
       else
       {
           //
           //	Setup the packet for DMA if there are available
           //  free PadTrailerBuffers.
           //
           tbAtm155TransmitPacket(Reserved->pVc, Packet);
       }
   }

   //
   //	Loop through the packets that are waiting for dma resources.
   //
   while (!PACKET_QUEUE_EMPTY(&pXmitDmaQ->DmaWait))
   {
       //
       //	Are there enough resources to process the
       //	packet?
       //
       Reserved = PACKET_RESERVED_FROM_PACKET(pXmitDmaQ->DmaWait.Head);
       pXmitSegInfo = Reserved->pVc->XmitSegInfo;

       if (pXmitSegInfo->FreePadTrailerBuffers == 0)
       {
           //
           // Bad!! We should never get here.
           //
           DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_FATAL,
               ("ProcessTxDmaWaitQueue: BAD!!(UsedPTB=%u, VC=%lx)\n",
               pXmitSegInfo->BeOrBeingUsedPadTrailerBufs, Reserved->pVc->VpiVci.Vci));

           break;                      // no chance, get out.
       }

       if (pXmitDmaQ->RemainingTransmitSlots < Reserved->PhysicalBufferCount)
       {
           break;                  // no chance, get out.
       }

       dbgLogSendPacket(Reserved->pVc->DebugInfo, Packet, 0, 0, 'WDQD');
       RemovePacketFromHead(&pXmitDmaQ->DmaWait, &tmpPacket);

       //
       //	Transmit the packet.
       //
       tbAtm155TransmitPacket(Reserved->pVc, tmpPacket);

       if (TRUE == fLimitedNoPkts)
       {
           TBATM155_WRITE_PORT(
               &pHwInfo->TbAtm155_SAR->Intr_Status,
               0);

           TBATM155_WRITE_PORT(
               &pHwInfo->TbAtm155_SAR->Intr_Status,
               0);
       }

   }

   NdisReleaseSpinLock(&pXmitDmaQ->lock);
   return(Status);
}



NDIS_STATUS
tbAtm155ProcessSegmentQueue(
   IN  PXMIT_SEG_INFO      pXmitSegInfo,
   IN  PNDIS_PACKET        Packet
	)
/*++

Routine Description:

   This routine will do one of two things depending on whether or not a valid
   Packet was passed in.  If a packet is passed in then we will determine if
   there are enough resources for segmentation of this packet.  If not then
   we will process the queue of packets that are waiting for segmentation
   resources.

Arguments:

   pXmitSegInfo    -   Pointer to the segmentation information to process
                       packets for.
   Packet          -	Pointer to the packet to acquire segmentation resources
                       for or NULL if we are to process the pending queue.

Return Value:

   NDIS_STATUS_SUCCESS if the packet was successfully sent to the DMA engine.
   NDIS_STATUS_PENDING if the packet was queued some where due to resource
                       constraints.

⌨️ 快捷键说明

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