📄 ndisisr.c
字号:
/* ---------------------------------------------------------------------------
Copyright (c) 2003-2006 Micrel, Inc. All rights reserved.
---------------------------------------------------------------------------
NdisISR.c - NDIS driver interrupt processing.
Author Date Description
THa 12/01/03 Created file.
THa 06/27/05 Updated for version 0.1.5.
THa 09/29/05 Changed descriptor structure.
THa 02/23/06 Updated for WinCE 5.0.
THa 06/02/06 Report statistics from MIB counters.
---------------------------------------------------------------------------
*/
#include "target.h"
#include "NdisDevice.h"
#if 0
#define RCV_UNTIL_NONE
#endif
#ifdef DEBUG_OVERRUN
int receive_overrun = 0;
#endif
/* -------------------------------------------------------------------------- */
/*
ProcessReceive
Description:
This function processes the buffer receiving.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
Return (BOOLEAN):
TRUE if a packet is received; FALSE otherwise.
*/
int ProcessReceive (
IN PNDIS_ADAPTER pAdapter )
{
int iNext;
TDescStat status;
PHARDWARE pHardware = &pAdapter->m_Hardware;
PTDescInfo pInfo = &pHardware->m_RxDescInfo;
PBUFFER_INFO pBufInfo = &pAdapter->m_RxBufInfo;
PNDIS_PACKET* PacketArray = pAdapter->m_PacketArray;
PNDIS_PACKET pPacket;
PTDesc pDesc;
PDMA_BUFFER pDma;
#ifndef RCV_UNTIL_NONE
int cnLeft = pInfo->cnAlloc;
#endif
UINT i;
UINT uiPacketCount = 0;
#ifndef NO_STATS
PUCHAR pBuffer;
#endif
int port = MAIN_PORT;
#ifdef DEBUG_RX_DATA
int nLength;
#endif
iNext = pInfo->iNext;
#ifdef RCV_UNTIL_NONE
while ( 1 )
#else
while ( cnLeft-- )
#endif
{
/* Get next descriptor which is not hardware owned. */
GetReceivedPacket( pInfo, iNext, pDesc, status.ulData );
if ( status.rx.fHWOwned )
break;
#ifdef CHECK_OVERRUN
if ( !( pDesc->pCheck->Control.ulData & CPU_TO_LE32( DESC_HW_OWNED )) )
{
#ifdef DEBUG_OVERRUN
receive_overrun = 1;
pHardware->m_ulDropped++;
#endif
ReleasePacket( pDesc );
FreeReceivedPacket( pInfo, iNext );
#ifndef RCV_UNTIL_NONE
cnLeft = pInfo->cnAlloc;
#endif
continue;
}
#endif
pDesc->sw.Control.ulData = status.ulData;
pInfo->pCurrent = pDesc;
HardwareReceive( pHardware );
if ( pHardware->m_nPacketLen )
{
#ifdef DEBUG_OVERRUN
pHardware->m_ulReceived++;
#endif
/* Get received packet information. */
pDma = DMA_BUFFER( pDesc );
/* Adjust the length of NDIS buffer to the length of the packet. */
NdisAdjustBufferLength( pDma->pNdisBuffer,
pHardware->m_nPacketLen );
/* Flush the receive buffer. */
NdisFlushBuffer( pDma->pNdisBuffer, FALSE );
NdisMUpdateSharedMemory(
pAdapter->m_hAdapter,
pDma->ulSize,
pDma->sm.pVirtual,
pDma->PhysicalAddr );
#ifndef NO_STATS
pBuffer = ( PUCHAR ) pDma->sm.pVirtual;
#ifdef DEBUG_RX_DATA
for ( nLength = 0; nLength < pHardware->m_nPacketLen; nLength++ )
{
DbgPrint( "%02X ", pBuffer[ nLength ]);
if ( ( nLength % 16 ) == 15 )
{
DbgPrint( "\n" );
}
}
DbgPrint( "\n" );
#endif
/* Descriptor does not have broadcast indication. */
if ( 0xFF == pBuffer[ 0 ] )
{
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_BROADCAST_FRAMES_RCV ]++;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_BROADCAST_BYTES_RCV ] +=
pHardware->m_nPacketLen;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_MULTICAST_FRAMES_RCV ]--;
}
else if ( pBuffer[ 0 ] != 0x01 )
{
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_UNICAST_FRAMES_RCV ]++;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_DIRECTED_FRAMES_RCV ]++;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_DIRECTED_BYTES_RCV ] +=
pHardware->m_nPacketLen;
}
#endif
pHardware->m_cnCounter[ port ][ OID_COUNTER_RCV_OK ]++;
/* Get pointer of associated packet for further processing. */
pPacket = pDma->pNdisPacket;
/* There are buffers available for using in descriptors. */
#ifndef UNDER_CE
if ( NdisQueryDepthSList( &pBufInfo->listHead ) )
#else
if ( pBufInfo->cnAvail )
#endif
{
/* Upper layer can keep this packet. */
NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_SUCCESS );
/* Reset this pointer so that we can debug the RX descriptor if
error happens.
*/
RESERVED( pPacket )->pDesc = NULL;
/* Get a new buffer for this descriptor. */
pDma = Alloc_DMA_Buffer( pBufInfo, pDesc );
/* Set descriptor for packet receive. */
SetReceiveBuffer( pDesc, pDma->sm.ulPhysical );
SetReceiveLength( pDesc, pDma->ulSize );
ReleasePacket( pDesc );
}
else
{
/* Upper layer must copy this packet immediately. */
NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_RESOURCES );
RESERVED( pPacket )->pDesc = pDesc;
/* Cannot release the descriptor yet. */
}
PacketArray[ uiPacketCount ] = pPacket;
uiPacketCount++;
}
else
{
ReleasePacket( pDesc );
}
FreeReceivedPacket( pInfo, iNext );
}
pInfo->iNext = iNext;
if ( uiPacketCount )
{
/* We have packets to indicate. */
NdisMIndicateReceivePacket( pAdapter->m_hAdapter, PacketArray,
uiPacketCount );
/* Determine which packets are kept for reuse and which ones are needed
to put back to the list.
*/
for ( i = 0; i < uiPacketCount; i++ )
{
pPacket = PacketArray[ i ];
if ( NDIS_STATUS_PENDING != NDIS_GET_PACKET_STATUS( pPacket ) )
{
/* If the status code for the packet is not status pending,
which should be modified by NdisMIndicateReceivePacket
function, then we can place the resouces back on the free
list.
*/
pDma = RESERVED( pPacket )->pDma;
#if 0
/* Adjust the buffer length. */
NdisAdjustBufferLength( pDma->pNdisBuffer, pDma->ulSize );
#endif
/* If we indicate to the upper that it could not keep this
packet then do not place it back to the list.
*/
if ( NDIS_STATUS_RESOURCES ==
NDIS_GET_PACKET_STATUS( pPacket ) )
{
pDesc = RESERVED( pPacket )->pDesc;
/* It is set by us so release the descriptor. */
if ( pDesc )
{
RESERVED( pPacket )->pDesc = NULL;
ReleasePacket( pDesc );
}
/* It should not happen unless upper layer really has no
resources.
*/
else
{
/* Place the buffer back to the free list for use next
time.
*/
Free_DMA_Buffer( pBufInfo, pDma );
}
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -