📄 nsmmpl.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 + -