www.pudn.com > 2410winceCE_l80t64.rar > Receive.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