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)
61 u8 et
; /* use private ioctls */
62 u8 gmii
; /* gigabit mii */
65 static u16
__mdio_access(robo_t
*robo
, u16 phy_id
, u8 reg
, u16 val
, u16 wr
)
67 static int __ioctl_args
[2][2] = { {SIOCGETCPHYRD
, SIOCGMIIREG
},
68 {SIOCSETCPHYWR
, SIOCSMIIREG
} };
71 int args
[2] = { reg
, val
};
73 if (phy_id
!= ROBO_PHY_ADDR
) {
75 "Access to real 'phy' registers unavaliable.\n"
76 "Upgrade kernel driver.\n");
81 robo
->ifr
.ifr_data
= (caddr_t
) args
;
82 if (ioctl(robo
->fd
, __ioctl_args
[wr
][0], (caddr_t
)&robo
->ifr
) < 0) {
88 struct mii_ioctl_data
*mii
= (struct mii_ioctl_data
*)&robo
->ifr
.ifr_data
;
92 if (ioctl(robo
->fd
, __ioctl_args
[wr
][1], &robo
->ifr
) < 0) {
100 static inline u16
mdio_read(robo_t
*robo
, u16 phy_id
, u8 reg
)
102 return __mdio_access(robo
, phy_id
, reg
, 0, 0);
105 static inline void mdio_write(robo_t
*robo
, u16 phy_id
, u8 reg
, u16 val
)
107 __mdio_access(robo
, phy_id
, reg
, val
, 1);
110 static int _robo_reg(robo_t
*robo
, u8 page
, u8 reg
, u8 op
)
114 /* set page number */
115 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_PAGE
,
116 (page
<< 8) | REG_MII_PAGE_ENABLE
);
118 /* set register address */
119 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_ADDR
,
122 /* check if operation completed */
124 if ((mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_ADDR
) & 3) == 0)
131 static int robo_reg(robo_t
*robo
, u8 page
, u8 reg
, u8 op
)
133 if (_robo_reg(robo
, page
, reg
, op
))
135 fprintf(stderr
, "robo_reg: %x/%x timeout\n", page
, reg
);
142 static void robo_read(robo_t
*robo
, u8 page
, u8 reg
, u16
*val
, int count
)
146 robo_reg(robo
, page
, reg
, REG_MII_ADDR_READ
);
148 for (i
= 0; i
< count
; i
++)
149 val
[i
] = mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ i
);
152 static u16
robo_read16(robo_t
*robo
, u8 page
, u8 reg
)
154 robo_reg(robo
, page
, reg
, REG_MII_ADDR_READ
);
156 return mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
);
159 static u32
robo_read32(robo_t
*robo
, u8 page
, u8 reg
)
161 robo_reg(robo
, page
, reg
, REG_MII_ADDR_READ
);
163 return ((u32
)mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
)) |
164 ((u32
)mdio_read(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ 1) << 16);
167 static void robo_write(robo_t
*robo
, u8 page
, u8 reg
, u16
*val
, int count
)
171 for (i
= 0; i
< count
; i
++)
172 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ i
, val
[i
]);
174 robo_reg(robo
, page
, reg
, REG_MII_ADDR_WRITE
);
177 static void robo_write16(robo_t
*robo
, u8 page
, u8 reg
, u16 val16
)
180 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
, val16
);
182 robo_reg(robo
, page
, reg
, REG_MII_ADDR_WRITE
);
185 static void robo_write32(robo_t
*robo
, u8 page
, u8 reg
, u32 val32
)
188 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
, (u16
)(val32
& 0xFFFF));
189 mdio_write(robo
, ROBO_PHY_ADDR
, REG_MII_DATA0
+ 1, (u16
)(val32
>> 16));
191 robo_reg(robo
, page
, reg
, REG_MII_ADDR_WRITE
);
194 /* checks that attached switch is 5325/5352/5354/5356/53115 */
195 static int robo_vlan535x(robo_t
*robo
, u32 phyid
)
197 /* set vlan access id to 15 and read it back */
199 robo_write16(robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
201 /* 5365 will refuse this as it does not have this reg */
202 if (robo_read16(robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
) != val16
)
205 if (robo
->et
== 0 && (mdio_read(robo
, 0, ROBO_MII_STAT
) & 0x0100))
206 robo
->gmii
= ((mdio_read(robo
, 0, 0x0f) & 0xf000) != 0);
208 if (robo
->gmii
&& robo_read32(robo
, ROBO_STAT_PAGE
, ROBO_LSA_IM_PORT
) != 0) {
209 robo_write16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
, val16
);
210 robo_write16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
211 (1 << 7) /* start */ | 1 /* read */);
212 if (robo_read16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
) == 1
213 && robo_read16(robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
) == val16
)
216 /* dirty trick for 5356 */
217 if ((phyid
& 0xfff0ffff ) == 0x5da00362)
223 u8 port
[] = { 0, 1, 2, 3, 4, 8, 0, 0, 8};
224 char ports
[] = "01234???5???????";
225 char *speed
[] = { "10", "100", "1000" , "4" };
226 char *rxtx
[] = { "enabled", "rx_disabled", "tx_disabled", "disabled" };
227 char *stp
[] = { "none", "disable", "block", "listen", "learn", "forward", "6", "7" };
228 char *jumbo
[] = { "off", "on" };
234 { "auto", BMCR_ANENABLE
| BMCR_ANRESTART
},
236 { "10FD", BMCR_FULLDPLX
},
237 { "100HD", BMCR_SPEED100
},
238 { "100FD", BMCR_SPEED100
| BMCR_FULLDPLX
}
239 #if defined(BMCR_SPEED1000)
241 { "1000HD", BMCR_SPEED1000
},
242 { "1000FD", BMCR_SPEED1000
| BMCR_FULLDPLX
}
253 { "auto", 0x0000, 0x0000, 0x8207, 0x0000 },
254 { "on", 0x1800, 0x4000, 0x8007, 0x0080 },
255 { "off", 0x0800, 0x4000, 0x8007, 0x0000 }
260 fprintf(stderr
, "Broadcom BCM5325/535x/536x/5311x switch configuration utility\n"
261 "Copyright (C) 2005-2008 Oleg I. Vdovikin (oleg@cs.msu.su)\n"
262 "Copyright (C) 2005 Dmitry 'dimss' Ivanov of \"Telecentrs\" (Riga, Latvia)\n\n"
263 "This program is distributed in the hope that it will be useful,\n"
264 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
265 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
266 "GNU General Public License for more details.\n\n");
268 fprintf(stderr
, "Usage: robocfg <op> ... <op>\n"
269 "Operations are as below:\n"
270 "\tshow -- show current config\n"
271 "\tshowmacs -- show known MAC addresses\n"
272 "\tswitch <enable|disable>\n"
273 "\tport <port_number> [state <%s|%s|%s|%s>]\n"
274 "\t\t[stp %s|%s|%s|%s|%s|%s] [tag <vlan_tag>]\n"
275 "\t\t[media %s|%s|%s|%s|%s"
276 #if defined(BMCR_SPEED1000)
279 "] [mdi-x %s|%s|%s]\n"
280 "\t\t[jumbo %s|%s]\n"
281 "\tvlan <vlan_number> [ports <ports_list>]\n"
282 "\tvlans <enable|disable|reset>\n\n"
283 "\tports_list should be one argument, space separated, quoted if needed,\n"
284 "\tport number could be followed by 't' to leave packet vlan tagged (CPU \n"
285 "\tport default) or by 'u' to untag packet (other ports default) before \n"
286 "\tbringing it to the port, '*' is ignored\n"
288 "1) ASUS WL-500g Deluxe stock config (eth0 is WAN, eth0.1 is LAN):\n"
289 "robocfg switch disable vlans enable reset vlan 0 ports \"0 5u\" vlan 1 ports \"1 2 3 4 5t\""
290 " port 0 state enabled stp none switch enable\n"
291 "2) WRT54g, WL-500g Deluxe OpenWRT config (vlan0 is LAN, vlan1 is WAN):\n"
292 "robocfg switch disable vlans enable reset vlan 0 ports \"1 2 3 4 5t\" vlan 1 ports \"0 5t\""
293 " port 0 state enabled stp none switch enable\n",
294 rxtx
[0], rxtx
[1], rxtx
[2], rxtx
[3], stp
[0], stp
[1], stp
[2], stp
[3], stp
[4], stp
[5],
295 media
[0].name
, media
[1].name
, media
[2].name
, media
[3].name
, media
[4].name
,
296 #if defined(BMCR_SPEED1000)
297 media
[5].name
, media
[6].name
,
299 mdix
[0].name
, mdix
[1].name
, mdix
[2].name
,
304 main(int argc
, char *argv
[])
310 int robo535x
= 0; /* 0 - 5365, 1 - 5325/5352/5354, 3 - 5356, 4 - 53115 */
314 struct ethtool_drvinfo info
;
316 if ((robo
.fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
321 /* the only interface for now */
322 strcpy(robo
.ifr
.ifr_name
, "eth0");
324 memset(&info
, 0, sizeof(info
));
325 info
.cmd
= ETHTOOL_GDRVINFO
;
326 robo
.ifr
.ifr_data
= (caddr_t
)&info
;
327 if (ioctl(robo
.fd
, SIOCETHTOOL
, (caddr_t
)&robo
.ifr
) < 0) {
328 perror("SIOCETHTOOL: your ethernet module is either unsupported or outdated");
331 if (strcmp(info
.driver
, "et0") && strcmp(info
.driver
, "b44")) {
332 fprintf(stderr
, "No suitable module found for %s (managed by %s)\n",
333 robo
.ifr
.ifr_name
, info
.driver
);
337 /* try access using MII ioctls - get phy address */
338 if (ioctl(robo
.fd
, SIOCGMIIPHY
, &robo
.ifr
) < 0) {
341 /* got phy address check for robo address */
342 struct mii_ioctl_data
*mii
= (struct mii_ioctl_data
*)&robo
.ifr
.ifr_data
;
343 if (mii
->phy_id
!= ROBO_PHY_ADDR
) {
344 fprintf(stderr
, "Invalid phy address (%d)\n", mii
->phy_id
);
349 phyid
= mdio_read(&robo
, ROBO_PHY_ADDR
, 0x2) |
350 (mdio_read(&robo
, ROBO_PHY_ADDR
, 0x3) << 16);
351 if (phyid
== 0 && robo
.et
== 0)
352 phyid
= mdio_read(&robo
, 0, 0x2) |
353 (mdio_read(&robo
, 0, 0x3) << 16);
355 if (phyid
== 0xffffffff || phyid
== 0x55210022) {
356 fprintf(stderr
, "No Robo switch in managed mode found\n");
360 robo535x
= robo_vlan535x(&robo
, phyid
);
362 for (i
= 1; i
< argc
;) {
363 if (strcasecmp(argv
[i
], "showmacs") == 0)
365 /* show MAC table of switch */
367 int idx
, off
, base_vlan
;
369 base_vlan
= 0; /*get_vid_by_idx(&robo, 0);*/
372 "--------------------------------------\n"
373 "VLAN MAC Type Port\n"
374 "--------------------------------------\n");
375 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_ARL_RW_CTRL
, 0x81);
376 robo_write16(&robo
, ROBO_ARLIO_PAGE
, (robo535x
== 4) ?
377 ROBO_ARL_SEARCH_CTRL_53115
: ROBO_ARL_SEARCH_CTRL
, 0x80);
378 for (idx
= 0; idx
< ((robo535x
== 4) ?
379 NUM_ARL_TABLE_ENTRIES_53115
: robo535x
?
380 NUM_ARL_TABLE_ENTRIES_5350
: NUM_ARL_TABLE_ENTRIES
); idx
++)
384 off
= (idx
& 0x01) << 4;
385 if (!off
&& (robo_read16(&robo
, ROBO_ARLIO_PAGE
,
386 ROBO_ARL_SEARCH_CTRL_53115
) & 0x80) == 0) break;
387 robo_read(&robo
, ROBO_ARLIO_PAGE
,
388 ROBO_ARL_SEARCH_RESULT_53115
+ off
, buf
, 4);
389 robo_read(&robo
, ROBO_ARLIO_PAGE
,
390 ROBO_ARL_SEARCH_RESULT_EXT_53115
+ off
, &buf
[4], 2);
392 robo_read(&robo
, ROBO_ARLIO_PAGE
, ROBO_ARL_SEARCH_RESULT
,
393 buf
, robo535x
? 4 : 5);
394 if ((robo535x
== 4) ? (buf
[5] & 0x01) : (buf
[3] & 0x8000) /* valid */)
396 printf("%04i %02x:%02x:%02x:%02x:%02x:%02x %7s %c\n",
397 (base_vlan
| (robo535x
== 4) ?
398 (base_vlan
| (buf
[3] & 0xfff)) :
399 ((buf
[3] >> 5) & 0x0f) |
400 (robo535x
? 0 : ((buf
[4] & 0x0f) << 4))),
401 buf
[2] >> 8, buf
[2] & 255,
402 buf
[1] >> 8, buf
[1] & 255,
403 buf
[0] >> 8, buf
[0] & 255,
405 (buf
[4] & 0x8000) : (buf
[3] & 0x4000)) ? "STATIC" : "DYNAMIC"),
407 '0'+(buf
[4] & 0x0f) : ports
[buf
[3] & 0x0f])
413 if (strcasecmp(argv
[i
], "port") == 0 && (i
+ 1) < argc
)
415 int index
= atoi(argv
[++i
]);
416 /* read port specs */
418 if (strcasecmp(argv
[i
], "state") == 0 && ++i
< argc
) {
419 for (j
= 0; j
< 4 && strcasecmp(argv
[i
], rxtx
[j
]); j
++);
422 robo_write16(&robo
,ROBO_CTRL_PAGE
, port
[index
],
423 (robo_read16(&robo
, ROBO_CTRL_PAGE
, port
[index
]) & ~(3 << 0)) | (j
<< 0));
425 fprintf(stderr
, "Invalid state '%s'.\n", argv
[i
]);
429 if (strcasecmp(argv
[i
], "stp") == 0 && ++i
< argc
) {
430 for (j
= 0; j
< 8 && strcasecmp(argv
[i
], stp
[j
]); j
++);
433 robo_write16(&robo
,ROBO_CTRL_PAGE
, port
[index
],
434 (robo_read16(&robo
, ROBO_CTRL_PAGE
, port
[index
]) & ~(7 << 5)) | (j
<< 5));
436 fprintf(stderr
, "Invalid stp '%s'.\n", argv
[i
]);
440 if (strcasecmp(argv
[i
], "media") == 0 && ++i
< argc
) {
441 for (j
= 0; j
< 7 && strcasecmp(argv
[i
], media
[j
].name
); j
++);
442 if (j
< ((robo535x
== 4) ? 7 : 5)) {
444 mdio_write(&robo
, port
[index
], MII_BMCR
, media
[j
].bmcr
);
446 fprintf(stderr
, "Invalid media '%s'.\n", argv
[i
]);
450 if (strcasecmp(argv
[i
], "mdi-x") == 0 && ++i
< argc
) {
451 for (j
= 0; j
< 3 && strcasecmp(argv
[i
], mdix
[j
].name
); j
++);
455 mdio_write(&robo
, port
[index
], 0x10, mdix
[j
].value1
|
456 (mdio_read(&robo
, port
[index
], 0x10) & ~0x4000));
457 mdio_write(&robo
, port
[index
], 0x18, 0x7007);
458 mdio_write(&robo
, port
[index
], 0x18, mdix
[j
].value2
|
459 (mdio_read(&robo
, port
[index
], 0x18) & ~0x8207));
460 mdio_write(&robo
, port
[index
], 0x1e, mdix
[j
].value3
|
461 (mdio_read(&robo
, port
[index
], 0x1e) & ~0x0080));
463 mdio_write(&robo
, port
[index
], 0x1c, mdix
[j
].value
|
464 (mdio_read(&robo
, port
[index
], 0x1c) & ~0x1800));
466 fprintf(stderr
, "Invalid mdi-x '%s'.\n", argv
[i
]);
470 if (strcasecmp(argv
[i
], "tag") == 0 && ++i
< argc
) {
472 /* change vlan tag */
473 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_PORT0_DEF_TAG
+ (index
<< 1), j
);
475 if (strcasecmp(argv
[i
], "jumbo") == 0 && ++i
< argc
) {
476 for (j
= 0; j
< 2 && strcasecmp(argv
[i
], jumbo
[j
]); j
++);
477 if (robo535x
== 4 && j
< 2) {
478 /* change jumbo frame feature */
479 robo_write32(&robo
, ROBO_JUMBO_PAGE
, ROBO_JUMBO_CTRL
,
480 (robo_read32(&robo
, ROBO_JUMBO_PAGE
, ROBO_JUMBO_CTRL
) &
481 ~(1 << port
[index
])) | (j
<< port
[index
]));
483 fprintf(stderr
, "Invalid jumbo state '%s'.\n", argv
[i
]);
489 if (strcasecmp(argv
[i
], "vlan") == 0 && (i
+ 1) < argc
)
491 int vid
= atoi(argv
[++i
]);
493 if (strcasecmp(argv
[i
], "ports") == 0 && ++i
< argc
) {
494 char *ports
= argv
[i
];
498 while (*ports
>= '0' && *ports
<= '9') {
502 /* untag if needed, CPU port requires special handling */
503 if (*ports
== 'u' || (j
!= 5 && (*ports
== ' ' || *ports
== 0)))
507 /* change default vlan tag */
508 robo_write16(&robo
, ROBO_VLAN_PAGE
,
509 ROBO_VLAN_PORT0_DEF_TAG
+ (j
<< 1), vid
);
511 if (*ports
== '*' || *ports
== 't' || *ports
== ' ') ports
++;
514 while (*ports
== ' ') ports
++;
518 fprintf(stderr
, "Invalid ports '%s'.\n", argv
[i
]);
521 /* write config now */
522 val16
= (vid
) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
524 val32
= (untag
<< 9) | member
;
526 robo_write32(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ENTRY_5395
, val32
);
528 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
, vid
);
530 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
531 (1 << 7) /* start */ | 0 /* write */);
532 } else if (robo535x
) {
534 val32
= (1 << 24) /* valid */ | (untag
<< 6) | member
| (vid
<< 12);
536 val32
= (1 << 20) /* valid */ | (untag
<< 6) | member
| ((vid
>> 4) << 12);
537 robo_write32(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE_5350
, val32
);
538 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
540 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE
,
541 (1 << 14) /* valid */ | (untag
<< 7) | member
);
542 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS
, val16
);
548 if (strcasecmp(argv
[i
], "switch") == 0 && (i
+ 1) < argc
)
550 /* enable/disable switching */
551 robo_write16(&robo
, ROBO_CTRL_PAGE
, ROBO_SWITCH_MODE
,
552 (robo_read16(&robo
, ROBO_CTRL_PAGE
, ROBO_SWITCH_MODE
) & ~2) |
553 (*argv
[++i
] == 'e' ? 2 : 0));
556 if (strcasecmp(argv
[i
], "vlans") == 0 && (i
+ 1) < argc
)
559 if (strcasecmp(argv
[i
], "reset") == 0) {
560 /* reset vlan validity bit */
562 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
563 (1 << 7) /* start */ | 2 /* flush */);
565 for (j
= 0; j
<= ((robo535x
== 1) ? VLAN_ID_MAX5350
: VLAN_ID_MAX
); j
++)
567 /* write config now */
568 val16
= (j
) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
570 robo_write32(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE_5350
, 0);
571 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
573 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_WRITE
, 0);
574 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS
, val16
);
578 if (strcasecmp(argv
[i
], "enable") == 0 || strcasecmp(argv
[i
], "disable") == 0)
580 int disable
= (*argv
[i
] == 'd') || (*argv
[i
] == 'D');
581 /* enable/disable vlans */
582 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL0
, disable
? 0 :
583 (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
585 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL1
, disable
? 0 :
586 (1 << 1) | (1 << 2) | (1 << 3) /* RSV multicast */);
588 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL4
, disable
? 0 :
589 (1 << 6) /* drop invalid VID frames */);
591 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL5
, disable
? 0 :
592 (1 << 3) /* drop miss V table frames */);
597 if (strcasecmp(argv
[i
], "show") == 0)
601 if (strncasecmp(argv
[i
], "robowr", 6) == 0 && (i
+ 2) < argc
)
603 long pagereg
= strtoul(argv
[i
+ 1], NULL
, 0);
604 int size
= strtoul(argv
[i
] + 6, NULL
, 0);
606 unsigned long long int v
;
609 size
= (size
> 0 && size
<= sizeof(buf
) * 16) ? (size
+ 15) >> 4 : 1;
611 v
= strtoull(argv
[i
+ 2], NULL
, 0);
612 for (k
= 0; k
< size
; k
++)
614 buf
[k
] = (u16
)(v
& 0xFFFF);
617 robo_write(&robo
, pagereg
>> 8, pagereg
& 255, buf
, size
);
619 printf("Page 0x%02x, Reg 0x%02x: ",
620 (u16
)(pagereg
>> 8), (u8
)(pagereg
& 255));
621 robo_read(&robo
, pagereg
>> 8, pagereg
& 255, buf
, size
);
623 printf("%04x", buf
[--size
]);
628 if (strncasecmp(argv
[i
], "robord", 6) == 0 && (i
+ 1) < argc
)
630 long pagereg
= strtoul(argv
[i
+ 1], NULL
, 0);
631 int size
= strtoul(argv
[i
] + 6, NULL
, 0);
634 size
= (size
> 0 && size
<= sizeof(buf
) * 16) ? (size
+ 15) >> 4 : 1;
636 printf("Page 0x%02x, Reg 0x%02x: ",
637 (u16
)(pagereg
>> 8), (u8
)(pagereg
& 255));
639 robo_read(&robo
, pagereg
>> 8, pagereg
& 255, buf
, size
);
641 printf("%04x", buf
[--size
]);
646 if (strcasecmp(argv
[i
], "dump") == 0)
648 for (i
= 0; i
< 256; i
++)
650 if (_robo_reg(&robo
, i
, 0, REG_MII_ADDR_READ
))
653 printf("Page %02x\n", i
);
655 for (j
= 0; j
< 128; j
++) {
657 robo_read16(&robo
, i
, j
), (j
% 16) == 15 ? "\n" : "");
663 fprintf(stderr
, "Invalid option %s\n", argv
[i
]);
670 if (argc
== 1) usage();
676 printf("Switch: %sabled %s\n", robo_read16(&robo
, ROBO_CTRL_PAGE
, ROBO_SWITCH_MODE
) & 2 ? "en" : "dis",
677 robo
.gmii
? "gigabit" : "");
679 for (i
= 0; i
< 6; i
++) {
680 printf(robo_read16(&robo
, ROBO_STAT_PAGE
, ROBO_LINK_STAT_SUMMARY
) & (1 << port
[i
]) ?
681 "Port %d: %4s%s " : "Port %d: DOWN ",
682 (robo535x
== 4) ? port
[i
] : i
,
683 speed
[(robo535x
== 4) ?
684 (robo_read32(&robo
, ROBO_STAT_PAGE
, ROBO_SPEED_STAT_SUMMARY
) >> port
[i
] * 2) & 3 :
685 (robo_read16(&robo
, ROBO_STAT_PAGE
, ROBO_SPEED_STAT_SUMMARY
) >> port
[i
]) & 1],
686 robo_read16(&robo
, ROBO_STAT_PAGE
, (robo535x
== 4) ?
687 ROBO_DUPLEX_STAT_SUMMARY_53115
: ROBO_DUPLEX_STAT_SUMMARY
) & (1 << port
[i
]) ? "FD" : "HD");
689 val16
= robo_read16(&robo
, ROBO_CTRL_PAGE
, port
[i
]);
691 printf("%s stp: %s vlan: %d ", rxtx
[val16
& 3], stp
[(val16
>> 5) & 7],
692 robo_read16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_PORT0_DEF_TAG
+ (i
<< 1)));
695 printf("jumbo: %s ", jumbo
[(robo_read32(&robo
, ROBO_JUMBO_PAGE
, ROBO_JUMBO_CTRL
) >> port
[i
]) & 1]);
697 robo_read(&robo
, ROBO_STAT_PAGE
, ROBO_LSA_PORT0
+ port
[i
] * 6, mac
, 3);
699 printf("mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
700 mac
[2] >> 8, mac
[2] & 255, mac
[1] >> 8, mac
[1] & 255, mac
[0] >> 8, mac
[0] & 255);
703 val16
= robo_read16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_CTRL0
);
705 printf("VLANs: %s %sabled%s%s\n",
706 (robo535x
== 4) ? "BCM53115" : (robo535x
? "BCM5325/535x" : "BCM536x"),
707 (val16
& (1 << 7)) ? "en" : "dis",
708 (val16
& (1 << 6)) ? " mac_check" : "",
709 (val16
& (1 << 5)) ? " mac_hash" : "");
712 for (i
= 0; i
<= ((robo535x
== 4) ? VLAN_ID_MAX5395
/* slow, needs rework, but how? */ :
713 (robo535x
? VLAN_ID_MAX5350
: VLAN_ID_MAX
)); i
++)
716 val16
= (i
) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
720 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_INDX_5395
, i
);
722 robo_write16(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ACCESS_5395
,
723 (1 << 7) /* start */ | 1 /* read */);
725 val32
= robo_read32(&robo
, ROBO_ARLIO_PAGE
, ROBO_VTBL_ENTRY_5395
);
727 printf("%4d: vlan%d:", i
, i
);
728 for (j
= 0; j
<= 8; j
++) {
729 if (val32
& (1 << j
)) {
730 printf(" %d%s", j
, (val32
& (1 << (j
+ 9))) ?
731 (j
== 8 ? "u" : "") : "t");
736 } else if (robo535x
) {
737 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS_5350
, val16
);
739 val32
= robo_read32(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_READ
);
740 if ((val32
& (robo535x
== 3 ? (1 << 24) : (1 << 20))) /* valid */) {
741 val16
= (robo535x
== 3)
742 ? ((val32
& 0xff000) >> 12)
743 : ((val32
& 0xff000) >> 12) << 4;
744 printf("%4d: vlan%d:", i
, val16
| i
);
745 for (j
= 0; j
< 6; j
++) {
746 if (val32
& (1 << j
)) {
747 printf(" %d%s", j
, (val32
& (1 << (j
+ 6))) ?
748 (j
== 5 ? "u" : "") : "t");
754 robo_write16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_TABLE_ACCESS
, val16
);
756 val16
= robo_read16(&robo
, ROBO_VLAN_PAGE
, ROBO_VLAN_READ
);
757 if ((val16
& (1 << 14)) /* valid */) {
758 printf("%4d: vlan%d:", i
, i
);
759 for (j
= 0; j
< 6; j
++) {
760 if (val16
& (1 << j
)) {
761 printf(" %d%s", j
, (val16
& (1 << (j
+ 7))) ?
762 (j
== 5 ? "u" : "") : "t");