📄 dec21140.c
字号:
WRITE_PORT_ULONG(CSR13_REG, 0); //pull it out of sleep sudhakar
WRITE_PORT_ULONG(CSR14_REG, 0xffff);
WRITE_PORT_ULONG(CSR15_REG, 0x1000);
WRITE_PORT_ULONG(CSR13_REG, 0xef01);
Delay (1200);
// CSR0
localCSR0.dwReg = READ_PORT_ULONG(CSR0_REG);
localCSR0.ProgrammableBurstLength = 0; // 16 DWORD transfer in one DMA transaction.
WRITE_PORT_ULONG(CSR0_REG, localCSR0.dwReg);
localCSR0.CacheAlignment = 1; // 8 DWORD boundary alignment.
WRITE_PORT_ULONG(CSR0_REG, localCSR0.dwReg);
// CSR 3 & CSR4
WRITE_PORT_ULONG(CSR3_REG, TO_REAL ((DWORD)pRxDesc));
WRITE_PORT_ULONG(CSR4_REG, TO_REAL ((DWORD)pTxDesc));
// CSR6
localCSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
localCSR6.ReceiveAll = 1; // Start off seeing everything...
localCSR6.PromiscuousMode = 1;
localCSR6.PassAllMulticast = 0; // No multicast...
localCSR6.FullDuplexMode = 0; // Use half duplex.
localCSR6.dwReg &= CSR6_MUST_AND;
localCSR6.dwReg |= CSR6_MUST_OR;
WRITE_PORT_ULONG(CSR6_REG, localCSR6.dwReg);
DEC21140ModeSetByAutoNegotiation();//change for 5474
DEC21140SetupPerfectFilter (NULL, 0);
// Turn on Receiver...
localCSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
localCSR6.StartReceive = 1;
WRITE_PORT_ULONG(CSR6_REG, localCSR6.dwReg);
return TRUE;
} // HWInit()
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// Interfaces exported to caller starts here:
// DEC21140Init()
// DEC21140InitDMABuffer()
// DEC21140EnableInts()
// DEC21140DisableInts()
// DEC21140ISR()
// DEC21140GetPendingInts()
// DEC21140GetFrame()
// DEC21140SendFrame()
//
//
/////////////////////////////////////////////////////////////////////////////////
// DEC21140Detect - Detect whether there is 21140 compatible chip.
// Input:
// - pbBaseAddress... Caller can pass in either physical or virtual address here.
// But have to make sure that it's non cached (if it is virtual).
//
BOOL
DEC21140Detect(BYTE *pbBaseAddress)
{
// Need to do proper detection here...
g_pIOBase = (PUCHAR)pbBaseAddress;
localDEBUGMSG ("DEC21140Detect()::: returning TRUE\r\n");
return TRUE;
} // DEC21140Detect()
/////////////////////////////////////////////////////////////////////////////////
// DEC21140Init - This is called to initialze the ethernet low level driver.
// The base address of the ethernet hardware is passed into
// the routine. The routine will return TRUE for a successful
// initialization.
// Initialization:
// 1. Perform 21140 hardware initialization.
// 2. Create transmit and receive descriptor lists.
// 3. Start transmit and receive process on 21140.
//
BOOL
DEC21140Init( BYTE *pbBaseAddress, ULONG dwMemOffset, USHORT MacAddr[3])
{
int n = 0;
PBYTE pDst = NULL;
PBYTE pSrc = NULL;
localDEBUGMSG ("DEC21140::: Init using i/o address : 0x%x - mem offset = 0x%x\r\n", pbBaseAddress, dwMemOffset);
dwMEM_OFFSET = dwMemOffset;
// ** NOTE - the method for determining the MAC address is platform
// ** dependent in the case of built-in controllers. For plug-in NICs, we
// ** generally assume the MAC address can be found in a common location.
// ** Either way, the following code needs to obtain the MAC address to
// ** be used with the controller.
if ((PUSHORT)MacAddr != NULL)
{
if (!EEPROMReadMAC(&MacAddr[0]))
{
localDEBUGMSG("ERROR: Unable to get MAC address for DEC21140.\r\n");
return(FALSE);
}
// Make a copy of the MAC address...
pSrc = (PBYTE)MacAddr;
pDst = pbEthernetAddr;
for (n = 6; n ; n--)
{
*pDst++ = *pSrc++;
}
localDEBUGMSG ("MAC = %x-%x-%x", pbEthernetAddr[0], pbEthernetAddr[1], pbEthernetAddr[2]);
localDEBUGMSG ("-%x-%x-%x\r\n", pbEthernetAddr[3], pbEthernetAddr[4], pbEthernetAddr[5]);
}
else
{
//localDEBUGMSG("INFO: MAC address to be provided via call to DEC21140SetMACAddress().\r\n");
}
// HWInit will return false if hardware is not detected.
g_pIOBase = (PUCHAR)pbBaseAddress;
if (!HWInit())
{
localDEBUGMSG ("DEC21140:::HWInit() failed...\r\n");
return FALSE;
}
localDEBUGMSG ("DEC21140Init()::: Done.\r\n");
return TRUE;
} // DEC21140Init()
////////////////////////////////////////////////////////////////////////////////
//
// InitTxDescriptor -
//
// Caller tells us where the descriptors and buffers should live. Furthermore,
// the size of buffer is fixed at MAX_BUFFER_SIZE. It is caller's
// responsibility to allocate enough memory. Note: Caller can use
// DEC21140QueryBufferSize() to find out the size of buffer used for each
// buffer and hence calculate the Total Buffer that can be allocated...
// DEC21140QueryDescriptorSize() will return size of descriptor...
//
// Input:
// - dwStartAddress = Location where descriptors start.
// - dwSize = Size of buffer allocated by caller.
//
// WARNING: IT IS CALLER RESPONSIBILITY TO GIVE PROPER DATA.
// NO SANITY CHECK HERE !!!
// THIS IS ONLY FOR INTERNAL USAGE...
//
void InitTxDescriptor(DWORD dwStartAddress, DWORD dwSize)
{
// Easy... Simply use the provided addresses and size to fit the maximum
// number of buffer and descriptors we can...
// We must have been called from Bootloader or Ethdbg.
BOOL bDone = FALSE;
int i = 1;
DWORD dwCostOfOneBuffer = sizeof(TX_DESCRIPTOR_FORMAT) + MAX_BUFFER_SIZE;
// Calculate the max number of descriptor + buffer that I can have for the
// given size.
while (!bDone)
{
if ((i * dwCostOfOneBuffer) > dwSize)
{
bDone = TRUE;
i--;
}
else
i++;
}
dwTRANSMIT_DESCRIPTORS_HEAD = dwStartAddress;
dwTRANSMIT_BUFFER_START = dwStartAddress + i * sizeof(TX_DESCRIPTOR_FORMAT);
dwTRANSMIT_RING_SIZE = i;
localDEBUGMSG ("InitTxDescriptor::: dwTRANSMIT_DESCRIPTORS_HEAD = 0x%x...\r\n", dwTRANSMIT_DESCRIPTORS_HEAD);
localDEBUGMSG ("InitTxDescriptor::: dwTRANSMIT_BUFFER_START = 0x%x...\r\n", dwTRANSMIT_BUFFER_START);
localDEBUGMSG ("InitTxDescriptor::: dwTRANSMIT_RING_SIZE = 0x%x...\r\n", dwTRANSMIT_RING_SIZE);
} // InitTxDescriptor()
////////////////////////////////////////////////////////////////////////////////
//
// InitRxDescriptor - See InitTxDescriptor()
//
//
void InitRxDescriptor(DWORD dwStartAddress, DWORD dwSize)
{
// Easy... Simply use the provided addresses and size to fit the maximum
// number of buffer and descriptors we can...
// We must have been called from Bootloader or Ethdbg.
BOOL bDone = FALSE;
int i = 1;
DWORD dwCostOfOneBuffer = sizeof(RX_DESCRIPTOR_FORMAT) + MAX_BUFFER_SIZE;
// Calculate the max number of descriptor + buffer that I can have for the
// given size.
while (!bDone)
{
if ((i * dwCostOfOneBuffer) > dwSize)
{
bDone = TRUE;
i--;
}
else
i++;
}
dwRECEIVE_DESCRIPTORS_HEAD = dwStartAddress;
dwRECEIVE_BUFFER_START = dwStartAddress + i * sizeof(RX_DESCRIPTOR_FORMAT);
dwRECEIVE_RING_SIZE = i;
localDEBUGMSG ("InitRxDescriptor::: dwRECEIVE_DESCRIPTORS_HEAD = 0x%x...\r\n", dwRECEIVE_DESCRIPTORS_HEAD);
localDEBUGMSG ("InitRxDescriptor::: dwRECEIVE_BUFFER_START = 0x%x...\r\n", dwRECEIVE_BUFFER_START);
localDEBUGMSG ("InitRxDescriptor::: dwRECEIVE_RING_SIZE = 0x%x...\r\n", dwRECEIVE_RING_SIZE);
} // InitRxDescriptor()
BOOL DEC21140InitDMABuffer(DWORD dwStartAddress, DWORD dwSize)
{
DWORD dwAlignedTxStart = 0;
DWORD dwAlignedRxStart = 0;
DWORD dwTxBufferSize = 0;
DWORD dwRxBufferSize = 0;
// Check for minimum buffer size.
if (dwSize < MIN_DMA_SIZE)
{
localDEBUGMSG("ERROR: DMA buffer is too small.\r\n");
return(FALSE);
}
// Determine aligned start address for DMA buffer.
dwAlignedTxStart = (dwStartAddress + 0x03) & 0xFFFFFFFC;
dwSize -= (dwAlignedTxStart - dwStartAddress);
// Roughly split buffer in two and init Tx and Rx regions.
dwTxBufferSize = dwSize / 2;
dwSize -= dwTxBufferSize;
dwStartAddress += dwTxBufferSize;
dwAlignedRxStart = (dwStartAddress + 0x03) & 0xFFFFFFFC;
dwSize -= (dwAlignedRxStart - dwStartAddress);
dwRxBufferSize = dwSize;
InitTxDescriptor(dwAlignedTxStart, dwTxBufferSize);
InitRxDescriptor(dwAlignedRxStart, dwRxBufferSize);
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////////
// DEC21140EnableInts - Interrupts left disabled at init, call this function
// to turn them on
// For Ethernet debug, we only need Receive Interrupt.
// Hence simply turn on CSR7[6] and CSR7[16]
//
void
DEC21140EnableInts()
{
CSR7_21140 localCSR7;
localDEBUGMSG ("DEC21140EnableInts::: Interrupt Enabled...\r\n");
localCSR7.dwReg = READ_PORT_ULONG(CSR7_REG);
localCSR7.ReceiveInterruptEnable = 1;
localCSR7.NormalIntrSummaryEnable = 1;
WRITE_PORT_ULONG(CSR7_REG, localCSR7.dwReg);
} // DEC21140EnableInts()
/////////////////////////////////////////////////////////////////////////////////
// DEC21140DisableInts - Disable interrupt.
// For etherent debug, we only worry about normal interrupt...
//
void
DEC21140DisableInts()
{
CSR7_21140 CSR7;
localDEBUGMSG ("+/- DEC21140DisableInts::: Interrupt Enabled...\r\n");
CSR7.dwReg = READ_PORT_ULONG(CSR7_REG);
CSR7.NormalIntrSummaryEnable = 0;
WRITE_PORT_ULONG(CSR7_REG, CSR7.dwReg);
} // DEC21140DisableInts()
/////////////////////////////////////////////////////////////////////////////////
// DEC21140GetPendingInts -
//
//
DWORD
DEC21140GetPendingInts()
{
CSR5_21140 CSR5;
//localDEBUGMSG ("+/- DEC21140GetPendingInts::: ...\r\n");
// The only time we get here is when RX interrupt happens.
// Let's check it and see if it is the case...
CSR5.dwReg = READ_PORT_ULONG(CSR5_REG);
if (CSR5.ReceiveInterrupt)
{
// Clear the interrupt...
CSR5.ReceiveInterrupt = 1;
WRITE_PORT_ULONG(CSR5_REG, CSR5.dwReg);
return INTR_TYPE_RX;
}
// Probably need to fix other abnormal interrupts here...
//localDEBUGMSG ("DEC21140GetPendingInts::: Suspicious... how do I get here ???\r\n");
return(0);
} // DEC21140GetPendngInts()
/////////////////////////////////////////////////////////////////////////////////
// DEC21140GetFrame - This routine is used to find out if a frame has been
// received. If there are no frames in the RX FIFO, the
// routine will return 0.
// If there was a frame that was received correctly,
// it will be stored in pwData, otherwise it will be discarded.
//
// Check if the address is broadcast address...
BOOL IsBroadcast(PBYTE pHeader)
{
int i = 0;
while (1)
{
if (pHeader[i++] != 0xff)
break;
if (i == 6)
return TRUE;
}
return FALSE;
} // IsBroadcast()
void PrintMAC (BYTE bData)
{
if (bData < 10)
localDEBUGMSG ("0");
//localDEBUGMSG ("%x", bData);
localDEBUGMSG ("%x", bData);
} // PrintMAC
/////////////////////////////////////////////////////////////////////////////////
// Not until SP1 that the problem in talking to DHCP server that does not reply
// discovery packet with ARP broadcast is solved.
// For altoona, the solution is to differentiate between a kernel call and
// bootloader call.
// We pass all broadcast packets up if it is bootloader.
// Bootloader has to call this function with bBootLoaderCall == TRUE
UINT16
DEC21140GetFrame(BYTE *pbData, UINT16 *pwLength)
{
RX_RDES0 localRDES0;
BOOL bMultiBufferDetected = FALSE;
PBYTE pHeader, pbOrig = pbData;
BOOL bBootLoaderCall = FALSE;
CSR5_21140 CSR5;
// localDEBUGMSG ("+/- DEC2114GetFrame:::...\r\n");
*pwLength = 0;
// Bail out immediately if the target descriptor is owned by DEC21140
if (pCurrentRxDesc->RDES0.OwnBit == 1)
return(0);
// KITL doesn't call GetPendingInts to clear the interrupt at the card
// therefore we need to do it here.
//
CSR5.dwReg = READ_PORT_ULONG(CSR5_REG);
if (CSR5.ReceiveInterrupt)
{
// Clear the interrupt...
CSR5.ReceiveInterrupt = 1;
WRITE_PORT_ULONG(CSR5_REG, CSR5.dwReg);
}
// A chance of getting valid packet...
// 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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -