#include <linux/mii.h>
#include "etc53xx.h"
+#define ROBO_PHY_ADDR 0x1E /* robo switch phy address */
/* MII registers */
#define REG_MII_PAGE 0x10 /* MII Page register */
int et; /* use private ioctls */
} robo_t;
-static u16 mdio_read(robo_t *robo, u8 reg)
+static u16 mdio_read(robo_t *robo, u16 phy_id, u8 reg)
{
if (robo->et) {
int args[2] = { reg };
+
+ if (phy_id != ROBO_PHY_ADDR) {
+ fprintf(stderr,
+ "Access to real 'phy' registers unavaliable.\n"
+ "Upgrade kernel driver.\n");
+
+ return 0xffff;
+ }
robo->ifr.ifr_data = (caddr_t) args;
if (ioctl(robo->fd, SIOCGETCPHYRD, (caddr_t)&robo->ifr) < 0) {
return args[1];
} else {
struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data;
+ mii->phy_id = phy_id;
mii->reg_num = reg;
if (ioctl(robo->fd, SIOCGMIIREG, &robo->ifr) < 0) {
perror("SIOCGMIIREG");
}
}
-static void mdio_write(robo_t *robo, u8 reg, u16 val)
+static void mdio_write(robo_t *robo, u16 phy_id, u8 reg, u16 val)
{
if (robo->et) {
int args[2] = { reg, val };
+ if (phy_id != ROBO_PHY_ADDR) {
+ fprintf(stderr,
+ "Access to real 'phy' registers unavaliable.\n"
+ "Upgrade kernel driver.\n");
+ return;
+ }
+
robo->ifr.ifr_data = (caddr_t) args;
if (ioctl(robo->fd, SIOCSETCPHYWR, (caddr_t)&robo->ifr) < 0) {
perror("SIOCGETCPHYWR");
}
} else {
struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data;
+ mii->phy_id = phy_id;
mii->reg_num = reg;
mii->val_in = val;
if (ioctl(robo->fd, SIOCSMIIREG, &robo->ifr) < 0) {
int i = 3;
/* set page number */
- mdio_write(robo, REG_MII_PAGE,
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_PAGE,
(page << 8) | REG_MII_PAGE_ENABLE);
/* set register address */
- mdio_write(robo, REG_MII_ADDR, (reg << 8) | op);
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_ADDR,
+ (reg << 8) | op);
/* check if operation completed */
while (i--) {
- if ((mdio_read(robo, REG_MII_ADDR) & 3) == 0)
+ if ((mdio_read(robo, ROBO_PHY_ADDR, REG_MII_ADDR) & 3) == 0)
return 0;
}
robo_reg(robo, page, reg, REG_MII_ADDR_READ);
for (i = 0; i < count; i++)
- val[i] = mdio_read(robo, REG_MII_DATA0 + i);
+ val[i] = mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + i);
}
static u16 robo_read16(robo_t *robo, u8 page, u8 reg)
{
robo_reg(robo, page, reg, REG_MII_ADDR_READ);
- return mdio_read(robo, REG_MII_DATA0);
+ return mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0);
}
static u32 robo_read32(robo_t *robo, u8 page, u8 reg)
{
robo_reg(robo, page, reg, REG_MII_ADDR_READ);
- return mdio_read(robo, REG_MII_DATA0) +
- (mdio_read(robo, REG_MII_DATA0 + 1) << 16);
+ return mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0) +
+ (mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16);
}
static void robo_write16(robo_t *robo, u8 page, u8 reg, u16 val16)
{
/* write data */
- mdio_write(robo, REG_MII_DATA0, val16);
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val16);
robo_reg(robo, page, reg, REG_MII_ADDR_WRITE);
}
static void robo_write32(robo_t *robo, u8 page, u8 reg, u32 val32)
{
/* write data */
- mdio_write(robo, REG_MII_DATA0, val32 & 65535);
- mdio_write(robo, REG_MII_DATA0 + 1, val32 >> 16);
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 65535);
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1, val32 >> 16);
robo_reg(robo, page, reg, REG_MII_ADDR_WRITE);
}
char *rxtx[4] = { "enabled", "rx_disabled", "tx_disabled", "disabled" };
char *stp[8] = { "none", "disable", "block", "listen", "learn", "forward", "6", "7" };
+struct {
+ char *name;
+ u16 bmcr;
+} media[5] = { { "auto", BMCR_ANENABLE | BMCR_ANRESTART },
+ { "10HD", 0 }, { "10FD", BMCR_FULLDPLX },
+ { "100HD", BMCR_SPEED100 }, { "100FD", BMCR_SPEED100 | BMCR_FULLDPLX } };
+
+struct {
+ char *name;
+ u16 value;
+} mdix[3] = { { "auto", 0x0000 }, { "on", 0x1800 }, { "off", 0x0800 } };
+
void usage()
{
fprintf(stderr, "Broadcom BCM5325E/536x switch configuration utility\n"
"\tshow\n"
"\tswitch <enable|disable>\n"
"\tport <port_number> [state <%s|%s|%s|%s>]\n\t\t[stp %s|%s|%s|%s|%s|%s] [tag <vlan_tag>]\n"
+ "\t\t[media %s|%s|%s|%s|%s] [mdi-x %s|%s|%s]\n"
"\tvlan <vlan_number> [ports <ports_list>]\n"
"\tvlans <enable|disable|reset>\n\n"
"\tports_list should be one argument, space separated, quoted if needed,\n"
"2) WRT54g, WL-500g Deluxe OpenWRT config (vlan0 is LAN, vlan1 is WAN):\n"
"robocfg switch disable vlans enable reset vlan 0 ports \"1 2 3 4 5t\" vlan 1 ports \"0 5t\""
" port 0 state enabled stp none switch enable\n",
- rxtx[0], rxtx[1], rxtx[2], rxtx[3], stp[0], stp[1], stp[2], stp[3], stp[4], stp[5]);
+ rxtx[0], rxtx[1], rxtx[2], rxtx[3], stp[0], stp[1], stp[2], stp[3], stp[4], stp[5],
+ media[0].name, media[1].name, media[2].name, media[3].name, media[4].name,
+ mdix[0].name, mdix[1].name, mdix[2].name);
}
int
} 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 != 30) {
+ if (mii->phy_id != ROBO_PHY_ADDR) {
fprintf(stderr, "Invalid phy address (%d)\n", mii->phy_id);
exit(1);
}
}
- phyid = mdio_read(&robo, 0x2) | (mdio_read(&robo, 0x3) << 16);
+ phyid = mdio_read(&robo, ROBO_PHY_ADDR, 0x2) |
+ (mdio_read(&robo, ROBO_PHY_ADDR, 0x3) << 16);
if (phyid == 0xffffffff || phyid == 0x55210022) {
fprintf(stderr, "No Robo switch in managed mode found\n");
robo5350 = robo_vlan5350(&robo);
for (i = 1; i < argc;) {
- if (strcmp(argv[i], "port") == 0 && (i + 1) < argc)
+ if (strcasecmp(argv[i], "port") == 0 && (i + 1) < argc)
{
int index = atoi(argv[++i]);
/* read port specs */
while (++i < argc) {
- if (strcmp(argv[i], "state") == 0 && ++i < argc) {
- for (j = 0; j < 4 && strcmp(argv[i], rxtx[j]); j++);
+ if (strcasecmp(argv[i], "state") == 0 && ++i < argc) {
+ for (j = 0; j < 4 && strcasecmp(argv[i], rxtx[j]); j++);
if (j < 4) {
/* change state */
robo_write16(&robo,ROBO_CTRL_PAGE, port[index],
exit(1);
}
} else
- if (strcmp(argv[i], "stp") == 0 && ++i < argc) {
- for (j = 0; j < 8 && strcmp(argv[i], stp[j]); j++);
+ if (strcasecmp(argv[i], "stp") == 0 && ++i < argc) {
+ for (j = 0; j < 8 && strcasecmp(argv[i], stp[j]); j++);
if (j < 8) {
/* change stp */
robo_write16(&robo,ROBO_CTRL_PAGE, port[index],
exit(1);
}
} else
- if (strcmp(argv[i], "tag") == 0 && ++i < argc) {
+ if (strcasecmp(argv[i], "media") == 0 && ++i < argc) {
+ for (j = 0; j < 5 && strcasecmp(argv[i], media[j].name); j++);
+ if (j < 5) {
+ mdio_write(&robo, port[index], MII_BMCR, media[j].bmcr);
+ } else {
+ fprintf(stderr, "Invalid media '%s'.\n", argv[i]);
+ exit(1);
+ }
+ } else
+ if (strcasecmp(argv[i], "mdi-x") == 0 && ++i < argc) {
+ for (j = 0; j < 3 && strcasecmp(argv[i], mdix[j].name); j++);
+ if (j < 3) {
+ mdio_write(&robo, port[index], 0x1c, mdix[j].value |
+ (mdio_read(&robo, port[index], 0x1c) & ~0x1800));
+ } else {
+ fprintf(stderr, "Invalid mdi-x '%s'.\n", argv[i]);
+ exit(1);
+ }
+ } else
+ if (strcasecmp(argv[i], "tag") == 0 && ++i < argc) {
j = atoi(argv[i]);
/* change vlan tag */
robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (index << 1), j);
} else break;
}
} else
- if (strcmp(argv[i], "vlan") == 0 && (i + 1) < argc)
+ if (strcasecmp(argv[i], "vlan") == 0 && (i + 1) < argc)
{
int index = atoi(argv[++i]);
while (++i < argc) {
- if (strcmp(argv[i], "ports") == 0 && ++i < argc) {
+ if (strcasecmp(argv[i], "ports") == 0 && ++i < argc) {
char *ports = argv[i];
int untag = 0;
int member = 0;
} else break;
}
} else
- if (strcmp(argv[i], "switch") == 0 && (i + 1) < argc)
+ if (strcasecmp(argv[i], "switch") == 0 && (i + 1) < argc)
{
/* enable/disable switching */
robo_write16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE,
(*argv[++i] == 'e' ? 2 : 0));
i++;
} else
- if (strcmp(argv[i], "vlans") == 0 && (i + 1) < argc)
+ if (strcasecmp(argv[i], "vlans") == 0 && (i + 1) < argc)
{
while (++i < argc) {
- if (strcmp(argv[i], "reset") == 0) {
+ if (strcasecmp(argv[i], "reset") == 0) {
/* reset vlan validity bit */
for (j = 0; j <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++)
{
}
}
} else
- if (strcmp(argv[i], "enable") == 0 || strcmp(argv[i], "disable") == 0)
+ if (strcasecmp(argv[i], "enable") == 0 || strcasecmp(argv[i], "disable") == 0)
{
- int disable = (*argv[i] == 'd');
+ int disable = (*argv[i] == 'd') || (*argv[i] == 'D');
/* enable/disable vlans */
robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 :
(1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
} else break;
}
} else
- if (strcmp(argv[i], "show") == 0)
+ if (strcasecmp(argv[i], "show") == 0)
{
break;
} else {