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

📄 nsmmpl.c

📁 NATIONAL公司DP83816芯片Linux下驱动
💻 C
字号:
//******************************************************************************
//
//  NSMMPL.C
//
//  Copyright (c) 2004 National Semiconductor Corporation.
//  All Rights Reserved
//
//  Interface file between NSM and MPL, implements
//   1. OAI APIs
//   2. MPL Callbacks
//
//******************************************************************************

#include <nsmos.h>
#include <nsm.h>

//+++++ Host DMA Memory Functions
//Allocate/free a region in host memory suitable for DMA
NS_BOOLEAN
OaiAllocDmaRegion(
    IN NS_VOID          *pClientDevHndl,
    IN NS_UINT           size,
    IN NS_UINT           byteAlignment,
    OUT MPL_MEM_REGION **pRgnHndl
    )
{
   dma_addr_t allocPA;
   NSM_MEM_REGION *pMemNode;

   // No allocations yet
   *pRgnHndl = NULL;

   // Allocate a DMA MEM node
   pMemNode = (NSM_MEM_REGION *)kmalloc(sizeof(NSM_MEM_REGION), GFP_KERNEL);
   if (pMemNode == NULL)
      return NS_FALSE;
   
   // Alloc consistent - Should be mapped on 4-byte
   pMemNode->pAddr = 
       pci_alloc_consistent(((NSM_CONTEXT *)pClientDevHndl)->pdev, 
                              size,
                              &allocPA);

   if (pMemNode->pAddr != NULL) 
   {
      pMemNode->phyAddr = (NS_ADDR)allocPA;
      pMemNode->size = size;
     *pRgnHndl = (MPL_MEM_REGION *)pMemNode;
      return NS_TRUE;
   }
   else
   {
      kfree((NS_VOID *)pMemNode);
      return NS_FALSE;
   }
}

NS_VOID
OaiFreeDmaRegion(
    IN NS_VOID            *pClientDevHndl,
    IN MPL_MEM_REGION     *pRgnHndl
    )
{
   NSM_MEM_REGION *pMemNode = (NSM_MEM_REGION *)pRgnHndl;

   if (pMemNode && pMemNode->pAddr)
   {
      pci_free_consistent(((NSM_CONTEXT *)pClientDevHndl)->pdev, 
                            pMemNode->size,
                            pMemNode->pAddr,
                            (dma_addr_t)pMemNode->phyAddr);

      kfree((NS_VOID *)pMemNode);
   }

   return;
}

//+++++ Timer Functions

//Allocate/free/start/cancel periodic timer w/ callback 'pTimerFunction'
NS_BOOLEAN
OaiCreateTimer( 
    IN MPL_TIMERCALLBACK  pTimerFunction,
    IN NS_VOID           *pTimerArg,
    OUT NS_VOID         **pTimerHandle
    )
{
   struct timer_list *timer;

   // Allocate a timer struct
   timer = (struct timer_list *)kmalloc(sizeof(struct timer_list), GFP_KERNEL);
   *pTimerHandle = timer;

   if (timer != NULL)
   {
       // Initialize the Timer 
       init_timer(timer);
       timer->function = (void (*)(unsigned long))pTimerFunction;
       timer->data     = (unsigned long)pTimerArg;
       return TRUE;
   }
   else
       return FALSE;

}

NS_VOID
OaiDeleteTimer(
    IN NS_VOID *pTimerHandle
    )
{
   if (pTimerHandle)
   {
      // To be safe cancel it first
      del_timer((struct timer_list *)pTimerHandle);

      // Free the memory
      kfree((NS_VOID *)pTimerHandle);
   }

   return;
}

NS_VOID 
OaiStartTimer(
    IN NS_VOID *pTimerHandle,
    IN NS_UINT  delayInMsec
    )
{
   // Note each jiffies is about 10msec (100 ticks per sec)
   mod_timer((struct timer_list *)pTimerHandle, (jiffies + (delayInMsec / 10)));
   return;
}

NS_BOOLEAN
OaiCancelTimer(
    IN NS_VOID *pTimerHandle
    )
{
   del_timer_sync((struct timer_list *)pTimerHandle);
   return NS_TRUE;
}

//+++++ Resource Synchronization Functions

//Initialize/free/acquire/release multiprocessor-safe synchronization lock
NS_BOOLEAN
OaiCreateLock(
    OUT NS_VOID **pLockHandle
    )
{
   return NS_TRUE;
}

NS_VOID
OaiDestroyLock(
    IN NS_VOID *pLockHandle
    )
{
   return;
}

NS_VOID
OaiAcquireLock(
    IN NS_VOID *pLockHandle
    )
{
   return;
}

NS_VOID
OaiReleaseLock(
    IN NS_VOID *pLockHandle
    )
{
   return;
}


//+++++ MPL Callbacks into NSM

//*****************************************************************************
//   NsmTransmitDone
//     Transmit Done Notification 
//
//   Parameters
//      pClientDevHndl
//         NSM device handle registered with MPL (during MplInitialize)
//      packetCnt
//         Count of packets whose completion is being reported.
//      pTxDone
//         MPL allocated MPL_TRANSMIT_DONE structure array in which the 
//          NSM packet handles and statuses are returned.
//
//   Return Value
//      None
//*****************************************************************************
NS_VOID
NsmTransmitDone(
    IN NS_VOID *pClientDevHndl,
    IN NS_UINT  packetCnt,
    IN MPL_TRANSMIT_DONE *pTxDone
    )
{
   NSM_CONTEXT *adapter = pClientDevHndl;
   struct sk_buff *skb;
   NS_UINT i;
   NS_ADDR physAddr;

   NI(NsmTransmitDone);
#ifdef NSM_DIAG_MODE
   if (adapter->opMode != MPL_MODE_NORMAL)
   {
      // Call the Diag Tx done handler
      NsmDiagTransmitDone(pClientDevHndl, packetCnt, pTxDone);
      NO(NsmTransmitDone);
      return;
   }
#endif //NSM_DIAG_MODE

   // Unmap and Free done skbs
   for(i = 0x0; i < packetCnt; i++)
   {
      // Get the skb which was noted as NSM private
      skb = pTxDone[i].pNsmPrivate;

      if (pTxDone[i].packetStatus == NS_STATUS_SUCCESS)
      {
         // Update counters
         adapter->netStats.tx_packets++;
         adapter->netStats.tx_bytes += skb->len;
      }
      else
      {
         // Update counters
         adapter->netStats.tx_errors++;

         // Detailed Error analysis - FM: Make call to MPL Stat?
         if (pTxDone[i].cmdSts & (CS_ERR_TXA | CS_ERR_TX_EC))
         {
            adapter->netStats.tx_aborted_errors++;
         }

         if (pTxDone[i].cmdSts & CS_ERR_TFU)
         {
            adapter->netStats.tx_fifo_errors++;
         }
         
         if (pTxDone[i].cmdSts & CS_ERR_TX_CRS)
         {
            adapter->netStats.tx_carrier_errors++;
         }

         if (pTxDone[i].cmdSts & CS_ERR_TX_OWC)
         {
            adapter->netStats.tx_window_errors++;
         }
      }

      // Unmap Buffers
      physAddr = (NS_ADDR)*((NS_UINT *)skb->cb);
      pci_unmap_single(adapter->pdev, physAddr, skb->len, PCI_DMA_TODEVICE);

      // If we had requested to stop new Tx to the Net Stack, 
      ///  then let it start again
      if (netif_queue_stopped(adapter->netdev))
      {
         netif_wake_queue(adapter->netdev);
      }

      // Free Skb
      dev_kfree_skb_irq(skb);
   }

   NO(NsmTransmitDone);
   return;
}

//*****************************************************************************
//   NsmReceive
//     Receive Done Notification
//
//   Parameters
//      pClientDevHndl
//         NSM device handle registered with MPL (during MplInitialize)
//      packetCnt
//         Count of packets whose reception is being reported.
//      pPkt
//         MPL allocated MPL_PKT structure array in which 
//         a list of the newly received packets are reported
//
//   Return Value
//      None
//*****************************************************************************
NS_VOID
NsmReceive(
    IN NS_VOID *pClientDevHndl,
    IN NS_UINT  packetCnt,
    IN MPL_PKT *pPkt
    )
{
   NSM_CONTEXT *adapter = pClientDevHndl;
   MPL_PKT_FRAG *pFragTail;
   struct sk_buff *skb;
   NS_UINT i, j;

   NI(NsmReceive);

#ifdef NSM_DIAG_MODE
   if (adapter->opMode != MPL_MODE_NORMAL)
   {
      // Call the Diag Tx done handler
      NsmDiagReceive(pClientDevHndl, packetCnt, pPkt);
      NO(NsmReceive);
      return;
   }
#endif //NSM_DIAG_MODE

   // Process the receive list
   for(i = 0x0; i < packetCnt; i++)
   {
      pFragTail = pPkt[i].pFragHead;

      // We should have only ONE fragment for Linux - Process it
      if (pPkt[i].fragCount == 0x01)
      {
         // Unmap the Skb
         pci_unmap_single(adapter->pdev, pFragTail->physAddr, 
                             adapter->rxBufferLen, PCI_DMA_FROMDEVICE);

         if (pPkt[i].packetStatus == NS_STATUS_SUCCESS)
         {
            // Decrement the size of CRC
            pPkt[i].packetSize -= CRC_LENGTH;

            // Update counters
            adapter->netStats.rx_packets++;
            adapter->netStats.rx_bytes += pPkt[i].packetSize;

            // Report Skb to Net Stack 
            skb = (struct sk_buff *)(pFragTail->pNsmPrivate);
            skb_put(skb, pPkt[i].packetSize);
            skb->protocol = eth_type_trans(skb, adapter->netdev);
            netif_rx(skb);

            // The Skb associated with this fragment is now history
            pFragTail->pNsmPrivate = NULL;
         }
         else
         {
            // Update counters
            adapter->netStats.rx_errors++;

            // Detailed Error analysis
            if (pPkt[i].rxOOB.cmdSts & (CS_RXA | CS_ERR_RXO))
            {
               adapter->netStats.rx_over_errors++;
            }

            if (pPkt[i].rxOOB.cmdSts & CS_ERR_RX_CRCE)
            {
               adapter->netStats.rx_crc_errors++;
            }

            if (pPkt[i].rxOOB.cmdSts & (CS_ERR_RX_LONG | CS_ERR_RX_RUNT))
            {
               adapter->netStats.rx_length_errors++;
            }

            if (pPkt[i].rxOOB.cmdSts & (CS_ERR_RX_ISE | CS_ERR_RX_FAE))
            {
               adapter->netStats.rx_frame_errors++;
            }
         }
      }
      else
      {

         if (pPkt[i].packetStatus != NS_STATUS_ABORTED)
         {
            adapter->netStats.rx_errors++;
            adapter->netStats.rx_length_errors++;
         }

         for (j = 0x0; j < (pPkt[i].fragCount - 1); j++)
         {
            pFragTail = pFragTail->pNextFrag;
         }
      }

      // Put the frags back on the cache
      adapter->rxFragsTail->pNextFrag = pPkt[i].pFragHead;
      pFragTail->pNextFrag = NULL;
      adapter->rxFragsTail = pFragTail;
   }

   NO(NsmReceive);
   return;
}

//*****************************************************************************
//   NsmLinkStatusChange
//     Link status change Notification
//
//   Parameters
//      pClientDevHndl
//         NSM device handle registered with MPL (during MplInitialize)
//
//   Return Value
//      None
//*****************************************************************************
NS_VOID
NsmLinkStatusChange(
    IN NS_VOID *pClientDevHndl
    )
{
   NSM_CONTEXT *adapter = pClientDevHndl;

   // Start a tasklet to process the Link change and return
   tasklet_schedule(&adapter->linkMonTask);

   return;
}

⌨️ 快捷键说明

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