📄 lan91c.c
字号:
switch (GET_CHIP_ID(g_chipRevision)) {
case CHIP_ID_LAN91C111:
OUTREG16(&g_pLAN91C->MMUCR, MMUCR_111_RELEASE_TX);
break;
default:
OUTREG16(&g_pLAN91C->MMUCR, MMUCR_REL_SPEC);
}
while ((INREG16(&g_pLAN91C->MMUCR) & MMUCR_BUSY) != 0);
// Clear the tx interrupt status
SETPORT16(&g_pLAN91C->INTR, INTR_TX);
// Tx error?
if (rc & (EPH_STAT_TXUNRN | EPH_STAT_SQET | EPH_STAT_LOSTCARR | EPH_STAT_LATCOL | EPH_STAT_16COL))
{
// Display error status.
OALMSGS(OAL_ERROR, (L"ERROR: LAN91CSendFrame: status = ( "));
if (rc & EPH_STAT_TXUNRN)
{
OALMSGS(OAL_ERROR, (L"TXUNRN "));
}
if (rc & EPH_STAT_SQET)
{
OALMSGS(OAL_ERROR, (L"SQET "));
}
if (rc & EPH_STAT_LOSTCARR)
{
OALMSGS(OAL_ERROR, (L"LOSTCARR "));
}
if (rc & EPH_STAT_LATCOL)
{
OALMSGS(OAL_ERROR, (L"LATCOL "));
}
if (rc & EPH_STAT_16COL)
{
OALMSGS(OAL_ERROR, (L"16COL "));
}
OALMSGS(OAL_ERROR, (L")\r\n"));
// Re-enable TXENA
OUTREG16(&g_pLAN91C->BANKSEL, 0);
OUTREG16(&g_pLAN91C->TCR, TCR_SWFDUP|TCR_PADEN|TCR_TXEN);
// Failure.
rc = 1;
}
else
{
// Success.
rc = 0;
}
// Clear the statistics registers
OUTREG16(&g_pLAN91C->BANKSEL, 0);
INREG16(&g_pLAN91C->ECR);
// Set back bank 2
OUTREG16(&g_pLAN91C->BANKSEL, 2);
return rc;
}
//------------------------------------------------------------------------------
UINT16 LAN91CGetFrame(UINT8 *pBuffer, UINT16 *pLength)
{
UINT8 *pos = pBuffer;
UINT16 code, pointer;
UINT32 length, count;
// Make sure that bank 2 is actual
OUTREG16(&g_pLAN91C->BANKSEL, 2);
length = 0;
while ((INREG16(&g_pLAN91C->INTR) & INTR_RX) != 0) {
// Setup pointer address register
pointer = PTR_RCV | PTR_READ;
// Read status
OUTREG16(&g_pLAN91C->PTR, pointer);
code = INREG16(&g_pLAN91C->DATA);
pointer += sizeof(UINT16);
if ((code & (STAT_ALGNERR|STAT_BADCRC|STAT_LONG|STAT_SHORT)) == 0) {
// Get packet size
OUTREG16(&g_pLAN91C->PTR, pointer);
length = (INREG16(&g_pLAN91C->DATA) & 0x07FF) - 6;
pointer += sizeof(UINT16);
// Copy packet
count = length;
while (count > 1) {
OUTREG16(&g_pLAN91C->PTR, pointer);
*(UINT16*)pos = INREG16(&g_pLAN91C->DATA);
pointer += sizeof(UINT16);
pos += sizeof(UINT16);
count -= sizeof(UINT16);
}
// Get control word (which can contain last byte)
OUTREG16(&g_pLAN91C->PTR, pointer);
code = INREG16(&g_pLAN91C->DATA);
pointer += sizeof(UINT16);
if ((code & CTRL_ODD) != 0) {
length++;
*pos = (UINT8)code;
}
}
// Release the memory for the received frame
switch (GET_CHIP_ID(g_chipRevision)) {
case CHIP_ID_LAN91C111:
OUTREG16(&g_pLAN91C->MMUCR, MMUCR_111_REM_REL_RX);
break;
default:
OUTREG16(&g_pLAN91C->MMUCR, MMUCR_REM_REL_TOP);
}
while ((INREG16(&g_pLAN91C->MMUCR) & MMUCR_BUSY) != 0);
// If length is non zero we get a packet
if (length > 0) break;
}
*pLength = (UINT16)length;
return (*pLength);
}
//------------------------------------------------------------------------------
VOID LAN91CEnableInts()
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+LAN91CEnableInts\r\n"));
// Only enable receive interrupts (we poll for Tx completion)
OUTREG16(&g_pLAN91C->BANKSEL, 2);
OUTREG16(&g_pLAN91C->INTR, INTR_RX_MASK);
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-LAN91CEnableInts\r\n"));
}
//------------------------------------------------------------------------------
VOID LAN91CDisableInts()
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+LAN91CDisableInts\r\n"));
// Disable all interrupts
OUTREG16(&g_pLAN91C->BANKSEL, 2);
OUTREG16(&g_pLAN91C->INTR, 0);
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-LAN91CDisableInts\r\n"));
}
//------------------------------------------------------------------------------
VOID LAN91CCurrentPacketFilter(UINT32 filter)
{
UINT16 rcr = RCR_RXEN|RCR_STRIP_CRC;
OALMSGS(OAL_ETHER&&OAL_FUNC, (
L"+LAN91CCurrentPacketFilter(0x%08x)\r\n", filter
));
if ((filter & PACKET_TYPE_ALL_MULTICAST) != 0) rcr |= RCR_ALMUL;
if ((filter & PACKET_TYPE_PROMISCUOUS) != 0) rcr |= RCR_PRMS;
OUTREG16(&g_pLAN91C->BANKSEL, 0);
OUTREG16(&g_pLAN91C->RCR, rcr);
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-LAN91CCurrentPacketFilter\r\n"));
}
//------------------------------------------------------------------------------
BOOL LAN91CMulticastList(UINT8 *pAddresses, UINT32 count)
{
UINT32 crc, i;
UINT16 h[4];
OALMSGS(OAL_ETHER&&OAL_FUNC, (
L"+LAN91CMulticastList(0x%08x, %d)\r\n", pAddresses, count
));
// Calculate hash bits
h[0] = h[1] = h[2] = h[3] = 0;
for (i = 0; i < count; i++) {
crc = Crc(pAddresses);
h[crc >> 30] |= 1 << ((crc >> 26) & 0x0F);
pAddresses += 6;
}
// Write it to hardware
OUTREG16(&g_pLAN91C->BANKSEL, 3);
OUTREG16(&g_pLAN91C->MT[0], h[0]);
OUTREG16(&g_pLAN91C->MT[1], h[1]);
OUTREG16(&g_pLAN91C->MT[2], h[2]);
OUTREG16(&g_pLAN91C->MT[3], h[3]);
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-LAN91CMulticastList(rc = 1)\r\n"));
return TRUE;
}
//------------------------------------------------------------------------------
UINT32 Crc(UINT8 *pAddress)
{
UINT32 crc, carry;
UINT32 i, j;
UINT8 uc;
crc = 0xFFFFFFFF;
for (i = 0; i < 6; i++) {
uc = pAddress[i];
for (j = 0; j < 8; j++) {
carry = ((crc & 0x80000000) ? 1 : 0) ^ (uc & 0x01);
crc <<= 1;
uc >>= 1;
if (carry) crc = (crc ^ 0x04c11db6) | carry;
}
}
return crc;
}
//------------------------------------------------------------------------------
static VOID PhyWrite(UINT8 PHYaddr, UINT8 PHYreg, UINT16 PHYdata)
{
INT32 i;
UINT16 mask;
UINT16 mii_reg;
UINT8 bits[65];
INT32 clk_idx = 0;
// 32 consecutive ones on MDO to establish sync.
//
for (i = 0; i < 32; ++i)
{
bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
}
// Start code <01>.
//
bits[clk_idx++] = MGMT_MDOE;
bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
// Write command <01>.
//
bits[clk_idx++] = MGMT_MDOE;
bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
// Output the PHY address, msb first.
//
mask = (UINT8)0x10;
for (i = 0; i < 5; ++i)
{
if (PHYaddr & mask)
bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
else
bits[clk_idx++] = MGMT_MDOE;
// Shift to next lowest bit.
mask >>= 1;
}
// Output the PHY register number, msb first.
//
mask = (UINT8)0x10;
for (i = 0; i < 5; ++i)
{
if (PHYreg & mask)
bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
else
bits[clk_idx++] = MGMT_MDOE;
// Shift to next lowest bit.
mask >>= 1;
}
// Tristate and turnaround (2 bit times).
//
bits[clk_idx++] = 0;
bits[clk_idx++] = 0;
// Write out 16 bits of data, msb first.
//
mask = 0x8000;
for (i = 0; i < 16; ++i)
{
if (PHYdata & mask)
bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
else
bits[clk_idx++] = MGMT_MDOE;
// Shift to next lowest bit.
mask >>= 1;
}
// Final clock bit (tristate).
//
bits[clk_idx++] = 0;
// Select bank 3.
//
OUTREG16(&g_pLAN91C->BANKSEL, 3);
// Get the current MII register value.
//
mii_reg = INREG16(&g_pLAN91C->MGMT);
// Turn off all MII Interface bits.
//
mii_reg &= ~(MGMT_MDOE | MGMT_MCLK |
MGMT_MDI | MGMT_MDO);
// Clock all cycles.
//
for (i = 0; i < sizeof bits; ++i)
{
// Clock Low - output data.
//
OUTREG16(&g_pLAN91C->MGMT, mii_reg | bits[i]);
OALStall(50);
// Clock Hi - input data.
//
OUTREG16(&g_pLAN91C->MGMT, (UINT16)(mii_reg | bits[i] | MGMT_MCLK));
OALStall(50);
bits[i] |= INREG16(&g_pLAN91C->MGMT) & MGMT_MDI;
}
// Return to idle state. Set clock to low, data to low, and output tristated.
//
OUTREG16(&g_pLAN91C->MGMT, mii_reg);
OALStall(50);
}
BOOL LAN91CsetMAC(UINT8 *pAddress, UINT16 mac[3])
{
BOOL rc = FALSE;
// Save address
g_pLAN91C = (LAN91C_REGS*)pAddress;
// Verify that network chip can be detected
if ((INREG16(&g_pLAN91C->BANKSEL) & 0xFF00) != 0x3300) {
OALMSGS(OAL_ERROR, (
L"ERROR: LAN91CInit: Network Chip not found at 0x%08x\r\n", pAddress
));
goto cleanUp;
}
// Select bank 1
OUTREG16(&g_pLAN91C->BANKSEL, 1);
OUTREG16(&g_pLAN91C->IAR0, mac[0]);
OUTREG16(&g_pLAN91C->IAR1, mac[1]);
OUTREG16(&g_pLAN91C->IAR2, mac[2]);
// Write the MAC address into EEPROM
SMCWriteEEPROM(0x20, mac[0]);
SMCWriteEEPROM(0x21, mac[1]);
SMCWriteEEPROM(0x22, mac[2]);
// We are done
rc = TRUE;
cleanUp:
OALMSGS(TRUE, (
L"\r\nSetting MAC Address(%02x:%02x:%02x:%02x:%02x:%02x)\r\n",
mac[0]&0xFF, mac[0]>>8, mac[1]&0xFF, mac[1]>>8, mac[2]&0xFF, mac[2]>>8
));
return rc;
}
BOOL SMCWriteEEPROM( UINT16 EEPROMAddress, UINT16 Data )
{
DWORD dwCurTime;
BOOL writeComplete;
UINT16 controlRegister;
OUTREG16(&g_pLAN91C->BANKSEL, 2);
OUTREG16(&g_pLAN91C->PTR, (USHORT)(EEPROMAddress & 0x003F | 0x6000));
OUTREG16(&g_pLAN91C->BANKSEL, 1);
OUTREG16(&g_pLAN91C->GPR, Data);
OUTREG16(&g_pLAN91C->BANKSEL, 1);
controlRegister = INREG16(&g_pLAN91C->CTR);
OUTREG16(&g_pLAN91C->BANKSEL, 1);
OUTREG16(&g_pLAN91C->CTR, (USHORT)(controlRegister | 0x0005));
// Loop until EEPROM data is written
dwCurTime = OEMEthGetSecs();
writeComplete = 1;
while(writeComplete)
{
OUTREG16(&g_pLAN91C->BANKSEL, 1);
writeComplete = INREG16(&g_pLAN91C->CTR) & 0x0003;
if ((OEMEthGetSecs() - dwCurTime) > 5) {
EdbgOutputDebugString("!SMCWriteEEPROM read timed out\n");
return FALSE;
}
}
return TRUE;
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -