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

📄 ndissend.c

📁 MICREL 网卡驱动 FOR CE 5.0
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ---------------------------------------------------------------------------
          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 + -