예제 #1
0
파일: robocfg.c 프로젝트: hajuuk/asuswrt
/* checks that attached switch is 5325/5352/5354/5356/5357/53115/5301x */
static int robo_vlan535x(robo_t *robo, u32 phyid)
{
#ifdef BCM5301X
	if ((robo_read32(robo, ROBO_MGMT_PAGE, ROBO_DEVICE_ID) & 0xfffffff0) == 0x53010)
		return 5;
#else
	/* set vlan access id to 15 and read it back */
	u16 val16 = 15;
	robo_write16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
	
	/* 5365 will refuse this as it does not have this reg */
	if (robo_read16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) != val16)
		return 0;
	/* gigabit ? */
	if (robo->et != 1 && (mdio_read(robo, 0, ROBO_MII_STAT) & 0x0100))
		robo->gmii = ((mdio_read(robo, 0, 0x0f) & 0xf000) != 0);
	/* 53115 ? */
	if (robo->gmii && robo_read32(robo, ROBO_STAT_PAGE, ROBO_LSA_IM_PORT) != 0) {
		robo_write16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395, val16);
		robo_write16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395,
					 (1 << 7) /* start */ | 1 /* read */);
		if (robo_read16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395) == 1
		    && robo_read16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395) == val16)
			return 4;
	}
	/* dirty trick for 5356/5357 */
	if ((phyid & 0xfff0ffff ) == 0x5da00362 ||
	    (phyid & 0xfff0ffff ) == 0x5e000362)
		return 3;
	/* 5325/5352/5354*/
	return 1;
#endif
}
예제 #2
0
파일: switch-robo.c 프로젝트: aircross/ray
static int robo_switch_enable(void)
{
	unsigned int i, last_port;
	u16 val;

	val = robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE);
	if (!(val & (1 << 1))) {
		/* Unmanaged mode */
		val &= ~(1 << 0);
		/* With forwarding */
		val |= (1 << 1);
		robo_write16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, val);
		val = robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE);
		if (!(val & (1 << 1))) {
			printk("Failed to enable switch\n");
			return -EBUSY;
		}

		last_port = (robo.devid == ROBO_DEVICE_ID_5398) ?
				ROBO_PORT6_CTRL : ROBO_PORT3_CTRL;
		for (i = ROBO_PORT0_CTRL; i < last_port + 1; i++)
			robo_write16(ROBO_CTRL_PAGE, i, 0);
	}

	/* WAN port LED */
	robo_write16(ROBO_CTRL_PAGE, 0x16, 0x1F);

	return 0;
}
예제 #3
0
static int handle_vlan_port_read(void *driver, char *buf, int nr)
{
	__u16 val16;
	int len = 0;
	int j;

	val16 = (nr) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
	
	if (is_5350) {
		u32 val32;
		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
		/* actual read */
		val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
		if ((val32 & (1 << 20)) /* valid */) {
			for (j = 0; j < 6; j++) {
				if (val32 & (1 << j)) {
					len += sprintf(buf + len, "%d", j);
					if (val32 & (1 << (j + 6))) {
						if (j == 5) buf[len++] = 'u';
					} else {
						buf[len++] = 't';
						if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
							buf[len++] = '*';
					}
					buf[len++] = '\t';
				}
			}
			len += sprintf(buf + len, "\n");
		}
	} else { 
		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
		/* actual read */
		val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
		if ((val16 & (1 << 14)) /* valid */) {
			for (j = 0; j < 6; j++) {
				if (val16 & (1 << j)) {
					len += sprintf(buf + len, "%d", j);
					if (val16 & (1 << (j + 7))) {
						if (j == 5) buf[len++] = 'u';
					} else {
						buf[len++] = 't';
						if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
							buf[len++] = '*';
					}
					buf[len++] = '\t';
				}
			}
			len += sprintf(buf + len, "\n");
		}
	}

	buf[len] = '\0';

	return len;
}
예제 #4
0
/* checks that attached switch is 5325E/5350 */
static int robo_vlan5350()
{
	/* set vlan access id to 15 and read it back */
	__u16 val16 = 15;
	robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
	
	/* 5365 will refuse this as it does not have this reg */
	return (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) == val16);
}
예제 #5
0
static int robo_switch_enable(void)
{
	unsigned int i, last_port;
	u16 val;
#ifdef CONFIG_BCM47XX
	char buf[20];
#endif

	val = robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE);
	if (!(val & (1 << 1))) {
		/* Unmanaged mode */
		val &= ~(1 << 0);
		/* With forwarding */
		val |= (1 << 1);
		robo_write16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, val);
		val = robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE);
		if (!(val & (1 << 1))) {
			printk("Failed to enable switch\n");
			return -EBUSY;
		}

		last_port = (robo.devid == ROBO_DEVICE_ID_5398) ?
				ROBO_PORT6_CTRL : ROBO_PORT3_CTRL;
		for (i = ROBO_PORT0_CTRL; i < last_port + 1; i++)
			robo_write16(ROBO_CTRL_PAGE, i, 0);
	}

#ifdef CONFIG_BCM47XX
	/* WAN port LED, except for Netgear WGT634U */
	if (nvram_getenv("nvram_type", buf, sizeof(buf)) >= 0) {
		if (strcmp(buf, "cfe") != 0)
			robo_write16(ROBO_CTRL_PAGE, 0x16, 0x1F);
	}
#endif
	return 0;
}
예제 #6
0
파일: switch-robo.c 프로젝트: cilynx/dd-wrt
static int handle_vlan_port_read(char *buf, int nr)
{
	__u16 val16;
	int len = 0;
	int j;

	val16 = (nr) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
	
	if (is_5350) {
		u32 val32;
		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
		/* actual read */
		val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
		if ((val32 & (1 << 20)) /* valid */) {
			for (j = 0; j < 6; j++) {
				if (val32 & (1 << j)) {
					len += sprintf(buf + len, "%d%s\t", j, 
						(val32 & (1 << (j + 6))) ? (j == 5 ? "u" : "") : "t");
				}
			}
			len += sprintf(buf + len, "\n");
		}
	} else { 
		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
		/* actual read */
		val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
		if ((val16 & (1 << 14)) /* valid */) {
			for (j = 0; j < 6; j++) {
				if (val16 & (1 << j)) {
					len += sprintf(buf + len, "%d%s\t", j, (val16 & (1 << (j + 7))) ? 
						(j == 5 ? "u" : "") : "t");
				}
			}
			len += sprintf(buf + len, "\n");
		}
	}

	return len;
}
예제 #7
0
static int handle_enable_vlan_read(void *driver, char *buf, int nr)
{
	return sprintf(buf, "%d\n", (((robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0) & (1 << 7)) == (1 << 7)) ? 1 : 0));
}
예제 #8
0
static int handle_enable_read(void *driver, char *buf, int nr)
{
	return sprintf(buf, "%d\n", (((robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & 2) == 2) ? 1 : 0));
}
예제 #9
0
파일: robocfg.c 프로젝트: hajuuk/asuswrt
int
main(int argc, char *argv[])
{
	u16 val16;
	u32 val32;
	u16 mac[3];
	int i = 0, j;
	int robo535x = 0; /* 0 - 5365, 1 - 5325/5352/5354, 3 - 5356, 4 - 53115, 5 - 5301x */
	u32 phyid;
	
	static robo_t robo;
	struct ethtool_drvinfo info;
	
	if ((robo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		exit(1);
	}

	/* the only interface for now */
	strcpy(robo.ifr.ifr_name, "eth0");

	memset(&info, 0, sizeof(info));
	info.cmd = ETHTOOL_GDRVINFO;
	robo.ifr.ifr_data = (caddr_t)&info;
	if (ioctl(robo.fd, SIOCETHTOOL, (caddr_t)&robo.ifr) < 0) {
		perror("SIOCETHTOOL: your ethernet module is either unsupported or outdated");
		exit(1);
	} else
	if (strcmp(info.driver, "et0") && strcmp(info.driver, "et1") &&
	    strcmp(info.driver, "b44")) {
		fprintf(stderr, "No suitable module found for %s (managed by %s)\n", 
			robo.ifr.ifr_name, info.driver);
		exit(1);
	}
	
	/* try access using MII ioctls - get phy address */
	if (ioctl(robo.fd, SIOCGMIIPHY, &robo.ifr) < 0) {
		int args[2] = { ROBO_PHY_ADDR << 16, 0x0 };

		robo.ifr.ifr_data = (caddr_t) args;
		if (ioctl(robo.fd, SIOCGETCPHYRD2, &robo.ifr) < 0)
			robo.et = 1;
		else	robo.et = 2;
	} else {
		/* got phy address check for robo address */
		struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo.ifr.ifr_data;
		if (mii->phy_id != ROBO_PHY_ADDR) {
			fprintf(stderr, "Invalid phy address (%d)\n", mii->phy_id);
			exit(1);
		}
	}

	phyid = mdio_read(&robo, ROBO_PHY_ADDR, 0x2) | 
		(mdio_read(&robo, ROBO_PHY_ADDR, 0x3) << 16);
	if (phyid == 0 && robo.et != 1)
	    phyid = mdio_read(&robo, 0, 0x2) | 
			(mdio_read(&robo, 0, 0x3) << 16);

	if (phyid == 0xffffffff || phyid == 0x55210022) {
		fprintf(stderr, "No Robo switch in managed mode found\n");
		exit(1);
	}
	
	robo535x = robo_vlan535x(&robo, phyid);
	/* fprintf(stderr, "phyid %08x id %d\n", phyid, robo535x); */
	
	for (i = 1; i < argc;) {
		if (strcasecmp(argv[i], "showmacs") == 0)
		{
			/* show MAC table of switch */
			u16 buf[6];
			int idx, off, base_vlan;

			base_vlan = 0; /*get_vid_by_idx(&robo, 0);*/

			printf(
				"--------------------------------------\n"
				"VLAN  MAC                Type     Port\n"
				"--------------------------------------\n");
			robo_write16(&robo, ROBO_ARLIO_PAGE, ROBO_ARL_RW_CTRL, 0x81);
			robo_write16(&robo, ROBO_ARLIO_PAGE, (robo535x >= 4) ?
			    ROBO_ARL_SEARCH_CTRL_53115 : ROBO_ARL_SEARCH_CTRL, 0x80);
			for (idx = 0; idx < ((robo535x >= 4) ?
				NUM_ARL_TABLE_ENTRIES_53115 : robo535x ?
				NUM_ARL_TABLE_ENTRIES_5350 : NUM_ARL_TABLE_ENTRIES); idx++)
			{
				if (robo535x >= 4)
				{
					off = (idx & 0x01) << 4;
					if (!off && (robo_read16(&robo, ROBO_ARLIO_PAGE,
					    ROBO_ARL_SEARCH_CTRL_53115) & 0x80) == 0) break;
					robo_read(&robo, ROBO_ARLIO_PAGE,
					    ROBO_ARL_SEARCH_RESULT_53115 + off, buf, 4);
					robo_read(&robo, ROBO_ARLIO_PAGE,
					    ROBO_ARL_SEARCH_RESULT_EXT_53115 + off, &buf[4], 2);
				} else
					robo_read(&robo, ROBO_ARLIO_PAGE, ROBO_ARL_SEARCH_RESULT, 
					    buf, robo535x ? 4 : 5);
				if ((robo535x >= 4) ? (buf[5] & 0x01) : (buf[3] & 0x8000) /* valid */)
				{
					printf("%04i  %02x:%02x:%02x:%02x:%02x:%02x  %7s  %c\n",
						(base_vlan | (robo535x >= 4) ?
						    (base_vlan | (buf[3] & 0xfff)) :
						    ((buf[3] >> 5) & 0x0f) |
							(robo535x ? 0 : ((buf[4] & 0x0f) << 4))),
						buf[2] >> 8, buf[2] & 255, 
						buf[1] >> 8, buf[1] & 255,
						buf[0] >> 8, buf[0] & 255,
						((robo535x >= 4 ?
						    (buf[4] & 0x8000) : (buf[3] & 0x4000)) ? "STATIC" : "DYNAMIC"),
						((robo535x >= 4) ?
						    '0'+(buf[4] & 0x0f) : ports[buf[3] & 0x0f])
					);
				}
			}
			i++;
		} else
예제 #10
0
파일: robocfg.c 프로젝트: hajuuk/asuswrt
static inline u16 mdio_read(robo_t *robo, u16 phy_id, u8 reg)
{
	return robo_read16(robo, 0x10 + phy_id, reg);
}
예제 #11
0
static int robo_probe(char *devname)
{
	__u32 phyid;
	unsigned int i;
	int err = 1;

	printk(KERN_INFO PFX "Probing device %s: ", devname);
	strcpy(robo.ifr.ifr_name, devname);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
	if ((robo.dev = dev_get_by_name(devname)) == NULL) {
#else
	if ((robo.dev = dev_get_by_name(&init_net, devname)) == NULL) {
#endif
		printk("No such device\n");
		return 1;
	}

	robo.device = devname;
	for (i = 0; i < 5; i++)
		robo.port[i] = i;
	robo.port[5] = 8;

	/* try access using MII ioctls - get phy address */
	if (do_ioctl(SIOCGMIIPHY, NULL) < 0) {
		robo.use_et = 1;
		robo.phy_addr = ROBO_PHY_ADDR;
	} else {
		/* got phy address check for robo address */
		struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &robo.ifr.ifr_data;
		if ((mii->phy_id != ROBO_PHY_ADDR) &&
		    (mii->phy_id != ROBO_PHY_ADDR_BCM63XX) &&
		    (mii->phy_id != ROBO_PHY_ADDR_TG3)) {
			printk("Invalid phy address (%d)\n", mii->phy_id);
			goto done;
		}
		robo.use_et = 0;
		/* The robo has a fixed PHY address that is different from the
		 * Tigon3 and BCM63xx PHY address. */
		robo.phy_addr = ROBO_PHY_ADDR;
	}

	phyid = mdio_read(robo.phy_addr, 0x2) | 
		(mdio_read(robo.phy_addr, 0x3) << 16);

	if (phyid == 0xffffffff || phyid == 0x55210022) {
		printk("No Robo switch in managed mode found, phy_id = 0x%08x\n", phyid);
		goto done;
	}

	/* Get the device ID */
	for (i = 0; i < 10; i++) {
		robo.devid = robo_read16(ROBO_MGMT_PAGE, ROBO_DEVICE_ID);
		if (robo.devid)
			break;
		udelay(10);
	}
	if (!robo.devid)
		robo.devid = ROBO_DEVICE_ID_5325; /* Fake it */
	robo.is_5350 = robo_vlan5350();

	robo_switch_reset();
	err = robo_switch_enable();
	if (err)
		goto done;
	err = 0;

	printk("found a 5%s%x!%s\n", robo.devid & 0xff00 ? "" : "3", robo.devid,
		robo.is_5350 ? " It's a 5350." : "");

done:
	if (err) {
		dev_put(robo.dev);
		robo.dev = NULL;
	}
	return err;
}


static int handle_vlan_port_read(void *driver, char *buf, int nr)
{
	__u16 val16;
	int len = 0;
	int j;

	val16 = (nr) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;

	if (robo.is_5350) {
		u32 val32;
		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
		/* actual read */
		val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
		if ((val32 & (1 << 20)) /* valid */) {
			for (j = 0; j < 6; j++) {
				if (val32 & (1 << j)) {
					len += sprintf(buf + len, "%d", j);
					if (val32 & (1 << (j + 6))) {
						if (j == 5) buf[len++] = 'u';
					} else {
						buf[len++] = 't';
						if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
							buf[len++] = '*';
					}
					buf[len++] = '\t';
				}
			}
			len += sprintf(buf + len, "\n");
		}
	} else {
		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
		/* actual read */
		val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
		if ((val16 & (1 << 14)) /* valid */) {
			for (j = 0; j < 6; j++) {
				if (val16 & (1 << j)) {
					len += sprintf(buf + len, "%d", j);
					if (val16 & (1 << (j + 7))) {
						if (j == 5) buf[len++] = 'u';
					} else {
						buf[len++] = 't';
						if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
							buf[len++] = '*';
					}
					buf[len++] = '\t';
				}
			}
			len += sprintf(buf + len, "\n");
		}
	}

	buf[len] = '\0';

	return len;
}
예제 #12
0
파일: switch-robo.c 프로젝트: cilynx/dd-wrt
static int robo_probe(char *devname)
{
	struct ethtool_drvinfo info;
	int i;
	__u32 phyid;

	printk("Probing device %s: ", devname);
	strcpy(ifr.ifr_name, devname);

	if ((dev = dev_get_by_name(devname)) == NULL) {
		printk("No such device\n");
		return 1;
	}

	info.cmd = ETHTOOL_GDRVINFO;
	if (do_ioctl(SIOCETHTOOL, (void *) &info) < 0) {
		printk("SIOCETHTOOL: not supported\n");
		return 1;
	}
	
	/* try access using MII ioctls - get phy address */
	if (do_ioctl(SIOCGMIIPHY, NULL) < 0) {
		use_et = 1;
	} else {
		/* got phy address check for robo address */
		struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &ifr.ifr_data;
		if (mii->phy_id != ROBO_PHY_ADDR) {
			printk("Invalid phy address (%d)\n", mii->phy_id);
			return 1;
		}
	}

	phyid = mdio_read(ROBO_PHY_ADDR, 0x2) | 
		(mdio_read(ROBO_PHY_ADDR, 0x3) << 16);

	if (phyid == 0xffffffff || phyid == 0x55210022) {
		printk("No Robo switch in managed mode found\n");
		return 1;
	}
	
	is_5350 = robo_vlan5350();
	max_ports = 6;
	
	for (i = 0; i <= (is_5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); i++) {
		/* issue read */
		__u16 val16 = (i) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
		
		if (is_5350) {
			u32 val32;
			robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
			/* actual read */
			val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
			if ((val32 & (1 << 20)) /* valid */) {
				max_vlans = i + 1;
			}
		} else {
			robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
			/* actual read */
			val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
			if ((val16 & (1 << 14)) /* valid */) {
				max_vlans = i + 1;
			}
		}
	}

	printk("found!\n");
	return 0;
}