📄 dec21140.c
字号:
// localDEBUGMSG ("DEC21140GetFrame::: Error Frame !!! 1 Buffer Tossed...\r\n");
localRDES0.dwReg = 0x00 | DESC_OWNED_BY_DEC21140;
pCurrentRxDesc->RDES0.dwReg = localRDES0.dwReg;
// Proceed to next descriptor...
pCurrentRxDesc = (PRX_DESCRIPTOR_FORMAT) TO_VIRT (pCurrentRxDesc->RDES3);
continue;
}
// Okay, by now we must have a valid buffer.
// Copy data pointed to by this buffer to user buffer...
// localDEBUGMSG ("DEC21140GetFrame()::: Copying %d bytes\r\n", (UINT16)localRDES0.FrameLength);
// For Ethernet Debug and Bootloader, only ARP packet is accepted...
// Hence filter out non-ARP broadcast or Multicast packets...
/////////////////////////////////////////////////////////////////////////
// Note: MULTICAST is ENABLED NOW. WE'LL PASS ALL FRAMES BACK
pHeader = (PBYTE) TO_VIRT(pCurrentRxDesc->RDES2);
#if 0
if (localRDES0.MulticastFrame || IsBroadcast(pHeader))
{
// This is multicast or broadcast packet.
// Toss away if it is non-ARP (i.e Header[16] != 8 || Header[17] != 6)
if (!bBootLoaderCall)
{
if (pHeader[12] != 0x08 && pHeader[13] != 0x06)
{
// The buffer is tossed !!!
//localDEBUGMSG ("DEC21140GetFrame()::: 1 non ARP broadcast/multicast buffer tossed.\r\n");
//localDEBUGMSG ("DEC21140GetFrame()::: RDES0 = 0x%x\r\n", localRDES0);
goto SkipCopy;
}
}
}
#endif
*pwLength = *pwLength + (UINT16)localRDES0.FrameLength;
memcpy (pbData, (PBYTE) TO_VIRT(pCurrentRxDesc->RDES2), (UINT16)localRDES0.FrameLength);
pbData += (UINT16)localRDES0.FrameLength;
//SkipCopy:
// Return descriptor back to 21140...
pCurrentRxDesc->RDES0.dwReg = 0x00 | DESC_OWNED_BY_DEC21140;
// Proceed to next descriptor...
pCurrentRxDesc = (PRX_DESCRIPTOR_FORMAT) TO_VIRT (pCurrentRxDesc->RDES3);
// Check the First and Last descriptor indications and take action accordingly...
switch ((localRDES0.dwReg & 0x300) >> 8)
{
/////////////////////////////////////////////////////////////////////
case 0x00: // Not first and not last...
//localDEBUGMSG ("DEC21140GetFrame()::: Middle buffer...\r\n");
break;
/////////////////////////////////////////////////////////////////////
case 0x01: // Last Descriptor...
if (bMultiBufferDetected)
{
//localDEBUGMSG ("DEC21140GetFrame()::: Last Descriptor found...length = %d\r\n", *pwLength);
// Remove checksum from the length
// returned...
//
if (*pwLength)
*pwLength -= sizeof(ULONG);
return(*pwLength);
}
else
{
// Must be an error, toss the whole buffer..
return(0);
}
/////////////////////////////////////////////////////////////////////
case 0x02: // First Descriptor...
if (!bMultiBufferDetected)
{
//localDEBUGMSG ("DEC21140GetFrame()::: First Descriptor detected...\r\n");
bMultiBufferDetected = TRUE;
}
else
{
// Another First Descriptor ???
// Must be something wrong !!!
// localDEBUGMSG ("DEC21140GetFrame()::: Multiple First Descriptor...Tossing all...\r\n");
return(0);
}
break;
/////////////////////////////////////////////////////////////////////
case 0x03: // One buffer frame...
// localDEBUGMSG ("DEC21140GetFrame()::: One buffer frame (%d bytes)...\r\n", *pwLength);
// Let's see the destination MAC...
// Destination MAC starts from 8th byte.
{
static DWORD dwTotalFrame = 0;
//localDEBUGMSG (" ... Total = %d\r\n", dwTotalFrame++);
}
// Remove checksum from the length
// returned...
//
if (*pwLength)
*pwLength -= sizeof(ULONG);
#if 0
if ((*pwLength > 0) && pbOrig[0] && (pbOrig[0] != 0xff))
{
localDEBUGMSG ("Dest MAC = ");
PrintMAC (pbOrig[0]);
PrintMAC (pbOrig[1]);
PrintMAC (pbOrig[2]);
PrintMAC (pbOrig[3]);
PrintMAC (pbOrig[4]);
PrintMAC (pbOrig[5]);
localDEBUGMSG ("\r\n");
}
#endif
return(*pwLength);
///////////////////////////////////////////////////////
default:
// Should NEVER get here..
// Just bail out...
return(0);
}
}
// Remove checksum from the length
// returned...
//
if (*pwLength)
*pwLength -= sizeof(ULONG);
#if 0
if (*pwLength && (pbOrig[0] != 0xff) && (pbOrig[0])) {
localDEBUGMSG ("Dest MAC2 = ");
PrintMAC (pbOrig[0]);
PrintMAC (pbOrig[1]);
PrintMAC (pbOrig[2]);
PrintMAC (pbOrig[3]);
PrintMAC (pbOrig[4]);
PrintMAC (pbOrig[5]);
localDEBUGMSG ("\r\n");
}
#endif
return(*pwLength);
} // DEC21140GetFrame()
/////////////////////////////////////////////////////////////////////////////////
// DEC21140ModeSetByAutoNegotiation()
// Set the DEC to the common denominator between what PHY (ICS1890) has negotiated
// with "link partner" and capability of DEC.
//
void DEC21140ModeSetByAutoNegotiation()
{
WORD wReg4;
WORD wReg5;
WORD wModes;
DWORD WaitCount;
CSR6_21140 CSR6;
CSR0_21140 CSR0;
WaitCount = 100000;
while ((!(MIIRead(0x01) & 0x20)) && ( 0 != WaitCount-- ))
{
// Wait till Autonegotiation completed...
// printf ("Autonegotiation not completed...\r\n");
}
// Make sure TX and Rx are stopped.
CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
CSR6.StartTransmit = 0x0;
CSR6.StartReceive = 0x0;
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
// Default to 10Base-TxHD.
CSR6.TransmitThresholdMode = 0x01; // FIFO threshold to 10Mbps
CSR6.FullDuplexMode = 0x00; // Set half duplex mode.
CSR6.StoreAndForward = 0x01; // Store/Forward...
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
wModes = 0;
// If autonegotiation was successful, get the communications
// that are supported by the local host and the remote host.
if ( 0 != WaitCount )
{
wReg4 = MIIRead(0x04);
wReg5 = MIIRead(0x05);
// Determine the common modes of operation.
wModes = wReg4 & wReg5;
}
// I know that ICS1890 does not support 100Base-T4
// Hence we start check for
// 100Base-TxFD
// 100Base-TxHD
// 10Base-TxFD
// 10Base-TxHD
// Enable 100Base-Tx if supported by both sides.
if (( wModes & 100 ) || ( wModes & 0x80 ))
{
CSR0.dwReg = READ_PORT_ULONG(CSR0_REG);
CSR0.ProgrammableBurstLength = 32;
WRITE_PORT_ULONG(CSR0_REG, CSR0.dwReg);
CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
CSR6.TransmitThresholdMode = 0x00; // FIFO threshold to 100Mbps
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
// Set bit 0 if full duplex is enabled.
wModes >>= 2;
}
wModes >>= 6;
// Enable full duplex if supported by both sides.
if ( wModes & 1 )
{
CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
CSR6.FullDuplexMode = 0x01; // Set Full duplex mode.
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
}
}
////////////////////////////////////////////////////////////////////////////////
//
// DEC21140SetupPerfectFilter (BYTE *pbPermittedAddress)
// This function creates a setup frame to be used to filter all incoming
// frames. A perfect filter filters out everything except its own IP address
// and broadcast address.
//
BOOL DEC21140SetupPerfectFilter (PUCHAR pucMulticastAddresses, DWORD dwNoOfAddresses)
{
// Here are the steps taken...
// 1. Prepare a zero-length buffer descriptor from current tx descriptor.
// 2. Setup the perfect filter frame with exactly 192 bytes data length.
// 3. First Segment = Last Segment = 0.
// 4. Finally, set TDES0[31] = 1 ... Adapter owned descriptor.
//
// Zero length descriptor needs:
// TDES1[30] = 0 ... Last Segment Bit 0
// TDES1[29] = 0 ... First Segment Bit 0
// TDES1[21..11] = ... Transmit buffer 2 = 0
// TDES1[10..0] = ... Transmit buffer 1 = 0
//
// 5. Trigger transmitter, wait for packet 'eaten' by DEC.
// 6. Reset descriptor to become normal descriptor.
PTX_DESCRIPTOR_FORMAT pSetupDescriptor = NULL;
PTX_DESCRIPTOR_FORMAT pZeroLengthDescriptor = NULL;
TX_TDES1 ZeroLengthDescriptorOriginTDES1;
TX_TDES1 SetupDescriptorOriginTDES1;
PBYTE pbBuffer = NULL;
CSR6_21140 CSR6;
CSR0_21140 CSR0;
DWORD i;
//
// for multicast: first two entries reserved for Local MAC address and broadcast address
//
if (DEC21140_SETUP_PERFECT_ENTRIES-2 < dwNoOfAddresses) {
return FALSE;
}
if (!pucMulticastAddresses) {
//
// Initial Setting -- make sure receiver is off and transmitter is on.
//
CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
CSR6.StartReceive = 0;
CSR6.StartTransmit = 1;
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
CSR0.dwReg = READ_PORT_ULONG(CSR0_REG);
CSR0.OnNow = 0;
WRITE_PORT_ULONG(CSR0_REG, CSR0.dwReg);
}
// Setup zero length buffer descriptor.
//
pZeroLengthDescriptor = pCurrentTxDesc;
pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);
pSetupDescriptor = pCurrentTxDesc;
pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);
ZeroLengthDescriptorOriginTDES1.dwReg = pZeroLengthDescriptor->TDES1.dwReg;
pZeroLengthDescriptor->TDES1.dwReg = 0x09000000;
pZeroLengthDescriptor->TDES0.OwnBit = 1;
CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
CSR6.StartTransmit = 1;
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
WRITE_PORT_ULONG(CSR1_REG, 0xffffffff); // Trigger transmitter...
localDEBUGMSG ("Waiting for Zero Length Descriptor...\r\n");
while ((pZeroLengthDescriptor->TDES0.OwnBit) == 1)
{
WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);
}
// Restore the original TDES1 descriptor.
//
pZeroLengthDescriptor->TDES1 = ZeroLengthDescriptorOriginTDES1;
// Now, setup the perfect filter packet...
//
// Store original TDES1 value to restore later.
//
SetupDescriptorOriginTDES1.dwReg = pSetupDescriptor->TDES1.dwReg;
//Store this into descriptor and it is ready to go...
//
pSetupDescriptor->TDES1.dwReg = (0x69000000 | 192);
pbBuffer = (PVOID)TO_VIRT(pSetupDescriptor->TDES2);
memset (pbBuffer, 0xff, 500);
pbBuffer[0] = pbEthernetAddr[0];
pbBuffer[1] = pbEthernetAddr[1];
pbBuffer[4] = pbEthernetAddr[2];
pbBuffer[5] = pbEthernetAddr[3];
pbBuffer[8] = pbEthernetAddr[4];
pbBuffer[9] = pbEthernetAddr[5];
//
// setup the rest of the addresses
//
for (i = 0; i < dwNoOfAddresses; i ++) {
pbBuffer[(i+2)*12] = pucMulticastAddresses[i*6];
pbBuffer[(i+2)*12+1] = pucMulticastAddresses[i*6+1];
pbBuffer[(i+2)*12+4] = pucMulticastAddresses[i*6+2];
pbBuffer[(i+2)*12+5] = pucMulticastAddresses[i*6+3];
pbBuffer[(i+2)*12+8] = pucMulticastAddresses[i*6+4];
pbBuffer[(i+2)*12+9] = pucMulticastAddresses[i*6+5];
}
// We are ready to go...
//
pSetupDescriptor->TDES0.OwnBit = 1;
WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);
// Now we just wait till it gobbles up the packets...
//
localDEBUGMSG ("Waiting for DEC21140 to perform perfect filtering...\r\n");
while ((pSetupDescriptor->TDES0.OwnBit) == 1)
WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);
// Finally, restore the original TDES1 for the setupdescriptor so that
// next packet won't be treated as setup packet.
//
pSetupDescriptor->TDES1.dwReg = SetupDescriptorOriginTDES1.dwReg;
if (!pucMulticastAddresses) {
//
// Initial setup: turn off promiscuous mode
//
CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
CSR6.PromiscuousMode = 0;
CSR6.ReceiveAll = 0;
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
}
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////////
// DEC21140SendFrame - This routine should be called with a pointer to the
// ethernet frame data. It is the caller's responsibility
// to fill in all information including the destination and
// source addresses and the frame type.
// The length parameter gives the number of bytes in
// the ethernet frame.
// The routine will return immediately regardless of
// whether transmission has successfully been performed by
// 21140.
// Error return: Non zero.
// No error: Returns zero.
//
UINT16 DEC21140SendFrame( BYTE *pbData, DWORD dwLength )
{
DWORD i = 0;
DWORD dwTotalSent = 0;
DWORD dwNumberOfDescriptorUsed = 0;
DWORD dwToSend;
CSR6_21140 CSR6;
volatile PTX_DESCRIPTOR_FORMAT pFirstTxDescriptor;
volatile PTX_DESCRIPTOR_FORMAT pRememberingTheVeryFirstDescriptor;
pFirstTxDescriptor = (PTX_DESCRIPTOR_FORMAT) NULL;
//printf ("DEC21140SendFrame()::: Sending %d bytes \r\n", dwLength);
// localDEBUGMSG ("DEC21140SendFrame()::: Sending : %d bytes\r\n", dwLength);
// Need time out... When all TX process of dec21140 STALL !!!
while (dwTotalSent < dwLength)
{
if (pCurrentTxDesc->TDES0.dwReg & ~DESC_OWNED_BY_HOST)
{
// Do something here to make sure the TX process get rid of all these packets...
// Then back to top of loop...
continue;
}
if (pCurrentTxDesc == pFirstTxDescriptor)
{
// This should NEVER happen if we have plenty of descriptors...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -