2 * Broadcom BCM5325E/536x switch configuration utility
4 * Copyright (C) 2005 Oleg I. Vdovikin
5 * Copyright (C) 2005 Dmitry 'dimss' Ivanov of "Telecentrs" (Riga, Latvia)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 #include <sys/param.h>
27 #include <sys/ioctl.h>
28 #include <sys/socket.h>
31 typedef u_int64_t u64
;
32 typedef u_int32_t u32
;
33 typedef u_int16_t u16
;
37 #include <linux/sockios.h>
38 #include <linux/ethtool.h>
39 #include <linux/types.h>
40 #include <linux/mii.h>
43 #define ROBO_PHY_ADDR 0x1E /* robo switch phy address */
46 #define REG_MII_PAGE 0x10 /* MII Page register */
47 #define REG_MII_ADDR 0x11 /* MII Address register */
48 #define REG_MII_DATA0 0x18 /* MII Data register 0 */
50 #define REG_MII_PAGE_ENABLE 1
51 #define REG_MII_ADDR_WRITE 1
52 #define REG_MII_ADDR_READ 2
54 /* Private et.o ioctls */
55 #define SIOCGETCPHYRD (SIOCDEVPRIVATE + 9)
56 #define SIOCSETCPHYWR (SIOCDEVPRIVATE + 10)
57 #define SIOCGETCPHYRD2 (SIOCDEVPRIVATE + 12)
58 #define SIOCSETCPHYWR2 (SIOCDEVPRIVATE + 13)
59 #define SIOCGETCROBORD (SIOCDEVPRIVATE + 14)
60 #define SIOCSETCROBOWR (SIOCDEVPRIVATE + 15)
65 u8 et
; /* use private ioctls */
66 u8 gmii
; /* gigabit mii */
69 static u16
__mdio_access(robo_t
*robo
, u16 phy_id
, u8 reg
, u16 val
, u16 wr
)
71 static int __ioctl_args
[2][3] = { {SIOCGETCPHYRD
, SIOCGETCPHYRD2
, SIOCGMIIREG
},
72 {SIOCSETCPHYWR
, SIOCSETCPHYWR2
, SIOCSMIIREG
} };
75 int args
[2] = { reg
, val
};
78 if (phy_id
!= ROBO_PHY_ADDR
) {
80 args
[0] |= phy_id
<< 16;
82 robo
->ifr
.ifr_data
= (caddr_t
) args
;
83 if (ioctl(robo
->fd
, __ioctl_args
[wr
][cmd
], (caddr_t
)&robo
->ifr
) < 0) {
84 if (phy_id
!= ROBO_PHY_ADDR
) {
86 "Access to real 'phy' registers unavaliable.\n"
87 "Upgrade kernel driver.\n");
95 struct mii_ioctl_data
*mii
= (struct mii_ioctl_data
*)&robo
->ifr
.ifr_data
;
99 if (ioctl(robo
->fd
, __ioctl_args
[wr
][2], &robo
->ifr
) < 0) {
107 static inline u16
mdio_read(robo_t
*robo
, u16 phy_id
, u8 reg
)
109 return __mdio_access(robo
, phy_id
, reg
, 0, 0);
112 static inline void mdio_write(robo_t
*robo
, u16 phy_id
, u8 reg
, u16 val
)
114 __mdio_access(robo
, phy_id
, reg
, val
, 1);
117 static int _robo_reg(robo_t
*robo
, u8 page
, u8 reg
, u8 op
)
121 /* set page number */
122 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_PAGE
,
123 (page
<< 8) | REG_MII_PAGE_ENABLE
);
125 /* set register address */
126 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_ADDR
,
129 /* check if operation completed */
131 if ((mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_ADDR
) & 3) == 0)
138 static int robo_reg(robo_t
*robo
, u8 page
, u8 reg
, u8 op
)
140 if (_robo_reg(robo
, page
, reg
, op
))
142 fprintf(stderr
, "robo_reg: %x/%x timeout\n", page
, reg
);
149 static void robo_read(robo_t
*robo
, u8 page
, u8 reg
, u16
*val
, int count
)
153 robo_reg(robo
, page
, reg
, REG_MII_ADDR_READ
);
155 for (i
= 0; i
< count
; i
++)
156 val
[i
] = mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ i
);
159 static u16
robo_read16(robo_t
*robo
, u8 page
, u8 reg
)
161 robo_reg(robo
, page
, reg
, REG_MII_ADDR_READ
);
163 return mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
);
166 static u32
robo_read32(robo_t
*robo
, u8 page
, u8 reg
)
168 robo_reg(robo
, page
, reg
, REG_MII_ADDR_READ
);
170 return ((u32
)mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
)) |
171 ((u32
)mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ 1) << 16);
174 static void robo_write(robo_t
*robo
, u8 page
, u8 reg
, u16
*val
, int count
)
178 for (i
= 0; i
< count
; i
++)
179 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ i
, val
[i
]);
181 robo_reg(robo
, page
, reg
, REG_MII_ADDR_WRITE
);
184 static void robo_write16(robo_t
*robo
, u8 page
, u8 reg
, u16 val16
)
187 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
, val16
);
189 robo_reg(robo
, page
, reg
, REG_MII_ADDR_WRITE
);
192 static void robo_write32(robo_t
*robo
, u8 page
, u8 reg
, u32 val32
)
195 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
, (u16
)(val32
& 0xFFFF));
196 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ 1, (u16
)(val32
>> 16));
198 robo_reg(robo
, page
, reg
, REG_MII_ADDR_WRITE
);
201 /* checks that attached switch is 5325/5352/5354/5356/5357/53115 */
202 static int robo_vlan535x(robo_t
*robo
, u32 phyid
)
204 /* set vlan access id to 15 and read it back */
206 robo_write16(robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
208 /* 5365 will refuse this as it does not have this reg */
209 if (robo_read16(robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
) != val16
)
212 if (robo
->et
!= 1 && (mdio_read(robo
, 0, ROBO_MII_STAT
) & 0x0100))
213 robo
->gmii
= ((mdio_read(robo
, 0, 0x0f) & 0xf000) != 0);
215 if (robo
->gmii
&& robo_read32(robo
, ROBO_STAT_PAGE
, ROBO_LSA_IM_PORT
) != 0) {
216 robo_write16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
, val16
);
217 robo_write16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
218 (1 << 7) /* start */ | 1 /* read */);
219 if (robo_read16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
) == 1
220 && robo_read16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
) == val16
)
223 /* dirty trick for 5356/5357 */
224 if ((phyid
& 0xfff0ffff ) == 0x5da00362 ||
225 (phyid
& 0xfff0ffff ) == 0x5e000362)
231 u8 port
[9] = { 0, 1, 2, 3, 4, 8, 0, 0, 8};
232 char ports
[] = "01234???5???????";
233 char *speed
[4] = { "10", "100", "1000" , "4" };
234 char *rxtx
[4] = { "enabled", "rx_disabled", "tx_disabled", "disabled" };
235 char *stp
[8] = { "none", "disable", "block", "listen", "learn", "forward", "6", "7" };
236 char *jumbo
[2] = { "off", "on" };
242 { "auto", BMCR_ANENABLE
| BMCR_ANRESTART
},
244 { "10FD", BMCR_FULLDPLX
},
245 { "100HD", BMCR_SPEED100
},
246 { "100FD", BMCR_SPEED100
| BMCR_FULLDPLX
}
247 #if defined(BMCR_SPEED1000)
249 { "1000HD", BMCR_SPEED1000
},
250 { "1000FD", BMCR_SPEED1000
| BMCR_FULLDPLX
}
261 { "auto", 0x0000, 0x0000, 0x8207, 0x0000 },
262 { "on", 0x1800, 0x4000, 0x8007, 0x0080 },
263 { "off", 0x0800, 0x4000, 0x8007, 0x0000 }
268 fprintf(stderr
, "Broadcom BCM5325/535x/536x/5311x switch configuration utility\n"
269 "Copyright (C) 2005-2008 Oleg I. Vdovikin (oleg@cs.msu.su)\n"
270 "Copyright (C) 2005 Dmitry 'dimss' Ivanov of \"Telecentrs\" (Riga, Latvia)\n\n"
271 "This program is distributed in the hope that it will be useful,\n"
272 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
273 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
274 "GNU General Public License for more details.\n\n");
276 fprintf(stderr
, "Usage: robocfg <op> ... <op>\n"
277 "Operations are as below:\n"
278 "\tshow -- show current config\n"
279 "\tshowports -- show only port config\n"
280 "\tshowmacs -- show known MAC addresses\n"
281 "\tswitch <enable|disable>\n"
282 "\tport <port_number> [state <%s|%s|%s|%s>]\n"
283 "\t\t[stp %s|%s|%s|%s|%s|%s] [tag <vlan_tag>]\n"
284 "\t\t[media %s|%s|%s|%s|%s"
285 #if defined(BMCR_SPEED1000)
288 "] [mdi-x %s|%s|%s]\n"
289 "\t\t[jumbo %s|%s]\n"
290 "\tvlan <vlan_number> [ports <ports_list>]\n"
291 "\tvlans <enable|disable|reset>\n\n"
292 "\tports_list should be one argument, space separated, quoted if needed,\n"
293 "\tport number could be followed by 't' to leave packet vlan tagged (CPU \n"
294 "\tport default) or by 'u' to untag packet (other ports default) before \n"
295 "\tbringing it to the port, '*' is ignored\n"
297 "1) ASUS WL-500g Deluxe stock config (eth0 is WAN, eth0.1 is LAN):\n"
298 "robocfg switch disable vlans enable reset vlan 0 ports \"0 5u\" vlan 1 ports \"1 2 3 4 5t\""
299 " port 0 state enabled stp none switch enable\n"
300 "2) WRT54g, WL-500g Deluxe OpenWRT config (vlan0 is LAN, vlan1 is WAN):\n"
301 "robocfg switch disable vlans enable reset vlan 0 ports \"1 2 3 4 5t\" vlan 1 ports \"0 5t\""
302 " port 0 state enabled stp none switch enable\n",
303 rxtx
[0], rxtx
[1], rxtx
[2], rxtx
[3], stp
[0], stp
[1], stp
[2], stp
[3], stp
[4], stp
[5],
304 media
[0].name
, media
[1].name
, media
[2].name
, media
[3].name
, media
[4].name
,
305 #if defined(BMCR_SPEED1000)
306 media
[5].name
, media
[6].name
,
308 mdix
[0].name
, mdix
[1].name
, mdix
[2].name
,
313 main(int argc
, char *argv
[])
319 int robo535x
= 0; /* 0 - 5365, 1 - 5325/5352/5354, 3 - 5356, 4 - 53115 */
324 struct ethtool_drvinfo info
;
326 if ((robo
.fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
331 /* the only interface for now */
332 strcpy(robo
.ifr
.ifr_name
, "eth0");
334 memset(&info
, 0, sizeof(info
));
335 info
.cmd
= ETHTOOL_GDRVINFO
;
336 robo
.ifr
.ifr_data
= (caddr_t
)&info
;
337 if (ioctl(robo
.fd
, SIOCETHTOOL
, (caddr_t
)&robo
.ifr
) < 0) {
338 perror("SIOCETHTOOL: your ethernet module is either unsupported or outdated");
341 if (strcmp(info
.driver
, "et0") && strcmp(info
.driver
, "b44")) {
342 fprintf(stderr
, "No suitable module found for %s (managed by %s)\n",
343 robo
.ifr
.ifr_name
, info
.driver
);
347 /* try access using MII ioctls - get phy address */
348 if (ioctl(robo
.fd
, SIOCGMIIPHY
, &robo
.ifr
) < 0) {
349 int args
[2] = { ROBO_PHY_ADDR
<< 16, 0x0 };
351 robo
.ifr
.ifr_data
= (caddr_t
) args
;
352 if (ioctl(robo
.fd
, SIOCGETCPHYRD2
, &robo
.ifr
) < 0)
356 /* got phy address check for robo address */
357 struct mii_ioctl_data
*mii
= (struct mii_ioctl_data
*)&robo
.ifr
.ifr_data
;
358 if (mii
->phy_id
!= ROBO_PHY_ADDR
) {
359 fprintf(stderr
, "Invalid phy address (%d)\n", mii
->phy_id
);
364 phyid
= mdio_read(&robo
, ROBO_PHY_ADDR
, 0x2) |
365 (mdio_read(&robo
, ROBO_PHY_ADDR
, 0x3) << 16);
366 if (phyid
== 0 && robo
.et
!= 1)
367 phyid
= mdio_read(&robo
, 0, 0x2) |
368 (mdio_read(&robo
, 0, 0x3) << 16);
370 if (phyid
== 0xffffffff || phyid
== 0x55210022) {
371 fprintf(stderr
, "No Robo switch in managed mode found\n");
375 robo535x
= robo_vlan535x(&robo
, phyid
);
376 /* fprintf(stderr, "phyid %08x id %d\n", phyid, robo535x); */
378 for (i
= 1; i
< argc
;) {
379 if (strcasecmp(argv
[i
], "showmacs") == 0)
381 /* show MAC table of switch */
383 int idx
, off
, base_vlan
;
385 base_vlan
= 0; /*get_vid_by_idx(&robo, 0);*/
388 "--------------------------------------\n"
389 "VLAN MAC Type Port\n"
390 "--------------------------------------\n");
391 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_ARL_RW_CTRL
, 0x81);
392 robo_write16(&robo
, ROBO_ARLIO_PAGE
, (robo535x
== 4) ?
393 ROBO_ARL_SEARCH_CTRL_53115
: ROBO_ARL_SEARCH_CTRL
, 0x80);
394 for (idx
= 0; idx
< ((robo535x
== 4) ?
395 NUM_ARL_TABLE_ENTRIES_53115
: robo535x
?
396 NUM_ARL_TABLE_ENTRIES_5350
: NUM_ARL_TABLE_ENTRIES
); idx
++)
400 off
= (idx
& 0x01) << 4;
401 if (!off
&& (robo_read16(&robo
, ROBO_ARLIO_PAGE
,
402 ROBO_ARL_SEARCH_CTRL_53115
) & 0x80) == 0) break;
403 robo_read(&robo
, ROBO_ARLIO_PAGE
,
404 ROBO_ARL_SEARCH_RESULT_53115
+ off
, buf
, 4);
405 robo_read(&robo
, ROBO_ARLIO_PAGE
,
406 ROBO_ARL_SEARCH_RESULT_EXT_53115
+ off
, &buf
[4], 2);
408 robo_read(&robo
, ROBO_ARLIO_PAGE
, ROBO_ARL_SEARCH_RESULT
,
409 buf
, robo535x
? 4 : 5);
410 if ((robo535x
== 4) ? (buf
[5] & 0x01) : (buf
[3] & 0x8000) /* valid */)
412 printf("%04i %02x:%02x:%02x:%02x:%02x:%02x %7s %c\n",
413 (base_vlan
| (robo535x
== 4) ?
414 (base_vlan
| (buf
[3] & 0xfff)) :
415 ((buf
[3] >> 5) & 0x0f) |
416 (robo535x
? 0 : ((buf
[4] & 0x0f) << 4))),
417 buf
[2] >> 8, buf
[2] & 255,
418 buf
[1] >> 8, buf
[1] & 255,
419 buf
[0] >> 8, buf
[0] & 255,
421 (buf
[4] & 0x8000) : (buf
[3] & 0x4000)) ? "STATIC" : "DYNAMIC"),
423 '0'+(buf
[4] & 0x0f) : ports
[buf
[3] & 0x0f])
429 if (strcasecmp(argv
[i
], "port") == 0 && (i
+ 1) < argc
)
431 int index
= atoi(argv
[++i
]);
432 /* read port specs */
434 if (strcasecmp(argv
[i
], "state") == 0 && ++i
< argc
) {
435 for (j
= 0; j
< 4 && strcasecmp(argv
[i
], rxtx
[j
]); j
++);
438 robo_write16(&robo
,ROBO_CTRL_PAGE
, port
[index
],
439 (robo_read16(&robo
, ROBO_CTRL_PAGE
, port
[index
]) & ~(3 << 0)) | (j
<< 0));
441 fprintf(stderr
, "Invalid state '%s'.\n", argv
[i
]);
445 if (strcasecmp(argv
[i
], "stp") == 0 && ++i
< argc
) {
446 for (j
= 0; j
< 8 && strcasecmp(argv
[i
], stp
[j
]); j
++);
449 robo_write16(&robo
,ROBO_CTRL_PAGE
, port
[index
],
450 (robo_read16(&robo
, ROBO_CTRL_PAGE
, port
[index
]) & ~(7 << 5)) | (j
<< 5));
452 fprintf(stderr
, "Invalid stp '%s'.\n", argv
[i
]);
456 if (strcasecmp(argv
[i
], "media") == 0 && ++i
< argc
) {
457 for (j
= 0; j
< 7 && strcasecmp(argv
[i
], media
[j
].name
); j
++);
458 if (j
< ((robo535x
== 4) ? 7 : 5)) {
460 mdio_write(&robo
, port
[index
], MII_BMCR
, media
[j
].bmcr
);
462 fprintf(stderr
, "Invalid media '%s'.\n", argv
[i
]);
466 if (strcasecmp(argv
[i
], "mdi-x") == 0 && ++i
< argc
) {
467 for (j
= 0; j
< 3 && strcasecmp(argv
[i
], mdix
[j
].name
); j
++);
471 mdio_write(&robo
, port
[index
], 0x10, mdix
[j
].value1
|
472 (mdio_read(&robo
, port
[index
], 0x10) & ~0x4000));
473 mdio_write(&robo
, port
[index
], 0x18, 0x7007);
474 mdio_write(&robo
, port
[index
], 0x18, mdix
[j
].value2
|
475 (mdio_read(&robo
, port
[index
], 0x18) & ~0x8207));
476 mdio_write(&robo
, port
[index
], 0x1e, mdix
[j
].value3
|
477 (mdio_read(&robo
, port
[index
], 0x1e) & ~0x0080));
479 mdio_write(&robo
, port
[index
], 0x1c, mdix
[j
].value
|
480 (mdio_read(&robo
, port
[index
], 0x1c) & ~0x1800));
482 fprintf(stderr
, "Invalid mdi-x '%s'.\n", argv
[i
]);
486 if (strcasecmp(argv
[i
], "tag") == 0 && ++i
< argc
) {
488 /* change vlan tag */
489 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_PORT0_DEF_TAG
+ (index
<< 1), j
);
491 if (strcasecmp(argv
[i
], "jumbo") == 0 && ++i
< argc
) {
492 for (j
= 0; j
< 2 && strcasecmp(argv
[i
], jumbo
[j
]); j
++);
493 if (robo535x
== 4 && j
< 2) {
494 /* change jumbo frame feature */
495 robo_write32(&robo
, ROBO_JUMBO_PAGE
, ROBO_JUMBO_CTRL
,
496 (robo_read32(&robo
, ROBO_JUMBO_PAGE
, ROBO_JUMBO_CTRL
) &
497 ~(1 << port
[index
])) | (j
<< port
[index
]));
499 fprintf(stderr
, "Invalid jumbo state '%s'.\n", argv
[i
]);
505 if (strcasecmp(argv
[i
], "vlan") == 0 && (i
+ 1) < argc
)
507 int vid
= atoi(argv
[++i
]);
509 if (strcasecmp(argv
[i
], "ports") == 0 && ++i
< argc
) {
510 char *ports
= argv
[i
];
514 while (*ports
>= '0' && *ports
<= '9') {
518 /* untag if needed, CPU port requires special handling */
519 if (*ports
== 'u' || (j
!= 5 && (*ports
== ' ' || *ports
== 0)))
523 /* change default vlan tag */
524 robo_write16(&robo
, ROBO_VLAN_PAGE
,
525 ROBO_VLAN_PORT0_DEF_TAG
+ (j
<< 1), vid
);
527 if (*ports
== '*' || *ports
== 't' || *ports
== ' ') ports
++;
530 while (*ports
== ' ') ports
++;
534 fprintf(stderr
, "Invalid ports '%s'.\n", argv
[i
]);
537 /* write config now */
538 val16
= (vid
) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
540 val32
= (untag
<< 9) | member
;
542 robo_write32(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ENTRY_5395
, val32
);
544 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
, vid
);
546 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
547 (1 << 7) /* start */ | 0 /* write */);
548 } else if (robo535x
) {
550 val32
= (1 << 24) /* valid */ | (untag
<< 6) | member
| (vid
<< 12);
552 val32
= (1 << 20) /* valid */ | (untag
<< 6) | member
| ((vid
>> 4) << 12);
553 robo_write32(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE_5350
, val32
);
554 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
556 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE
,
557 (1 << 14) /* valid */ | (untag
<< 7) | member
);
558 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS
, val16
);
564 if (strcasecmp(argv
[i
], "switch") == 0 && (i
+ 1) < argc
)
566 /* enable/disable switching */
567 robo_write16(&robo
, ROBO_CTRL_PAGE
, ROBO_SWITCH_MODE
,
568 (robo_read16(&robo
, ROBO_CTRL_PAGE
, ROBO_SWITCH_MODE
) & ~2) |
569 (*argv
[++i
] == 'e' ? 2 : 0));
572 if (strcasecmp(argv
[i
], "vlans") == 0 && (i
+ 1) < argc
)
575 if (strcasecmp(argv
[i
], "reset") == 0) {
577 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
578 (1 << 7) /* start */ | 2 /* flush */);
580 /* reset vlan validity bit */
581 for (j
= 0; j
<= ((robo535x
== 1) ? VLAN_ID_MAX5350
: VLAN_ID_MAX
); j
++)
583 /* write config now */
584 val16
= (j
) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
586 robo_write32(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE_5350
, 0);
587 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
589 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE
, 0);
590 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS
, val16
);
594 if (strcasecmp(argv
[i
], "enable") == 0 || strcasecmp(argv
[i
], "disable") == 0)
596 int disable
= (*argv
[i
] == 'd') || (*argv
[i
] == 'D');
597 /* enable/disable vlans */
598 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL0
, disable
? 0 :
599 (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
601 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL1
, disable
? 0 :
602 (1 << 1) | (1 << 2) | (1 << 3) /* RSV multicast */);
604 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL4
, disable
? 0 :
605 (1 << 6) /* drop invalid VID frames */);
607 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL5
, disable
? 0 :
608 (1 << 3) /* drop miss V table frames */);
613 if (strcasecmp(argv
[i
], "show") == 0)
617 if (strcasecmp(argv
[i
], "showports") == 0)
622 if (strncasecmp(argv
[i
], "robowr", 6) == 0 && (i
+ 2) < argc
)
624 long pagereg
= strtoul(argv
[i
+ 1], NULL
, 0);
625 int size
= strtoul(argv
[i
] + 6, NULL
, 0);
627 unsigned long long int v
;
630 size
= (size
> 0 && size
<= sizeof(buf
) * 16) ? (size
+ 15) >> 4 : 1;
632 v
= strtoull(argv
[i
+ 2], NULL
, 0);
633 for (k
= 0; k
< size
; k
++)
635 buf
[k
] = (u16
)(v
& 0xFFFF);
638 robo_write(&robo
, pagereg
>> 8, pagereg
& 255, buf
, size
);
640 printf("Page 0x%02x, Reg 0x%02x: ",
641 (u16
)(pagereg
>> 8), (u8
)(pagereg
& 255));
642 robo_read(&robo
, pagereg
>> 8, pagereg
& 255, buf
, size
);
644 printf("%04x", buf
[--size
]);
649 if (strncasecmp(argv
[i
], "robord", 6) == 0 && (i
+ 1) < argc
)
651 long pagereg
= strtoul(argv
[i
+ 1], NULL
, 0);
652 int size
= strtoul(argv
[i
] + 6, NULL
, 0);
655 size
= (size
> 0 && size
<= sizeof(buf
) * 16) ? (size
+ 15) >> 4 : 1;
657 printf("Page 0x%02x, Reg 0x%02x: ",
658 (u16
)(pagereg
>> 8), (u8
)(pagereg
& 255));
660 robo_read(&robo
, pagereg
>> 8, pagereg
& 255, buf
, size
);
662 printf("%04x", buf
[--size
]);
667 if (strcasecmp(argv
[i
], "dump") == 0)
669 for (i
= 0; i
< 256; i
++)
671 if (_robo_reg(&robo
, i
, 0, REG_MII_ADDR_READ
))
674 printf("Page %02x\n", i
);
676 for (j
= 0; j
< 128; j
++) {
678 robo_read16(&robo
, i
, j
), (j
% 16) == 15 ? "\n" : "");
684 fprintf(stderr
, "Invalid option %s\n", argv
[i
]);
691 if (argc
== 1) usage();
697 printf("Switch: %sabled %s\n", robo_read16(&robo
, ROBO_CTRL_PAGE
, ROBO_SWITCH_MODE
) & 2 ? "en" : "dis",
698 robo
.gmii
? "gigabit" : "");
700 for (i
= 0; i
< 6; i
++) {
701 printf(robo_read16(&robo
, ROBO_STAT_PAGE
, ROBO_LINK_STAT_SUMMARY
) & (1 << port
[i
]) ?
702 "Port %d: %4s%s " : "Port %d: DOWN ",
703 (robo535x
== 4) ? port
[i
] : i
,
704 speed
[(robo535x
== 4) ?
705 (robo_read32(&robo
, ROBO_STAT_PAGE
, ROBO_SPEED_STAT_SUMMARY
) >> port
[i
] * 2) & 3 :
706 (robo_read16(&robo
, ROBO_STAT_PAGE
, ROBO_SPEED_STAT_SUMMARY
) >> port
[i
]) & 1],
707 robo_read16(&robo
, ROBO_STAT_PAGE
, (robo535x
== 4) ?
708 ROBO_DUPLEX_STAT_SUMMARY_53115
: ROBO_DUPLEX_STAT_SUMMARY
) & (1 << port
[i
]) ? "FD" : "HD");
710 val16
= robo_read16(&robo
, ROBO_CTRL_PAGE
, port
[i
]);
712 printf("%s stp: %s vlan: %d ", rxtx
[val16
& 3], stp
[(val16
>> 5) & 7],
713 robo_read16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_PORT0_DEF_TAG
+ (i
<< 1)));
716 printf("jumbo: %s ", jumbo
[(robo_read32(&robo
, ROBO_JUMBO_PAGE
, ROBO_JUMBO_CTRL
) >> port
[i
]) & 1]);
718 robo_read(&robo
, ROBO_STAT_PAGE
, ROBO_LSA_PORT0
+ port
[i
] * 6, mac
, 3);
720 printf("mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
721 mac
[2] >> 8, mac
[2] & 255, mac
[1] >> 8, mac
[1] & 255, mac
[0] >> 8, mac
[0] & 255);
724 if (novlan
) return (0); // Only show ethernet port states, used by webui
726 val16
= robo_read16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL0
);
728 printf("VLANs: %s %sabled%s%s\n",
729 (robo535x
== 4) ? "BCM53115" : (robo535x
? "BCM5325/535x" : "BCM536x"),
730 (val16
& (1 << 7)) ? "en" : "dis",
731 (val16
& (1 << 6)) ? " mac_check" : "",
732 (val16
& (1 << 5)) ? " mac_hash" : "");
735 for (i
= 0; i
<= ((robo535x
== 4) ? VLAN_ID_MAX5395
/* slow, needs rework, but how? */ :
736 (robo535x
? VLAN_ID_MAX5350
: VLAN_ID_MAX
)); i
++)
739 val16
= (i
) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
743 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
, i
);
745 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
746 (1 << 7) /* start */ | 1 /* read */);
748 val32
= robo_read32(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ENTRY_5395
);
750 printf("%4d: vlan%d:", i
, i
);
751 for (j
= 0; j
<= 8; j
++) {
752 if (val32
& (1 << j
)) {
753 printf(" %d%s", j
, (val32
& (1 << (j
+ 9))) ?
754 (j
== 8 ? "u" : "") : "t");
759 } else if (robo535x
) {
760 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
762 val32
= robo_read32(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_READ
);
763 if ((val32
& (robo535x
== 3 ? (1 << 24) : (1 << 20))) /* valid */) {
764 val16
= (robo535x
== 3)
765 ? ((val32
& 0xff000) >> 12)
766 : ((val32
& 0xff000) >> 12) << 4;
767 printf("%4d: vlan%d:", i
, val16
| i
);
768 for (j
= 0; j
< 6; j
++) {
769 if (val32
& (1 << j
)) {
770 printf(" %d%s", j
, (val32
& (1 << (j
+ 6))) ?
771 (j
== 5 ? "u" : "") : "t");
777 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS
, val16
);
779 val16
= robo_read16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_READ
);
780 if ((val16
& (1 << 14)) /* valid */) {
781 printf("%4d: vlan%d:", i
, i
);
782 for (j
= 0; j
< 6; j
++) {
783 if (val16
& (1 << j
)) {
784 printf(" %d%s", j
, (val16
& (1 << (j
+ 7))) ?
785 (j
== 5 ? "u" : "") : "t");