📄 ndissend.c
字号:
/* ---------------------------------------------------------------------------
Copyright (c) 2003-2006 Micrel, Inc. All rights reserved.
---------------------------------------------------------------------------
NdisSend.c - NDIS driver send functions.
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 04/03/06 Disable send queue because of crashes.
THa 06/02/06 Report statistics from MIB counters.
---------------------------------------------------------------------------
*/
#include "target.h"
#include "NdisDevice.h"
#if 0
#define SEND_QUEUE
#endif
/* -------------------------------------------------------------------------- */
USHORT ntohs (
USHORT wNetValue )
{
USHORT wHostValue;
wHostValue = (( UCHAR ) wNetValue << 8 ) | ( UCHAR )( wNetValue >> 8 );
return( wHostValue );
} // ntohs
/*
GetFirstBuffer
Description:
This function retrieves the first NDIS buffer in the NDIS packet.
Parameters:
PNDIS_BUFFER* ppndisBuffer
Pointer to NDIS buffer pointer.
PUINT puiLength
Buffer to store the length of the data buffer.
Return (PUCHAR):
Pointer to data buffer in the NDIS buffer.
*/
__inline
PUCHAR GetFirstBuffer (
PNDIS_BUFFER* ppndisBuffer,
PUINT puiLength )
{
PUCHAR pBuffer;
// Each packet may be made up of several buffers, linked together. Get the
// virtual address (in pBuffer) and the length (in uiLength) of the first
// buffer in the packet by calling NdisQueryBuffer.
NdisQueryBuffer( *ppndisBuffer, ( PVOID* ) &pBuffer, puiLength );
// If the pointer to the buffer is not NULL and the length returned from
// the above call is zero, skip to the next buffer and query it for its
// length.
while ( !*puiLength )
{
NdisGetNextBuffer( *ppndisBuffer, ppndisBuffer );
if ( !*ppndisBuffer )
{
return NULL;
}
NdisQueryBuffer( *ppndisBuffer, ( PVOID* ) &pBuffer, puiLength );
}
return( pBuffer );
} // GetFirstBuffer
/*
GetNextBuffer
Description:
This function retrieves the next NDIS buffer in the NDIS packet.
Parameters:
PNDIS_BUFFER* ppndisBuffer
Pointer to NDIS buffer pointer.
PUINT puiLength
Buffer to store the length of the data buffer.
Return (PUCHAR):
Pointer to data buffer in the NDIS buffer.
*/
__inline
PUCHAR GetNextBuffer (
PNDIS_BUFFER* ppndisBuffer,
PUINT puiLength )
{
PUCHAR pBuffer;
*puiLength = 0;
// Go through the process of eliminating buffers with no data in them.
// Exit the following while loop when we run out of buffers or have one
// that contains some data.
while ( !*puiLength )
{
NdisGetNextBuffer( *ppndisBuffer, ppndisBuffer );
if ( !*ppndisBuffer )
{
return NULL;
}
NdisQueryBuffer( *ppndisBuffer, ( PVOID* ) &pBuffer, puiLength );
}
return( pBuffer );
} // GetNextBuffer
/*
AdapterCopyDownPacket
Description:
This function copies the packet down to the adapter buffer.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
PNDIS_BUFFER pndisBuffer
Pointer to NDIS buffer.
UINT uiPacketLength
The length of the buffer.
PUINT puiLength
Buffer to store the actual length of data copied.
BOOLEAN* pbBroadcast
Buffer to store the broadcast flag.
Return (BOOLEAN):
TRUE if successful; otherwise, FALSE.
*/
BOOLEAN AdapterCopyDownPacket (
IN PNDIS_ADAPTER pAdapter,
IN PNDIS_BUFFER pndisBuffer,
IN UINT uiPacketLength,
OUT PUINT puiLength,
OUT BOOLEAN* pbBroadcast )
{
PHARDWARE pHardware = &pAdapter->m_Hardware;
PDMA_BUFFER pDma = pAdapter->m_TxBufInfo.pCurrent;
// Length of current source buffer
UINT uiBufferLength;
// Address of current source buffer
PUCHAR pBuffer;
*puiLength = 0;
pBuffer = GetFirstBuffer( &pndisBuffer, &uiBufferLength );
if ( pBuffer )
{
if ( ( pBuffer[ 0 ] & 0x01 ) )
{
*pbBroadcast = TRUE;
}
else
{
*pbBroadcast = FALSE;
}
HardwareSetTransmitBuffer( pHardware, pDma->sm.ulPhysical );
HardwareSetTransmitLength( pHardware, uiPacketLength );
}
while ( pBuffer )
{
NdisMoveMemory( &pDma->sm.pVirtual[ *puiLength ], pBuffer,
uiBufferLength );
*puiLength += uiBufferLength;
pBuffer = GetNextBuffer( &pndisBuffer, &uiBufferLength );
}
if ( !*puiLength )
{
goto CopyDownPacketError;
}
/* Flush buffer. */
NdisFlushBuffer( pDma->pNdisBuffer, TRUE );
return TRUE;
CopyDownPacketError:
#ifdef DEBUG_COUNTER
pHardware->m_nBad[ COUNT_BAD_COPY_DOWN ]++;
#endif
return FALSE;
} // AdapterCopyDownPacket
/*
AllocMapReg
Description:
This function allocates a mapping register information block for
transmission.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
Return (PMAP_REG):
Pointer to mapping register information block if one is allocated, else
NULL.
*/
__inline
PMAP_REG AllocMapReg (
PNDIS_ADAPTER pAdapter )
{
PMAP_REG pMapReg = NULL;
ASSERT( pAdapter->m_cnMapRegAvail > 0 );
#if 0
if ( pAdapter->m_cnMapRegAvail )
#endif
{
pMapReg = pAdapter->m_pMapRegTop;
pAdapter->m_pMapRegTop = pMapReg->pNext;
pAdapter->m_cnMapRegAvail--;
}
return( pMapReg );
} // AllocMapReg
/*
FreeMapReg
Description:
This routine frees the mapping register information block.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
PMAP_REG pMapReg
Pointer to the mapping register information block.
Return (None):
*/
__inline
VOID FreeMapReg (
PNDIS_ADAPTER pAdapter,
PMAP_REG pMapReg )
{
pMapReg->pNdisBuffer = NULL;
pMapReg->pNext = pAdapter->m_pMapRegTop;
pAdapter->m_pMapRegTop = pMapReg;
pAdapter->m_cnMapRegAvail++;
} // FreeMapReg
/* -------------------------------------------------------------------------- */
/*
SendPacket
Description:
This function sends a packet to hardware.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
PNDIS_BUFFER pBuffer
Pointer to NDIS buffer.
UINT uiPacketLength
The length of the buffer.
Return (NDIS_STATUS):
NDIS_STATUS_PENDING if successful; otherwise, an error code indicating
failure.
*/
NDIS_STATUS SendPacket (
PNDIS_ADAPTER pAdapter,
PNDIS_PACKET pPacket,
PNDIS_BUFFER pBuffer,
UINT uiPacketLength )
{
PBUFFER_INFO pBufInfo = &pAdapter->m_TxBufInfo;
PHARDWARE pHardware = &pAdapter->m_Hardware;
PTDescInfo pInfo = &pHardware->m_TxDescInfo;
NDIS_STATUS nsStatus = NDIS_STATUS_FAILURE;
UINT uiLength;
BOOLEAN bBroadcast;
BOOLEAN bResult;
int port = MAIN_PORT;
pBufInfo->pCurrent = Alloc_DMA_Buffer( pBufInfo, pInfo->pCurrent );
bResult = AdapterCopyDownPacket( pAdapter, pBuffer, uiPacketLength,
&uiLength, &bBroadcast );
if ( !bResult )
{
Free_DMA_Buffer( pBufInfo, pBufInfo->pCurrent );
pInfo->pCurrent->pReserved = NULL;
HardwareFreeTxPacket( pInfo );
goto SendIntrDone;
}
pBufInfo->pCurrent->pNdisPacket = pPacket;
if ( HardwareSendPacket( pHardware ) )
{
nsStatus = NDIS_STATUS_PENDING;
if ( uiLength )
{
pHardware->m_cnCounter[ port ][ OID_COUNTER_XMIT_OK ]++;
#ifndef NO_STATS
if ( bBroadcast )
{
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_BROADCAST_FRAME_XMIT ]++;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_BROADCAST_BYTES_XMIT ] += uiLength;
}
else
{
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_DIRECTED_FRAMES_XMIT ]++;
pHardware->m_cnCounter[ port ]
[ OID_COUNTER_DIRECTED_BYTES_XMIT ] += uiLength;
}
#endif
}
}
SendIntrDone:
return( nsStatus );
} // SendPacket
#define DRV_PACKET_ARRAY_SIZE 32
/*
SendBuffers
Description:
This function sends a packet in several buffer descriptors to hardware.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
PNDIS_Packet pPacket
Pointer to NDIS packet.
PNDIS_BUFFER pndisBuffer
Pointer to NDIS buffer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -