📄 enetlib.c
字号:
dev.ctl_rspeed = 10;#ifdef DEBUG_MSG_SETSPEED s1printf ("SMSC SPEED: 10Mbs\n");#endif rtn &= ~PHY_CNTL_SPEED ; /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CNTL_REG, rtn); } if( dev.ctl_autoneg ) {#ifdef DEBUG_MSG_SETSPEED s1printf ("Smsc91c110 AutoNeg.: Enabled\n");#endif rtn |= PHY_CNTL_ANEG_EN; /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CNTL_REG, rtn); } else {#ifdef DEBUG_MSG_SETSPEED s1printf ("Smsc91c110 AutoNeg.: Disabled\n");#endif rtn &= ~PHY_CNTL_ANEG_EN; /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CNTL_REG, rtn); } }/********************************************************************************* SetDuplex - sets the duples mode of the device** sets the duplex of the device.** RETURNS: N/A*/static void SetDuplex ( int duplex, /* deuplex flag */ int autoNeg /* auto negotiation flag */ ) { unsigned int PHYAddr = dev.phyaddr; unsigned int rtn; /* Read PHY_CONTROL Register */ rtn = phy_readreg ( PHYAddr, PHY_CNTL_REG ); if( duplex ) { rtn |= PHY_CNTL_DPLX; /* autoNegotiation flag */ if( dev.ctl_autoneg ) rtn |= PHY_CNTL_ANEG_EN; else rtn &= ~PHY_CNTL_ANEG_EN; /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CNTL_REG, rtn);#if 0 // YYD rtn = phy_readreg( PHYAddr, PHY_83C180_SPEC ); rtn |= PHY_83C180_SPEC_FDPLX ; phy_writereg( PHYAddr, PHY_83C180_SPEC, rtn ); /* Must leave in or FDUPLEX will not work! */ rtn = phy_readreg( PHYAddr, PHY_83C180_SPEC );#endif /* set MAC to same duplex as PHY */ out16( ENET_IO_ADDR + BANK_SELECT, 0x00); rtn = in16( ENET_IO_ADDR + TCR_REG ); rtn |= TCR_SWFDUP; out16 (ENET_IO_ADDR + TCR_REG, rtn ); dev.ctl_rfduplx = 1;#ifdef DEBUG_MSG_SETDUPLEX s1printf ("SMSC DUPLEX: FULL\n");#endif } else { rtn &= ~PHY_CNTL_DPLX; /* autoNegotiation flag */ if( dev.ctl_autoneg ) rtn |= PHY_CNTL_ANEG_EN; else rtn &= ~PHY_CNTL_ANEG_EN; /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CNTL_REG, rtn);#if 0 // YYD rtn = phy_readreg( PHYAddr, PHY_83C180_SPEC ); rtn &= ~PHY_83C180_SPEC_FDPLX ; phy_writereg( PHYAddr, PHY_83C180_SPEC, rtn ); /* Must leave in or FDUPLEX will not work! */ rtn = phy_readreg( PHYAddr, PHY_83C180_SPEC );#endif /* set MAC to same duplex as PHY */ out16( ENET_IO_ADDR + BANK_SELECT, 0x00); rtn = in16( ENET_IO_ADDR + TCR_REG ); rtn &= ~TCR_SWFDUP; out16 (ENET_IO_ADDR + TCR_REG, rtn ); dev.ctl_rfduplx = 0;#ifdef DEBUG_MSG_SETDUPLEX s1printf ("SMSC DUPLEX: HALF\n");#endif } }/********************************************************************************* PHYReset - Reset the PHY module** This function resets the 83C180 PHY chip.** RETURNS: N/A*/static void PHYReset () { unsigned int PHYAddr; unsigned int rtn, tout; unsigned int setVal; unsigned int id1; unsigned int id2; unsigned int reg; PHYAddr = dev.phyaddr; // YYD { // YYD#ifdef DEBUG_MSG_PHYRESET s1printf("Physical Reset ..\n");#endif phy_writereg ( PHYAddr, PHY_CNTL_REG, PHY_CNTL_RST ); tout = 30; // 3 seconds while((phy_readreg ( PHYAddr, PHY_CNTL_REG ) & PHY_CNTL_RST) && tout ) { msdelay(100); tout--; } if(!tout) { s1printf("Physical Reset Fail\n"); return; } } // YYD, someone suggest to set the transmit levels rtn = phy_readreg ( PHYAddr, PHY_CFG1_REG ); /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CFG1_REG, (rtn & ~(PHY_CFG1_TLVL_MASK << PHY_CFG1_TLVL_SHIFT)) | (SMC_TLVL<< PHY_CFG1_TLVL_SHIFT) ); #ifdef DEBUG_MSG_PHYRESET s1printf("Physical Config1 = %08x\n", phy_readreg ( PHYAddr, PHY_CFG1_REG ));#endif /* REVISIT: ISOLATE bit after a SW reset. * * There seems to be a problem with either the chip or the * documentation for the chip in the fact that it defaults to * the ISOLATE bit being left on. This means that no * transmissions are made. Therefore the following code * ensures that this bit is not on. That happens after a SW reset. * Also reset the MII_DISABLE bit. */ rtn = phy_readreg ( PHYAddr, PHY_CNTL_REG ); /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CNTL_REG, rtn & ~PHY_CNTL_ISOLATE ); rtn = phy_readreg(PHYAddr, PHY_CNTL_REG );#ifdef DEBUG_MSG_PHYRESET s1printf("Read PHY_CONTROL Register after isolate bit 0x%x\n", rtn );#endif msdelay(10); /* Read PHY's ID registers to make sure it's the SMSC 83C180 */ id1=phy_readreg( PHYAddr,PHY_ID1_REG); id2=phy_readreg( PHYAddr,PHY_ID2_REG);#ifdef DEBUG_MSG_PHYRESET s1printf("id1=%X id2=%X\n", id1, id2); // YYD#endif msdelay(50); //YYD: It's tricky that this delay is a must for the Autonegotiate to work. // Could this be a potential unspotted bug somewhere ? if ( id1 != 0x0016 || ( id2 & 0xfff0) != 0xf840 ) // check for smc91c111 internel phy chip { s1printf("SMSC: PHY chip not supported\n"); return; } if (dev.ctl_autoneg) { /* Enable PHY auto negotiation mode */ out16( ENET_IO_ADDR + BANK_SELECT, 0x00 ); reg = in16(ENET_IO_ADDR + RPC_REG); out16(ENET_IO_ADDR + RPC_REG, reg | RPC_ANEG); phy_writereg ( PHYAddr, PHY_CNTL_REG, PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST); rtn = phy_readreg( PHYAddr, PHY_CNTL_REG );#ifdef DEBUG_MSG_PHYRESET s1printf("SMSC: after new ANEG %x\n", rtn ) ;#endif /* Poll the NWAY complete bit... */ tout = 400; // 40 seconds#ifdef DEBUG_MSG_PHYRESET s1printf("AutoNegotiation in progress...\n");#endif s1printf("Dectecting net speed .. "); while( !((rtn = phy_readreg( PHYAddr, PHY_STAT_REG )) & PHY_STAT_ANEG_ACK) && tout ) {#ifdef DEBUG_MSG_PHYRESET s1printf("SMSC: SHY_STATUS = %04x\n", rtn);#endif if(rtn & PHY_STAT_REM_FLT) // remote fault {#ifdef DEBUG_MSG_PHYRESET s1printf("SMSC: remote fault\n");#endif phy_writereg ( PHYAddr, PHY_CNTL_REG, PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST); } msdelay(100); // delay 100ms tout--; if(tout%5) spinning(); } s1printf("\r"); if( tout == 0 ) { phy_readreg( PHYAddr, PHY_STAT_REG ); // clear the latched link status msdelay(50); if(!(phy_readreg( PHYAddr, PHY_STAT_REG ) & PHY_STAT_LINK)) // the link is not valid { s1printf("Network is not connected, please check your cable.\n"); } s1printf( "SMSC: PHY AutoNegotiate timeout. Assume 10Mbps/half duplex\n"); SetSpeed( 0, 1/*0*/); /* Set to 10Mbs, YYD, try to enable autoneg */ SetDuplex(0, 1/*0*/); /* Set to half duplex */ } else { rtn = phy_readreg( PHYAddr, PHY_INT_REG ); msdelay(10);#ifdef DEBUG_MSG_PHYRESET s1printf( "SMSC: PHY AutoNegotiate %x %x \n", rtn); // YYD#endif rtn = phy_readreg( PHYAddr, PHY_INT_REG ); // YYD s1printf("Ethernet:"); s1printf(" Link speed = %dMbps", rtn & PHY_INT_SPDDET ? 100 : 10); s1printf(" Duplex = %s\n", rtn & PHY_INT_DPLXDET ? "full" : "half"); SetSpeed( rtn & PHY_INT_SPDDET,1); // YYD SetDuplex(rtn & PHY_INT_DPLXDET,1); // YYD } } else { /* Configure the PHY for No Auto-Negotiation; No Isolation; * No Loopback; */ /* 10 or 100 BaseT; Half or Full Duplex Operation */ /* Zero the PHY_CONTROL Register */ setVal = 0; phy_writereg ( PHYAddr, PHY_CNTL_REG, setVal ); /* Read PHY_CONTROL Register */ /* Set to 10Mbits per sec if necessary */ if( dev.ctl_rspeed != 0 ) { /* set 100Mbs */ SetSpeed(1,0); } else { /* set 10Mbs */ SetSpeed(0,0); } /* Set to Half or Full Duplex if necessary */ if( dev.ctl_rfduplx !=0 ) { /* set Full duplex */ SetDuplex(1,0); } else { /* set Half duplex */ SetDuplex(0,0); } } }/********************************************************************************* enet_reset - reset SMSC91cxx chip** This routine disables interrupts, configures the smsc91cxx chip,* enables MII and AUI support, resets and initializes the PHY chip.** RETURNS: N/A*/static void enet_reset ( ){ unsigned int config;#ifdef DEBUG_MSG_ENETRESET s1printf ( "Enet Reset!\n");#endif /* SoftWare reset */ out16( ENET_IO_ADDR + BANK_SELECT, 0x00) ; out16 (ENET_IO_ADDR + RCR_REG, RCR_SOFTRST); nsdelay(1000000); out16 (ENET_IO_ADDR + RCR_REG, 0x0000); nsdelay(100000); /* Disable RX and TX */ out16 (ENET_IO_ADDR + TCR_REG, 0x0000); // YYD, reconfig the LEDs out16 (ENET_IO_ADDR + RPC_REG, (in16(ENET_IO_ADDR + RPC_REG)&0xff00) | (RPC_LED_100_10 <<RPC_LSXA_SHFT) | (RPC_LED_TX_RX << RPC_LSXB_SHFT)); nsdelay(100000000); /* Disable interrupts */ out16(ENET_IO_ADDR + INT_REG, 0); /* Reset the PHY chip */ PHYReset( ); /* Configure: TX auto release */ out16( ENET_IO_ADDR + BANK_SELECT, 0x01); out16 (ENET_IO_ADDR + CTL_REG, in16 (ENET_IO_ADDR + CTL_REG) | CTL_AUTO_RELEASE /* Auto Release */ | CTL_LE_ENABLE /* Link error enable */ ); /* The BW has an RJ45 connector with MII Support, */ /* and AUISEL drives PHY reset... */ out16( ENET_IO_ADDR + BANK_SELECT, 0x01); config = in16 (ENET_IO_ADDR + CONFIG_REG); out16 (ENET_IO_ADDR + CONFIG_REG, config | CONFIG_EPH_POWER_EN /* EPH power enable */ ); /* MMU reset */ out16( ENET_IO_ADDR + BANK_SELECT, 0x02); out16 (ENET_IO_ADDR + MMU_CMD_REG, MC_RESET);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -