📄 cs8900a.c
字号:
//------------------------------------------------------------------------------
//
// Function: Cs8900aSend
//
// This function handles transmission of packet through adapter into the medium.
//
// Parameters:
// MiniportAdapterContext
// [in] pointer to adapter.
//
// Packet
// [in] pointer to a descriptor for the packet that is to be transmitted.
//
// SendFlags
// [in] optional send flags.
//
// Returns:
// Returns NDIS_STATUS_PENDING if success.
// Returns NDIS_STATUS_FAILURE if bad frame encountered.
//
//------------------------------------------------------------------------------
NDIS_STATUS Cs8900aSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT SendFlags
)
{
UINT PacketLength;
pCs8900_t pEthernet = ((pCs8900_t)(MiniportAdapterContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +Cs8900aSend\r\n")));
NdisQueryPacket( Packet,NULL,NULL,NULL,&PacketLength);
if ( (PacketLength > ETH_MAX_PACKET) ||(PacketLength < ETH_MIN_FRAME))
{
pEthernet->FramesXmitBad++;
return NDIS_STATUS_FAILURE;
}
// Put the packet on the send queue.
EnterCriticalSection (&gCS8900BufCs);
if (pEthernet->HeadPacket == NULL)
{
pEthernet->HeadPacket = Packet;
}
else
{
RESERVED(pEthernet->TailPacket)->Next = Packet;
}
RESERVED(Packet)->Next = NULL;
pEthernet->TailPacket = Packet;
LeaveCriticalSection (&gCS8900BufCs);
// check whether is there transmission going on
if (!(pEthernet->TransmitInProgress))
{
pEthernet->TransmitInProgress = TRUE;
// check whether is the chip ready for transmission
if ( CheckReadyForTransmit(pEthernet) == TRUE )
{
TransferPacketToChip(pEthernet);
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -Cs8900aSend\r\n")));
return NDIS_STATUS_PENDING;
}
//------------------------------------------------------------------------------
//
// Function: Cs8900aTransferData
//
// A protocol calls the Cs8900aTransferData request (indirectly via NdisTransferData)
// from within its Receive event handler to instruct the driver to copy the
// contents of the received packet.
//
// Parameters:
// Packet
// [out] A pointer to a descriptor for the packet storage into which
// the MAC is to copy the received packet.
//
// BytesTransferred
// [out] 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.
//
// MiniportAdapterContext
// [in] Context registered with the wrapper, a pointer to adapter.
//
// MiniportReceiveContext
// [in] 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
// [in] 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.
//
// BytesTransfered
// [in] 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.
//
// Returns:
// Returns NDIS_STATUS_SUCCESS if success.
// Return NDIS_STATUS_FAILURE if not.
//
//------------------------------------------------------------------------------
NDIS_STATUS
Cs8900aTransferData(
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer
)
{
PNDIS_BUFFER pCurrentBuffer;
UINT BufferLength;
PUCHAR pBufferSource;
PUCHAR pBufferStart;
UINT BytesWanted, BytesCopied, BytesLeft;
ULONG PacketSize;
// The adapter to transfer from.
pCs8900_t pEthernet = ((pCs8900_t)(MiniportReceiveContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +Cs8900aTransferData\r\n")));
// Add the packet header onto the offset.
ByteOffset += ETHER_HDR_SIZE;
pBufferSource = pEthernet->ReceiveBuffer+ByteOffset;
PacketSize = pEthernet->ReceivePacketSize;
if ((BytesToTransfer==0) || ByteOffset >= PacketSize )
{
*BytesTransferred = 0;
return NDIS_STATUS_FAILURE;
}
NdisQueryPacket( Packet, NULL, NULL, &pCurrentBuffer, NULL);
NdisQueryBuffer( pCurrentBuffer, &pBufferStart, &BufferLength);
*BytesTransferred = 0;
BytesWanted = 0;
BytesCopied = 0;
BytesLeft=BytesToTransfer;
do{
if(!BufferLength)
{
NdisGetNextBuffer(pCurrentBuffer, &pCurrentBuffer);
NdisQueryBuffer( pCurrentBuffer, &pBufferStart, &BufferLength);
}
if(BufferLength>BytesLeft) // PacketSize == ByteToTransfer
{
BytesCopied +=BytesLeft;
BytesWanted = BytesLeft;
}
else
{
BytesCopied += BufferLength;
BytesWanted = BufferLength;
BufferLength = 0;
}
NdisMoveMemory( pBufferStart, pBufferSource, BytesWanted );
pBufferStart += BytesWanted;
pBufferSource += BytesWanted;
BytesLeft -= BytesWanted;
}while(BytesCopied<BytesToTransfer);
*BytesTransferred=BytesCopied;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -Cs8900aTransferData\r\n")));
return NDIS_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: Cs8900aSetInformation
//
// This function handles a set operation for a single OID.
//
// Parameters:
// MiniportAdapterContext
// [in] pointer to adapter.
//
// Oid
// [out] The OID of the set.
//
// InformationBuffer
// [in] Holds the data to be set.
//
// InformationBufferLength
// [in] Length of InformationBuffer.
//
// BytesRead
// [out] If the call is successful, returns the number of bytes read
// from InformationBuffer.
//
// BytesNeeded
// [out] If there is not enough data in InformationBuffer to satisfy the OID,
// returns the amount of storage needed.
//
// Returns:
// Returns NDIS_STATUS_SUCCESS if success.
// Return NDIS_STATUS_INVALID_LENGTH or NDIS_STATUS_INVALID_OID or
// NDIS_STATUS_MULTICAST_FULL or NDIS_STATUS_NOT_SUPPORTED if not.
//
//------------------------------------------------------------------------------
NDIS_STATUS
Cs8900aSetInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
{
UINT BytesLeft = InformationBufferLength;
PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
// Variables for a particular request
UINT OidLength;
// Variables for holding the new values to be used.
ULONG LookAhead;
ULONG Filter;
// Status of the operation.
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
pCs8900_t pEthernet = ((pCs8900_t)(MiniportAdapterContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +Cs8900aSetInformation\r\n")));
// Get Oid and Length of request
OidLength = BytesLeft;
switch (Oid)
{
case OID_802_3_MULTICAST_LIST:
// Verify length
if ((OidLength % ETHER_ADDR_SIZE) != 0)
{
StatusToReturn = NDIS_STATUS_INVALID_DATA;
*BytesRead = 0;
*BytesNeeded = 0;
break;
}
else
{ // Ensure that the multi cast list is not full yet
if(OidLength <= (MCAST_LIST_SIZE * ETHER_ADDR_SIZE))
{
// Get the multicast address and update CS8900A
NdisMoveMemory(pEthernet->McastList, InfoBuffer, OidLength);
*BytesRead = OidLength;
pEthernet->NumMulticastAddressesInUse = OidLength / ETHER_ADDR_SIZE;
// clear all the value in Hash Table
ClearAllMultiCast(pEthernet);
// Add the hash table value according to the multicast address
for(LookAhead=0; LookAhead < pEthernet->NumMulticastAddressesInUse; LookAhead++)
{
AddMultiCast(pEthernet, &(pEthernet->McastList[LookAhead][0]));
}
}
else
{
*BytesRead = 0;
StatusToReturn = NDIS_STATUS_MULTICAST_FULL;
}
}
break;
case OID_GEN_CURRENT_PACKET_FILTER:
// Verify length
if (OidLength != 4 )
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*BytesRead = 0;
*BytesNeeded = 0;
break;
}
NdisMoveMemory((PUCHAR)&Filter, (PUCHAR)InfoBuffer, 4);
// Verify bits
if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
NDIS_PACKET_TYPE_SMT |
NDIS_PACKET_TYPE_MAC_FRAME |
NDIS_PACKET_TYPE_FUNCTIONAL |
NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
NDIS_PACKET_TYPE_GROUP |
NDIS_PACKET_TYPE_ALL_MULTICAST | // Fails Cert test
NDIS_PACKET_TYPE_ALL_LOCAL // No Loopback!
))
{
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
*BytesRead = 4;
*BytesNeeded = 0;
}
else
{
// Set the new value on the adapter.
pEthernet->PacketFilter = Filter;
if(Filter & NDIS_PACKET_TYPE_MULTICAST )
{
// clear all the value in Hash Table
ClearAllMultiCast(pEthernet);
// Add the hash table value according to the multicast address
for(LookAhead=0; LookAhead < pEthernet->NumMulticastAddressesInUse; LookAhead++)
{
AddMultiCast(pEthernet, &(pEthernet->McastList[LookAhead][0]));
}
}
SetFilterType(pEthernet);
StatusToReturn = NDIS_STATUS_SUCCESS;
}
break;
case OID_GEN_CURRENT_LOOKAHEAD:
// Verify length
if (OidLength != 4)
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*BytesRead = 0;
*BytesNeeded = 0;
break;
}
// Store the new value.
NdisMoveMemory(&LookAhead, InfoBuffer, 4);
if (LookAhead <= (ETH_MAX_PACKET -ETHER_HDR_SIZE) )
{
pEthernet->CurrentLookAhead= LookAhead;
}
else
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
}
break;
case OID_GEN_PROTOCOL_OPTIONS:
break;
default:
*BytesRead = 0;
*BytesNeeded = 0;
return NDIS_STATUS_INVALID_OID;
break;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -Cs8900aSetInformation [0x%.8X]\r\n"), StatusToReturn));
return(StatusToReturn);
}
//------------------------------------------------------------------------------
//
// Function: Cs8900aShutdown
//
// This function handles proper shutdown.
//
// Parameters:
// MiniportAdapterContext
// [in] pointer to adapter.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void Cs8900aShutdown(IN NDIS_HANDLE MiniportAdapterContext)
{
pCs8900_t pEthernet = ((pCs8900_t)(MiniportAdapterContext));
//MiniportShutdown should call no NdisXXX functions.
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +Cs8900aShutdown\r\n")));
pEthernet->CurrentState = NdisHardwareStatusNotReady;
DeleteCriticalSection (&gCS8900RegCs);
DeleteCriticalSection (&gCS8900BufCs);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -Cs8900aShutdown\r\n")));
return;
}
//------------------------------------------------------------------------------
//
// Function: Cs8900aCheckForHang
//
// This function checks for media connection status.
//
// Parameters:
// MiniportAdapterContext
// [in] pointer to adapter.
//
// Returns:
// return TRUE if it detects that the network adapter is not operating correctly.
// return FALSE if the asapter is operating correctly.
//
//------------------------------------------------------------------------------
BOOLEAN Cs8900aCheckForHang(IN NDIS_HANDLE MiniportAdapterContext)
{
pCs8900_t pEthernet = ((pCs8900_t)(MiniportAdapterContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +Cs8900aCheckForHang\r\n")));
pEthernet->MediaState = UpdateMediaConnectStatus(pEthernet, pEthernet->MediaState);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -Cs8900aCheckForHang\r\n")));
return(FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -