dec21140.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,694 行 · 第 1/4 页
C
1,694 行
// Need to bail out if we wait too long for a frame completion...
while (pCurrentRxDesc->RDES0.OwnBit == 0 || bMultiBufferDetected)
{
localRDES0 = pCurrentRxDesc->RDES0;
// localDEBUGMSG ("DEC21140GetFrame::: Looking at descriptor: %d... RDES0 = 0x%x\r\n",
// (pCurrentRxDesc - pRxDesc), localRDES0.dwReg);
// Discard Error Frame for now... Donno what to do to them.
// Error frame detected if RDES0[15] and RDES0[8] are set.
// In this case, we simply clean up the Descriptor and release it back to 21140.
if (localRDES0.ErrorSummary && localRDES0.LastDescriptor)
{
// 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:
// Some DHCP server returns broadcast packet and some return directed packets.
// The bBootLoaderCall will prevent filtering out "Non ARP broadcast" packets sent from DHCP server
// during bootloader time (i.e. Bootloader will use this function with bBootLoaderCall == TRUE).
pHeader = (PBYTE) TO_VIRT(pCurrentRxDesc->RDES2);
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;
}
}
}
*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);
return *pwLength;
}
else
{
// Must be an error, toss the whole buffer..
return 0x00;
}
/////////////////////////////////////////////////////////////////////
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 0x00;
}
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 ("Dest MAC = ");
//PrintMAC (pHeader[0]);
//PrintMAC (pHeader[1]);
//PrintMAC (pHeader[2]);
//PrintMAC (pHeader[3]);
//PrintMAC (pHeader[4]);
//PrintMAC (pHeader[5]);
//localDEBUGMSG (" ... Total = %d\r\n", dwTotalFrame++);
}
return (*pwLength);
/////////////////////////////////////////////////////////////////////
default:
// Should NEVER get here..
// Just bail out...
return (0x00);
}
}
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);
}
}
BOOL DEC21140SetupPerfectFilter ()
{
CSR6_21140 csr;
PTX_DESCRIPTOR_FORMAT pTxDesc;
PBYTE pbBuffer;
int i;
pTxDesc = pCurrentTxDesc;
//
// Advance to next descriptor...
//
pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);
//PrintTransmitState();
csr.dwReg = READ_PORT_ULONG(CSR6_REG);
csr.StartTransmit = 1;
WRITE_PORT_ULONG(CSR6_REG, csr.dwReg);
pTxDesc->TDES1.dwReg = 0x09000000;
pTxDesc->TDES0.OwnBit = 1;
WRITE_PORT_ULONG(CSR1_REG, 0xFFFFFFFF);
i=0;
while((pTxDesc->TDES0.OwnBit) == 1 && (i++ < 10))
;
pTxDesc->TDES1.dwReg = SECOND_ADDRESS_CHAINED;
pTxDesc = pCurrentTxDesc;
//
// Advance to next descriptor...
//
pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pCurrentTxDesc->TDES3);
pTxDesc->TDES0.dwReg = 0;
pTxDesc->TDES1.dwReg = 0x69000000 | 192;
pbBuffer = (PBYTE) TO_VIRT(pTxDesc->TDES2);
memset(pbBuffer, 0xff, 192);
pbBuffer[0] = pbEthernetAddr[0];
pbBuffer[1] = pbEthernetAddr[1];
pbBuffer[4] = pbEthernetAddr[2];
pbBuffer[5] = pbEthernetAddr[3];
pbBuffer[8] = pbEthernetAddr[4];
pbBuffer[9] = pbEthernetAddr[5];
pTxDesc->TDES0.OwnBit = 1;
WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);
i = 0;
while((pTxDesc->TDES0.OwnBit) == 1 && (i++ < 10))
;
pTxDesc->TDES1.dwReg = SECOND_ADDRESS_CHAINED;
return(TRUE);
}
#if 0
/////////////////////////////////////////////////////////////////////////////////
// DEC21140SetupPerfectFilter (BYTE *pbPermittedAddress)
// This function creates 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 ()
{
// 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;
PTX_DESCRIPTOR_FORMAT pZeroLengthDescriptor;
TX_TDES1 ZeroLengthDescriptorOriginTDES1;
TX_TDES1 SetupDescriptorOriginTDES1;
PBYTE pbBuffer;
CSR6_21140 CSR6;
CSR0_21140 CSR0;
// 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...
SetupDescriptorOriginTDES1.dwReg = pSetupDescriptor->TDES1.dwReg; // Store original TDES1 value to restore later.
pSetupDescriptor->TDES1.dwReg = (0x69000000 | 192); // Store this into descriptor and it is ready to go...
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];
{
PDWORD pData = (PDWORD) pbBuffer;
localDEBUGMSG ("pData[0] = 0x%x \r\n", *pData++);
localDEBUGMSG ("pData[1] = 0x%x \r\n", *pData++);
localDEBUGMSG ("pData[2] = 0x%x \r\n", *pData++);
}
// We are ready to hoo ha...
pSetupDescriptor->TDES0.OwnBit = 1;
WRITE_PORT_ULONG(CSR1_REG, 0xffffffff);
// Now we just wait till it gobbles up the packets...
localDEBUGMSG ("Waiting for DEC 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;
// Turn off promiscuous mode from now onwards...
CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
CSR6.PromiscuousMode = 0;
CSR6.ReceiveAll = 0;
WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);
return TRUE;
}
#endif
/////////////////////////////////////////////////////////////////////////////////
// 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?