added media and mdi-x port settings

SVN-Revision: 1141
This commit is contained in:
Oleg I. Vdovikin 2005-06-05 06:06:23 +00:00
parent ca8b9fa8bd
commit 34cdd1fc82

View File

@ -38,6 +38,7 @@ typedef u_int8_t u8;
#include <linux/mii.h> #include <linux/mii.h>
#include "etc53xx.h" #include "etc53xx.h"
#define ROBO_PHY_ADDR 0x1E /* robo switch phy address */
/* MII registers */ /* MII registers */
#define REG_MII_PAGE 0x10 /* MII Page register */ #define REG_MII_PAGE 0x10 /* MII Page register */
@ -58,11 +59,19 @@ typedef struct {
int et; /* use private ioctls */ int et; /* use private ioctls */
} robo_t; } 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) { if (robo->et) {
int args[2] = { reg }; 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; robo->ifr.ifr_data = (caddr_t) args;
if (ioctl(robo->fd, SIOCGETCPHYRD, (caddr_t)&robo->ifr) < 0) { if (ioctl(robo->fd, SIOCGETCPHYRD, (caddr_t)&robo->ifr) < 0) {
perror("SIOCGETCPHYRD"); perror("SIOCGETCPHYRD");
@ -72,6 +81,7 @@ static u16 mdio_read(robo_t *robo, u8 reg)
return args[1]; return args[1];
} else { } else {
struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data; struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data;
mii->phy_id = phy_id;
mii->reg_num = reg; mii->reg_num = reg;
if (ioctl(robo->fd, SIOCGMIIREG, &robo->ifr) < 0) { if (ioctl(robo->fd, SIOCGMIIREG, &robo->ifr) < 0) {
perror("SIOCGMIIREG"); perror("SIOCGMIIREG");
@ -81,11 +91,18 @@ static u16 mdio_read(robo_t *robo, u8 reg)
} }
} }
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) { if (robo->et) {
int args[2] = { reg, val }; 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; robo->ifr.ifr_data = (caddr_t) args;
if (ioctl(robo->fd, SIOCSETCPHYWR, (caddr_t)&robo->ifr) < 0) { if (ioctl(robo->fd, SIOCSETCPHYWR, (caddr_t)&robo->ifr) < 0) {
perror("SIOCGETCPHYWR"); perror("SIOCGETCPHYWR");
@ -93,6 +110,7 @@ static void mdio_write(robo_t *robo, u8 reg, u16 val)
} }
} else { } else {
struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data; struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data;
mii->phy_id = phy_id;
mii->reg_num = reg; mii->reg_num = reg;
mii->val_in = val; mii->val_in = val;
if (ioctl(robo->fd, SIOCSMIIREG, &robo->ifr) < 0) { if (ioctl(robo->fd, SIOCSMIIREG, &robo->ifr) < 0) {
@ -107,15 +125,16 @@ static int robo_reg(robo_t *robo, u8 page, u8 reg, u8 op)
int i = 3; int i = 3;
/* set page number */ /* set page number */
mdio_write(robo, REG_MII_PAGE, mdio_write(robo, ROBO_PHY_ADDR, REG_MII_PAGE,
(page << 8) | REG_MII_PAGE_ENABLE); (page << 8) | REG_MII_PAGE_ENABLE);
/* set register address */ /* 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 */ /* check if operation completed */
while (i--) { 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; return 0;
} }
@ -132,28 +151,28 @@ static void robo_read(robo_t *robo, u8 page, u8 reg, u16 *val, int count)
robo_reg(robo, page, reg, REG_MII_ADDR_READ); robo_reg(robo, page, reg, REG_MII_ADDR_READ);
for (i = 0; i < count; i++) 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) static u16 robo_read16(robo_t *robo, u8 page, u8 reg)
{ {
robo_reg(robo, page, reg, REG_MII_ADDR_READ); 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) static u32 robo_read32(robo_t *robo, u8 page, u8 reg)
{ {
robo_reg(robo, page, reg, REG_MII_ADDR_READ); 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) +
(mdio_read(robo, REG_MII_DATA0 + 1) << 16); (mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16);
} }
static void robo_write16(robo_t *robo, u8 page, u8 reg, u16 val16) static void robo_write16(robo_t *robo, u8 page, u8 reg, u16 val16)
{ {
/* write data */ /* 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); robo_reg(robo, page, reg, REG_MII_ADDR_WRITE);
} }
@ -161,8 +180,8 @@ static void robo_write16(robo_t *robo, u8 page, u8 reg, u16 val16)
static void robo_write32(robo_t *robo, u8 page, u8 reg, u32 val32) static void robo_write32(robo_t *robo, u8 page, u8 reg, u32 val32)
{ {
/* write data */ /* write data */
mdio_write(robo, REG_MII_DATA0, val32 & 65535); mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 65535);
mdio_write(robo, REG_MII_DATA0 + 1, val32 >> 16); mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1, val32 >> 16);
robo_reg(robo, page, reg, REG_MII_ADDR_WRITE); robo_reg(robo, page, reg, REG_MII_ADDR_WRITE);
} }
@ -183,6 +202,18 @@ char ports[6] = { 'W', '4', '3', '2', '1', 'C' };
char *rxtx[4] = { "enabled", "rx_disabled", "tx_disabled", "disabled" }; char *rxtx[4] = { "enabled", "rx_disabled", "tx_disabled", "disabled" };
char *stp[8] = { "none", "disable", "block", "listen", "learn", "forward", "6", "7" }; 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() void usage()
{ {
fprintf(stderr, "Broadcom BCM5325E/536x switch configuration utility\n" fprintf(stderr, "Broadcom BCM5325E/536x switch configuration utility\n"
@ -197,6 +228,7 @@ void usage()
"\tshow\n" "\tshow\n"
"\tswitch <enable|disable>\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" "\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" "\tvlan <vlan_number> [ports <ports_list>]\n"
"\tvlans <enable|disable|reset>\n\n" "\tvlans <enable|disable|reset>\n\n"
"\tports_list should be one argument, space separated, quoted if needed,\n" "\tports_list should be one argument, space separated, quoted if needed,\n"
@ -210,7 +242,9 @@ void usage()
"2) WRT54g, WL-500g Deluxe OpenWRT config (vlan0 is LAN, vlan1 is WAN):\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\"" "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", " 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 int
@ -252,13 +286,14 @@ main(int argc, char *argv[])
} else { } else {
/* got phy address check for robo address */ /* got phy address check for robo address */
struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo.ifr.ifr_data; 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); fprintf(stderr, "Invalid phy address (%d)\n", mii->phy_id);
exit(1); 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) { if (phyid == 0xffffffff || phyid == 0x55210022) {
fprintf(stderr, "No Robo switch in managed mode found\n"); fprintf(stderr, "No Robo switch in managed mode found\n");
@ -268,13 +303,13 @@ main(int argc, char *argv[])
robo5350 = robo_vlan5350(&robo); robo5350 = robo_vlan5350(&robo);
for (i = 1; i < argc;) { 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]); int index = atoi(argv[++i]);
/* read port specs */ /* read port specs */
while (++i < argc) { while (++i < argc) {
if (strcmp(argv[i], "state") == 0 && ++i < argc) { if (strcasecmp(argv[i], "state") == 0 && ++i < argc) {
for (j = 0; j < 4 && strcmp(argv[i], rxtx[j]); j++); for (j = 0; j < 4 && strcasecmp(argv[i], rxtx[j]); j++);
if (j < 4) { if (j < 4) {
/* change state */ /* change state */
robo_write16(&robo,ROBO_CTRL_PAGE, port[index], robo_write16(&robo,ROBO_CTRL_PAGE, port[index],
@ -284,8 +319,8 @@ main(int argc, char *argv[])
exit(1); exit(1);
} }
} else } else
if (strcmp(argv[i], "stp") == 0 && ++i < argc) { if (strcasecmp(argv[i], "stp") == 0 && ++i < argc) {
for (j = 0; j < 8 && strcmp(argv[i], stp[j]); j++); for (j = 0; j < 8 && strcasecmp(argv[i], stp[j]); j++);
if (j < 8) { if (j < 8) {
/* change stp */ /* change stp */
robo_write16(&robo,ROBO_CTRL_PAGE, port[index], robo_write16(&robo,ROBO_CTRL_PAGE, port[index],
@ -295,18 +330,37 @@ main(int argc, char *argv[])
exit(1); exit(1);
} }
} else } 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]); j = atoi(argv[i]);
/* change vlan tag */ /* change vlan tag */
robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (index << 1), j); robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (index << 1), j);
} else break; } else break;
} }
} else } else
if (strcmp(argv[i], "vlan") == 0 && (i + 1) < argc) if (strcasecmp(argv[i], "vlan") == 0 && (i + 1) < argc)
{ {
int index = atoi(argv[++i]); int index = atoi(argv[++i]);
while (++i < argc) { while (++i < argc) {
if (strcmp(argv[i], "ports") == 0 && ++i < argc) { if (strcasecmp(argv[i], "ports") == 0 && ++i < argc) {
char *ports = argv[i]; char *ports = argv[i];
int untag = 0; int untag = 0;
int member = 0; int member = 0;
@ -349,7 +403,7 @@ main(int argc, char *argv[])
} else break; } else break;
} }
} else } else
if (strcmp(argv[i], "switch") == 0 && (i + 1) < argc) if (strcasecmp(argv[i], "switch") == 0 && (i + 1) < argc)
{ {
/* enable/disable switching */ /* enable/disable switching */
robo_write16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, robo_write16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE,
@ -357,10 +411,10 @@ main(int argc, char *argv[])
(*argv[++i] == 'e' ? 2 : 0)); (*argv[++i] == 'e' ? 2 : 0));
i++; i++;
} else } else
if (strcmp(argv[i], "vlans") == 0 && (i + 1) < argc) if (strcasecmp(argv[i], "vlans") == 0 && (i + 1) < argc)
{ {
while (++i < argc) { while (++i < argc) {
if (strcmp(argv[i], "reset") == 0) { if (strcasecmp(argv[i], "reset") == 0) {
/* reset vlan validity bit */ /* reset vlan validity bit */
for (j = 0; j <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) for (j = 0; j <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++)
{ {
@ -375,9 +429,9 @@ main(int argc, char *argv[])
} }
} }
} else } 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 */ /* enable/disable vlans */
robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 : robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 :
(1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */); (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
@ -394,7 +448,7 @@ main(int argc, char *argv[])
} else break; } else break;
} }
} else } else
if (strcmp(argv[i], "show") == 0) if (strcasecmp(argv[i], "show") == 0)
{ {
break; break;
} else { } else {