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

📄 ndisdevice.c

📁 MICREL 网卡驱动 FOR CE 5.0
💻 C
📖 第 1 页 / 共 5 页
字号:
    pDma = pBufInfo->BufArray;
    for ( i = 0; i < pBufInfo->cnAlloc; i++ )
    {
#ifndef UNDER_CE
        NdisInterlockedPushEntrySList( &pBufInfo->listHead, &pDma->listEntry,
            &pBufInfo->listLock );
        pDma++;

#else
        pPrevious = pDma;
        pDma++;
        pPrevious->pNext = pDma;
#endif
    }

#ifdef UNDER_CE
    pPrevious->pNext = NULL;
#endif
}  /* InitBuffers */


/*
    AllocateBuffers

    Description:
        This local function allocates DMA buffers for use in receiving and
        transmitting.

    Parameters:
        PNDIS_ADAPTER pAdapter
            Pointer to adapter information structure.

        PBUFFER_INFO pBufInfo
            Pointer to DMA buffer information structure.

        int fPacket
            Indication that packets are allocated for receiving.

    Return (NDIS_STATUS):
        NDIS_STATUS_SUCCESS if successful; otherwise an error code indicating
        failure.
*/

static NDIS_STATUS AllocateBuffers (
    PNDIS_ADAPTER pAdapter,
    PBUFFER_INFO  pBufInfo,
    int           fPacket )
{
    NDIS_PHYSICAL_ADDRESS AllocPhysicalAddr;
    NDIS_PHYSICAL_ADDRESS PhysicalAddr;
    NDIS_STATUS           NdisStatus;
    PDMA_BUFFER           pDma;
    PUCHAR                pAllocVirtual;
    PUCHAR                pVirtual;
    ULONG                 ulAllocSize;
    ULONG                 ulPhysical;
    int                   i;
    int                   nOffset;
    PSHARED_MEM           pBufPool = &pBufInfo->MemPool;
    NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
        NDIS_PHYSICAL_ADDRESS_CONST( -1, -1 );

    /* Attempt to allocate all the buffer space in one big block. */
    /* If it fails, allocate each buffer individually. */
    pBufPool->ulAllocSize = ( pBufInfo->cnAlloc * NDIS_BUFFER_SIZE ) +
        BUFFER_ALIGNMENT;
    pBufPool->bCached = TRUE;

    NdisMAllocateSharedMemory( pAdapter->m_hAdapter,
        pBufPool->ulAllocSize,
        pBufPool->bCached,
        &pBufPool->pAllocVirtual,
        &pBufPool->AllocPhysicalAddr );

    /* Big buffer not allocated. */
    if ( pBufPool->pAllocVirtual == NULL )
    {
        pBufPool->ulAllocSize = 0;
    }
    else if ( NdisGetPhysicalAddressHigh( pBufPool->AllocPhysicalAddr ) != 0 )
    {
        NdisMFreeSharedMemory( pAdapter->m_hAdapter,
            pBufPool->ulAllocSize,
            pBufPool->bCached,
            pBufPool->pAllocVirtual,
            pBufPool->AllocPhysicalAddr );
        pBufPool->pAllocVirtual = NULL;
        pBufPool->ulAllocSize = 0;
    }
    else
    {
        NdisZeroMemory( pBufPool->pAllocVirtual, pBufPool->ulAllocSize );
        nOffset = ((( ULONG ) pBufPool->pAllocVirtual % BUFFER_ALIGNMENT ) ?
            ( BUFFER_ALIGNMENT -
            (( ULONG ) pBufPool->pAllocVirtual % BUFFER_ALIGNMENT )) : 0 );
        pBufPool->pVirtual = pBufPool->pAllocVirtual + nOffset;
        pBufPool->ulPhysical = NdisGetPhysicalAddressLow(
            pBufPool->AllocPhysicalAddr ) + nOffset;
        nOffset = 0;
    }

#if (NDISVER >= 50)
    NdisStatus = NdisAllocateMemoryWithTag(( PVOID* ) &pBufInfo->BufArray,
        sizeof( DMA_BUFFER ) * pBufInfo->cnAlloc, 'rciM' );
#else
    NdisStatus = NdisAllocateMemory(( PVOID* ) &pBufInfo->BufArray,
        sizeof( DMA_BUFFER ) * pBufInfo->cnAlloc,
        0, HighestAcceptableMax );
#endif
    NdisZeroMemory( pBufInfo->BufArray, sizeof( DMA_BUFFER ) *
        pBufInfo->cnAlloc );

    /* Set up each buffer. */
    pAllocVirtual = NULL;
    NdisSetPhysicalAddressHigh( AllocPhysicalAddr, 0 );
    NdisSetPhysicalAddressLow( AllocPhysicalAddr, 0 );
    NdisSetPhysicalAddressHigh( PhysicalAddr, 0 );
    ulAllocSize = pBufPool->ulAllocSize;

    pDma = pBufInfo->BufArray;
    for ( i = 0; i < pBufInfo->cnAlloc; i++ )
    {
        /* Big buffer allocated. */
        if ( pBufPool->pAllocVirtual )
        {
            /* Allocate each small buffer from big buffer. */
            pVirtual = pBufPool->pVirtual + nOffset;
            ulPhysical = pBufPool->ulPhysical + nOffset;
            NdisSetPhysicalAddressLow( PhysicalAddr, ulPhysical );
            nOffset += NDIS_BUFFER_SIZE;
        }
        else
        {
            ulAllocSize = NDIS_BUFFER_SIZE + BUFFER_ALIGNMENT;

            /* Allocate each small buffer from system. */
            NdisMAllocateSharedMemory( pAdapter->m_hAdapter,
                ulAllocSize,
                TRUE,
                &pAllocVirtual,
                &AllocPhysicalAddr );
            if ( pAllocVirtual == NULL )
            {
                return NDIS_STATUS_RESOURCES;
            }
            else if ( NdisGetPhysicalAddressHigh( AllocPhysicalAddr ) != 0 )
            {
                NdisMFreeSharedMemory( pAdapter->m_hAdapter,
                    ulAllocSize,
                    TRUE,
                    pAllocVirtual,
                    AllocPhysicalAddr );
                return NDIS_STATUS_RESOURCES;
            }

            NdisZeroMemory( pAllocVirtual, ulAllocSize );
            nOffset = ((( ULONG ) pAllocVirtual % BUFFER_ALIGNMENT ) ?
                ( BUFFER_ALIGNMENT -
                (( ULONG ) pAllocVirtual % BUFFER_ALIGNMENT )) : 0 );
            pVirtual = pAllocVirtual + nOffset;
            ulPhysical = NdisGetPhysicalAddressLow( AllocPhysicalAddr ) +
                nOffset;
            NdisSetPhysicalAddressLow( PhysicalAddr, ulPhysical );
        }

        /* Save the allocated memory information. */
        pDma->sm.ulAllocSize = ulAllocSize;
        pDma->sm.pAllocVirtual = pAllocVirtual;
        pDma->sm.AllocPhysicalAddr = AllocPhysicalAddr;

        /* These addresses point to the data buffer. */
        pDma->sm.pVirtual = pVirtual;
        pDma->sm.ulPhysical = ulPhysical;
        pDma->PhysicalAddr = PhysicalAddr;
        pDma->ulSize = NDIS_BUFFER_SIZE;

        /* Allocate an NDIS flush buffer for each buffer. */
        NdisAllocateBuffer(
            &NdisStatus,
            &pDma->pNdisBuffer,
            pAdapter->m_hBufferPool,
            pDma->sm.pVirtual,
            pDma->ulSize );
        if ( NdisStatus != NDIS_STATUS_SUCCESS )
        {
            pDma->pNdisBuffer = NULL;
            return NDIS_STATUS_RESOURCES;
        }

        if ( fPacket )
        {
            /* Allocate a packet for each receive buffer. */
            NdisAllocatePacket(
                &NdisStatus,
                &pDma->pNdisPacket,
                pAdapter->m_hPacketPool );
            if ( NdisStatus != NDIS_STATUS_SUCCESS )
            {
                pDma->pNdisPacket = NULL;
                return NDIS_STATUS_RESOURCES;
            }

            /* Set the header size in the packet's Out-Of-Band information. */
            /* All other fields in the Out-Of-Band information have been    */
            /* initialized to 0 by NdisAllocatePacket().                    */
            NDIS_SET_PACKET_HEADER_SIZE(( pDma->pNdisPacket ),
                ETHERNET_HEADER_SIZE );

            /* Chain the buffer on the packet. */
            NdisChainBufferAtFront( pDma->pNdisPacket, pDma->pNdisBuffer );

            /* Save a pointer to the receive buffer with the packet. */
            RESERVED( pDma->pNdisPacket )->pDma = pDma;
        }
        pDma++;
    }
    NdisAllocateSpinLock( &pBufInfo->listLock );

#ifndef UNDER_CE
    NdisInitializeSListHead( &pBufInfo->listHead );
#endif
    InitBuffers( pBufInfo );

    return NDIS_STATUS_SUCCESS;
}  /* AllocateBuffers */


#ifndef INLINE
/*
    Alloc_DMA_Buffer

    Description:
        This function allocates a DMA buffer information block for either
        transmitting or receiving.

    Parameters:
        PBUFFER_INFO pBufInfo
            Pointer to DMA buffer information structure.

        PTDesc pCurrent
            Pointer to current descriptor.

    Return (PDMA_BUFFER):
        Pointer to the DMA buffer information block if successful; NULL
        otherwise.
*/

PDMA_BUFFER Alloc_DMA_Buffer (
    PBUFFER_INFO pBufInfo,
    PTDesc       pCurrent )
{
    PDMA_BUFFER        pDma;

#ifndef UNDER_CE
    PSINGLE_LIST_ENTRY pEntry;

    pEntry = NdisInterlockedPopEntrySList( &pBufInfo->listHead,
        &pBufInfo->listLock );
    ASSERT( pEntry != NULL );
    pDma = CONTAINING_RECORD( pEntry, DMA_BUFFER, listEntry );

#else
    ASSERT( pBufInfo->cnAvail );
    pDma = pBufInfo->pTop;
    pBufInfo->pTop = pDma->pNext;
    pBufInfo->cnAvail--;
#endif

    /* Link to current descriptor. */
    pCurrent->pReserved = pDma;
    return( pDma );
}  // Alloc_DMA_Buffer


/*
    Free_DMA_Buffer

    Description:
        This routine frees the DMA buffer information block.

    Parameters:
        PBUFFER_INFO pBufInfo
            Pointer to DMA buffer information structure.

        PDMA_BUFFER pDma
            Pointer to DMA buffer information block.

    Return (None):
*/

VOID Free_DMA_Buffer (
    PBUFFER_INFO pBufInfo,
    PDMA_BUFFER  pDma )
{
#ifndef UNDER_CE
    NdisInterlockedPushEntrySList( &pBufInfo->listHead, &pDma->listEntry,
        &pBufInfo->listLock );

#else
    pDma->pNext = pBufInfo->pTop;
    pBufInfo->pTop = pDma;
    pBufInfo->cnAvail++;
#endif
}  // Free_DMA_Buffer
#endif


/*
    InitReceiveBuffers

    Description:
        This routine initializes DMA buffers for receiving.

    Parameters:
        PNDIS_ADAPTER pAdapter
            Pointer to adapter information structure.

    Return (None):
*/

void InitReceiveBuffers (
        PNDIS_ADAPTER pAdapter )
{
    int         i;
    PTDesc      pDesc;
    PDMA_BUFFER pDma;
    PHARDWARE   pHardware = &pAdapter->m_Hardware;
    PTDescInfo  pInfo = &pHardware->m_RxDescInfo;

    for ( i = 0; i < pHardware->m_RxDescInfo.cnAlloc; i++ )
    {
        GetRxPacket( pInfo, pDesc );

        /* Get a new buffer for this descriptor. */
        pDma = Alloc_DMA_Buffer( &pAdapter->m_RxBufInfo, pDesc );

        /* Set descriptor. */
        SetReceiveBuffer( pDesc, pDma->sm.ulPhysical );
        SetReceiveLength( pDesc, pDma->ulSize );
        ReleasePacket( pDesc );
    }
}  /* InitReceiveBuffers */


/*
    AllocateMemory

    Description:
        This function allocates memory for use by hardware descriptors for
        receiving and transmitting.

    Parameters:
        PNDIS_ADAPTER pAdapter
            Pointer to adapter information structure.

    Return (NDIS_STATUS):
        NDIS_STATUS_SUCCESS if successful; otherwise an error code indicating
        failure.
*/

NDIS_STATUS AllocateMemory (
        PNDIS_ADAPTER pAdapter )
{
    PHARDWARE   pHardware = &pAdapter->m_Hardware;
    NDIS_STATUS NdisStatus;

    /* Determine the number of receive and transmit descriptors. */

    /* Determine the descriptor size. */
    pHardware->m_RxDescInfo.nSize =
        ((( sizeof( THw_Desc ) + DESC_ALIGNMENT - 1 ) / DESC_ALIGNMENT ) *
        DESC_ALIGNMENT );
    pHardware->m_TxDescInfo.nSize =
        ((( sizeof( THw_Desc ) + DESC_ALIGNMENT - 1 ) / DESC_ALIGNMENT ) *
        DESC_ALIGNMENT );

    if ( pHardware->m_RxDescInfo.nSize != sizeof( THw_Desc ) )
    {
        DBG_PRINT( "Hardware descriptor size not right!"NEWLINE );
    }
    CheckDescriptorNum( &pHardware->m_RxDescInfo );
    CheckDescriptorNum( &pHardware->m_TxDescInfo );

    /* TX/RX buffers we need. */
#if 1
    /* More receive buffers so that they can be used by upper layer and
       returned later in the MiniportReturnPacket call.
    */
    pAdapter->m_RxBufInfo.cnAlloc = pHardware->m_RxDescInfo.cnAlloc << 1;
#else
    pAdapter->m_RxBufInfo.cnAlloc = pHardware->m_RxDescInfo.cnAlloc;
#endif
    pAdapter->m_TxBufInfo.cnAlloc = pHardware->m_TxDescInfo.cnAlloc;

    /* Allocate map registers. */
    NdisStatus = AllocateMapRegisters( pAdapter );
    if ( NdisStatus != NDIS_STATUS_SUCCESS )
    {
        return NdisStatus;
    }

    /* Allocate descriptors */
    NdisStatus = AllocateDescriptors( pAdapter );
    if ( NdisStatus != NDIS_STATUS_SUCCESS )
    {
        return NdisStatus;
    }

    /* Allocate a pool of NDIS buffers. */
    NdisAllocateBufferPool(
        &NdisStatus,
        &pAdapter->m_hBufferPool,
        pAdapter->m_RxBufInfo.cnAlloc + pAdapter->m_TxBufInfo.cnAlloc );
    if ( NdisStatus != NDIS_STATUS_SUCCESS )
    {
        return NdisStatus;
    }

    /* Allocate a pool of packets. */
    NdisAllocatePacketPool(
        &NdisStatus,
        &pAdapter->m_hPacketPool,
        pAdapter->m_RxBufInfo.cnAlloc,
        0 );
    if ( NdisStatus != NDIS_STATUS_SUCCESS )
    {
        return NdisStatus;
    }

    /* Allocate receive buffers. */
    NdisStatus = AllocateBuffers( pAdapter, &pAdapter->m_RxBufInfo, TRUE );
    if ( NdisStatus != NDIS_STATUS_SUCCESS )
    {
        return NdisStatus;
    }

    /* Allocate transmit buffers. */
    NdisStatus = AllocateBuffers( pAdapter, &pAdapter->m_TxBufInfo, FALSE );
    if ( NdisStatus != NDIS_STATUS_SUCCESS )
    {
        return NdisStatus;
    }

    InitReceiveBuffers( pAdapter );

#ifdef DBG_

⌨️ 快捷键说明

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