mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-29 13:04:15 +02:00
kmod-switch: vlan parser rewrite, some api changes, minor fixes
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@2819 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
d52c94217f
commit
7e96759271
@ -240,7 +240,7 @@ static int port_conf[] = { 0x01, 0x03, 0x05, 0x07, 0x08, 0x09 };
|
|||||||
/* Bits in VLAN port mapping */
|
/* Bits in VLAN port mapping */
|
||||||
static int vlan_ports[] = { 1 << 0, 1 << 2, 1 << 4, 1 << 6, 1 << 7, 1 << 8 };
|
static int vlan_ports[] = { 1 << 0, 1 << 2, 1 << 4, 1 << 6, 1 << 7, 1 << 8 };
|
||||||
|
|
||||||
static int handle_vlan_port_read(char *buf, int nr)
|
static int handle_vlan_port_read(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int ports, i, c, len = 0;
|
int ports, i, c, len = 0;
|
||||||
|
|
||||||
@ -261,30 +261,33 @@ static int handle_vlan_port_read(char *buf, int nr)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_vlan_port_write(char *buf, int nr)
|
static int handle_vlan_port_write(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int i, c, ports;
|
int i, cfg, ports;
|
||||||
int map = switch_parse_vlan(buf);
|
switch_driver *d = (switch_driver *) driver;
|
||||||
|
switch_vlan_config *c = switch_parse_vlan(d, buf);
|
||||||
|
|
||||||
if (map == -1)
|
if (c == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ports = adm_rreg(0, 0x13 + nr);
|
ports = adm_rreg(0, 0x13 + nr);
|
||||||
for (i = 0; i <= 5; i++) {
|
for (i = 0; i < d->ports; i++) {
|
||||||
if (map & (1 << i)) {
|
if (c->port & (1 << i)) {
|
||||||
ports |= vlan_ports[i];
|
ports |= vlan_ports[i];
|
||||||
|
|
||||||
c = adm_rreg(0, port_conf[i]);
|
cfg = adm_rreg(0, port_conf[i]);
|
||||||
|
|
||||||
/* Tagging */
|
/* Tagging */
|
||||||
if (map & (1 << (8 + i)))
|
if (c->untag & (1 << i))
|
||||||
c |= (1 << 4);
|
cfg &= ~(1 << 4);
|
||||||
else
|
else
|
||||||
c &= ~(1 << 4);
|
cfg |= (1 << 4);
|
||||||
|
|
||||||
c = (c & ~(0xf << 10)) | (nr << 10);
|
|
||||||
|
|
||||||
adm_wreg(port_conf[i], (__u16) c);
|
if ((c->untag | c->pvid) & (1 << i)) {
|
||||||
|
cfg = (cfg & ~(0xf << 10)) | (nr << 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
adm_wreg(port_conf[i], (__u16) cfg);
|
||||||
} else {
|
} else {
|
||||||
ports &= ~(vlan_ports[i]);
|
ports &= ~(vlan_ports[i]);
|
||||||
}
|
}
|
||||||
@ -294,12 +297,12 @@ static int handle_vlan_port_write(char *buf, int nr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_port_enable_read(char *buf, int nr)
|
static int handle_port_enable_read(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
return sprintf(buf, "%d\n", ((adm_rreg(0, port_conf[nr]) & (1 << 5)) ? 0 : 1));
|
return sprintf(buf, "%d\n", ((adm_rreg(0, port_conf[nr]) & (1 << 5)) ? 0 : 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_port_enable_write(char *buf, int nr)
|
static int handle_port_enable_write(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int reg = adm_rreg(0, port_conf[nr]);
|
int reg = adm_rreg(0, port_conf[nr]);
|
||||||
|
|
||||||
@ -313,7 +316,7 @@ static int handle_port_enable_write(char *buf, int nr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_port_media_read(char *buf, int nr)
|
static int handle_port_media_read(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int media = 0;
|
int media = 0;
|
||||||
@ -330,7 +333,7 @@ static int handle_port_media_read(char *buf, int nr)
|
|||||||
return len + sprintf(buf + len, "\n");
|
return len + sprintf(buf + len, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_port_media_write(char *buf, int nr)
|
static int handle_port_media_write(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int media = switch_parse_media(buf);
|
int media = switch_parse_media(buf);
|
||||||
int reg = adm_rreg(0, port_conf[nr]);
|
int reg = adm_rreg(0, port_conf[nr]);
|
||||||
@ -351,12 +354,12 @@ static int handle_port_media_write(char *buf, int nr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_vlan_enable_read(char *buf, int nr)
|
static int handle_vlan_enable_read(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
return sprintf(buf, "%d\n", ((adm_rreg(0, 0x11) & (1 << 5)) ? 1 : 0));
|
return sprintf(buf, "%d\n", ((adm_rreg(0, 0x11) & (1 << 5)) ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_vlan_enable_write(char *buf, int nr)
|
static int handle_vlan_enable_write(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int reg = adm_rreg(0, 0x11);
|
int reg = adm_rreg(0, 0x11);
|
||||||
|
|
||||||
@ -370,7 +373,7 @@ static int handle_vlan_enable_write(char *buf, int nr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_reset(char *buf, int nr)
|
static int handle_reset(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -412,7 +415,7 @@ static int handle_reset(char *buf, int nr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_registers(char *buf, int nr)
|
static int handle_registers(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int i, len = 0;
|
int i, len = 0;
|
||||||
|
|
||||||
@ -423,7 +426,7 @@ static int handle_registers(char *buf, int nr)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_counters(char *buf, int nr)
|
static int handle_counters(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int i, len = 0;
|
int i, len = 0;
|
||||||
|
|
||||||
@ -451,6 +454,13 @@ static int detect_adm()
|
|||||||
#else
|
#else
|
||||||
ret = 1;
|
ret = 1;
|
||||||
#endif
|
#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;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -475,7 +485,9 @@ static int __init adm_init()
|
|||||||
};
|
};
|
||||||
switch_driver driver = {
|
switch_driver driver = {
|
||||||
name: DRIVER_NAME,
|
name: DRIVER_NAME,
|
||||||
|
interface: "eth0",
|
||||||
ports: 6,
|
ports: 6,
|
||||||
|
cpuport: 5,
|
||||||
vlans: 16,
|
vlans: 16,
|
||||||
driver_handlers: cfg,
|
driver_handlers: cfg,
|
||||||
port_handlers: port,
|
port_handlers: port,
|
||||||
|
@ -37,6 +37,7 @@ typedef struct {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct proc_dir_entry *parent;
|
struct proc_dir_entry *parent;
|
||||||
int nr;
|
int nr;
|
||||||
|
void *driver;
|
||||||
switch_config handler;
|
switch_config handler;
|
||||||
} switch_proc_handler;
|
} switch_proc_handler;
|
||||||
|
|
||||||
@ -47,7 +48,6 @@ typedef struct {
|
|||||||
int nr;
|
int nr;
|
||||||
} switch_priv;
|
} switch_priv;
|
||||||
|
|
||||||
|
|
||||||
static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos);
|
static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos);
|
||||||
static ssize_t switch_proc_write(struct file *file, const char *buf, size_t count, void *data);
|
static ssize_t switch_proc_write(struct file *file, const char *buf, size_t count, void *data);
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ static struct file_operations switch_proc_fops = {
|
|||||||
write: switch_proc_write
|
write: switch_proc_write
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *strdup(char *str)
|
static inline char *strdup(char *str)
|
||||||
{
|
{
|
||||||
char *new = kmalloc(strlen(str) + 1, GFP_KERNEL);
|
char *new = kmalloc(strlen(str) + 1, GFP_KERNEL);
|
||||||
strcpy(new, str);
|
strcpy(new, str);
|
||||||
@ -80,7 +80,7 @@ static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff
|
|||||||
if (dent->data != NULL) {
|
if (dent->data != NULL) {
|
||||||
switch_proc_handler *handler = (switch_proc_handler *) dent->data;
|
switch_proc_handler *handler = (switch_proc_handler *) dent->data;
|
||||||
if (handler->handler.read != NULL)
|
if (handler->handler.read != NULL)
|
||||||
len += handler->handler.read(page + len, handler->nr);
|
len += handler->handler.read(handler->driver, page + len, handler->nr);
|
||||||
}
|
}
|
||||||
len += 1;
|
len += 1;
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ static ssize_t switch_proc_write(struct file *file, const char *buf, size_t coun
|
|||||||
if (dent->data != NULL) {
|
if (dent->data != NULL) {
|
||||||
switch_proc_handler *handler = (switch_proc_handler *) dent->data;
|
switch_proc_handler *handler = (switch_proc_handler *) dent->data;
|
||||||
if (handler->handler.write != NULL) {
|
if (handler->handler.write != NULL) {
|
||||||
if ((ret = handler->handler.write(page, handler->nr)) >= 0)
|
if ((ret = handler->handler.write(handler->driver, page, handler->nr)) >= 0)
|
||||||
ret = count;
|
ret = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,8 +131,9 @@ static ssize_t switch_proc_write(struct file *file, const char *buf, size_t coun
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_handlers(switch_priv *priv, switch_config *handlers, struct proc_dir_entry *parent, int nr)
|
static void add_handlers(switch_driver *driver, switch_config *handlers, struct proc_dir_entry *parent, int nr)
|
||||||
{
|
{
|
||||||
|
switch_priv *priv = (switch_priv *) driver->data;
|
||||||
switch_proc_handler *tmp;
|
switch_proc_handler *tmp;
|
||||||
int i, mode;
|
int i, mode;
|
||||||
struct proc_dir_entry *p;
|
struct proc_dir_entry *p;
|
||||||
@ -142,6 +143,7 @@ static void add_handlers(switch_priv *priv, switch_config *handlers, struct proc
|
|||||||
INIT_LIST_HEAD(&tmp->list);
|
INIT_LIST_HEAD(&tmp->list);
|
||||||
tmp->parent = parent;
|
tmp->parent = parent;
|
||||||
tmp->nr = nr;
|
tmp->nr = nr;
|
||||||
|
tmp->driver = driver;
|
||||||
memcpy(&tmp->handler, &(handlers[i]), sizeof(switch_config));
|
memcpy(&tmp->handler, &(handlers[i]), sizeof(switch_config));
|
||||||
list_add(&tmp->list, &priv->data.list);
|
list_add(&tmp->list, &priv->data.list);
|
||||||
|
|
||||||
@ -192,7 +194,7 @@ static void do_unregister(switch_driver *driver)
|
|||||||
kfree(priv->vlans);
|
kfree(priv->vlans);
|
||||||
remove_proc_entry("vlan", priv->driver_dir);
|
remove_proc_entry("vlan", priv->driver_dir);
|
||||||
|
|
||||||
remove_proc_entry(driver->name, switch_root);
|
remove_proc_entry(driver->interface, switch_root);
|
||||||
|
|
||||||
if (priv->nr == (drv_num - 1))
|
if (priv->nr == (drv_num - 1))
|
||||||
drv_num--;
|
drv_num--;
|
||||||
@ -213,10 +215,9 @@ static int do_register(switch_driver *driver)
|
|||||||
INIT_LIST_HEAD(&priv->data.list);
|
INIT_LIST_HEAD(&priv->data.list);
|
||||||
|
|
||||||
priv->nr = drv_num++;
|
priv->nr = drv_num++;
|
||||||
sprintf(buf, "%d", priv->nr);
|
priv->driver_dir = proc_mkdir(driver->interface, switch_root);
|
||||||
priv->driver_dir = proc_mkdir(buf, switch_root);
|
|
||||||
if (driver->driver_handlers != NULL)
|
if (driver->driver_handlers != NULL)
|
||||||
add_handlers(priv, driver->driver_handlers, priv->driver_dir, 0);
|
add_handlers(driver, driver->driver_handlers, priv->driver_dir, 0);
|
||||||
|
|
||||||
priv->port_dir = proc_mkdir("port", priv->driver_dir);
|
priv->port_dir = proc_mkdir("port", priv->driver_dir);
|
||||||
priv->ports = kmalloc((driver->ports + 1) * sizeof(struct proc_dir_entry *), GFP_KERNEL);
|
priv->ports = kmalloc((driver->ports + 1) * sizeof(struct proc_dir_entry *), GFP_KERNEL);
|
||||||
@ -224,7 +225,7 @@ static int do_register(switch_driver *driver)
|
|||||||
sprintf(buf, "%d", i);
|
sprintf(buf, "%d", i);
|
||||||
priv->ports[i] = proc_mkdir(buf, priv->port_dir);
|
priv->ports[i] = proc_mkdir(buf, priv->port_dir);
|
||||||
if (driver->port_handlers != NULL)
|
if (driver->port_handlers != NULL)
|
||||||
add_handlers(priv, driver->port_handlers, priv->ports[i], i);
|
add_handlers(driver, driver->port_handlers, priv->ports[i], i);
|
||||||
}
|
}
|
||||||
priv->ports[i] = NULL;
|
priv->ports[i] = NULL;
|
||||||
|
|
||||||
@ -234,7 +235,7 @@ static int do_register(switch_driver *driver)
|
|||||||
sprintf(buf, "%d", i);
|
sprintf(buf, "%d", i);
|
||||||
priv->vlans[i] = proc_mkdir(buf, priv->vlan_dir);
|
priv->vlans[i] = proc_mkdir(buf, priv->vlan_dir);
|
||||||
if (driver->vlan_handlers != NULL)
|
if (driver->vlan_handlers != NULL)
|
||||||
add_handlers(priv, driver->vlan_handlers, priv->vlans[i], i);
|
add_handlers(driver, driver->vlan_handlers, priv->vlans[i], i);
|
||||||
}
|
}
|
||||||
priv->vlans[i] = NULL;
|
priv->vlans[i] = NULL;
|
||||||
|
|
||||||
@ -242,7 +243,7 @@ static int do_register(switch_driver *driver)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isspace(char c) {
|
static inline int isspace(char c) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case ' ':
|
case ' ':
|
||||||
case 0x09:
|
case 0x09:
|
||||||
@ -298,39 +299,57 @@ int switch_print_media(char *buf, int media)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int switch_parse_vlan(char *buf)
|
switch_vlan_config *switch_parse_vlan(switch_driver *driver, char *buf)
|
||||||
{
|
{
|
||||||
char vlan = 0, tag = 0, pvid_port = 0;
|
switch_vlan_config *c;
|
||||||
int untag, j;
|
int j, u, p, s;
|
||||||
|
|
||||||
|
c = kmalloc(sizeof(switch_vlan_config), GFP_KERNEL);
|
||||||
|
memset(c, 0, sizeof(switch_vlan_config));
|
||||||
|
|
||||||
while (isspace(*buf)) buf++;
|
while (isspace(*buf)) buf++;
|
||||||
|
j = 0;
|
||||||
while (*buf >= '0' && *buf <= '9') {
|
while (*buf >= '0' && *buf <= '9') {
|
||||||
j = *buf++ - '0';
|
j *= 10;
|
||||||
vlan |= 1 << j;
|
j += *buf++ - '0';
|
||||||
|
|
||||||
untag = 0;
|
|
||||||
/* untag if needed, CPU port requires special handling */
|
|
||||||
if (*buf == 'u' || (j != 5 && (isspace(*buf) || *buf == 0))) {
|
|
||||||
untag = 1;
|
|
||||||
if (*buf) buf++;
|
|
||||||
} else if (*buf == '*') {
|
|
||||||
pvid_port |= (1 << j);
|
|
||||||
buf++;
|
|
||||||
} else if (*buf == 't' || isspace(*buf)) {
|
|
||||||
buf++;
|
|
||||||
} else break;
|
|
||||||
|
|
||||||
if (!untag)
|
u = ((j == driver->cpuport) ? 0 : 1);
|
||||||
tag |= 1 << j;
|
p = 0;
|
||||||
|
s = !(*buf >= '0' && *buf <= '9');
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
while (s && !isspace(*buf) && (*buf != 0)) {
|
||||||
|
switch(*buf) {
|
||||||
|
case 'u':
|
||||||
|
u = 1;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
u = 0;
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
p = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
c->port |= (1 << j);
|
||||||
|
if (u)
|
||||||
|
c->untag |= (1 << j);
|
||||||
|
if (p)
|
||||||
|
c->pvid |= (1 << j);
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (isspace(*buf)) buf++;
|
while (isspace(*buf)) buf++;
|
||||||
}
|
}
|
||||||
|
if (*buf != 0) return NULL;
|
||||||
if (*buf)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return (pvid_port << 16) | (tag << 8) | vlan;
|
c->port &= (1 << driver->ports) - 1;
|
||||||
|
c->untag &= (1 << driver->ports) - 1;
|
||||||
|
c->pvid &= (1 << driver->ports) - 1;
|
||||||
|
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -345,11 +364,16 @@ int switch_register_driver(switch_driver *driver)
|
|||||||
printk("Switch driver '%s' already exists in the kernel\n", driver->name);
|
printk("Switch driver '%s' already exists in the kernel\n", driver->name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (strcmp(list_entry(pos, switch_driver, list)->interface, driver->interface) == 0) {
|
||||||
|
printk("There is already a switch registered on the device '%s'\n", driver->interface);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new = kmalloc(sizeof(switch_driver), GFP_KERNEL);
|
new = kmalloc(sizeof(switch_driver), GFP_KERNEL);
|
||||||
memcpy(new, driver, sizeof(switch_driver));
|
memcpy(new, driver, sizeof(switch_driver));
|
||||||
new->name = strdup(driver->name);
|
new->name = strdup(driver->name);
|
||||||
|
new->interface = strdup(driver->interface);
|
||||||
|
|
||||||
if ((ret = do_register(new)) < 0) {
|
if ((ret = do_register(new)) < 0) {
|
||||||
kfree(new->name);
|
kfree(new->name);
|
||||||
|
@ -17,27 +17,33 @@
|
|||||||
#define LINUX_2_4
|
#define LINUX_2_4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef int (*switch_handler)(char *buf, int nr);
|
typedef int (*switch_handler)(void *driver, char *buf, int nr);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
switch_handler read, write;
|
switch_handler read, write;
|
||||||
} switch_config;
|
} switch_config;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
char *name;
|
char *name;
|
||||||
|
char *interface;
|
||||||
|
int cpuport;
|
||||||
int ports;
|
int ports;
|
||||||
int vlans;
|
int vlans;
|
||||||
switch_config *driver_handlers, *port_handlers, *vlan_handlers;
|
switch_config *driver_handlers, *port_handlers, *vlan_handlers;
|
||||||
void *data;
|
void *data;
|
||||||
|
void *priv;
|
||||||
} switch_driver;
|
} switch_driver;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 port, untag, pvid;
|
||||||
|
} switch_vlan_config;
|
||||||
|
|
||||||
|
|
||||||
extern int switch_register_driver(switch_driver *driver);
|
extern int switch_register_driver(switch_driver *driver);
|
||||||
extern void switch_unregister_driver(char *name);
|
extern void switch_unregister_driver(char *name);
|
||||||
extern int switch_parse_vlan(char *buf);
|
extern switch_vlan_config *switch_parse_vlan(switch_driver *driver, char *buf);
|
||||||
extern int switch_parse_media(char *buf);
|
extern int switch_parse_media(char *buf);
|
||||||
extern int switch_print_media(char *buf, int media);
|
extern int switch_print_media(char *buf, int media);
|
||||||
|
|
||||||
|
@ -56,18 +56,6 @@ static int max_vlans, max_ports;
|
|||||||
static struct ifreq ifr;
|
static struct ifreq ifr;
|
||||||
static struct net_device *dev;
|
static struct net_device *dev;
|
||||||
|
|
||||||
static int isspace(char c) {
|
|
||||||
switch(c) {
|
|
||||||
case ' ':
|
|
||||||
case 0x09:
|
|
||||||
case 0x0a:
|
|
||||||
case 0x0d:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_ioctl(int cmd, void *buf)
|
static int do_ioctl(int cmd, void *buf)
|
||||||
{
|
{
|
||||||
mm_segment_t old_fs = get_fs();
|
mm_segment_t old_fs = get_fs();
|
||||||
@ -297,7 +285,7 @@ static int robo_probe(char *devname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int handle_vlan_port_read(char *buf, int nr)
|
static int handle_vlan_port_read(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
__u16 val16;
|
__u16 val16;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@ -337,45 +325,34 @@ static int handle_vlan_port_read(char *buf, int nr)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_vlan_port_write(char *buf, int nr)
|
static int handle_vlan_port_write(void *driver, char *buf, int nr)
|
||||||
{
|
{
|
||||||
int untag = 0;
|
switch_driver *d = (switch_driver *) driver;
|
||||||
int member = 0;
|
switch_vlan_config *c = switch_parse_vlan(d, buf);
|
||||||
int j;
|
int j;
|
||||||
__u16 val16;
|
__u16 val16;
|
||||||
|
|
||||||
while (*buf >= '0' && *buf <= '9') {
|
if (c == NULL)
|
||||||
j = *buf++ - '0';
|
return -EINVAL;
|
||||||
member |= 1 << j;
|
|
||||||
|
for (j = 0; j < d->ports; j++) {
|
||||||
/* untag if needed, CPU port requires special handling */
|
if ((c->untag | c->pvid) & (1 << j))
|
||||||
if (*buf == 'u' || (j != 5 && (isspace(*buf) || *buf == 0))) {
|
|
||||||
untag |= 1 << j;
|
|
||||||
if (*buf) buf++;
|
|
||||||
/* change default vlan tag */
|
/* change default vlan tag */
|
||||||
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), nr);
|
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), nr);
|
||||||
} else if (*buf == '*' || *buf == 't' || isspace(*buf)) {
|
|
||||||
buf++;
|
|
||||||
} else break;
|
|
||||||
|
|
||||||
while (isspace(*buf)) buf++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*buf) {
|
/* write config now */
|
||||||
return -1;
|
val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
|
||||||
|
if (is_5350) {
|
||||||
|
robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350,
|
||||||
|
(1 << 20) /* valid */ | (c->untag << 6) | c->port);
|
||||||
|
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
|
||||||
} else {
|
} else {
|
||||||
/* write config now */
|
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE,
|
||||||
val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
|
(1 << 14) /* valid */ | (c->untag << 7) | c->port);
|
||||||
if (is_5350) {
|
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
|
||||||
robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350,
|
|
||||||
(1 << 20) /* valid */ | (untag << 6) | member);
|
|
||||||
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
|
|
||||||
} else {
|
|
||||||
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE,
|
|
||||||
(1 << 14) /* valid */ | (untag << 7) | member);
|
|
||||||
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,6 +364,7 @@ static int __init robo_init()
|
|||||||
for (device[3] = '0'; (device[3] <= '3') && notfound; device[3]++) {
|
for (device[3] = '0'; (device[3] <= '3') && notfound; device[3]++) {
|
||||||
notfound = robo_probe(device);
|
notfound = robo_probe(device);
|
||||||
}
|
}
|
||||||
|
device[3]--;
|
||||||
|
|
||||||
if (notfound)
|
if (notfound)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -397,6 +375,8 @@ static int __init robo_init()
|
|||||||
};
|
};
|
||||||
switch_driver driver = {
|
switch_driver driver = {
|
||||||
name: DRIVER_NAME,
|
name: DRIVER_NAME,
|
||||||
|
interface: device,
|
||||||
|
cpuport: max_ports - 1,
|
||||||
ports: max_ports,
|
ports: max_ports,
|
||||||
vlans: max_vlans,
|
vlans: max_vlans,
|
||||||
driver_handlers: NULL,
|
driver_handlers: NULL,
|
||||||
|
Loading…
Reference in New Issue
Block a user