From cecf4df4d5dbbac4bcf28c3bfe9ae5e37b8e5539 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 11 Jan 2006 22:57:52 +0000 Subject: [PATCH] switch driver updates and fixes SVN-Revision: 2925 --- .../linux/package/switch/src/switch-adm.c | 21 ++--- .../linux/package/switch/src/switch-core.c | 68 +++++++++++----- .../linux/package/switch/src/switch-core.h | 1 + .../linux/package/switch/src/switch-robo.c | 79 ++++++++++++++++++- 4 files changed, 134 insertions(+), 35 deletions(-) diff --git a/openwrt/target/linux/package/switch/src/switch-adm.c b/openwrt/target/linux/package/switch/src/switch-adm.c index 6ad98447b324..f2bc8e152ee5 100644 --- a/openwrt/target/linux/package/switch/src/switch-adm.c +++ b/openwrt/target/linux/package/switch/src/switch-adm.c @@ -32,6 +32,7 @@ #include "gpio.h" #define DRIVER_NAME "adm6996" +#define DRIVER_VERSION "0.01" static int eecs = 2; static int eesk = 3; @@ -57,8 +58,9 @@ MODULE_PARM(force, "i"); #define adm_write16(cs, w) { __u16 val = hton16(w); adm_write(cs, (__u8 *)&val, sizeof(val)*8); } #define adm_write32(cs, i) { uint32 val = hton32(i); adm_write(cs, (__u8 *)&val, sizeof(val)*8); } +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0) -extern int getintvar(char **vars, char *name); +extern char *nvram_get(char *name); static void adm_write(int cs, char *buf, unsigned int bits) @@ -442,11 +444,8 @@ static int detect_adm() int ret = 0; #if defined(BCMGPIO2) || defined(BCMGPIO) -#ifdef LINUX_2_4 - int boardflags = getintvar(NULL, "boardflags"); -#else - extern int boardflags; -#endif + int boardflags = atoi(nvram_get("boardflags")); + if ((boardflags & 0x80) || force) ret = 1; else @@ -454,13 +453,6 @@ static int detect_adm() #else ret = 1; #endif - if (ret == 1) { - int i = adm_rreg(0, 0); - if ((i == 0) || (i == 0xffff)) { - printk("No ADM6996 chip detected.\n"); - ret = 0; - } - } return ret; } @@ -475,7 +467,7 @@ static int __init adm_init() {NULL, NULL, NULL} }; switch_config port[] = { - {"enabled", handle_port_enable_read, handle_port_enable_write}, + {"enable", handle_port_enable_read, handle_port_enable_write}, {"media", handle_port_media_read, handle_port_media_write}, {NULL, NULL, NULL} }; @@ -485,6 +477,7 @@ static int __init adm_init() }; switch_driver driver = { name: DRIVER_NAME, + version: DRIVER_VERSION, interface: "eth0", ports: 6, cpuport: 5, diff --git a/openwrt/target/linux/package/switch/src/switch-core.c b/openwrt/target/linux/package/switch/src/switch-core.c index c0e5cc9eaa27..31a02506dba2 100644 --- a/openwrt/target/linux/package/switch/src/switch-core.c +++ b/openwrt/target/linux/package/switch/src/switch-core.c @@ -131,30 +131,50 @@ static ssize_t switch_proc_write(struct file *file, const char *buf, size_t coun return ret; } -static void add_handlers(switch_driver *driver, switch_config *handlers, struct proc_dir_entry *parent, int nr) +static int handle_driver_name(void *driver, char *buf, int nr) +{ + char *name = ((switch_driver *) driver)->name; + return sprintf(buf, "%s\n", name); +} + +static int handle_driver_version(void *driver, char *buf, int nr) +{ + char *version = ((switch_driver *) driver)->version; + strcpy(buf, version); + return sprintf(buf, "%s\n", version); +} + +static void add_handler(switch_driver *driver, switch_config *handler, struct proc_dir_entry *parent, int nr) { switch_priv *priv = (switch_priv *) driver->data; - switch_proc_handler *tmp; - int i, mode; struct proc_dir_entry *p; + int mode; + + switch_proc_handler *tmp; + tmp = (switch_proc_handler *) kmalloc(sizeof(switch_proc_handler), GFP_KERNEL); + INIT_LIST_HEAD(&tmp->list); + tmp->parent = parent; + tmp->nr = nr; + tmp->driver = driver; + memcpy(&tmp->handler, handler, sizeof(switch_config)); + list_add(&tmp->list, &priv->data.list); + + mode = 0; + if (handler->read != NULL) mode |= S_IRUSR; + if (handler->write != NULL) mode |= S_IWUSR; + + if ((p = create_proc_entry(handler->name, mode, parent)) != NULL) { + p->data = (void *) tmp; + p->proc_fops = &switch_proc_fops; + } +} + +static inline void add_handlers(switch_driver *driver, switch_config *handlers, struct proc_dir_entry *parent, int nr) +{ + int i; for (i = 0; handlers[i].name != NULL; i++) { - tmp = kmalloc(sizeof(switch_proc_handler), GFP_KERNEL); - INIT_LIST_HEAD(&tmp->list); - tmp->parent = parent; - tmp->nr = nr; - tmp->driver = driver; - memcpy(&tmp->handler, &(handlers[i]), sizeof(switch_config)); - list_add(&tmp->list, &priv->data.list); - - mode = 0; - if (handlers[i].read != NULL) mode |= S_IRUSR; - if (handlers[i].write != NULL) mode |= S_IWUSR; - - if ((p = create_proc_entry(handlers[i].name, mode, parent)) != NULL) { - p->data = (void *) tmp; - p->proc_fops = &switch_proc_fops; - } + add_handler(driver, &(handlers[i]), parent, nr); } } @@ -202,6 +222,12 @@ static void do_unregister(switch_driver *driver) kfree(priv); } +switch_config global_driver_handlers[] = { + {"driver", handle_driver_name, NULL}, + {"version", handle_driver_version, NULL}, + {NULL, NULL, NULL} +}; + static int do_register(switch_driver *driver) { switch_priv *priv; @@ -216,8 +242,10 @@ static int do_register(switch_driver *driver) priv->nr = drv_num++; priv->driver_dir = proc_mkdir(driver->interface, switch_root); - if (driver->driver_handlers != NULL) + if (driver->driver_handlers != NULL) { add_handlers(driver, driver->driver_handlers, priv->driver_dir, 0); + add_handlers(driver, global_driver_handlers, priv->driver_dir, 0); + } priv->port_dir = proc_mkdir("port", priv->driver_dir); priv->ports = kmalloc((driver->ports + 1) * sizeof(struct proc_dir_entry *), GFP_KERNEL); diff --git a/openwrt/target/linux/package/switch/src/switch-core.h b/openwrt/target/linux/package/switch/src/switch-core.h index bdf0ae1f89ef..a6621eed227a 100644 --- a/openwrt/target/linux/package/switch/src/switch-core.h +++ b/openwrt/target/linux/package/switch/src/switch-core.h @@ -27,6 +27,7 @@ typedef struct { typedef struct { struct list_head list; char *name; + char *version; char *interface; int cpuport; int ports; diff --git a/openwrt/target/linux/package/switch/src/switch-robo.c b/openwrt/target/linux/package/switch/src/switch-robo.c index 4983eec8e25c..63110d7c94d1 100644 --- a/openwrt/target/linux/package/switch/src/switch-robo.c +++ b/openwrt/target/linux/package/switch/src/switch-robo.c @@ -34,6 +34,7 @@ #include "etc53xx.h" #define DRIVER_NAME "bcm53xx" +#define DRIVER_VERSION "0.01" #define ROBO_PHY_ADDR 0x1E /* robo switch phy address */ @@ -332,6 +333,75 @@ static int handle_vlan_port_write(void *driver, char *buf, int nr) return 0; } +#define set_switch(state) \ + robo_write16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, (robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & ~2) | (state ? 2 : 0)); + +static int handle_enable_read(void *driver, char *buf, int nr) +{ + return sprintf(buf, "%d\n", (((robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & 2) == 2) ? 1 : 0)); +} + +static int handle_enable_write(void *driver, char *buf, int nr) +{ + set_switch(buf[0] == '1'); + + return 0; +} + +static int handle_enable_vlan_read(void *driver, char *buf, int nr) +{ + return sprintf(buf, "%d\n", (((robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0) & (1 << 7)) == (1 << 7)) ? 1 : 0)); +} + +static int handle_enable_vlan_write(void *driver, char *buf, int nr) +{ + int disable = ((buf[0] != '1') ? 1 : 0); + + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 : + (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */); + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1, disable ? 0 : + (1 << 1) | (1 << 2) | (1 << 3) /* RSV multicast */); + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL4, disable ? 0 : + (1 << 6) /* drop invalid VID frames */); + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL5, disable ? 0 : + (1 << 3) /* drop miss V table frames */); + + return 0; +} + +static int handle_reset(void *driver, char *buf, int nr) +{ + switch_driver *d = (switch_driver *) driver; + switch_vlan_config *c = switch_parse_vlan(d, buf); + int j; + __u16 val16; + + if (c == NULL) + return -EINVAL; + + /* disable switching */ + set_switch(0); + + /* reset vlans */ + for (j = 0; j <= (is_5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) { + /* write config now */ + val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; + if (is_5350) + robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, 0); + else + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, 0); + robo_write16(ROBO_VLAN_PAGE, (is_5350 ? ROBO_VLAN_TABLE_ACCESS_5350 : ROBO_VLAN_TABLE_ACCESS), val16); + } + + /* enable switching */ + set_switch(1); + + /* enable vlans */ + handle_enable_vlan_write(driver, "1", 0); + + return 0; +} + static int __init robo_init() { char *device = "ethX"; @@ -345,17 +415,24 @@ static int __init robo_init() if (notfound) return -ENODEV; else { + switch_config main[] = { + {"enable", handle_enable_read, handle_enable_write}, + {"enable_vlan", handle_enable_vlan_read, handle_enable_vlan_write}, + {"reset", NULL, handle_reset}, + {NULL, NULL, NULL} + }; switch_config vlan[] = { {"ports", handle_vlan_port_read, handle_vlan_port_write}, {NULL, NULL, NULL} }; switch_driver driver = { name: DRIVER_NAME, + version: DRIVER_VERSION, interface: device, cpuport: 5, ports: 6, vlans: 16, - driver_handlers: NULL, + driver_handlers: main, port_handlers: NULL, vlan_handlers: vlan, }; -- 2.30.2