-diff -Nur linux-2.4.30/drivers/net/diag/diag_led.c linux-2.4.30.dev/drivers/net/diag/diag_led.c
---- linux-2.4.30/drivers/net/diag/diag_led.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.30.dev/drivers/net/diag/diag_led.c 2006-02-06 00:42:46.000000000 +0100
-@@ -0,0 +1,253 @@
+diff -urN linux.old/drivers/net/Makefile linux.dev/drivers/net/Makefile
+--- linux.old/drivers/net/Makefile 2006-03-09 09:41:28.000000000 +0100
++++ linux.dev/drivers/net/Makefile 2006-01-24 20:52:08.000000000 +0100
+@@ -41,6 +41,8 @@
+ obj-$(CONFIG_ISDN) += slhc.o
+ endif
+
++subdir-m += diag
++
+ subdir-$(CONFIG_HND) += hnd
+ subdir-$(CONFIG_ET) += et
+ subdir-$(CONFIG_WL) += wl
+diff -urN linux.old/drivers/net/diag/Makefile linux.dev/drivers/net/diag/Makefile
+--- linux.old/drivers/net/diag/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/diag/Makefile 2006-01-24 20:52:08.000000000 +0100
+@@ -0,0 +1,13 @@
++#$Id$
++
++EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER
++
++O_TARGET := diag.o
++
++MAC_OBJS := diag_led.o
++
++export-objs :=
++obj-y := $(MAC_OBJS)
++obj-m := $(O_TARGET)
++
++include $(TOPDIR)/Rules.make
+diff -urN linux.old/drivers/net/diag/diag_led.c linux.dev/drivers/net/diag/diag_led.c
+--- linux.old/drivers/net/diag/diag_led.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/drivers/net/diag/diag_led.c 2006-03-09 11:04:09.000000000 +0100
+@@ -0,0 +1,309 @@
+/*
+ * diag_led.c - replacement diag module
+ *
-+ * Copyright (C) 2004 Mike Baker,
-+ * Imre Kaloz <kaloz@dune.hu>
++ * Copyright (C) 2004-2006 Mike Baker,
++ * Imre Kaloz <kaloz@dune.hu>,
++ * Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+static void *sbh;
+
+// v2.x - - - - -
++#define BITS(n) ((1 << n) - 1)
++#define ISSET(n,b) ((n & (1 << b)) ? 1 : 0)
+#define DIAG_GPIO (1<<1)
++#define AOSS_GPIO (1<<6)
+#define DMZ_GPIO (1<<7)
++#define SES_GPIO ((1 << 2) | (1 << 3) | (1 << 5))
+
+static void set_gpio(uint32 mask, uint32 value) {
+ sb_gpiocontrol(sbh,mask,0);
+static void v2_set_dmz(u8 state) {
+ set_gpio(DMZ_GPIO,state);
+}
++static void v2_set_aoss(u8 state) {
++ set_gpio(AOSS_GPIO,state);
++}
++static void v2_set_ses(u8 state) {
++ set_gpio(SES_GPIO, (ISSET(state, 0) << 2) | (ISSET(state, 1) << 3) | (ISSET(state, 2) << 5));
++}
+
+// v1.x - - - - -
+#define LED_DIAG 0x13
+static void ignore(u8 ignored) {};
+
+// - - - - -
-+#define BIT_DMZ 0x01
-+#define BIT_DIAG 0x04
++#define BIT_DMZ (1 << 0)
++#define BIT_DIAG (1 << 2)
++#define BIT_SES (BITS(3) << 3)
+
+void (*set_diag)(u8 state);
+void (*set_dmz)(u8 state);
++void (*set_ses)(u8 state);
+
+static unsigned int diag_reverse = 1;
++static unsigned int ses_reverse = 1;
+static unsigned int diag = 0;
+
+static void diag_change()
+{
+ set_diag(diag_reverse ? 0xFF : 0x00); // off
+ set_dmz(diag_reverse ? 0xFF : 0x00); // off
++ set_ses(ses_reverse ? 0xFF : 0x00); // off
+
+ if(diag & BIT_DIAG)
+ set_diag(diag_reverse ? 0x00 : 0xFF); // on
+ if(diag & BIT_DMZ)
+ set_dmz(diag_reverse ? 0x00 : 0xFF); // on
++ if(diag & BIT_SES)
++ set_ses(((ses_reverse ? ~diag : diag) >> 3) & BITS(3));
+}
+
+static int proc_diag(ctl_table *table, int write, struct file *filp,
+static unsigned char reset_gpio = 0;
+static unsigned char reset_polarity = 0;
+static unsigned int reset = 0;
++static unsigned char button_gpio = 0;
++static unsigned char button_polarity = 0;
++static unsigned int button = 0;
++
++
++static int read_gpio(int gpio, int polarity)
++{
++ int res;
++
++ if (gpio) {
++ sb_gpiocontrol(sbh,gpio,gpio);
++ sb_gpioouten(sbh,gpio,0);
++ res=!(sb_gpioin(sbh)&gpio);
++
++ return (polarity ? !res : res);
++ }
++
++ return 0;
++}
+
+static int proc_reset(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
++ reset = read_gpio(reset_gpio, reset_polarity);
+
-+ if (reset_gpio) {
-+ sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
-+ sb_gpioouten(sbh,reset_gpio,0);
-+ reset=!(sb_gpioin(sbh)&reset_gpio);
++ return proc_dointvec(table, write, filp, buffer, lenp);
++}
+
-+ if (reset_polarity) reset=!reset;
-+ } else {
-+ reset=0;
-+ }
++static int proc_button(ctl_table *table, int write, struct file *filp,
++ void *buffer, size_t *lenp)
++{
++ button = read_gpio(button_gpio, button_polarity);
+
+ return proc_dointvec(table, write, filp, buffer, lenp);
+}
+ mode: 0444,
+ proc_handler: proc_reset
+ },
++ {
++ ctl_name: 2002,
++ procname: "button",
++ data: &button,
++ maxlen: sizeof(button),
++ mode: 0444,
++ proc_handler: proc_button
++ },
+ { 0 }
+};
+
+
+ set_diag=ignore;
+ set_dmz=ignore;
++ set_ses=ignore;
+
+ buf=nvram_get("pmon_ver") ?: "";
+ if (((board_type & 0xf00) == 0x400) && (strncmp(buf, "CFE", 3) != 0)) {
+ //asus wl-500g
+ reset_gpio=(1<<6);
+ }
-+ if (!strcmp(buf,"2")) {
-+ // wa840g v1 / we800g v1
-+ reset_gpio=(1<<0);
-+ }
-+
+ }
+ if (!strcmp(buf,"bcm94710ap")) {
+ buf=nvram_get("boardnum")?:"";
+ //linksys
+ set_diag=v2_set_diag;
+ set_dmz=v2_set_dmz;
++ set_ses=v2_set_ses;
++
+ reset_gpio=(1<<6);
++ button_gpio=(1<<4);
++
++ if (!strcmp((nvram_get("boardflags")?:""), "0x0318")) // WRT54G3G
++ ses_reverse = 0;
++ else
++ ses_reverse = 1;
+ }
+ if (!strcmp(buf,"44")) {
+ //motorola
+ //buffalo
+ diag_reverse = 0;
+ set_dmz=v2_set_diag;
++ set_diag=v2_set_aoss;
+ reset_gpio=(1<<7);
+ }
+ if (!strcmp(buf,"45")) {
+ }
+ }
+
-+
+ sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
+ sb_gpioouten(sbh,reset_gpio,0);
+ reset_polarity=!(sb_gpioin(sbh)&reset_gpio);
+
++ if (button_gpio) {
++ sb_gpiocontrol(sbh,button_gpio,button_gpio);
++ sb_gpioouten(sbh,button_gpio,0);
++ button_polarity=!(sb_gpioin(sbh)&button_gpio);
++ } else {
++ // don't create /proc/button
++ sys_diag[2].ctl_name = 0;
++ }
++
+ diag_sysctl_header = register_sysctl_table(sys_diag, 0);
+ diag_change();
+
+
+module_init(diag_init);
+module_exit(diag_exit);
-diff -Nur linux-2.4.30/drivers/net/diag/Makefile linux-2.4.30.dev/drivers/net/diag/Makefile
---- linux-2.4.30/drivers/net/diag/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.30.dev/drivers/net/diag/Makefile 2006-02-05 15:35:11.000000000 +0100
-@@ -0,0 +1,13 @@
-+#$Id$
-+
-+EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER
-+
-+O_TARGET := diag.o
-+
-+MAC_OBJS := diag_led.o
-+
-+export-objs :=
-+obj-y := $(MAC_OBJS)
-+obj-m := $(O_TARGET)
-+
-+include $(TOPDIR)/Rules.make
-diff -Nur linux-2.4.30/drivers/net/Makefile linux-2.4.30.dev/drivers/net/Makefile
---- linux-2.4.30/drivers/net/Makefile 2006-02-05 15:34:40.000000000 +0100
-+++ linux-2.4.30.dev/drivers/net/Makefile 2006-02-05 15:35:11.000000000 +0100
-@@ -41,6 +41,8 @@
- obj-$(CONFIG_ISDN) += slhc.o
- endif
-
-+subdir-m += diag
-+
- subdir-$(CONFIG_HND) += hnd
- subdir-$(CONFIG_ET) += et
- subdir-$(CONFIG_WL) += wl