📄 chip.c
字号:
//
//------------------------------------------------------------------------------
void WriteMultiCastTable(pCs8900_t pEthernet, WORD *pHashTable)
{
WORD Counter;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +WriteMultiCastTable\r\n")));
for(Counter=0; Counter < 4; Counter++)
{
WriteCs8900Register(PKTPG_LOG_ADDR+Counter*2, *pHashTable);
pHashTable++;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -WriteMultiCastTable\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: SetAllMultiCastTable
//
// This function sets the Hash table.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void SetAllMultiCastTable(pCs8900_t pEthernet)
{
WORD HashTable[4] = {0xffff,0xffff,0xffff,0xffff};
WORD data;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +SetAllMultiCastTable\r\n")));
// Turn off the receiver
data = ReadCs8900Register(PKTPG_LINE_CTL);
data &= (~LCR_RX_ON);
WriteCs8900Register(PKTPG_LINE_CTL, data);
WriteMultiCastTable(pEthernet, HashTable);
// Turn on the receiver
data |= LCR_RX_ON;
WriteCs8900Register(PKTPG_LINE_CTL, data);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -SetAllMultiCastTable\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: ClearAllMultiCast
//
// This function clears the Hash table.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void ClearAllMultiCast(pCs8900_t pEthernet)
{
WORD HashTable[4] = {0, 0, 0, 0};
WORD data;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +ClearAllMultiCast\r\n")));
// Turn off the receiver
data = ReadCs8900Register(PKTPG_LINE_CTL);
data &= (~LCR_RX_ON);
WriteCs8900Register(PKTPG_LINE_CTL, data);
WriteMultiCastTable(pEthernet, HashTable);
// Turn on the receiver
data |= LCR_RX_ON;
WriteCs8900Register(PKTPG_LINE_CTL, data);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -ClearAllMultiCast\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: SetFilterType
//
// This function sets the filter type for CS8900 chip.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void SetFilterType(pCs8900_t pEthernet)
{
WORD LineData, FilterData;
ULONG Filter;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +SetFilterType\r\n")));
// Turn off the receiver
LineData = ReadCs8900Register(PKTPG_LINE_CTL);
LineData &= (~LCR_RX_ON);
WriteCs8900Register(PKTPG_LINE_CTL, LineData);
// Get the current filter settings from structure
FilterData = ReadCs8900Register(PKTPG_RX_CTL);
// Clear broadcast, multicast and promiscuous bits
FilterData &= ~(RX_CTL_MCAST_A | RX_CTL_IND_A|RX_CTL_BCAST_A|
RX_CTL_PROM_A);
Filter = pEthernet->PacketFilter;
if(Filter & NDIS_PACKET_TYPE_DIRECTED)
{
FilterData |= RX_CTL_IND_A;
}
if(Filter & NDIS_PACKET_TYPE_BROADCAST)
{
FilterData |= RX_CTL_BCAST_A;
}
if(Filter & NDIS_PACKET_TYPE_MULTICAST)
{
FilterData |= RX_CTL_MCAST_A;
}
if(Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
{
FilterData |= RX_CTL_PROM_A;
}
// Update the filtering in the CS8900A
WriteCs8900Register(PKTPG_RX_CTL, FilterData);
// Turn on the receiver
LineData |= LCR_RX_ON;
WriteCs8900Register(PKTPG_LINE_CTL, LineData);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -SetFilterType\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: CheckReadyForTransmit
//
// This function checks CS8900 chip for ready to transmit.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// Returns:
// Returns TRUE if ready for transmit. Returns FALSE if not ready.
//
//------------------------------------------------------------------------------
WORD CheckReadyForTransmit(pCs8900_t pEthernet)
{
WORD Data;
UINT PacketSize;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +CheckReadyForTransmit\r\n")));
// Have to do as outlined in datasheet pg 102
// Write the transmit command into the transmit command request register
NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_TX_CMD), TX_CMD_START_1021 );
// Get the packet size of the packet from the head of the queue
NdisQueryPacket(pEthernet->HeadPacket, NULL, NULL, NULL, &PacketSize);
// Write the packet length into the Transmit Length I/O register of CS8900A
NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_TX_LENGTH), (WORD)PacketSize );
Data = ReadCs8900Register(PKTPG_BUS_ST);
if(Data & BUS_ST_TX_BID_ERR)
{
pEthernet->StartTX = TRUE; // Better start another TX at end of next interrupt
// Assumes Receives are cause of bid failure
return FALSE;
}
if(Data & BUS_ST_RDY4TXNOW)
{
return TRUE;
}
else
{
pEthernet->TransmitBidPending = TRUE;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -CheckReadyForTransmit\r\n")));
return FALSE;
}
//------------------------------------------------------------------------------
//
// Function: TransferPacketToChip
//
// This function transfer the packet to CS8900 chip.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void TransferPacketToChip(pCs8900_t pEthernet)
{
// Packet size of the packet
UINT PacketSize;
PNDIS_BUFFER pNDISBuffer;
// Current counter for number of bytes copying
DWORD CurrentBytes = 0;
// This flag indicates that an odd byte is to be transferred in the previous
// fragment which is to be transferred with a byte from next fragment
WORD OddWordFlag = FALSE;
// The variable to store the odd byte to be transferred with the next
// fragment.
WORD OddWordValue = 0;
// Holds the virtual address of the current buffer.
PUCHAR CurrentBufAddress;
// Holds the length of the current buffer of the packet.
DWORD BufferLength;
// temporary location for odd starting address data
WORD TmpWord, i;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +TransferPacketToChip\r\n")));
// check whether the first packet is NULL
if(pEthernet->HeadPacket==NULL)
{
return;
}
// Get the length of the packet and the pointer to NDIS Buffer
NdisQueryPacket(pEthernet->HeadPacket, NULL, NULL, &pNDISBuffer, &PacketSize);
NdisQueryBuffer(pNDISBuffer,(PVOID *)&CurrentBufAddress,&BufferLength);
while (pNDISBuffer && (BufferLength == 0 || CurrentBufAddress == NULL))
{
NdisGetNextBuffer(pNDISBuffer, &pNDISBuffer);
NdisQueryBuffer(pNDISBuffer, (PVOID *)&CurrentBufAddress, &BufferLength);
}
if(CurrentBufAddress)
{
do{ // do while there is valid pNDISBuffer pointer
// check for OddWordFlag
if(OddWordFlag)
{
OddWordValue |= ((USHORT)(*CurrentBufAddress)) << 8;
NdisRawWritePortUshort((unsigned long)&(g_pCS8900Reg->CS8900_RX_TX_DATA_0), OddWordValue);
BufferLength--;
OddWordFlag = FALSE;
OddWordValue=0;
CurrentBufAddress++;
}
// check for starting odd address
if ( ((ULONG)CurrentBufAddress & 0x1) != 0)
{
for (i=0; i < BufferLength/2; i++)
{
// for ARM 16 bit data-write alignment
// CurrentBufAddress may not point to a 16 bit boundary address. Use
// memcpy() to move data from unaligned memory to aligned memory.
// It works since memcpy() casts pointers it copies to char*
memcpy(&TmpWord, (WORD*)CurrentBufAddress, min(BufferLength,sizeof(WORD)));
NdisRawWritePortUshort((unsigned long)&(g_pCS8900Reg->CS8900_RX_TX_DATA_0), TmpWord);
((WORD*)CurrentBufAddress)++;
} // end for
} // end if
else
{
for (i=0; i < BufferLength/2; i++)
{
NdisRawWritePortUshort((unsigned long)&(g_pCS8900Reg->CS8900_RX_TX_DATA_0), *((PWORD)CurrentBufAddress)++);
} // end for
}// end else
// check for odd buffer length
if ( BufferLength % 2 == 1 )
{
// Store the byte from the current fragment to be transmitted
// with the next fragment and set the odd_bytes flag.
OddWordValue = *((PUCHAR)CurrentBufAddress);
OddWordFlag = TRUE;
}
// Move to the next buffer
NdisGetNextBuffer(pNDISBuffer, &pNDISBuffer);
if (pNDISBuffer)
{
NdisQueryBuffer(pNDISBuffer, (PVOID *)&CurrentBufAddress, &BufferLength);
}
// Get address and length of the next buffer
while (pNDISBuffer && (BufferLength == 0 || CurrentBufAddress == NULL))
{
NdisGetNextBuffer(pNDISBuffer, &pNDISBuffer);
if (pNDISBuffer)
{
NdisQueryBuffer(pNDISBuffer, (PVOID *)&CurrentBufAddress, &BufferLength);
}
}
}while(pNDISBuffer);
// check for extra odd byte
if(OddWordFlag)
{
NdisRawWritePortUshort((unsigned long)&(g_pCS8900Reg->CS8900_RX_TX_DATA_0), OddWordValue );
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -TransferPacketToChip\r\n")));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -