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

📄 mplreceive.c

📁 NATIONAL公司DP83816芯片Linux下驱动
💻 C
📖 第 1 页 / 共 2 页
字号:

//******************************************************************************
//
//  MPLRECEIVE.C
//
//  Copyright (c) 2004 National Semiconductor Corporation.
//  All Rights Reserved
//
//  MPL Receive engine.
//
//  This file contains the API implementations for
//     o MPL receive engine configuration
//     o MPL packet reception and completion handlers
//     o Receive engine filter configuration
//
//******************************************************************************

#include <mplinternal.h>

// Local helful debug macros
#undef ENTER
#undef EXIT
#undef ASSERT
#undef PRINT
#undef PRINTI
#undef PRINTS
#undef TBREAK

#define ENTER(fn) MPL_CENTER(DZONE_MPL_RECV, fn)
#define EXIT(fn) MPL_CEXIT(DZONE_MPL_RECV, fn)
#define ASSERT(le) MPL_CASSERT(DZONE_MPL_RECV, le)
#define PRINT(fmt) MPL_CTRACE(DZONE_MPL_RECV, fmt)
#define PRINTI(v) MPL_CTRACE(DZONE_MPL_RECV, (" "#v": %x \n",(NS_UINT)(v)))
#define PRINTS(v) MPL_CTRACE(DZONE_MPL_RECV, (" "#v": %s \n", v))
#define TBREAK(fmt) MPL_CTRACEBREAK(DZONE_MPL_RECV, fmt)

// Locals
static NS_VOID setRxCfg(MPL_CONTEXT *pMplCtx, MPL_RECEIVE_CFG *pCfgReceive);
static MPL_STATUS allocRxdRing(MPL_CONTEXT *pMplCtx);
static NS_VOID    setupRxdRing(MPL_CONTEXT  *pMplCtx);

//*****************************************************************************
//   MplReceiveCfg
//      Configures the receive engine on the device. 
//
//   Parameters
//      pMplHandle
//         MPL device handle returned following a call to MplInitialize
//      pCfgReceive
//         Pointer to a caller allocated MPL_RECEIVE_CFG structure with 
//          configuration values for the receive engine
//
//   Return Value
//      NS_STATUS_SUCCESS
//         The configurations were successfully applied
//      NS_STATUS_INVALID_PARM
//         An invalid parameter value was detected
//
//*****************************************************************************
MPL_STATUS
   MplReceiveCfg (
      IN NS_VOID            *pMplHandle,
      IN MPL_RECEIVE_CFG    *pCfgReceive
      )
{
   MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;

   ENTER(MplReceiveCfg);

   // FM: Assert for pCfgReceive == NULL

   // Configure FIFO and DMA if client desires
   if (pCfgReceive->cfgFlags & MPL_RECEIVE_CFG_FIFO)
   {
      // Validate the FIFO thresholds and DMA burst size
      if ((pCfgReceive->drainThreshold < pMplCtx->caps.rxCaps.minDrain) ||
          (pCfgReceive->maxDmaBurst > pMplCtx->caps.rxCaps.maxDma))
      {
         EXIT(MplReceiveCfg);
         return NS_STATUS_INVALID_PARM;
      }

      // Notify the hardware about the FIFO thresholds and DMA burst
      setRxCfg(pMplCtx, pCfgReceive);
   }

   // Configure Rx queues if client desires
   if (pCfgReceive->cfgFlags & MPL_RECEIVE_CFG_QUEUES)
   {
      // Validate the priority queue count
      if (pCfgReceive->priorityQueueCnt > pMplCtx->caps.rxCaps.priorityQCnt)
      {
         EXIT(MplReceiveCfg);
         return NS_STATUS_INVALID_PARM;
      }

      // If this is a runtime reconfiguration request, then free the old ring
      if (pMplCtx->rxDescCnt)
      {
         freeRxdRing(pMplCtx);
      }

      // Get the Rxd count - Only one Rx queue
      pMplCtx->rxQueue.descCnt = pCfgReceive->descCnt[0x0];
      pMplCtx->rxDescCnt       = pCfgReceive->descCnt[0x0];

      // Note max receive done indications to be passed to NSM in one pass
      pMplCtx->maxRxDones = pCfgReceive->maxIndications;

      // Allocate Rxd ring 
      if (allocRxdRing(pMplCtx) != NS_STATUS_SUCCESS)
      {
         EXIT(MplReceiveCfg);
         return NS_STATUS_RESOURCES;
      }

      // Setup Rxd ring 
      setupRxdRing(pMplCtx);

      // Notify the device about the head node on the ring
      MPL_WRITE32(pMplCtx, RXDP,  pMplCtx->rxQueue.ringPA);
   }

   EXIT(MplReceiveCfg);
   return NS_STATUS_SUCCESS; // All done
}

//*****************************************************************************
//   MplReceiveSetFilter
//       MplReceiveSetFilter enables receive filters on the device. 
//
//   Parameters
//      pMplHandle
//         MPL device handle returned following a call to MplInitialize
//      filterFlag
//         Bit-map of receiver filter types that need to be enabled on the 
//          device
//       Note: This function overwrites all previous filter settings and 
//       sets the device's behavior to that of the filterFlag passed to it.
//
//   Return Value
//      NS_STATUS_SUCCESS
//         The filter configurations were successfully applied
//      NS_STATUS_NOT_SUPPORTED
//         The device did not support one or more filters
//
//*****************************************************************************
MPL_STATUS
   MplReceiveSetFilter (
      IN NS_VOID   *pMplHandle,
      IN NS_UINT    filterFlag
      )
{
   MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;
   NS_UINT32 fltrRegSetting = 0x0, regVal;

   ENTER(MplReceiveSetFilter);

   // Check for Promiscuous Mode
   if (filterFlag & MPL_RECEIVE_FILTER_PROMISCUOUS_MODE)
   {
      fltrRegSetting |= (ACCEPT_ALLBCAST | ACCEPT_ALLMCAST | ACCEPT_ALLUNICAST);
   }
   else
   {
      // Various individual filters
      if (filterFlag & MPL_RECEIVE_FILTER_ACCEPTALL_BROADCAST)
      {
         fltrRegSetting |= ACCEPT_ALLBCAST;
      }

      if (filterFlag & MPL_RECEIVE_FILTER_ACCEPTALL_MCAST)
      {
         fltrRegSetting |= ACCEPT_ALLMCAST;
      }

      if (filterFlag & MPL_RECEIVE_FILTER_ACCEPTALL_UNICAST)
      {
         fltrRegSetting |= ACCEPT_ALLUNICAST;
      }

      if (filterFlag & MPL_RECEIVE_FILTER_ACCEPTALL_ARP)
      {
         fltrRegSetting |= ACCEPT_ALLARP;
      }

      if (filterFlag & MPL_RECEIVE_FILTER_DIRECTED_UNICAST)
      {
         fltrRegSetting |= ACCEPT_PERFECTMATCH;
      }

      if (filterFlag & MPL_RECEIVE_FILTER_DIRECTED_MCAST)
      {
         fltrRegSetting |= MCASTHASH_EN;
      }
   }

   // Disable Rx Filter - Before changing it
   regVal = MPL_READ32(pMplCtx, RFCR);
   MPL_WRITE32(pMplCtx, RFCR, regVal & ~RXFLTR_EN);

   regVal &= (~(ACCEPT_ALLBCAST | ACCEPT_ALLMCAST | ACCEPT_ALLUNICAST 
                 | ACCEPT_ALLARP | ACCEPT_PERFECTMATCH));
   regVal |= (fltrRegSetting | RXFLTR_EN);
   MPL_WRITE32(pMplCtx, RFCR, regVal);

   // In Promiscuous or Accept Err mode - Enable acceptance of runts, CRC err,
   //   FAE, in-range-length errors
   // Acceptance of long packets depends on the MTU size and NSM's ablility to
   //   provide larger buffers etc. - So this function does not deal with it.
   //   NSM can call MplCfgMTU to accept Long packets

   regVal = MPL_READ32(pMplCtx, RXCFG);
   if ((filterFlag & MPL_RECEIVE_FILTER_ERROREDPKTS) ||
         (filterFlag & MPL_RECEIVE_FILTER_PROMISCUOUS_MODE))
   {
      regVal |= (ACCEPT_CRCALIGNERR | ACCEPT_RUNTS | ACCEPT_INRNG_LENERR);
   }
   else
   {
      // Clear all Err acceptance
      regVal &= (~(ACCEPT_CRCALIGNERR | ACCEPT_RUNTS | ACCEPT_INRNG_LENERR));
   }
   MPL_WRITE32(pMplCtx, RXCFG, regVal);

   EXIT(MplReceiveSetFilter);
   return NS_STATUS_SUCCESS;
}

//*****************************************************************************
//   MplReceive
//      Handles the packet reception event and moves the received packet from
//       the device to the host.
//
//   Parameters
//      pMplHandle
//         MPL device handle returned following a call to MplInitialize
//      maxEvents
//         The maximum receive engine related events (e.g. receive complete)
//          that MPL should process before returning back to the caller.
//      pBufFragConsumed
//         A caller supplied pointer variable in which this function returns the
//          number of buffer fragments that were consumed while processing this
//          receive pass.
//
//   Return Value
//      NS_STATUS_SUCCESS
//         The receive events were successfully processed.
//      NS_STATUS_ABORTED
//         The processing was aborted since the maximum event count specified 
//          was met.
//
//*****************************************************************************
MPL_STATUS
   MplReceive (
      IN NS_VOID     *pMplHandle,
      IN NS_UINT      maxEvents,
      OUT NS_UINT    *pBufFragConsumed
      )
{
   MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;
   NS_UINT entry, pendRxds, evtCnt = 0x0, pktCnt = 0x0;
   NS_UINT32 cmdSts = 0x0;
   MPL_PKT_FRAG *currFrag;
   MPL_DESC *currRxd;
   MPL_STATUS status = NS_STATUS_SUCCESS;

   ENTER(MplReceive);

   // Get the starting Rxd and number of Rxds to process
   entry = pMplCtx->rxQueue.curr % pMplCtx->rxQueue.descCnt;
   currRxd = &pMplCtx->rxQueue.pRing[entry];
   pendRxds = pMplCtx->rxQueue.dirty + pMplCtx->rxQueue.descCnt 
                       - pMplCtx->rxQueue.curr;
   *pBufFragConsumed = 0x0;

   // Process the Rxd ring - We break once all pending Rxds are processed or
   //                         the maxEvents are processed
   while ((currRxd->cmdSts & CS_OWN_ES) && (pendRxds--))
   {
      // The software now owns this Rxd
      cmdSts = MPL_LTOH32(currRxd->cmdSts);

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

      // Get the frag ptr
      currFrag = (MPL_PKT_FRAG *)currRxd->mplPriv;
      // Copy the physical addr of Rxd -  for diag mode operations only
      currFrag->pMplPrivate = (NS_VOID *)(pMplCtx->rxQueue.ringPA + 
                                           (entry * sizeof(MPL_DESC)));

      // Setup reference ptr to handle situations where a packet spans
      //  into multiple Rxds, and we need to link them all up
      if (pMplCtx->rxQueue.pFragHead == NULL)
      {
         pMplCtx->rxQueue.pFragHead = currFrag; // Head frag 
      }
      else
      {
         pMplCtx->rxQueue.pFragTail->pNextFrag = currFrag; // Tail Frag
      }

      pMplCtx->rxQueue.fragCnt++;

      // Accumulate the frag sizes
      currFrag->fragSize = cmdSts & CS_LEN_MASK;
      pMplCtx->rxQueue.packetSize += currFrag->fragSize;

      // Check if this packet has more Rxds coming
      if (cmdSts & CS_MORE)
      {
PRINT(("Multi Rxd  cmdSts = %x \n", (NS_UINT)cmdSts));

         // Add to the tail of pending list
         pMplCtx->rxQueue.pFragTail = currFrag;
      }
      else
      {
         // We have all Rxd frags for this pkt - Prepare a indication
        *pBufFragConsumed += pMplCtx->rxQueue.fragCnt;
         currFrag->pNextFrag = NULL; // End list
         pMplCtx->rxDone[pktCnt].fragCount = pMplCtx->rxQueue.fragCnt;
         pMplCtx->rxDone[pktCnt].pFragHead = pMplCtx->rxQueue.pFragHead;
         pMplCtx->rxDone[pktCnt].rxOOB.cmdSts = cmdSts;
         pMplCtx->rxDone[pktCnt].packetSize = pMplCtx->rxQueue.packetSize;

#ifdef MPL_TASK_VLAN
         // If VLAN is enabled then get the extended status
         pMplCtx->rxDone[pktCnt].rxOOB.extSts = MPL_LTOH32(currRxd->extCtlSts);
#endif
         
         if (cmdSts & CS_OK) 
         {
            pMplCtx->rxDone[pktCnt].packetStatus = NS_STATUS_SUCCESS;
         }
         else
         {
            // PacketQry APIs return more details on the error
            pMplCtx->rxDone[pktCnt].packetStatus = NS_STATUS_FAILURE;
         }
        
         // Increment pkt count
         pktCnt++;

         // Check if it is time to report to NSM
         if (pktCnt >= pMplCtx->maxRxDones)
         {
            NsmReceive(pMplCtx->pClientHandle, pktCnt, pMplCtx->rxDone);
            pktCnt = 0x0;
         }

         // Clean up partial tracker
         pMplCtx->rxQueue.pFragHead = pMplCtx->rxQueue.pFragTail = NULL;
         pMplCtx->rxQueue.fragCnt = pMplCtx->rxQueue.packetSize = 0x0 ;

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

      // Get the next Rxd and Read its cmdSts
      entry = (++pMplCtx->rxQueue.curr) % pMplCtx->rxQueue.descCnt;
      currRxd = &pMplCtx->rxQueue.pRing[entry];
   }

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

   EXIT(MplReceive);
   return status;
}

//*****************************************************************************
//   MplReceiveReplenish
//      Restock the MPL receive engine with fresh buffers for packet reception.
//
//   Parameters
//      pMplHandle
//         MPL device handle returned following a call to MplInitialize.
//      bufFragCount
//         Number of buffer fragments being replenished.
//      pFragList
//         Pointer to a caller supplied variable of type MPL_PKT_FRAG pointing 
//          to the head node of the buffer fragment list being replenished.
//          If all the buffer fragments were not consumed by MPL then the 
//          pointer to the first unused fragment is returned back to NSM.
//
//   Return Value
//      NS_STATUS_SUCCESS
//         The buffers were successfully replenished.
//
//*****************************************************************************
MPL_STATUS
   MplReceiveReplenish (
      IN NS_VOID           *pMplHandle,
      IN NS_UINT            bufFragCount,
      IN OUT MPL_PKT_FRAG **pFragList
      )
{
   MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;
   MPL_PKT_FRAG *currFrag;
   MPL_DESC *currRxd;
   NS_UINT entry;

   ENTER(MplReceiveReplenish);

   // Loop through the Rxd ring filling it up with new buffers
   currFrag = *pFragList;

   for (;bufFragCount && (pMplCtx->rxQueue.curr - pMplCtx->rxQueue.dirty > 0x0); 
               pMplCtx->rxQueue.dirty++, bufFragCount--)
   {
   
      entry = pMplCtx->rxQueue.dirty % pMplCtx->rxQueue.descCnt;
      currRxd = &pMplCtx->rxQueue.pRing[entry];

⌨️ 快捷键说明

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