⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 enetlib.c

📁 Ibmstb02500 miniboot 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
      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 + -