Companion patch to: https://lists.openwrt.org/pipermail/openwrt-devel/2012-December/017995.html
Signed-off-by: Nathan Hintz <[email protected]> Index: package/robocfg/src/etc53xx.h =================================================================== --- package/robocfg/src/etc53xx.h (revision 34996) +++ package/robocfg/src/etc53xx.h (working copy) @@ -15,9 +15,10 @@ #define __BCM535M_H_ /* ROBO embedded device type */ -#define ROBO_DEV_5380 1 -#define ROBO_DEV_5365 2 -#define ROBO_DEV_5350 3 +#define ROBO_DEV_5380 1 +#define ROBO_DEV_5365 2 +#define ROBO_DEV_5350 3 +#define ROBO_DEV_53115 4 /* BCM5325m GLOBAL PAGE REGISTER MAP */ #ifndef _CFE_ @@ -316,7 +317,19 @@ #define ROBO_ARL_SEARCH_RESULT_EXT 0x2c /* ARL Search Result Extension (5350): 8bit */ #define ROBO_ARL_VID_ENTRY0 0x30 /* ARL VID Entry 0: 64bit */ #define ROBO_ARL_VID_ENTRY1 0x32 /* ARL VID Entry 1: 64bit */ +#define ROBO_ARL_SEARCH_CTRL_53115 0x50 /* ARL Search Control: 8bit */ +#define ROBO_ARL_SEARCH_ADDR_53115 0x51 /* ARL Search Address: 16bit */ +#define ROBO_ARL_SEARCH_RESULT_53115 0x60 /* ARL Search Result: 64bit */ +#define ROBO_ARL_SEARCH_RESULT_EXT_53115 0x68 /* ARL Search Result Extension (53115): 16bit */ +/* BCM5395/5397/5398/53115 */ +#define ROBO_VTBL_ACCESS 0x60 /* VLAN table access: 8bit */ +#define ROBO_VTBL_INDX 0x61 /* VLAN table address index: 16bit */ +#define ROBO_VTBL_ENTRY 0x63 /* VLAN table entry: 32bit */ +#define ROBO_VTBL_ACCESS_5395 0x80 /* VLAN table access: 8bit */ +#define ROBO_VTBL_INDX_5395 0x81 /* VLAN table address index: 16bit */ +#define ROBO_VTBL_ENTRY_5395 0x83 /* VLAN table entry: 32bit */ + /* BCM5325m MANAGEMENT FRAME REGISTERS (0x6) REGISTER MAP: 8/16 bit regs */ #define ROBO_MGMT_FRAME_RD_DATA 0x00 /* Management Frame Read Data :8bit*/ #define ROBO_MGMT_FRAME_WR_DATA 0x01 /* Management Frame Write Data:8bit*/ @@ -342,6 +355,8 @@ #define NUM_VLAN_TABLE_ENTRIES_5350 16 /* number of entries in VLAN table */ #define ARL_TABLE_ADDR_5350 0x1c00 /* offset of ARL table start (5350) */ #endif +#define NUM_ARL_TABLE_ENTRIES_53115 4096 /* number of entries in ARL table (53115) */ +#define NUM_VLAN_TABLE_ENTRIES_53115 4096 /* number of entries in VLAN table */ typedef struct _ROBO_MEM_ACCESS_CTRL_STRUC { unsigned int memAddr:14; /* 64-bit memory address */ @@ -529,6 +544,7 @@ #define VLAN_ID_HIGH_BITS 0 /* static high bits in table access reg */ #define VLAN_ID_MAX 255 /* max VLAN id */ #define VLAN_ID_MAX5350 15 /* max VLAN id (5350) */ +#define VLAN_ID_MAX5395 4094 /* max VLAN id (5395) */ #define VLAN_ID_MASK VLAN_ID_MAX /* VLAN id mask */ #ifdef BCM5380 #define VLAN_UNTAG_SHIFT 13 /* for postioning untag bits in write reg */ @@ -594,26 +610,15 @@ #define ROBO_VLAN_PORT5_DEF_TAG 0x1a /* 16b: VLAN Port 5 Default Tag Register */ #define ROBO_VLAN_PORT6_DEF_TAG 0x1c /* 16b: VLAN Port 6 Default Tag Register */ #define ROBO_VLAN_PORT7_DEF_TAG 0x1e /* 16b: VLAN Port 7 Default Tag Register */ +#define ROBO_VLAN_PORT8_DEF_TAG 0x20 /* 16b: VLAN Port 8 Default Tag Register */ +/* 53115 only */ +#define ROBO_DUPLEX_STAT_SUMMARY_53115 0x08 /* Duplex Status Summary: 16bit */ +#define ROBO_JUMBO_PAGE 0x40 +#define ROBO_JUMBO_CTRL 0x01 /* 32bit */ +#define ROBO_JUMBO_SIZE 0x05 /* 16bit */ -/* obsolete */ -#define ROBO_VLAN_PORT0_CTRL 0x00 /* 16b: Port 0 VLAN Register */ -#define ROBO_VLAN_PORT1_CTRL 0x02 /* 16b: Port 1 VLAN Register */ -#define ROBO_VLAN_PORT2_CTRL 0x04 /* 16b: Port 2 VLAN Register */ -#define ROBO_VLAN_PORT3_CTRL 0x06 /* 16b: Port 3 VLAN Register */ -#define ROBO_VLAN_PORT4_CTRL 0x08 /* 16b: Port 4 VLAN Register */ -#define ROBO_VLAN_IM_PORT_CTRL 0x10 /* 16b: Inverse MII Port VLAN Reg */ -#define ROBO_VLAN_SMP_PORT_CTRL 0x12 /* 16b: Serial Port VLAN Register */ -#define ROBO_VLAN_PORTSPI_DEF_TAG 0x1c /* 16b: VLAN Port SPI Default Tag Register */ -#define ROBO_VLAN_PRIORITY_REMAP 0x20 /* 24b: VLAN Priority Re-Map Register */ - #ifndef _CFE_ #pragma pack() #endif - #endif /* !__BCM535M_H_ */ - - - - - Index: package/robocfg/src/robocfg.c =================================================================== --- package/robocfg/src/robocfg.c (revision 34996) +++ package/robocfg/src/robocfg.c (working copy) @@ -2,6 +2,7 @@ * Broadcom BCM5325E/536x switch configuration utility * * Copyright (C) 2005 Oleg I. Vdovikin + * Copyright (C) 2005 Dmitry 'dimss' Ivanov of "Telecentrs" (Riga, Latvia) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,7 +20,6 @@ * 02110-1301, USA. */ -#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -36,6 +36,7 @@ #include <linux/if.h> #include <linux/sockios.h> #include <linux/ethtool.h> +#include <linux/types.h> #include <linux/mii.h> #include "etc53xx.h" @@ -51,87 +52,79 @@ #define REG_MII_ADDR_READ 2 /* Private et.o ioctls */ -#define SIOCGETCPHYRD (SIOCDEVPRIVATE + 9) -#define SIOCSETCPHYWR (SIOCDEVPRIVATE + 10) +#define SIOCGETCPHYRD (SIOCDEVPRIVATE + 9) +#define SIOCSETCPHYWR (SIOCDEVPRIVATE + 10) +#define SIOCGETCPHYRD2 (SIOCDEVPRIVATE + 12) +#define SIOCSETCPHYWR2 (SIOCDEVPRIVATE + 13) +#define SIOCGETCROBORD (SIOCDEVPRIVATE + 14) +#define SIOCSETCROBOWR (SIOCDEVPRIVATE + 15) typedef struct { struct ifreq ifr; int fd; - int et; /* use private ioctls */ + u8 et; /* use private ioctls */ + u8 gmii; /* gigabit mii */ } robo_t; -static u16 mdio_read(robo_t *robo, u16 phy_id, u8 reg) +static u16 __mdio_access(robo_t *robo, u16 phy_id, u8 reg, u16 val, u16 wr) { + static int __ioctl_args[2][3] = { {SIOCGETCPHYRD, SIOCGETCPHYRD2, SIOCGMIIREG}, + {SIOCSETCPHYWR, SIOCSETCPHYWR2, SIOCSMIIREG} }; + if (robo->et) { - int args[2] = { reg }; - + u32 args[2] = { reg, val }; + int cmd = 0; + if (phy_id != ROBO_PHY_ADDR) { - fprintf(stderr, - "Access to real 'phy' registers unavaliable.\n" - "Upgrade kernel driver.\n"); - - return 0xffff; + cmd = 1; + args[0] |= ((u32)phy_id) << 16; } - robo->ifr.ifr_data = (caddr_t) args; - if (ioctl(robo->fd, SIOCGETCPHYRD, (caddr_t)&robo->ifr) < 0) { - perror("SIOCGETCPHYRD"); + if (ioctl(robo->fd, __ioctl_args[wr][cmd], (caddr_t)&robo->ifr) < 0) { + if (phy_id != ROBO_PHY_ADDR) { + fprintf(stderr, + "Access to real 'phy' registers unavaliable.\n" + "Upgrade kernel driver.\n"); + return 0xffff; + } + perror("ET ioctl"); exit(1); } - 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"); + mii->val_in = val; + if (ioctl(robo->fd, __ioctl_args[wr][2], &robo->ifr) < 0) { + perror("MII ioctl"); exit(1); } return mii->val_out; } } -static void mdio_write(robo_t *robo, u16 phy_id, u8 reg, u16 val) +static inline u16 mdio_read(robo_t *robo, u16 phy_id, u8 reg) { - if (robo->et) { - int args[2] = { reg, val }; + return __mdio_access(robo, phy_id, reg, 0, 0); +} - 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"); - exit(1); - } - } 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) { - perror("SIOCSMIIREG"); - exit(1); - } - } +static inline void mdio_write(robo_t *robo, u16 phy_id, u8 reg, u16 val) +{ + __mdio_access(robo, phy_id, reg, val, 1); } -static int robo_reg(robo_t *robo, u8 page, u8 reg, u8 op) +static int _robo_reg(robo_t *robo, u8 page, u8 reg, u8 op) { int i = 3; /* set page number */ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_PAGE, - (page << 8) | REG_MII_PAGE_ENABLE); + (((u16)page) << 8) | REG_MII_PAGE_ENABLE); /* set register address */ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_ADDR, - (reg << 8) | op); + (((u16)reg) << 8) | op); /* check if operation completed */ while (i--) { @@ -139,9 +132,17 @@ return 0; } - fprintf(stderr, "robo_reg: timeout\n"); - exit(1); - + return -1; +} + +static int robo_reg(robo_t *robo, u8 page, u8 reg, u8 op) +{ + if (_robo_reg(robo, page, reg, op)) + { + fprintf(stderr, "robo_reg: %x/%x timeout\n", page, reg); + exit(1); + } + return 0; } @@ -166,10 +167,20 @@ { robo_reg(robo, page, reg, REG_MII_ADDR_READ); - return mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0) + - (mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16); + return ((u32)mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0)) | + ((u32)mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16); } +static void robo_write(robo_t *robo, u8 page, u8 reg, u16 *val, int count) +{ + int i; + + for (i = 0; i < count; i++) + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + i, val[i]); + + robo_reg(robo, page, reg, REG_MII_ADDR_WRITE); +} + static void robo_write16(robo_t *robo, u8 page, u8 reg, u16 val16) { /* write data */ @@ -181,44 +192,79 @@ static void robo_write32(robo_t *robo, u8 page, u8 reg, u32 val32) { /* write data */ - mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 65535); - mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1, val32 >> 16); + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, (u16)(val32 & 0xFFFF)); + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1, (u16)(val32 >> 16)); robo_reg(robo, page, reg, REG_MII_ADDR_WRITE); } -/* checks that attached switch is 5325E/5350 */ -static int robo_vlan5350(robo_t *robo) +/* checks that attached switch is 5325/5352/5354/5356/5357/53115 */ +static int robo_vlan535x(robo_t *robo, u32 phyid) { /* 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 */ - return (robo_read16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) == val16); + 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; } -u8 port[6] = { 0, 1, 2, 3, 4, 8 }; -char ports[6] = { 'W', '4', '3', '2', '1', 'C' }; +u8 port[9] = { 0, 1, 2, 3, 4, 8, 0, 0, 8}; +char ports[] = "01234???5???????"; +char *speed[4] = { "10", "100", "1000" , "4" }; char *rxtx[4] = { "enabled", "rx_disabled", "tx_disabled", "disabled" }; char *stp[8] = { "none", "disable", "block", "listen", "learn", "forward", "6", "7" }; +char *jumbo[2] = { "off", "on" }; 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 } }; +} media[7] = { + { "auto", BMCR_ANENABLE | BMCR_ANRESTART }, + { "10HD", 0 }, + { "10FD", BMCR_FULLDPLX }, + { "100HD", BMCR_SPEED100 }, + { "100FD", BMCR_SPEED100 | BMCR_FULLDPLX }, + { "1000HD", BMCR_SPEED1000 }, + { "1000FD", BMCR_SPEED1000 | BMCR_FULLDPLX } +}; struct { char *name; u16 value; -} mdix[3] = { { "auto", 0x0000 }, { "on", 0x1800 }, { "off", 0x0800 } }; + u16 value1; + u16 value2; + u16 value3; +} mdix[3] = { + { "auto", 0x0000, 0x0000, 0x8207, 0x0000 }, + { "on", 0x1800, 0x4000, 0x8007, 0x0080 }, + { "off", 0x0800, 0x4000, 0x8007, 0x0000 } +}; void usage() { - fprintf(stderr, "Broadcom BCM5325E/536x switch configuration utility\n" - "Copyright (C) 2005 Oleg I. Vdovikin\n\n" + fprintf(stderr, "Broadcom BCM5325/535x/536x/5311x switch configuration utility\n" + "Copyright (C) 2005-2008 Oleg I. Vdovikin ([email protected])\n" + "Copyright (C) 2005 Dmitry 'dimss' Ivanov of \"Telecentrs\" (Riga, Latvia)\n\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" @@ -226,10 +272,13 @@ fprintf(stderr, "Usage: robocfg <op> ... <op>\n" "Operations are as below:\n" - "\tshow\n" + "\tshow -- show current config\n" + "\tshowmacs -- show known MAC addresses\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" + "\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|%s|%s]\n" + "\t\t[mdi-x %s|%s|%s] [jumbo %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" @@ -244,113 +293,132 @@ "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], - media[0].name, media[1].name, media[2].name, media[3].name, media[4].name, - mdix[0].name, mdix[1].name, mdix[2].name); + media[0].name, media[1].name, media[2].name, media[3].name, media[4].name, media[5].name, media[6].name, + mdix[0].name, mdix[1].name, mdix[2].name, + jumbo[0], jumbo[1]); } -static robo_t robo; -int bcm53xx_probe(const char *dev) +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 */ + u32 phyid; + + static robo_t robo; struct ethtool_drvinfo info; - unsigned int phyid; - int ret; + + memset(&robo, 0, sizeof(robo)); + if ((robo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + exit(1); + } - fprintf(stderr, "probing %s\n", dev); + /* the only interface for now */ + strcpy(robo.ifr.ifr_name, "eth0"); - strcpy(robo.ifr.ifr_name, dev); memset(&info, 0, sizeof(info)); info.cmd = ETHTOOL_GDRVINFO; robo.ifr.ifr_data = (caddr_t)&info; - ret = ioctl(robo.fd, SIOCETHTOOL, (caddr_t)&robo.ifr); - if (ret < 0) { - perror("SIOCETHTOOL"); - return ret; + 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, "b44") && + strcmp(info.driver, "bgmac") && + strcmp(info.driver, "bcm63xx_enet") ) { + fprintf(stderr, "No suitable module found for %s (managed by %s)\n", + robo.ifr.ifr_name, info.driver); + exit(1); } - - if ( strcmp(info.driver, "et0") && - strcmp(info.driver, "b44") && - strcmp(info.driver, "bcm63xx_enet") ) { - fprintf(stderr, "driver not supported %s\n", info.driver); - return -ENOSYS; - } - + /* try access using MII ioctls - get phy address */ - robo.et = 0; - if (ioctl(robo.fd, SIOCGMIIPHY, &robo.ifr) < 0) - robo.et = 1; + if (ioctl(robo.fd, SIOCGMIIPHY, &robo.ifr) < 0) { + u32 args[2] = { ((u32)ROBO_PHY_ADDR) << 16, 0x0 }; - if (robo.et) { - unsigned int args[2] = { 2 }; - robo.ifr.ifr_data = (caddr_t) args; - ret = ioctl(robo.fd, SIOCGETCPHYRD, (caddr_t)&robo.ifr); - if (ret < 0) { - perror("SIOCGETCPHYRD"); - return ret; - } - phyid = args[1] & 0xffff; - - args[0] = 3; - robo.ifr.ifr_data = (caddr_t) args; - ret = ioctl(robo.fd, SIOCGETCPHYRD, (caddr_t)&robo.ifr); - if (ret < 0) { - perror("SIOCGETCPHYRD"); - return ret; - } - phyid |= args[1] << 16; + 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; - mii->phy_id = ROBO_PHY_ADDR; - mii->reg_num = 2; - ret = ioctl(robo.fd, SIOCGMIIREG, &robo.ifr); - if (ret < 0) { - perror("SIOCGMIIREG"); - return ret; + if (mii->phy_id != ROBO_PHY_ADDR) { + fprintf(stderr, "Invalid phy address (%d)\n", mii->phy_id); + exit(1); } - phyid = mii->val_out & 0xffff; - - mii->phy_id = ROBO_PHY_ADDR; - mii->reg_num = 3; - ret = ioctl(robo.fd, SIOCGMIIREG, &robo.ifr); - if (ret < 0) { - perror("SIOCGMIIREG"); - return ret; - } - phyid |= mii->val_out << 16; } + phyid = ((u32)mdio_read(&robo, ROBO_PHY_ADDR, 0x2)) | + (((u32)mdio_read(&robo, ROBO_PHY_ADDR, 0x3)) << 16); + if (phyid == 0 && robo.et != 1) + phyid = ((u32)mdio_read(&robo, 0, 0x2)) | + (((u32)mdio_read(&robo, 0, 0x3)) << 16); + if (phyid == 0xffffffff || phyid == 0x55210022) { - perror("phyid"); - return -EIO; + fprintf(stderr, "No Robo switch in managed mode found\n"); + exit(1); } - return 0; -} - -int -main(int argc, char *argv[]) -{ - u16 val16; - u16 mac[3]; - int i = 0, j; - int robo5350 = 0; - u32 phyid; + robo535x = robo_vlan535x(&robo, phyid); + /* fprintf(stderr, "phyid %08x id %d\n", phyid, robo535x); */ - if ((robo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket"); - exit(1); - } + for (i = 1; i < argc;) { + if (strcasecmp(argv[i], "showmacs") == 0) + { + /* show MAC table of switch */ + u16 buf[6]; + int idx, off, base_vlan; - if (bcm53xx_probe("eth1")) { - if (bcm53xx_probe("eth0")) { - perror("bcm53xx_probe"); - exit(1); - } - } + base_vlan = 0; /*get_vid_by_idx(&robo, 0);*/ - robo5350 = robo_vlan5350(&robo); - - for (i = 1; i < argc;) { + 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 if (strcasecmp(argv[i], "port") == 0 && (i + 1) < argc) { int index = atoi(argv[++i]); @@ -379,8 +447,9 @@ } } else if (strcasecmp(argv[i], "media") == 0 && ++i < argc) { - for (j = 0; j < 5 && strcasecmp(argv[i], media[j].name); j++); - if (j < 5) { + for (j = 0; j < 7 && strcasecmp(argv[i], media[j].name); j++); + if (j < ((robo535x == 4) ? 7 : 5)) { + /* change media */ mdio_write(&robo, port[index], MII_BMCR, media[j].bmcr); } else { fprintf(stderr, "Invalid media '%s'.\n", argv[i]); @@ -390,8 +459,18 @@ 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)); + /* change mdi-x */ + if (robo535x == 4) { + mdio_write(&robo, port[index], 0x10, mdix[j].value1 | + (mdio_read(&robo, port[index], 0x10) & ~0x4000)); + mdio_write(&robo, port[index], 0x18, 0x7007); + mdio_write(&robo, port[index], 0x18, mdix[j].value2 | + (mdio_read(&robo, port[index], 0x18) & ~0x8207)); + mdio_write(&robo, port[index], 0x1e, mdix[j].value3 | + (mdio_read(&robo, port[index], 0x1e) & ~0x0080)); + } else + 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); @@ -401,12 +480,24 @@ j = atoi(argv[i]); /* change vlan tag */ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (index << 1), j); + } else + if (strcasecmp(argv[i], "jumbo") == 0 && ++i < argc) { + for (j = 0; j < 2 && strcasecmp(argv[i], jumbo[j]); j++); + if (robo535x == 4 && j < 2) { + /* change jumbo frame feature */ + robo_write32(&robo, ROBO_JUMBO_PAGE, ROBO_JUMBO_CTRL, + (robo_read32(&robo, ROBO_JUMBO_PAGE, ROBO_JUMBO_CTRL) & + ~(1 << port[index])) | (j << port[index])); + } else { + fprintf(stderr, "Invalid jumbo state '%s'.\n", argv[i]); + exit(1); + } } else break; } } else if (strcasecmp(argv[i], "vlan") == 0 && (i + 1) < argc) { - int index = atoi(argv[++i]); + int vid = atoi(argv[++i]); while (++i < argc) { if (strcasecmp(argv[i], "ports") == 0 && ++i < argc) { char *ports = argv[i]; @@ -424,7 +515,7 @@ if (*ports) ports++; /* change default vlan tag */ robo_write16(&robo, ROBO_VLAN_PAGE, - ROBO_VLAN_PORT0_DEF_TAG + (j << 1), index); + ROBO_VLAN_PORT0_DEF_TAG + (j << 1), vid); } else if (*ports == '*' || *ports == 't' || *ports == ' ') ports++; else break; @@ -437,10 +528,22 @@ exit(1); } else { /* write config now */ - val16 = (index) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; - if (robo5350) { - robo_write32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, - (1 << 20) /* valid */ | (untag << 6) | member); + val16 = (vid) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; + if (robo535x == 4) { + val32 = (untag << 9) | member; + /* entry */ + robo_write32(&robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ENTRY_5395, val32); + /* index */ + robo_write16(&robo, ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395, vid); + /* access */ + robo_write16(&robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395, + (1 << 7) /* start */ | 0 /* write */); + } else if (robo535x) { + if (robo535x == 3) + val32 = (1 << 24) /* valid */ | (untag << 6) | member | (vid << 12); + else + val32 = (1 << 20) /* valid */ | (untag << 6) | member | ((vid >> 4) << 12); + robo_write32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, val32); robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); } else { robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, @@ -463,12 +566,16 @@ { while (++i < argc) { if (strcasecmp(argv[i], "reset") == 0) { + if (robo535x == 4) { + robo_write16(&robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395, + (1 << 7) /* start */ | 2 /* flush */); + } else /* reset vlan validity bit */ - for (j = 0; j <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) + for (j = 0; j <= ((robo535x == 1) ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) { /* write config now */ val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; - if (robo5350) { + if (robo535x) { robo_write32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, 0); robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); } else { @@ -499,6 +606,68 @@ if (strcasecmp(argv[i], "show") == 0) { break; + } else + if (strncasecmp(argv[i], "robowr", 6) == 0 && (i + 2) < argc) + { + long pagereg = strtoul(argv[i + 1], NULL, 0); + int size = strtoul(argv[i] + 6, NULL, 0); + int k; + unsigned long long int v; + u16 buf[4]; + + size = (size > 0 && size <= sizeof(buf) * 16) ? (size + 15) >> 4 : 1; + + v = strtoull(argv[i + 2], NULL, 0); + for (k = 0; k < size; k++) + { + buf[k] = (u16 )(v & 0xFFFF); + v >>= 16; + } + robo_write(&robo, pagereg >> 8, pagereg & 255, buf, size); + + printf("Page 0x%02x, Reg 0x%02x: ", + (u16 )(pagereg >> 8), (u8 )(pagereg & 255)); + robo_read(&robo, pagereg >> 8, pagereg & 255, buf, size); + while (size > 0) + printf("%04x", buf[--size]); + printf("\n"); + + i += 3; + } else + if (strncasecmp(argv[i], "robord", 6) == 0 && (i + 1) < argc) + { + long pagereg = strtoul(argv[i + 1], NULL, 0); + int size = strtoul(argv[i] + 6, NULL, 0); + u16 buf[4]; + + size = (size > 0 && size <= sizeof(buf) * 16) ? (size + 15) >> 4 : 1; + + printf("Page 0x%02x, Reg 0x%02x: ", + (u16 )(pagereg >> 8), (u8 )(pagereg & 255)); + + robo_read(&robo, pagereg >> 8, pagereg & 255, buf, size); + while (size > 0) + printf("%04x", buf[--size]); + printf("\n"); + + i += 2; + } else + if (strcasecmp(argv[i], "dump") == 0) + { + for (i = 0; i < 256; i++) + { + if (_robo_reg(&robo, i, 0, REG_MII_ADDR_READ)) + continue; + + printf("Page %02x\n", i); + + for (j = 0; j < 128; j++) { + printf(" %04x%s", + robo_read16(&robo, i, j), (j % 16) == 15 ? "\n" : ""); + } + } + + i = 2; } else { fprintf(stderr, "Invalid option %s\n", argv[i]); usage(); @@ -513,21 +682,29 @@ /* show config */ - printf("Switch: %sabled\n", robo_read16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & 2 ? "en" : "dis"); + printf("Switch: %sabled %s\n", robo_read16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & 2 ? "en" : "dis", + robo.gmii ? "gigabit" : ""); for (i = 0; i < 6; i++) { printf(robo_read16(&robo, ROBO_STAT_PAGE, ROBO_LINK_STAT_SUMMARY) & (1 << port[i]) ? - "Port %d(%c): %s%s " : "Port %d(%c): DOWN ", i, ports[i], - robo_read16(&robo, ROBO_STAT_PAGE, ROBO_SPEED_STAT_SUMMARY) & (1 << port[i]) ? "100" : " 10", - robo_read16(&robo, ROBO_STAT_PAGE, ROBO_DUPLEX_STAT_SUMMARY) & (1 << port[i]) ? "FD" : "HD"); - + "Port %d: %4s%s " : "Port %d: DOWN ", + (robo535x == 4) ? port[i] : i, + speed[(robo535x == 4) ? + (robo_read32(&robo, ROBO_STAT_PAGE, ROBO_SPEED_STAT_SUMMARY) >> port[i] * 2) & 3 : + (robo_read16(&robo, ROBO_STAT_PAGE, ROBO_SPEED_STAT_SUMMARY) >> port[i]) & 1], + robo_read16(&robo, ROBO_STAT_PAGE, (robo535x == 4) ? + ROBO_DUPLEX_STAT_SUMMARY_53115 : ROBO_DUPLEX_STAT_SUMMARY) & (1 << port[i]) ? "FD" : "HD"); + val16 = robo_read16(&robo, ROBO_CTRL_PAGE, port[i]); - + printf("%s stp: %s vlan: %d ", rxtx[val16 & 3], stp[(val16 >> 5) & 7], robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (i << 1))); - + + if (robo535x == 4) + printf("jumbo: %s ", jumbo[(robo_read32(&robo, ROBO_JUMBO_PAGE, ROBO_JUMBO_CTRL) >> port[i]) & 1]); + robo_read(&robo, ROBO_STAT_PAGE, ROBO_LSA_PORT0 + port[i] * 6, mac, 3); - + printf("mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[2] >> 8, mac[2] & 255, mac[1] >> 8, mac[1] & 255, mac[0] >> 8, mac[0] & 255); } @@ -535,23 +712,45 @@ val16 = robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0); printf("VLANs: %s %sabled%s%s\n", - robo5350 ? "BCM5325/535x" : "BCM536x", + (robo535x == 4) ? "BCM53115" : (robo535x ? "BCM5325/535x" : "BCM536x"), (val16 & (1 << 7)) ? "en" : "dis", (val16 & (1 << 6)) ? " mac_check" : "", (val16 & (1 << 5)) ? " mac_hash" : ""); /* scan VLANs */ - for (i = 0; i <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); i++) { + for (i = 0; i <= ((robo535x == 4) ? VLAN_ID_MAX5395 /* slow, needs rework, but how? */ : + (robo535x ? VLAN_ID_MAX5350 : VLAN_ID_MAX)); i++) + { /* issue read */ val16 = (i) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */; - if (robo5350) { - u32 val32; + if (robo535x == 4) { + /* index */ + robo_write16(&robo, ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395, i); + /* access */ + robo_write16(&robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395, + (1 << 7) /* start */ | 1 /* read */); + /* actual read */ + val32 = robo_read32(&robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ENTRY_5395); + if ((val32)) { + printf("%4d: vlan%d:", i, i); + for (j = 0; j <= 8; j++) { + if (val32 & (1 << j)) { + printf(" %d%s", j, (val32 & (1 << (j + 9))) ? + (j == 8 ? "u" : "") : "t"); + } + } + printf("\n"); + } + } else if (robo535x) { robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); /* actual read */ val32 = robo_read32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_READ); - if ((val32 & (1 << 20)) /* valid */) { - printf("vlan%d:", i); + if ((val32 & (robo535x == 3 ? (1 << 24) : (1 << 20))) /* valid */) { + val16 = (robo535x == 3) + ? ((val32 & 0xff000) >> 12) + : ((val32 & 0xff000) >> 12) << 4; + printf("%4d: vlan%d:", i, val16 | i); for (j = 0; j < 6; j++) { if (val32 & (1 << j)) { printf(" %d%s", j, (val32 & (1 << (j + 6))) ? @@ -565,7 +764,7 @@ /* actual read */ val16 = robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_READ); if ((val16 & (1 << 14)) /* valid */) { - printf("vlan%d:", i); + printf("%4d: vlan%d:", i, i); for (j = 0; j < 6; j++) { if (val16 & (1 << j)) { printf(" %d%s", j, (val16 & (1 << (j + 7))) ? Index: package/robocfg/Makefile =================================================================== --- package/robocfg/Makefile (revision 34996) +++ package/robocfg/Makefile (working copy) @@ -9,7 +9,7 @@ PKG_NAME:=robocfg PKG_VERSION:=0.01 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_BUILD_DIR:=$(BUILD_DIR)/robocfg _______________________________________________ openwrt-devel mailing list [email protected] https://lists.openwrt.org/mailman/listinfo/openwrt-devel
