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

Reply via email to