📄 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<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 + -