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

📄 receive.c

📁 PXA255/270平台的 CS8900网卡驱动程序
💻 C
字号:
//---------------------------------------------------------------------------
//
//  Copyright (C) 1996-1997. Unpublished Work of Crystal Semiconductor Corp.
//  All Rights Reserved.
//
//  THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
//  PROPRIETARY AND TRADE SECRET INFORMATION OF CRYSTAL SEMICONDUCTOR.
//  ACCESS TO THIS WORK IS RESTRICTED TO (I) CRYSTAL SEMICONDUCTOR EMPLOYEES
//  WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR
//  ASSIGNMENTS  AND (II) ENTITIES OTHER THAN CRYSTAL SEMICONDUCTOR WHO
//  HAVE ENTERED INTO  APPROPRIATE LICENSE AGREEMENTS.  NO PART OF THIS
//  WORK MAY BE USED, PRACTICED, PERFORMED, COPIED, DISTRIBUTED, REVISED,
//  MODIFIED, TRANSLATED, ABRIDGED, CONDENSED, EXPANDED, COLLECTED,
//  COMPILED,LINKED,RECAST, TRANSFORMED, ADAPTED IN ANY FORM OR BY ANY
//  MEANS,MANUAL, MECHANICAL, CHEMICAL, ELECTRICAL, ELECTRONIC, OPTICAL,
//  BIOLOGICAL, OR OTHERWISE WITHOUT THE PRIOR WRITTEN PERMISSION AND
//  CONSENT OF CRYSTAL SEMICONDUCTOR . ANY USE OR EXPLOITATION OF THIS WORK
//  WITHOUT THE PRIOR WRITTEN CONSENT OF CRYSTAL SEMICONDUCTOR  COULD
//  SUBJECT THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
//
//---------------------------------------------------------------------------

#include "cs8900a.h"
#include "cshrd.h"

#define COPYCRC 1


void VpsRecvError( PCHIP pChip, WORD Errors );


void CopyFromChip(PCHIP pChip, WORD Offset, WORD Count )
{
    PCD   pData = pChip->pData;
    PBYTE target;
    WORD i;

    PRINTDEBUGMSG(1, (TEXT("==>CS8900:CopyFromChip \r\n")));
    if(Offset + Count > CRYSTAL_INDICATE_MAXIMUM+4)
        RETAILMSG(1, (TEXT("offset = %d Count = %d is too large\r\n"), Offset, Count));

    target = pData->RxFlatBuff + Offset;
    if((DWORD)target & 0x01)
        RETAILMSG(1, (TEXT("Poniter = 0x%x is not aligned\r\n"), target));

    for (i=0; i<(Count/2); i++) 
    {
	    /* ARM can read/write only 16 bit data at a time under WinCE. 
	       NdisRawWritePortUlong() does NOT work for ARM.*/
	    *(WORD *)target = v_pCS8900Regs->DATA0;
        target += 2;
    } /* endfor */

    PRINTDEBUGMSG(1, (TEXT("<==CS8900:CopyFromChip \r\n")));
}

void ReceivePacket( PCHIP pChip, WORD IsqEvent )
{
    PCD   pData = pChip->pData;
    WORD  PacketSize;
    VPM_SetupMiniContextFromPchip

    PRINTDEBUGMSG(1, (TEXT("==>CS8900:ReceivePacket \r\n")));
    PacketSize = v_pCS8900Regs->DATA0;      // Discard RxStatus
    PacketSize = v_pCS8900Regs->DATA0;
    // Copy the data out of chip RAM into host memory
    CopyFromChip(pChip, 0, PacketSize);

#ifdef COPYCRC
    PacketSize -= 4;                            // remove CRC bytes
#endif

    pvMini_Context->RcvOKs++;
    pData->RxPacketSize=PacketSize;

    #if 0
    {
    int i;
    RETAILMSG(1, (TEXT("Recv length = %d: "), PacketSize));
    for(i = 0; i < PacketSize; i++)
        RETAILMSG(1, (TEXT("%02x-"), pData->RxFlatBuff[i]));
    RETAILMSG(1, (TEXT("\r\n")));
    }
    #endif

    NdisMEthIndicateReceive(MiniportAdapterHandle,
                            (NDIS_HANDLE)pData,  
                            pData->RxFlatBuff,
                            VP_HEADERSIZE,
                            pData->RxFlatBuff +VP_HEADERSIZE,
                            PacketSize-VP_HEADERSIZE,
                            PacketSize-VP_HEADERSIZE);

    pData->NeedToIssueRcvCmpltFlag = TRUE;
    PRINTDEBUGMSG(1, (TEXT("<==CS8900:ReceivePacket \r\n")));
};

void ReceiveEarlyPacket( PCHIP pChip, WORD IsqEvent )
{
    PCD   pData = pChip->pData;
    WORD  BytesCopied = 0;
    WORD  ByteCount = 0;
    WORD  LastByteCount = 0;
    WORD  LoopCount = 0;
    WORD  Remainder = 0;
    WORD  CopyCount = 0;
    WORD  LastDifference = 0;
    WORD  RxEvent;
    WORD  ResidualDifCount = 0;
    WORD  Errors = 0;
    VPM_SetupMiniContextFromPchip

    PRINTDEBUGMSG(1, (TEXT("==>CS8900:ReceiveEarlyPacket\r\n")));   
    BytesCopied = 0;

    while (1 == 1) 
    {
        //
        // Read the Byte Count for the frame
        //
        ByteCount = ReadPacketPage(CRYSTAL_FRAME_BYTE_COUNT);

        // if Byte Count is zero, we already reached the end of the frame
        // so get out of the loop.
        if (ByteCount == 0) 
            break;

        if ((ByteCount < BytesCopied) ||
#ifdef COPYCRC
           (ByteCount > CRYSTAL_INDICATE_MAXIMUM+4) ||
#else
           (ByteCount > CRYSTAL_INDICATE_MAXIMUM) ||
#endif
           (LoopCount > 64)) 
        {
            BytesCopied = 0;
            break;
        }

        if (LastByteCount == ByteCount) 
            LoopCount++;
        else 
        {
            LoopCount=0;
            LastByteCount = ByteCount;

            // Copy the bytes to the local receive buffer.  Only
            // copy a multiple of 4 bytes.
            Remainder = (ByteCount - BytesCopied) % 4;
            CopyCount = (ByteCount - BytesCopied) - Remainder;

#ifndef COPYCRC
            if (CopyCount > 4) 
            {
                CopyCount -= 4;

#endif

                if (ByteCount >= 32)  
                {
                    CopyFromChip(pChip, BytesCopied, CopyCount);

                    // Increase bytes copied count
                    BytesCopied += CopyCount;

#ifndef COPYCRC
                }
#endif

            }
        } /* endif */
    }

    if (BytesCopied != 0) 
    {
        // Read RxEvent, if everything okay then proceed with indicating the
        // frame to the protocol

        RxEvent = ReadPacketPage(CRYSTAL_RX_EVENT_REGISTER);

        if (RxEvent & CRYSTAL_RER_PACKET_RECEIVED_OK) 
        {
            // Skip Frame Status and read Size
            ByteCount = v_pCS8900Regs->DATA0;
            ByteCount = v_pCS8900Regs->DATA0;

#ifdef COPYCRC
            if (ByteCount != (BytesCopied+Remainder)) 
            { // If Receive Length bigger than data found in Byte Count loop
                LastDifference = ByteCount - (BytesCopied+Remainder);

#else
            if ((ByteCount-4) != (BytesCopied+Remainder)) 
            { // If Receive Length adjusted for CRC bigger than data found in Byte Count loop
                LastDifference = (ByteCount-4) - (BytesCopied+Remainder);
#endif

                if ((BytesCopied+Remainder+LastDifference) > CRYSTAL_INDICATE_MAXIMUM) 
                {
                    Remainder = 0;
                    BytesCopied = 0;
                } 
                else 
                {
                    Remainder += LastDifference;
                    ResidualDifCount++;
                } /* endif */
            } /* endif */

            // get the remainder of the bytes

            if (Remainder) 
            {
                CopyFromChip(pChip, BytesCopied, Remainder);
                BytesCopied += Remainder;
            }

            if (BytesCopied) 
            {
#ifdef COPYCRC
                BytesCopied -= 4;                            // remove CRC bytes
#endif
                //
                // Do a skip command to free up the receive buffer on the chip
                //
                WritePacketPage(CRYSTAL_RX_CONFIG_REGISTER, 
                                pData->CurrentReceiveConfiguration | CRYSTAL_RCR_SKIP_1);
 		        pvMini_Context->RcvOKs++;

                pData->RxPacketSize=BytesCopied;
 
 		        NdisMEthIndicateReceive(MiniportAdapterHandle,
                                        (NDIS_HANDLE)pData,  
                                        pData->RxFlatBuff,
                                        VP_HEADERSIZE,
                                        pData->RxFlatBuff +VP_HEADERSIZE,
                                        BytesCopied-VP_HEADERSIZE,
                                        BytesCopied-VP_HEADERSIZE);

 		        //pData->NeedToIssueRcvCmpltFlag = TRUE;
                NdisMEthIndicateReceiveComplete( MiniportAdapterHandle );

            } /* endif */
        }
        else 
        {
            //
            // A receive error occurred
            //
            if (RxEvent & CRYSTAL_RER_CRC_ERROR) 
            {
                Errors |= RX_ERR_CRC_ERROR;

                if(RxEvent & CRYSTAL_RER_DRIBBLE) 
                    Errors |= RX_ERR_DRIBBLE;
            }

            if (RxEvent & CRYSTAL_RER_EXTRA_DATA) 
                Errors |= RX_ERR_EXTRA_DATA;
            if (RxEvent & CRYSTAL_RER_RUNT) 
                Errors |= RX_ERR_RUNT;
            VpsRecvError( pChip, Errors );
        } // endif
    }
    PRINTDEBUGMSG(1, (TEXT("<==CS8900:ReceiveEarlyPacket\r\n")));   
}

void VpsRecvError( PCHIP pChip, WORD Errors )
{
    VPM_SetupMiniContextFromPchip

    PRINTDEBUGMSG(1, (TEXT("==>CS8900:VpsRecvError\r\n")));   
    // Keep track of OKs, Errors and confirm packet if necessary
    pvMini_Context->RcvErrors++;
    if (Errors & RX_ERR_CRC_ERROR)
        pvMini_Context->RcvCRCErrors++;

    if (Errors & RX_ERR_FRAMING)
        pvMini_Context->RcvErrorAlignments++;

    if (Errors & RX_ERR_OVERRUN)
        pvMini_Context->RcvOverrun++;

    if (Errors & RX_ERR_NO_BUFFER)
        pvMini_Context->RcvNoBuffers++;
    PRINTDEBUGMSG(1, (TEXT("<==CS8900:VpsRecvError\r\n")));   
};

/*++
Routine Description:
    A protocol calls the CrystalTransferData request (indirectly via
    NdisTransferData) from within its Receive event handler
    to instruct the driver to copy the contents of the received packet
    a specified paqcket buffer.

Arguments:
    MiniportAdapterContext - Context registered with the wrapper, really
        a pointer to the VP context.
    MiniportReceiveContext - The context value passed by the driver on its call
    to NdisMEthIndicateReceive.  The driver can use this value to determine
    which packet, on which adapter, is being received.
    ByteOffset - An unsigned integer specifying the offset within the
    received packet at which the copy is to begin.  If the entire packet
    is to be copied, ByteOffset must be zero.
    BytesToTransfer - An unsigned integer specifying the number of bytes
    to copy.  It is legal to transfer zero bytes; this has no effect.  If
    the sum of ByteOffset and BytesToTransfer is greater than the size
    of the received packet, then the remainder of the packet (starting from
    ByteOffset) is transferred, and the trailing portion of the receive
    buffer is not modified.
    Packet - A pointer to a descriptor for the packet storage into which
    the MAC is to copy the received packet.
    BytesTransfered - A pointer to an unsigned integer.  The MAC writes
    the actual number of bytes transferred into this location.  This value
    is not valid if the return status is STATUS_PENDING.

Return Value:
    The function value is the status of the operation.

--*/
extern NDIS_STATUS CrystalTransferData(OUT PNDIS_PACKET  Packet,
                                       OUT PUINT  BytesTransferred,
                                       IN NDIS_HANDLE  MiniportAdapterHandle,
                                       IN NDIS_HANDLE  MacReceiveContext,
                                       IN UINT  ByteOffset,
                                       IN UINT  BytesToTransfer)
{
    UINT   ProtocolBufferCount;
    PNDIS_BUFFER  pProtocolBuffer;
    UINT   ProtocolTotalBufferLength;
    PUCHAR pProtocolVBuffer;
    ULONG  ProtocolVBufferLength;
    PUCHAR pSource;
    ULONG   CurrentSize;
    UINT   BytesLeftToCopy;
    ULONG  PacketSize;
    PCD   pData;

    PRINTDEBUGMSG(1, (TEXT("==>CS8900:CrystalTransferData\r\n")));   

	ByteOffset += VP_HEADERSIZE;
  
    pData = (PCD) MacReceiveContext;
    pSource         = pData->RxFlatBuff+ByteOffset;
    PacketSize      = pData->RxPacketSize;

    if ((BytesToTransfer==0) || ByteOffset >= PacketSize ) 
    {
		*BytesTransferred = 0;
        PRINTDEBUGMSG(1, (TEXT("==>CS8900:CrystalTransferData 111\r\n")));   
        return NDIS_STATUS_SUCCESS;
    } /* endif */												

    NdisQueryPacket( Packet,
                     NULL,
                     &ProtocolBufferCount,
                     &pProtocolBuffer,
                     &ProtocolTotalBufferLength);

    NdisQueryBuffer(pProtocolBuffer,
                    &pProtocolVBuffer,
                    &ProtocolVBufferLength);

    *BytesTransferred = 0;
    BytesLeftToCopy   = BytesToTransfer;
   
    while((*BytesTransferred < BytesToTransfer) && (ByteOffset<PacketSize)) 
    {
        if (ProtocolVBufferLength == 0) 
        {
            NdisGetNextBuffer(pProtocolBuffer, &pProtocolBuffer);
            NdisQueryBuffer(pProtocolBuffer, &pProtocolVBuffer, &ProtocolVBufferLength);
        } /* endif */

        CurrentSize = BytesLeftToCopy;
        if ( ProtocolVBufferLength < CurrentSize) 
        {
            CurrentSize = ProtocolVBufferLength;
		    ProtocolVBufferLength = 0;
            BytesLeftToCopy       -=CurrentSize;
	    } 
        else 
        {
            ProtocolVBufferLength -=CurrentSize;
            BytesLeftToCopy       = 0;
        } /* endif */

        NdisMoveMemory(  pProtocolVBuffer, pSource, CurrentSize );
      
        pProtocolVBuffer     += CurrentSize;
        pSource              += CurrentSize;
        ByteOffset           += CurrentSize;
        
        *BytesTransferred     +=CurrentSize;
    } /* endwhile */

    // Find proper fragment to start from based on bytes to copy
    // Copy from starting offset to either bytes to copy or fragment length
    // etc...
    // Update BytesTransferred along the way

    PRINTDEBUGMSG(1, (TEXT("<==CS8900:CrystalTransferData\r\n")));   
    return NDIS_STATUS_SUCCESS;
}

⌨️ 快捷键说明

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