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

📄 mpltransmit.c

📁 NATIONAL公司DP83816芯片Linux下驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
   else
   {
      // Only one queue to process
      priQSel = 0x01;
   }

   // Process each queue - Start with highest priority
   for (qNum = pMplCtx->txQueueCnt; 
                        (qNum > 0x0) && (status == NS_STATUS_SUCCESS); 
                                    qNum--)
   {
      pQueue = qNum - 1; // 0-Indexed

      // Check if this queue has any completed packets
      if ((1 << pQueue) & priQSel)
      {
         // Process the Txd ring
         while ((pMplCtx->txQueue[pQueue].curr - pMplCtx->txQueue[pQueue].dirty)
                                > 0x0)
         {
            // Get the entry index
            entry = pMplCtx->txQueue[pQueue].dirty % 
                             pMplCtx->txQueue[pQueue].descCnt;
            currTxd = &pMplCtx->txQueue[pQueue].pRing[entry];

            // Check if the hardware is done i.e. OWN is cleared
            if (currTxd->cmdSts & CS_OWN_ES)
            {
               break;
            }

            // Check if we reached limit
            if ((maxEvents != 0x0) && (evtCnt >= maxEvents))
            {
               status = NS_STATUS_ABORTED;
               break;
            }

            // Check if this is the last Txd for this packet
            if (currTxd->cmdSts & CS_MORE_ES)
            {
               // Go to the next Txd
               pMplCtx->txQueue[pQueue].dirty++;
               continue;
            }

            // FM : Define event.. Is it per pkt or per processed Txd?
            // Below it is defined as per packet
            evtCnt++;

            // FM : Need to add Stat code for collecting Tx errors

            // Prepare indication event to NSM
            pMplCtx->txDone[pktCnt].pNsmPrivate = currTxd->mplPriv;
            pMplCtx->txDone[pktCnt].cmdSts = MPL_LTOH32(currTxd->cmdSts);
            pMplCtx->txDone[pktCnt++].packetStatus = 
                  (currTxd->cmdSts & CS_OK_ES) ?
                            NS_STATUS_SUCCESS : NS_STATUS_FAILURE;

            // Check if it is time to report to NSM
            if (pktCnt >= pMplCtx->maxTxDones)
            {
               NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
               pktCnt = 0x0;
            }

            // Go to the next Txd
            pMplCtx->txQueue[pQueue].dirty++;
         }
      }
   }

   // Report remaining completed packets to NSM
   if (pktCnt > 0x0)
   {
      NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
   }

   EXIT(MplTransmitDone);
   return status;
}

//*****************************************************************************
//   MplTransmitReset
//      Resets the transmit engine on the device and associated resources. 
//      NOTE: This function is non-reentrant with respect to itself, 
//        MplTransmit and MplTransmitDone
//
//   Parameters
//      pMplHandle
//         MPL device handle returned following a call to MplInitialize
//
//   Return Value
//      NS_STATUS_SUCCESS
//         The transmit engine was successfully reset.
//      NS_STATUS_HARDWARE_FAILURE
//         Unexpected hardware error - No reset done notification from Hw
//
//*****************************************************************************
MPL_STATUS
   MplTransmitReset (
      IN NS_VOID       *pMplHandle
      )
{
   MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;
   MPL_DESC *currTxd;
   NS_UINT pQueue, entry, pktCnt = 0x0;

   ENTER(MplTransmitReset);

   // Make sure we were initialized to begin with
   if (pMplCtx->txQueueCnt == 0x0)
   {
      EXIT(MplTransmitReset);
      return NS_STATUS_SUCCESS;
   }

   // Tell the hardware to reset its Tx engine
   MPL_WRITE32(pMplCtx, CR, TXRESET);

   // Total 4msec - Not waiting for notification
   OaiSleep(4 * RESETINTERVAL_MAC);

   // Process each Tx queue
   for (pQueue = 0x0; pQueue < pMplCtx->txQueueCnt; pQueue++)
   {
      // Process the Txd ring - Look for pending packets
      while ((pMplCtx->txQueue[pQueue].curr - pMplCtx->txQueue[pQueue].dirty)
                                > 0x0)
      {
         // Get the entry index and corresponding Txd
         entry = pMplCtx->txQueue[pQueue].dirty % 
                          pMplCtx->txQueue[pQueue].descCnt;
         currTxd = &pMplCtx->txQueue[pQueue].pRing[entry];

         // If the current Txd is the last one in a packet, report its
         // status as ABORTED to NSM
         if ((currTxd->cmdSts & CS_MORE_ES) == 0x0)
         {
            // Prepare indication event to NSM
            pMplCtx->txDone[pktCnt].pNsmPrivate = currTxd->mplPriv;
            pMplCtx->txDone[pktCnt].cmdSts = 0x0;
            pMplCtx->txDone[pktCnt++].packetStatus = NS_STATUS_ABORTED;

            // Check if it is time to report to NSM
            if (pktCnt >= pMplCtx->maxTxDones)
            {
               NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
               pktCnt = 0x0;
            }
         }

         // Clear Txd
         currTxd->cmdSts   = 0x0;
         currTxd->bufptrPA = 0x0;
         currTxd->mplPriv  = 0x0;

         // Go to the next Txd
         pMplCtx->txQueue[pQueue].dirty++;
      }

      // Reinit the ring
      pMplCtx->txQueue[pQueue].curr = 0x0;
      pMplCtx->txQueue[pQueue].dirty = 0x0;
      pMplCtx->txQueue[pQueue].ringPA = 
                       pMplCtx->txQueue[pQueue].pRgnHndl->phyAddr;
      pMplCtx->txQueue[pQueue].pRing = 
                       (MPL_DESC *)pMplCtx->txQueue[pQueue].pRgnHndl->pAddr;
   }

   // Report remaining pkts to NSM
   if (pktCnt > 0x0)
   {
      NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
   }

   // Notify the device about the head node on the ring
   MPL_WRITE32(pMplCtx, TXDP,  pMplCtx->txQueue[0].ringPA);
   MPL_WRITE32(pMplCtx, TXDP1, pMplCtx->txQueue[1].ringPA);
   MPL_WRITE32(pMplCtx, TXDP2, pMplCtx->txQueue[2].ringPA);
   MPL_WRITE32(pMplCtx, TXDP3, pMplCtx->txQueue[3].ringPA);

   EXIT(MplTransmitReset);
   return NS_STATUS_SUCCESS;
}


//*****************************************************************************
//   setTxCfg
//      Set the FIFO and DMA burst related configurations on the device
//
//   Parameters
//      pMplCtx
//         Pointer to MPL Context
//      pCfgTransmit
//         Pointer to a caller allocated MPL_TRANSMIT_CFG structure with 
//          configuration values for the transmit engine
//
//   Return Value
//      None
//
//*****************************************************************************
static
NS_VOID
   setTxCfg(
      IN MPL_CONTEXT       *pMplCtx,
      IN MPL_TRANSMIT_CFG  *pCfgTransmit
      )
{
   NS_UINT32 txDma, txCfg, drain , fill;

   ENTER(setTxCfg);

   // Get the Tx DMA size
   txDma = 0x0;
   if (pCfgTransmit->maxDmaBurst < 8) 
      txDma = MXDMA4; //Min
   else if (pCfgTransmit->maxDmaBurst < 16) 
           txDma = MXDMA8;
        else
           if (pCfgTransmit->maxDmaBurst < 32) 
                txDma = MXDMA16;
           else if (pCfgTransmit->maxDmaBurst < 64) 
                     txDma = MXDMA32;
                else if (pCfgTransmit->maxDmaBurst < 128) 
                          txDma = MXDMA64;
                     else if (pCfgTransmit->maxDmaBurst < 256) 
                               txDma = MXDMA128;
                          else if (pCfgTransmit->maxDmaBurst < 512) 
                                    txDma = MXDMA256;
                               else if (pCfgTransmit->maxDmaBurst < 1024) 
                                       txDma = MXDMA512;
                                     else if (pCfgTransmit->maxDmaBurst < 2048) 
                                             txDma = (MXDMA256 | TXDMA4);
                                          else
                                             txDma = (MXDMA512 | TXDMA4); //Max

   // Read the Txcfg contents
   txCfg = MPL_READ32(pMplCtx, TXCFG);
    
   // Mask the tx settable values
   txCfg &= ~TXSET_MASK;

   // Generate the TXCFG contents - The fill and drain are specified in
   //  32 byte units
   drain = (pCfgTransmit->drainThreshold / 32) & TXDRAIN_MASK;
   fill  = ((pCfgTransmit->fillThreshold / 32) << TXFILL_SHIFT) & TXFILL_MASK;
   txCfg |= txDma | fill | drain;

   // Write TXCFG
   MPL_WRITE32(pMplCtx, TXCFG, txCfg);

   EXIT(setTxCfg);
   return;
}


//*****************************************************************************
//   allocTxdRing
//      Alloc all the Txd rings
//
//   Parameters
//      pMplCtx
//         Pointer to MPL Context
//
//   Return Value
//      NS_STATUS_SUCCESS
//         The rings were correctly setup
//      NS_STATUS_RESOURCES
//         Failed to allocate the resources (transmit control blocks)
//
//*****************************************************************************
static
MPL_STATUS
   allocTxdRing(
      IN MPL_CONTEXT       *pMplCtx
      )
{
   MPL_STATUS status = NS_STATUS_SUCCESS;
   NS_UINT i, j;

   ENTER(allocTxdRing);

   // Allocate resources for the Tx done indications 
   pMplCtx->txDone = (MPL_TRANSMIT_DONE *)OaiMalloc(sizeof(MPL_TRANSMIT_DONE) *
                                                         pMplCtx->maxTxDones);
   if (pMplCtx->txDone == NULL)
   {
      EXIT(allocTxdRing);
      return NS_STATUS_RESOURCES;
   }
   OaiZeroMem(pMplCtx->txDone, sizeof(MPL_TRANSMIT_DONE) * pMplCtx->maxTxDones);

   // Allocate memory for the descriptors
   for (i = 0x0; i < pMplCtx->txQueueCnt; i++)
   {
      if (OaiAllocDmaRegion(pMplCtx->pClientHandle, 
                            sizeof(MPL_DESC) * pMplCtx->txQueue[i].descCnt,
                            4, // Aligned on 32-bits
                            &pMplCtx->txQueue[i].pRgnHndl) == NS_FALSE)
       {
          // Allocation failed - Free all prev allocations
          for (j = 0x0; j < i; j++)
          {
             OaiFreeDmaRegion(pMplCtx->pClientHandle, 
                              pMplCtx->txQueue[j].pRgnHndl);

          }
       
          OaiFree(sizeof(MPL_TRANSMIT_DONE) * pMplCtx->maxTxDones, 
                                   pMplCtx->txDone);
          status = NS_STATUS_RESOURCES;
          break;
       }
       else
       {
          // Reset mem block
          OaiZeroMem(pMplCtx->txQueue[i].pRgnHndl->pAddr, 
                     sizeof(MPL_DESC) * pMplCtx->txQueue[i].descCnt);
       }
   }

   EXIT(allocTxdRing);
   return status;
}

//*****************************************************************************
//   freeTxdRing
//      Free the Txd rings
//
//   Parameters
//      pMplCtx
//         Pointer to MPL Context
//
//   Return Value
//      None
//
//*****************************************************************************
NS_VOID
   freeTxdRing(
      IN MPL_CONTEXT       *pMplCtx
      )
{
   NS_UINT i;

   ENTER(freeTxdRing);

   // Free resources for the Tx done indications 
   if (pMplCtx->txDone != NULL)
   {
      OaiFree(sizeof(MPL_TRANSMIT_DONE) * pMplCtx->maxTxDones, pMplCtx->txDone);
      pMplCtx->txDone = NULL;
   }

   // Free memory for the descriptors
   for (i = 0x0; i < pMplCtx->txQueueCnt; i++)
   {
      if (pMplCtx->txQueue[i].pRgnHndl != NULL)
      {
         OaiFreeDmaRegion(pMplCtx->pClientHandle, pMplCtx->txQueue[i].pRgnHndl);
         pMplCtx->txQueue[i].pRgnHndl = NULL;
      }
   }

   EXIT(freeTxdRing);
   return;
}

//*****************************************************************************
//   setupTxdRing     
//      Setup the Txd Rings
//
//   Parameters
//      pMplCtx
//         Pointer to MPL Context
//
//   Return Value
//      None
//
//*****************************************************************************
static
NS_VOID   
   setupTxdRing(
      IN MPL_CONTEXT       *pMplCtx
      )
{
   NS_UINT i, j;

   ENTER(setupTxdRing);

   // Set the Txd rings on each of enabled queue
   for (i = 0x0; i < pMplCtx->txQueueCnt; i++)
   {
      pMplCtx->txQueue[i].curr = 0x0;
      pMplCtx->txQueue[i].dirty = 0x0;

      // Note the ring's physical and logical start address
      pMplCtx->txQueue[i].ringPA = pMplCtx->txQueue[i].pRgnHndl->phyAddr;
      pMplCtx->txQueue[i].pRing = 
                       (MPL_DESC *)pMplCtx->txQueue[i].pRgnHndl->pAddr;

      for (j = 0x0; j < pMplCtx->txQueue[i].descCnt; j++)
      {
         // Link up and form a ring
         pMplCtx->txQueue[i].pRing[j].linkPA  = 
                 MPL_ADDR_HTOL(pMplCtx->txQueue[i].ringPA +
                                 (sizeof(MPL_DESC) * 
                                   ((j+1) % (pMplCtx->txQueue[i].descCnt))));

         // Clear cmdstatus
         pMplCtx->txQueue[i].pRing[j].cmdSts = 0x0;
      }
   }
   
   EXIT(setupTxdRing);
   return;
}

⌨️ 快捷键说明

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