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

📄 receive.c

📁 CS8900 for windows ce 4.2 驱动程序源码
💻 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 )
{
   PORT  IOBase = pChip->Config.IOBase;
   PCD   pData = pChip->pData;
   PBYTE target;
   WORD i;
   WORD  StartOffset;


   target = pData->RxFlatBuff + Offset;

   // Set the packet page pointer.  The StartOffset
   // is increased by 4 to account for the status and length words
   // prefixing the frame in the CS8900A packet page RAM.
   // Also, we force the auto-increment bit on.

   StartOffset = CRYSTAL_RECEIVE_FRAME_PTR + Offset;
   StartOffset |= CRYSTAL_ENABLE_AUTO_INCREMENT;

   

   NdisRawWritePortUshort(
      (PORT)(IOBase+CRYSTAL_ADDRESS_PORT),
      StartOffset
      );

   for (i=0; i<(Count/4); i++) {
#ifdef ARM_PROCESSOR
	  /* ARM can read/write only 16 bit data at a time under WinCE. 
	     NdisRawWritePortUlong() does NOT work for ARM.*/
	   NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_DATA_PORT), ((PWORD)target)++ );
	   NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_DATA_PORT), ((PWORD)target)++ );
#else
	   NdisRawReadPortUlong( (PORT)(IOBase+CRYSTAL_DATA_PORT), ((PDWORD)target)++ );
#endif
   } /* endfor */


   switch (Count % 4) {
      case 3:
         NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_DATA_PORT), ((PWORD)target)++ );
         // NOTE: This case falls through to the next case on purpose!!

      case 2:
      case 1:
         NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_DATA_PORT), ((PWORD)target) );
   }  // end switch

}

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



   NdisRawWritePortUshort(
      (PORT)(IOBase+CRYSTAL_ADDRESS_PORT),
      CRYSTAL_RECEIVE_LENGTH
      );

   NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_DATA_PORT), &PacketSize );




      // 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;


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

   pData->NeedToIssueRcvCmpltFlag = TRUE;


};

void ReceiveEarlyPacket( PCHIP pChip, WORD IsqEvent )
{
   PORT  IOBase = pChip->Config.IOBase;
   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


   BytesCopied = 0;

   while (1 == 1) {

      //
      // Read the Byte Count for the frame
      //

      NdisRawWritePortUshort(
         (PORT)(IOBase+CRYSTAL_ADDRESS_PORT),
         CRYSTAL_FRAME_BYTE_COUNT
         );

      NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_DATA_PORT), &ByteCount );

      // 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


      NdisRawWritePortUshort(
         (PORT)(IOBase+CRYSTAL_ADDRESS_PORT),
         CRYSTAL_RX_EVENT_REGISTER
         );

      NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_DATA_PORT), &RxEvent );

      if (RxEvent & CRYSTAL_RER_PACKET_RECEIVED_OK) {

         // Skip Frame Status and read Size
         NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_RECEIVE_FRAME_PORT), &ByteCount );
         NdisRawReadPortUshort( (PORT)(IOBase+CRYSTAL_RECEIVE_FRAME_PORT), &ByteCount );

#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
            //
            NdisRawWritePortUshort(
               (PORT)(IOBase+CRYSTAL_ADDRESS_PORT),
               CRYSTAL_RX_CONFIG_REGISTER
               );

            NdisRawWritePortUshort(
               (PORT)(IOBase+CRYSTAL_DATA_PORT),
               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
   }

}


void VpsRecvError( PCHIP pChip, WORD Errors )
{
   VPM_SetupMiniContextFromPchip


   // 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++;
   }


};


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
    )

/*++

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.


--*/

{
   UINT   ProtocolBufferCount;
   PNDIS_BUFFER  pProtocolBuffer;
   UINT   ProtocolTotalBufferLength;
   PUCHAR pProtocolVBuffer;
   ULONG  ProtocolVBufferLength;
   PUCHAR pSource;
   ULONG   CurrentSize;
   UINT   BytesLeftToCopy;
   ULONG  PacketSize;
   PCD   pData;

//     DbgPrint("\nCs8900a(): TransferData()\n");

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


   if ((BytesToTransfer==0) || ByteOffset >= PacketSize ) {
		 *BytesTransferred = 0;
         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

   return NDIS_STATUS_SUCCESS;


}

⌨️ 快捷键说明

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