示例#1
0
void vlan_init(int numports)
{
	int phyUnit;
	UINT16 phyHwStatus;
	UINT16 timeout;
	int liveLinks = 0;
	UINT32 phyBase = 0;
	BOOL foundPhy = FALSE;
	UINT32 phyAddr;
	UINT32 reg = 0;

	/*
	 * Reset PHYs 
	 */
	for (phyUnit = 0; phyUnit < ADM_PHY_MAX; phyUnit++) {
		if (!ADM_IS_ETHUNIT(phyUnit, 0)) {
			continue;
		}

		phyAddr = ADM_PHYADDR(phyUnit);

		setPhy(phyAddr, ADM_PHY_CONTROL, ADM_CTRL_SOFTWARE_RESET);
	}
	/*
	 * After the phy is reset, it takes a little while before
	 * it can respond properly.
	 */
	sleep(1);
	/*
	 * Verify that the switch is what we think it is, and that it's ready 
	 */
	adm_verifyReady(0);

	/*
	 * LAN SETTING: enable Auto-MDIX 
	 */
	phyAddr = ADM_SW_PHY_PORT0_REG / ADM_PHY_BASE_REG_NUM;
	reg = getPhy(phyAddr, ADM_SW_PHY_PORT0_REG);
	reg |= ADM_SW_AUTO_MDIX_EN;
	setPhy(phyAddr, ADM_SW_PHY_PORT0_REG, reg);

	phyAddr = ADM_SW_PHY_PORT1_REG / ADM_PHY_BASE_REG_NUM;
	reg = getPhy(phyAddr, ADM_SW_PHY_PORT1_REG);
	reg |= ADM_SW_AUTO_MDIX_EN;
	setPhy(phyAddr, ADM_SW_PHY_PORT1_REG, reg);

	phyAddr = ADM_SW_PHY_PORT2_REG / ADM_PHY_BASE_REG_NUM;
	getPhy(phyAddr, ADM_SW_PHY_PORT2_REG);
	reg |= ADM_SW_AUTO_MDIX_EN;
	setPhy(phyAddr, ADM_SW_PHY_PORT2_REG, reg);

	phyAddr = ADM_SW_PHY_PORT3_REG / ADM_PHY_BASE_REG_NUM;
	reg = getPhy(phyAddr, ADM_SW_PHY_PORT3_REG);
	reg |= ADM_SW_AUTO_MDIX_EN;
	setPhy(phyAddr, ADM_SW_PHY_PORT3_REG, reg);

	phyAddr = ADM_SW_PHY_PORT4_REG / ADM_PHY_BASE_REG_NUM;
	reg = getPhy(phyAddr, ADM_SW_PHY_PORT4_REG);
	reg |= ADM_SW_AUTO_MDIX_EN;
	setPhy(phyAddr, ADM_SW_PHY_PORT4_REG, reg);

	phyAddr = ADM_SW_PHY_PORT5_REG / ADM_PHY_BASE_REG_NUM;
	reg = getPhy(phyAddr, ADM_SW_PHY_PORT5_REG);
	reg |= ADM_SW_AUTO_MDIX_EN;
	setPhy(phyAddr, ADM_SW_PHY_PORT5_REG, reg);

	/*
	 * See if there's any configuration data for this enet 
	 */
	for (phyUnit = 0; phyUnit < ADM_PHY_MAX; phyUnit++) {
		if (ADM_ETHUNIT(phyUnit) != 0) {
			continue;
		}

		foundPhy = TRUE;
		break;
	}

	if (!foundPhy) {
		return FALSE;	/* No PHY's configured for this ethUnit */
	}

	/*
	 * start auto negogiation on each phy 
	 */
	for (phyUnit = 0; phyUnit < ADM_PHY_MAX; phyUnit++) {
		if (!ADM_IS_ETHUNIT(phyUnit, 0)) {
			continue;
		}
		phyAddr = ADM_PHYADDR(phyUnit);

		setPhy(phyAddr, ADM_AUTONEG_ADVERT, ADM_ADVERTISE_ALL);

		setPhy(phyAddr, ADM_PHY_CONTROL,
		       ADM_CTRL_AUTONEGOTIATION_ENABLE |
		       ADM_CTRL_START_AUTONEGOTIATION);
	}

	/*
	 * Wait up to .75 seconds for ALL associated PHYs to finish
	 * autonegotiation.  The only way we get out of here sooner is
	 * if ALL PHYs are connected AND finish autonegotiation.
	 */
	timeout = 15;
	for (phyUnit = 0; (phyUnit < ADM_PHY_MAX) /* && (timeout > 0) */ ;
	     phyUnit++) {
		if (!ADM_IS_ETHUNIT(phyUnit, 0)) {
			continue;
		}
		for (;;) {
			phyAddr = ADM_PHYADDR(phyUnit);

			phyHwStatus = getPhy(phyAddr, ADM_PHY_STATUS);

			if (ADM_AUTONEG_DONE(phyHwStatus)) {
				fprintf(stderr,
					"Port %d, Negotiation Success\n",
					phyUnit);
				break;
			}
			if (timeout == 0) {
				fprintf(stderr,
					"Port %d, Negotiation timeout\n",
					phyUnit);
				break;
			}
			if (--timeout == 0) {
				fprintf(stderr,
					"Port %d, Negotiation timeout\n",
					phyUnit);
				break;
			}

			usleep(75);
		}
	}

	/*
	 * All PHYs have had adequate time to autonegotiate.
	 * Now initialize software status.
	 *
	 * It's possible that some ports may take a bit longer
	 * to autonegotiate; but we can't wait forever.  They'll
	 * get noticed by mv_phyCheckStatusChange during regular
	 * polling activities.
	 */
	for (phyUnit = 0; phyUnit < ADM_PHY_MAX; phyUnit++) {

		if (adm_phyIsLinkAlive(phyUnit)) {
			liveLinks++;
			ADM_IS_PHY_ALIVE(phyUnit) = TRUE;
		} else {
			ADM_IS_PHY_ALIVE(phyUnit) = FALSE;
		}

		fprintf(stderr, "adm_phySetup: eth%d phy%d: Phy Status=%4.4x\n",
			0, phyUnit, getPhy(ADM_PHYADDR(phyUnit),
					   ADM_PHY_STATUS));
	}

	config_vlan();
	eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD");
	eval("vconfig", "add", "eth0", "1");
	eval("vconfig", "add", "eth0", "2");
	struct ifreq ifr;
	int s;

	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))) {
		char eabuf[32];

		strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
		ioctl(s, SIOCGIFHWADDR, &ifr);
		char macaddr[32];

		strcpy(macaddr,
		       ether_etoa((unsigned char *)ifr.ifr_hwaddr.sa_data,
				  eabuf));
		nvram_set("et0macaddr", macaddr);
		MAC_ADD(macaddr);
		ether_atoe(macaddr, (unsigned char *)ifr.ifr_hwaddr.sa_data);
		strncpy(ifr.ifr_name, "vlan2", IFNAMSIZ);
		ioctl(s, SIOCSIFHWADDR, &ifr);
		close(s);
	}

}
示例#2
0
BOOL
adm_phySetup(int ethUnit)
{
    int     phyUnit, global;
    uint16_t  phyHwStatus;
    uint16_t  timeout;
    int     liveLinks = 0;
    uint32_t  phyBase = 0;
    BOOL    foundPhy = FALSE;
    uint32_t  phyAddr;
    static int inited = 0;
    
    /* Reset PHYs*/
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        phyBase = ADM_PHYBASE(phyUnit);
        phyAddr = ADM_PHYADDR(phyUnit);

        phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL,
                    ADM_CTRL_SOFTWARE_RESET);
    }
    /*
     * After the phy is reset, it takes a little while before
     * it can respond properly.
     */
    sysMsDelay(300);

    /* See if there's any configuration data for this enet */
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        phyBase = ADM_PHYBASE(phyUnit);
        foundPhy = TRUE;
        break;
    }

    if (!foundPhy) {
        return FALSE; /* No PHY's configured for this ethUnit */
    }

    /* start auto negogiation on each phy */
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        phyBase = ADM_PHYBASE(phyUnit);
        phyAddr = ADM_PHYADDR(phyUnit);
        
        phy_reg_write(phyBase, phyAddr, ADM_AUTONEG_ADVERT,
                                        ADM_ADVERTISE_ALL);

        phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL,
                    ADM_CTRL_AUTONEGOTIATION_ENABLE | ADM_CTRL_START_AUTONEGOTIATION);
    }

    /*
     * Wait up to .75 seconds for ALL associated PHYs to finish
     * autonegotiation.  The only way we get out of here sooner is
     * if ALL PHYs are connected AND finish autonegotiation.
     */
    timeout=5;
    for (phyUnit=0; (phyUnit < ADM_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }
        for (;;) {
            phyBase = ADM_PHYBASE(phyUnit);
            phyAddr = ADM_PHYADDR(phyUnit);

            phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS);

            if (ADM_AUTONEG_DONE(phyHwStatus)) {
                DRV_PRINT(DRV_DEBUG_PHYSETUP,
                          ("Port %d, Neg Success\n", phyUnit));
                break;
            }
            if (timeout == 0) {
                DRV_PRINT(DRV_DEBUG_PHYSETUP,
                          ("Port %d, Negogiation timeout\n", phyUnit));
                break;
            }
            if (--timeout == 0) {
                DRV_PRINT(DRV_DEBUG_PHYSETUP,
                          ("Port %d, Negogiation timeout\n", phyUnit));
                break;
            }

            sysMsDelay(150);
        }
    }

    /*
     * All PHYs have had adequate time to autonegotiate.
     * Now initialize software status.
     *
     * It's possible that some ports may take a bit longer
     * to autonegotiate; but we can't wait forever.  They'll
     * get noticed by mv_phyCheckStatusChange during regular
     * polling activities.
     */
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        if (adm_phyIsLinkAlive(phyUnit)) {
            liveLinks++;
            ADM_IS_PHY_ALIVE(phyUnit) = TRUE;
        } else {
            ADM_IS_PHY_ALIVE(phyUnit) = FALSE;
        }

        DRV_PRINT(DRV_DEBUG_PHYSETUP,
            ("eth%d: Phy Status=%4.4x\n",
            ethUnit, 
            phy_reg_read(ADM_PHYBASE(phyUnit),
                       ADM_PHYADDR(phyUnit),
                       ADM_PHY_STATUS)));
    }

    /*
     * XXX
     */
    phy_reg_write(0, 0, 0x10, 0x50);
    return (liveLinks > 0);
}
示例#3
0
int
adm_phyIsUp(int ethUnit)
{

    int           phyUnit;
    uint16_t        phyHwStatus;
    admPhyInfo_t   *lastStatus;
    int           linkCount   = 0;
    int           lostLinks   = 0;
    int           gainedLinks = 0;
    uint32_t        phyBase;
    uint32_t        phyAddr;

    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        phyBase = ADM_PHYBASE(phyUnit);
        phyAddr = ADM_PHYADDR(phyUnit);


        lastStatus = &admPhyInfo[phyUnit];
        phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS);

        if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
            /* See if we've lost link */
            if (phyHwStatus & ADM_STATUS_LINK_PASS) {
                linkCount++;
            } else {
                lostLinks++;
#ifdef COBRA_TODO
                mv_flushATUDB(phyUnit);
#endif
                DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n",
                                               ethUnit, phyUnit));
                lastStatus->isPhyAlive = FALSE;
            }
        } else { /* last known link status was DEAD */
            /* Check for AutoNegotiation complete */
            if (ADM_AUTONEG_DONE(phyHwStatus)) {
                //printk("autoneg done\n");
                gainedLinks++;
                linkCount++;
                DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n",
                                               ethUnit, phyUnit));
                lastStatus->isPhyAlive = TRUE;
            }
        }
    }

    return (linkCount);

#if 0
    if (linkCount == 0) {
        if (lostLinks) {
            /* We just lost the last link for this MAC */
            phyLinkLost(ethUnit);
        }
    } else {
        if (gainedLinks == linkCount) {
            /* We just gained our first link(s) for this MAC */
            phyLinkGained(ethUnit);
        }
    }
#endif
}
示例#4
0
文件: adm_phy.c 项目: janfj/dd-wrt
BOOL
adm_phySetup(int ethUnit)
{
    int     phyUnit;
    uint16_t  phyHwStatus;
    uint16_t  timeout;
    int     liveLinks = 0;
    uint32_t  phyBase = 0;
    BOOL    foundPhy = FALSE;
    uint32_t  phyAddr;
    
    /* Reset PHYs*/
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        phyBase = ADM_PHYBASE(phyUnit);
        phyAddr = ADM_PHYADDR(phyUnit);

        phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL,
                    ADM_CTRL_SOFTWARE_RESET);
    }
    /*
     * After the phy is reset, it takes a little while before
     * it can respond properly.
     */
    mdelay(300);

    /* See if there's any configuration data for this enet */
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        phyBase = ADM_PHYBASE(phyUnit);
        foundPhy = TRUE;
        break;
    }

    if (!foundPhy) {
        return FALSE; /* No PHY's configured for this ethUnit */
    }

    /* start auto negogiation on each phy */
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        phyBase = ADM_PHYBASE(phyUnit);
        phyAddr = ADM_PHYADDR(phyUnit);
        
        phy_reg_write(phyBase, phyAddr, ADM_AUTONEG_ADVERT,
                                        ADM_ADVERTISE_ALL);

        phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL,
                    ADM_CTRL_AUTONEGOTIATION_ENABLE | ADM_CTRL_START_AUTONEGOTIATION);
    }

    /*
     * Wait up to .75 seconds for ALL associated PHYs to finish
     * autonegotiation.  The only way we get out of here sooner is
     * if ALL PHYs are connected AND finish autonegotiation.
     */
    timeout=5;
    for (phyUnit=0; (phyUnit < ADM_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }
        for (;;) {
            phyBase = ADM_PHYBASE(phyUnit);
            phyAddr = ADM_PHYADDR(phyUnit);

            phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS);

            if (ADM_AUTONEG_DONE(phyHwStatus)) {
                DRV_PRINT(DRV_DEBUG_PHYSETUP,
                          ("Port %d, Neg Success\n", phyUnit));
                break;
            }
            if (timeout == 0) {
                DRV_PRINT(DRV_DEBUG_PHYSETUP,
                          ("Port %d, Negogiation timeout\n", phyUnit));
                break;
            }
            if (--timeout == 0) {
                DRV_PRINT(DRV_DEBUG_PHYSETUP,
                          ("Port %d, Negogiation timeout\n", phyUnit));
                break;
            }

            mdelay(150);
        }
    }

    /*
     * All PHYs have had adequate time to autonegotiate.
     * Now initialize software status.
     *
     * It's possible that some ports may take a bit longer
     * to autonegotiate; but we can't wait forever.  They'll
     * get noticed by mv_phyCheckStatusChange during regular
     * polling activities.
     */
    for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) {
        if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) {
            continue;
        }

        if (adm_phyIsLinkAlive(phyUnit)) {
            liveLinks++;
            ADM_IS_PHY_ALIVE(phyUnit) = TRUE;
        } else {
            ADM_IS_PHY_ALIVE(phyUnit) = FALSE;
        }

        DRV_PRINT(DRV_DEBUG_PHYSETUP,
            ("eth%d: Phy Status=%4.4x\n",
            ethUnit, 
            phy_reg_read(ADM_PHYBASE(phyUnit),
                       ADM_PHYADDR(phyUnit),
                       ADM_PHY_STATUS)));
    }

#ifdef CONFIG_MV6060
	/* added by lsz 30Apri07 to configure port vlan registers */
	
/****************************************************************************
	Port VLan:
	
	 ---------------------------------------------------------------
	|	| Port6	         | Port5	| Port4	        | Port3	        | Port2	        | Port1	        | Port0	|
	 ---------------------------------------------------------------
	| Port0	|	0	|	1	|	0	|	0	|	0	|	0	|	0	|
	 ---------------------------------------------------------------
	| Port1	|	0	|	1	|	1	|	1	|	1	|	0	|	0	|
	 ---------------------------------------------------------------
	| Port2	|	0	|	1	|	1	|	1	|	0	|	1	|	0	|
	 ---------------------------------------------------------------
	| Port3	|	0	|	1	|	1	|	0	|	1	|	1	|	0	|
	 ---------------------------------------------------------------
	| Port4	|	0	|	1	|	0	|	1	|	1	|	1	|	0	|
	 ---------------------------------------------------------------
	| Port5	|	0	|	0	|	1	|	1	|	1	|	1	|	1	|
	 ---------------------------------------------------------------
	| Port6	|	0	|	0	|	0	|	0	|	0	|	0	|	0	|
	 ---------------------------------------------------------------
	 
	Port 0:		Wan
	Port 1~4:	Lan

	e.g. Port 0 is 010 0000, i.e. 0x20.
****************************************************************************/
	#define PORT_VALN_MAP_REG	0x06
	uint32_t portAddr[7] = {0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE};
	
	phy_reg_write(0, portAddr[0], PORT_VALN_MAP_REG, 0x103E);
	phy_reg_write(0, portAddr[1], PORT_VALN_MAP_REG, 0x103D);
	phy_reg_write(0, portAddr[2], PORT_VALN_MAP_REG, 0x103B);
	phy_reg_write(0, portAddr[3], PORT_VALN_MAP_REG, 0x1037);
	phy_reg_write(0, portAddr[4], PORT_VALN_MAP_REG, 0x102F);
	phy_reg_write(0, portAddr[5], PORT_VALN_MAP_REG, 0x101F);

/*	phy_reg_write(0, portAddr[0], PORT_VALN_MAP_REG, 0x1020);
	phy_reg_write(0, portAddr[1], PORT_VALN_MAP_REG, 0x103C);
	phy_reg_write(0, portAddr[2], PORT_VALN_MAP_REG, 0x103A);
	phy_reg_write(0, portAddr[3], PORT_VALN_MAP_REG, 0x1036);
	phy_reg_write(0, portAddr[4], PORT_VALN_MAP_REG, 0x102E);
	phy_reg_write(0, portAddr[5], PORT_VALN_MAP_REG, 0x101F);*/
	//phy_reg_write(0, portAddr[6], PORT_VALN_MAP_REG, 0x0000);
	
	/* added by lsz to configure header mode registers */
	#define PORT_CONTROL_REG	0x04
	uint16_t reg_data = 0x8803;	/* Flow Control | Header Mode | Forwarding */
	
	phy_reg_write(0, portAddr[0], PORT_CONTROL_REG, 0x8003);
	phy_reg_write(0, portAddr[1], PORT_CONTROL_REG, 0x8003);
	phy_reg_write(0, portAddr[2], PORT_CONTROL_REG, 0x8003);
	phy_reg_write(0, portAddr[3], PORT_CONTROL_REG, 0x8003);
	phy_reg_write(0, portAddr[4], PORT_CONTROL_REG, 0x8003);
	phy_reg_write(0, portAddr[5], PORT_CONTROL_REG, 0x8003);
	phy_reg_write(0, 0x1E, PORT_CONTROL_REG, reg_data);

#else
    /*
     * XXX
     */
    phy_reg_write(0, 0, 0x10, 0x50);
#endif
    return (liveLinks > 0);
}