X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=package%2Fbroadcom-diag%2Fsrc%2Fdiag.c;h=e672982dc905eea639c57fddbb10554a5af20d69;hb=209f76b1df5ab38f2cd14bae3025bbba0f5c72ab;hp=af1907992f3ffdc6f588c92975935dab83d0ce4d;hpb=37d063a852a3425457079fa30aab5bd6c760f383;p=openwrt.git diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c index af1907992f..e672982dc9 100644 --- a/package/broadcom-diag/src/diag.c +++ b/package/broadcom-diag/src/diag.c @@ -2,7 +2,7 @@ * diag.c - GPIO interface driver for Broadcom boards * * Copyright (C) 2006 Mike Baker , - * Felix Fietkau + * Copyright (C) 2006-2007 Felix Fietkau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,10 +28,13 @@ #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#include +#ifndef LINUX_2_4 #include -#define hotplug_path uevent_helper +#include +#include +#include +extern struct sock *uevent_sock; +extern u64 uevent_next_seqnum(void); #else #include #define INIT_WORK INIT_TQUEUE @@ -43,6 +46,7 @@ #include "diag.h" #define getvar(str) (nvram_get(str)?:"") +static int fill_event(struct event_t *); static unsigned int gpiomask = 0; module_param(gpiomask, int, 0644); @@ -70,6 +74,7 @@ enum { WBR2_G54, WHR_G54S, WHR_HP_G54, + WHR_G125, WHR2_A54G54, WLA2_G54L, WZR_G300N, @@ -92,6 +97,7 @@ enum { WE800G, WR850GV1, WR850GV2V3, + WR850GP, /* Belkin */ BELKIN_UNKNOWN, @@ -108,6 +114,10 @@ enum { /* D-Link */ DIR130, DIR330, + DWL3150, + + /* Sitecom */ + WL105B, }; static void __init bcm4780_init(void) { @@ -124,6 +134,14 @@ static void __init bcm4780_init(void) { schedule_timeout(HZ * 5); } +static void __init bcm57xx_init(void) { + int pin = 1 << 2; + + gpio_outen(pin, pin); + gpio_control(pin, 0); + gpio_out(pin, pin); +} + static struct platform_t __initdata platforms[] = { /* Linksys */ [WAP54GV1] = { @@ -131,7 +149,7 @@ static struct platform_t __initdata platforms[] = { .buttons = { { .name = "reset", .gpio = 1 << 0 }, }, - .leds = { + .leds = { { .name = "diag", .gpio = 1 << 3 }, { .name = "wlan", .gpio = 1 << 4 }, }, @@ -207,8 +225,12 @@ static struct platform_t __initdata platforms[] = { }, .leds = { { .name = "power", .gpio = 1 << 1, .polarity = NORMAL }, - { .name = "ses", .gpio = 1 << 3, .polarity = REVERSE }, + { .name = "ses_amber", .gpio = 1 << 3, .polarity = REVERSE }, + { .name = "ses_green", .gpio = 1 << 9, .polarity = REVERSE }, + { .name = "usb_blink", .gpio = 1 << 10, .polarity = REVERSE }, + { .name = "usb", .gpio = 1 << 11, .polarity = REVERSE }, }, + .platform_init = bcm57xx_init, }, /* Asus */ [WLHDD] = { @@ -337,6 +359,21 @@ static struct platform_t __initdata platforms[] = { { .name = "wlan", .gpio = 1 << 2, .polarity = REVERSE }, }, }, + [WHR_G125] = { + .name = "Buffalo WHR-G125", + .buttons = { + { .name = "reset", .gpio = 1 << 4 }, + { .name = "bridge", .gpio = 1 << 5 }, + { .name = "ses", .gpio = 1 << 0 }, + }, + .leds = { + { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE }, + { .name = "internal", .gpio = 1 << 3, .polarity = REVERSE }, + { .name = "bridge", .gpio = 1 << 1, .polarity = REVERSE }, + { .name = "ses", .gpio = 1 << 6, .polarity = REVERSE }, + { .name = "wlan", .gpio = 1 << 2, .polarity = REVERSE }, + }, + }, [WHR2_A54G54] = { .name = "Buffalo WHR2-A54G54", .buttons = { @@ -486,10 +523,23 @@ static struct platform_t __initdata platforms[] = { .leds = { { .name = "power", .gpio = 1 << 1, .polarity = NORMAL }, { .name = "wlan", .gpio = 1 << 0, .polarity = REVERSE }, + { .name = "wan", .gpio = 1 << 6, .polarity = INPUT }, + { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE }, + }, + }, + [WR850GP] = { + .name = "Motorola WR850GP", + .buttons = { + { .name = "reset", .gpio = 1 << 5 }, + }, + .leds = { + { .name = "power", .gpio = 1 << 1, .polarity = NORMAL }, + { .name = "wlan", .gpio = 1 << 0, .polarity = REVERSE }, { .name = "dmz", .gpio = 1 << 6, .polarity = REVERSE }, { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE }, }, }, + /* Belkin */ [BELKIN_UNKNOWN] = { .name = "Belkin (unknown)", @@ -561,20 +611,88 @@ static struct platform_t __initdata platforms[] = { { .name = "blue", .gpio = 1 << 6}, }, }, + [DWL3150] = { + .name = "D-Link DWL-3150", + .buttons = { + { .name = "reset", .gpio = 1 << 7}, + }, + .leds = { + { .name = "diag", .gpio = 1 << 2}, + { .name = "status", .gpio = 1 << 1}, + }, + }, + /* Double check */ + [WL105B] = { + .name = "Sitecom WL-105b", + .buttons = { + { .name = "reset", .gpio = 1 << 10}, + }, + .leds = { + { .name = "wlan", .gpio = 1 << 4}, + { .name = "power", .gpio = 1 << 3}, + }, + }, }; static struct platform_t __init *platform_detect(void) { char *boardnum, *boardtype, *buf; - boardnum = getvar("boardnum"); - boardtype = getvar("boardtype"); - if (strcmp(getvar("nvram_type"), "cfe") == 0) return &platforms[WGT634U]; - - if (strncmp(getvar("model_no"), "WL700",5) == 0) - return &platforms[WL700GE]; + + /* Look for a model identifier */ + + /* Based on "model_name" */ + if (buf = nvram_get("model_name")) { + if (!strcmp(buf, "DIR-130")) + return &platforms[DIR130]; + if (!strcmp(buf, "DIR-330")) + return &platforms[DIR330]; + } + + /* Based on "model_no" */ + if (buf = nvram_get("model_no")) { + if (!strncmp(buf,"WL700", 5)) /* WL700* */ + return &platforms[WL700GE]; + } + + /* Based on "ModelId" */ + if (buf = nvram_get("ModelId")) { + if (!strcmp(buf, "WR850GP")) + return &platforms[WR850GP]; + if (!strcmp(buf,"WX-5565")) + return &platforms[TM2300]; + if (!strncmp(buf,"WE800G", 6)) /* WE800G* */ + return &platforms[WE800G]; + } + + /* Buffalo */ + if ((buf = (nvram_get("melco_id") ?: nvram_get("buffalo_id")))) { + /* Buffalo hardware, check id for specific hardware matches */ + if (!strcmp(buf, "29bb0332")) + return &platforms[WBR2_G54]; + if (!strcmp(buf, "29129")) + return &platforms[WLA2_G54L]; + if (!strcmp(buf, "30189")) + return &platforms[WHR_HP_G54]; + if (!strcmp(buf, "32093")) + return &platforms[WHR_G125]; + if (!strcmp(buf, "30182")) + return &platforms[WHR_G54S]; + if (!strcmp(buf, "290441dd")) + return &platforms[WHR2_A54G54]; + if (!strcmp(buf, "31120")) + return &platforms[WZR_G300N]; + if (!strcmp(buf, "30083")) + return &platforms[WZR_RS_G54]; + if (!strcmp(buf, "30103")) + return &platforms[WZR_RS_G54HP]; + } + + /* no easy model number, attempt to guess */ + boardnum = getvar("boardnum"); + boardtype = getvar("boardtype"); if (strncmp(getvar("pmon_ver"), "CFE", 3) == 0) { /* CFE based - newer hardware */ @@ -604,24 +722,10 @@ static struct platform_t __init *platform_detect(void) if (!strcmp(boardnum, "10496")) return &platforms[USR5461]; - /* D-Link */ - if (!strcmp(getvar("model_name"), "DIR-130")) - return &platforms[DIR130]; - if (!strcmp(getvar("model_name"), "DIR-330")) - return &platforms[DIR330]; - } else { /* PMON based - old stuff */ - - /* Dell TrueMobile 2300 */ - if (!strcmp(getvar("ModelId"),"WX-5565")) - return &platforms[TM2300]; - if ((simple_strtoul(getvar("GemtekPmonVer"), NULL, 0) == 9) && (simple_strtoul(getvar("et0phyaddr"), NULL, 0) == 30)) { - if (!strncmp(getvar("ModelId"),"WE800G", 6)) - return &platforms[WE800G]; - else - return &platforms[WR850GV1]; + return &platforms[WR850GV1]; } if (!strncmp(boardtype, "bcm94710dev", 11)) { if (!strcmp(boardnum, "42")) @@ -640,32 +744,15 @@ static struct platform_t __init *platform_detect(void) (simple_strtoul(getvar("et1phyaddr"), NULL, 0) == 10)) return &platforms[WL300G]; } + /* Sitecom WL-105b */ + if (!strncmp(boardnum, "2", 1) && simple_strtoul(getvar("GemtekPmonVer"), NULL, 0) == 1) + return &platforms[WL105B]; /* unknown asus stuff, probably bcm4702 */ if (!strncmp(boardnum, "asusX", 5)) return &platforms[ASUS_4702]; } - if ((buf = (nvram_get("melco_id") ?: nvram_get("buffalo_id")))) { - /* Buffalo hardware, check id for specific hardware matches */ - if (!strcmp(buf, "29bb0332")) - return &platforms[WBR2_G54]; - if (!strcmp(buf, "29129")) - return &platforms[WLA2_G54L]; - if (!strcmp(buf, "30189")) - return &platforms[WHR_HP_G54]; - if (!strcmp(buf, "30182")) - return &platforms[WHR_G54S]; - if (!strcmp(buf, "290441dd")) - return &platforms[WHR2_A54G54]; - if (!strcmp(buf, "31120")) - return &platforms[WZR_G300N]; - if (!strcmp(buf, "30083")) - return &platforms[WZR_RS_G54]; - if (!strcmp(buf, "30103")) - return &platforms[WZR_RS_G54HP]; - } - if (buf || !strcmp(boardnum, "00")) {/* probably buffalo */ if (!strncmp(boardtype, "bcm94710ap", 10)) return &platforms[BUFFALO_UNKNOWN_4710]; @@ -673,19 +760,23 @@ static struct platform_t __init *platform_detect(void) return &platforms[BUFFALO_UNKNOWN]; } - if (!strcmp(getvar("CFEver"), "MotoWRv203") || + if (!strncmp(getvar("CFEver"), "MotoWRv2", 8) || + !strncmp(getvar("CFEver"), "MotoWRv3", 8) || !strcmp(getvar("MOTO_BOARD_TYPE"), "WR_FEM1")) { return &platforms[WR850GV2V3]; } - if (!strcmp(boardnum, "44")) { /* Trendware TEW-411BRP+ */ + if (!strcmp(boardnum, "44") && !strcmp(getvar("boardflags"),"0x0388")) { /* Trendware TEW-411BRP+ */ return &platforms[TEW411BRPP]; } if (!strncmp(boardnum, "04FN52", 6)) /* SimpleTech SimpleShare */ return &platforms[STI_NAS]; + if (!strcmp(getvar("boardnum"), "10") && !strcmp(getvar("boardrev"), "0x13")) /* D-Link DWL-3150 */ + return &platforms[DWL3150]; + /* not found */ return NULL; } @@ -713,23 +804,104 @@ static void unregister_buttons(struct button_t *b) gpio_set_irqenable(0, button_handler); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + +#ifndef LINUX_2_4 +static void add_msg(struct event_t *event, char *msg, int argv) +{ + char *s; + + if (argv) + return; + + s = skb_put(event->skb, strlen(msg) + 1); + strcpy(s, msg); +} + static void hotplug_button(struct work_struct *work) { struct event_t *event = container_of(work, struct event_t, wq); -#else + char *s; + + if (!uevent_sock) + return; + + event->skb = alloc_skb(2048, GFP_KERNEL); + + s = skb_put(event->skb, strlen(event->action) + 2); + sprintf(s, "%s@", event->action); + fill_event(event); + + NETLINK_CB(event->skb).dst_group = 1; + netlink_broadcast(uevent_sock, event->skb, 0, 1, GFP_KERNEL); + + kfree(event); +} + +#else /* !LINUX_2_4 */ +static inline char *kzalloc(unsigned int size, unsigned int gfp) +{ + char *p; + + p = kmalloc(size, gfp); + if (p == NULL) + return NULL; + + memset(p, 0, size); + + return p; +} + +static void add_msg(struct event_t *event, char *msg, int argv) +{ + if (argv) + event->argv[event->anr++] = event->scratch; + else + event->envp[event->enr++] = event->scratch; + + event->scratch += sprintf(event->scratch, "%s", msg) + 1; +} + static void hotplug_button(struct event_t *event) { -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - call_usermodehelper (event->argv[0], event->argv, event->envp, 1); -#else + char *scratch = kzalloc(256, GFP_KERNEL); + event->scratch = scratch; + + add_msg(event, hotplug_path, 1); + add_msg(event, "button", 1); + fill_event(event); call_usermodehelper (event->argv[0], event->argv, event->envp); -#endif + kfree(scratch); kfree(event); } +#endif /* !LINUX_2_4 */ + +static int fill_event (struct event_t *event) +{ + static char buf[128]; + + add_msg(event, "HOME=/", 0); + add_msg(event, "PATH=/sbin:/bin:/usr/sbin:/usr/bin", 0); + add_msg(event, "SUBSYSTEM=button", 0); + snprintf(buf, 128, "ACTION=%s", event->action); + add_msg(event, buf, 0); + snprintf(buf, 128, "BUTTON=%s", event->name); + add_msg(event, buf, 0); + snprintf(buf, 128, "SEEN=%ld", event->seen); + add_msg(event, buf, 0); +#ifndef LINUX_2_4 + snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum()); + add_msg(event, buf, 0); +#endif + + return 0; +} + +#ifndef LINUX_2_4 +static irqreturn_t button_handler(int irq, void *dev_id) +#else static irqreturn_t button_handler(int irq, void *dev_id, struct pt_regs *regs) +#endif { struct button_t *b; u32 in, changed; @@ -748,26 +920,10 @@ static irqreturn_t button_handler(int irq, void *dev_id, struct pt_regs *regs) b->pressed ^= 1; - if ((event = (struct event_t *)kmalloc (sizeof(struct event_t), GFP_ATOMIC))) { - int i; - char *scratch = event->buf; - - i = 0; - event->argv[i++] = hotplug_path; - event->argv[i++] = "button"; - event->argv[i] = 0; - - i = 0; - event->envp[i++] = "HOME=/"; - event->envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - event->envp[i++] = scratch; - scratch += sprintf (scratch, "ACTION=%s", b->pressed?"pressed":"released") + 1; - event->envp[i++] = scratch; - scratch += sprintf (scratch, "BUTTON=%s", b->name) + 1; - event->envp[i++] = scratch; - scratch += sprintf (scratch, "SEEN=%ld", (jiffies - b->seen)/HZ) + 1; - event->envp[i] = 0; - + if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) { + event->seen = (jiffies - b->seen)/HZ; + event->name = b->name; + event->action = b->pressed ? "pressed" : "released"; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) INIT_WORK(&event->wq, (void *)(void *)hotplug_button); #else @@ -785,6 +941,7 @@ static void register_leds(struct led_t *l) { struct proc_dir_entry *p; u32 mask = 0; + u32 oe_mask = 0; u32 val = 0; leds = proc_mkdir("led", diag); @@ -799,10 +956,13 @@ static void register_leds(struct led_t *l) l->state = 0; set_led_extif(l); } else { + if (l->polarity != INPUT) oe_mask != l->gpio; mask |= l->gpio; val |= (l->polarity == NORMAL)?0:l->gpio; } + if (l->polarity == INPUT) continue; + if ((p = create_proc_entry(l->name, S_IRUSR, leds))) { l->proc.type = PROC_LED; l->proc.ptr = l; @@ -811,7 +971,7 @@ static void register_leds(struct led_t *l) } } - gpio_outen(mask, mask); + gpio_outen(mask, oe_mask); gpio_control(mask, 0); gpio_out(mask, val); } @@ -1024,7 +1184,6 @@ static int __init diag_init(void) static void __exit diag_exit(void) { - del_timer(&led_timer); if (platform.buttons)