more diag cleanup
authorMike Baker <mbm@openwrt.org>
Sat, 4 Nov 2006 01:45:26 +0000 (01:45 +0000)
committerMike Baker <mbm@openwrt.org>
Sat, 4 Nov 2006 01:45:26 +0000 (01:45 +0000)
SVN-Revision: 5434

openwrt/target/linux/package/diag/src/diag.c
openwrt/target/linux/package/diag/src/diag.h [new file with mode: 0644]

index 149dc91ac6d59cfcd063c50cb32581fae7fe9b11..5f460f59d955307c2dc1acf20944175d2e83aa07 100644 (file)
 #include <sbconfig.h>
 #include <sbchipc.h>
 
-#define MODULE_NAME "diag"
-
-#define MAX_GPIO 8
-#define FLASH_TIME HZ/6
-
-#define EXTIF_ADDR 0x1f000000
-#define EXTIF_UART (EXTIF_ADDR + 0x00800000)
-
-/* For LEDs */
-#define GPIO_TYPE_NORMAL       (0x0 << 24)
-#define GPIO_TYPE_EXTIF        (0x1 << 24)
-#define GPIO_TYPE_MASK         (0xf << 24)
+#include "diag.h"
 
 static unsigned int gpiomask = 0;
 module_param(gpiomask, int, 0644);
 
-enum polarity_t {
-       REVERSE = 0,
-       NORMAL = 1,
-};
-
-enum {
-       PROC_BUTTON,
-       PROC_LED,
-       PROC_MODEL,
-       PROC_GPIOMASK
-};
-
-struct prochandler_t {
-       int type;
-       void *ptr;
-};
-
-struct button_t {
-       struct prochandler_t proc;
-       char *name;
-       u32 gpio;
-       unsigned long seen;
-       u8 pressed;
-};
-
-struct led_t {
-       struct prochandler_t proc;
-       char *name;
-       u32 gpio;
-       u8 polarity;
-       u8 flash;
-       u8 state;
-};
-
-struct platform_t {
-       char *name;
-
-       struct button_t buttons[MAX_GPIO];
-       u32 button_mask;
-       u32 button_polarity;
-
-       struct led_t leds[MAX_GPIO];
-};
-
 enum {
        /* Linksys */
        WAP54GV1,
@@ -439,34 +384,11 @@ static struct platform_t __init platforms[] = {
        },
 };
 
-static struct proc_dir_entry *diag, *leds;
-
-extern void *bcm947xx_sbh;
-#define sbh bcm947xx_sbh
-extern spinlock_t bcm947xx_sbh_lock;
-#define sbh_lock bcm947xx_sbh_lock
-
-static int sb_irq(void *sbh);
-static struct platform_t platform;
-
-extern char *nvram_get(char *str);
-
-static void led_flash(unsigned long dummy);
-
 static inline char __init *getvar(char *str)
 {
        return nvram_get(str)?:"";
 }
 
-static void set_led_extif(struct led_t *led)
-{
-       volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK);
-       if (led->state)
-               *addr = 0xFF;
-       else
-               *addr;
-}
-
 static struct platform_t __init *platform_detect(void)
 {
        char *boardnum, *boardtype, *buf;
@@ -559,161 +481,23 @@ static struct platform_t __init *platform_detect(void)
        return NULL;
 }
 
-static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos);
-static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data);
-static struct file_operations diag_proc_fops = {
-       read: diag_proc_read,
-       write: diag_proc_write
-};
-
-
-
-static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
-#ifdef LINUX_2_4
-       struct inode *inode = file->f_dentry->d_inode;
-       struct proc_dir_entry *dent = inode->u.generic_ip;
-#else
-       struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
-#endif
-       char *page;
-       int len = 0;
-       
-       if ((page = kmalloc(1024, GFP_KERNEL)) == NULL)
-               return -ENOBUFS;
-       
-       if (dent->data != NULL) {
-               struct prochandler_t *handler = (struct prochandler_t *) dent->data;
-               switch (handler->type) {
-                       case PROC_LED: {
-                               struct led_t * led = (struct led_t *) handler->ptr;
-                               if (led->flash) {
-                                       len = sprintf(page, "f\n");
-                               } else {
-                                       if (led->gpio & GPIO_TYPE_EXTIF) {
-                                               len = sprintf(page, "%d\n", led->state);
-                                       } else {
-                                               u32 in = (sb_gpioin(sbh) & led->gpio ? 1 : 0);
-                                               u8 p = (led->polarity == NORMAL ? 0 : 1);
-                                               len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0));
-                                       }
-                               }
-                               break;
-                       }
-                       case PROC_MODEL:
-                               len = sprintf(page, "%s\n", platform.name);
-                               break;
-                       case PROC_GPIOMASK:
-                               len = sprintf(page, "%d\n", gpiomask);
-                               break;
-               }
-       }
-       len += 1;
-
-       if (*ppos < len) {
-               len = min_t(int, len - *ppos, count);
-               if (copy_to_user(buf, (page + *ppos), len)) {
-                       kfree(page);
-                       return -EFAULT;
-               }
-               *ppos += len;
-       } else {
-               len = 0;
-       }
-
-       return len;
-}
-
-
-static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data)
-{
-#ifdef LINUX_2_4
-       struct inode *inode = file->f_dentry->d_inode;
-       struct proc_dir_entry *dent = inode->u.generic_ip;
-#else
-       struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
-#endif
-       char *page;
-       int ret = -EINVAL;
-
-       if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL)
-               return -ENOBUFS;
-
-       if (copy_from_user(page, buf, count)) {
-               kfree(page);
-               return -EINVAL;
-       }
-       page[count] = 0;
-       
-       if (dent->data != NULL) {
-               struct prochandler_t *handler = (struct prochandler_t *) dent->data;
-               switch (handler->type) {
-                       case PROC_LED: {
-                               struct led_t *led = (struct led_t *) handler->ptr;
-                               int p = (led->polarity == NORMAL ? 0 : 1);
-                               
-                               if (!(led->gpio & GPIO_TYPE_EXTIF) && (led->gpio & gpiomask))
-                                       break;
-
-                               if (page[0] == 'f') {
-                                       led->flash = 1;
-                                       led_flash(0);
-                               } else {
-                                       led->flash = 0;
-                                       if (led->gpio & GPIO_TYPE_EXTIF) {
-                                               led->state = p ^ ((page[0] == '1') ? 1 : 0);
-                                               set_led_extif(led);
-                                       } else {
-                                               sb_gpioouten(sbh, led->gpio, led->gpio);
-                                               sb_gpiocontrol(sbh, led->gpio, 0);
-                                               sb_gpioout(sbh, led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0));
-                                       }
-                               }
-                               break;
-                       }
-                       case PROC_GPIOMASK: {
-                               u32 mask;
-                               gpiomask = simple_strtoul(page, NULL, 16);
-
-                               mask = platform.button_mask & ~gpiomask;
-
-                               sb_gpioouten(sbh, mask, 0);
-                               sb_gpiocontrol(sbh, mask, 0);
-                               platform.button_polarity = sb_gpioin(sbh) & mask;
-                               sb_gpiointpolarity(sbh, mask, platform.button_polarity);
-                               sb_gpiointmask(sbh, mask, mask);
-
-                               break;
-                       }
-               }
-               ret = count;
-       }
-
-       kfree(page);
-       return ret;
-}
-
-struct event_t {
-       struct tq_struct tq;
-       char buf[256];
-       char *argv[3];
-       char *envp[6];
-};
-
-static void hotplug_button(struct event_t *event)
-{
-       call_usermodehelper (event->argv[0], event->argv, event->envp);
-       kfree(event);
-}
-
 static void set_irqenable(int enabled)
 {
        unsigned int coreidx;
        unsigned long flags;
        chipcregs_t *cc;
+       int irq;
 
        spin_lock_irqsave(sbh_lock, flags);
        coreidx = sb_coreidx(sbh);
+
+
+       irq = sb_irq(sbh) + 2;
+       if (enabled)
+               request_irq(irq, button_handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", button_handler);
+       else
+               free_irq(irq, button_handler);
+
        if ((cc = sb_setcore(sbh, SB_CC, 0))) {
                int intmask;
 
@@ -728,6 +512,36 @@ static void set_irqenable(int enabled)
        spin_unlock_irqrestore(sbh_lock, flags);
 }
 
+static void register_buttons(struct button_t *b)
+{
+       for (; b->name; b++)
+               platform.button_mask |= b->gpio;
+
+       platform.button_mask &= ~gpiomask;
+
+       sb_gpioouten(sbh, platform.button_mask, 0);
+       sb_gpiocontrol(sbh, platform.button_mask, 0);
+       platform.button_polarity = sb_gpioin(sbh) & platform.button_mask;
+       sb_gpiointpolarity(sbh, platform.button_mask, platform.button_polarity);
+       sb_gpiointmask(sbh, platform.button_mask, platform.button_mask);
+
+       set_irqenable(1);
+}
+
+static void unregister_buttons(struct button_t *b)
+{
+
+       sb_gpiointmask(sbh, platform.button_mask, 0);
+
+       set_irqenable(0);
+}
+
+static void hotplug_button(struct event_t *event)
+{
+       call_usermodehelper (event->argv[0], event->argv, event->envp);
+       kfree(event);
+}
+
 
 static void button_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -739,7 +553,6 @@ static void button_handler(int irq, void *dev_id, struct pt_regs *regs)
        changed = platform.button_polarity ^ in;
        platform.button_polarity = in;
 
-       set_irqenable(0);
        for (b = platform.buttons; b->name; b++) { 
                struct event_t *event;
 
@@ -773,12 +586,59 @@ static void button_handler(int irq, void *dev_id, struct pt_regs *regs)
 
                b->seen = jiffies;
        }
-       set_irqenable(1);
 }
 
-static struct timer_list led_timer = {
-       function: &led_flash
-};
+static void register_leds(struct led_t *l)
+{
+       struct proc_dir_entry *p;
+       u32 mask;
+       u32 val;
+
+       leds = proc_mkdir("led", diag);
+       if (!leds) 
+               return;
+
+       for(; l->name; l++) {
+               if (l->gpio & gpiomask)
+                       continue;
+       
+               if (l->gpio & GPIO_TYPE_EXTIF) {
+                       l->state = 0;
+                       set_led_extif(l);
+               } else {
+                       mask |= l->gpio;
+                       val |= (l->polarity == NORMAL)?0:l->gpio;
+               }
+
+               if ((p = create_proc_entry(l->name, S_IRUSR, leds))) {
+                       l->proc.type = PROC_LED;
+                       l->proc.ptr = l;
+                       p->data = (void *) &l->proc;
+                       p->proc_fops = &diag_proc_fops;
+               }
+       }
+
+       sb_gpioouten(sbh, mask, mask);
+       sb_gpiocontrol(sbh, mask, 0);
+       sb_gpioout(sbh, mask, val);
+}
+
+static void unregister_leds(struct led_t *l)
+{
+       for(; l->name; l++)
+               remove_proc_entry(l->name, leds);
+
+       remove_proc_entry("led", diag);
+}
+
+static void set_led_extif(struct led_t *led)
+{
+       volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK);
+       if (led->state)
+               *addr = 0xFF;
+       else
+               *addr;
+}
 
 static void led_flash(unsigned long dummy) {
        struct led_t *l;
@@ -810,92 +670,126 @@ static void led_flash(unsigned long dummy) {
        }
 }
 
-static void __init register_buttons(struct button_t *b)
-{
-       int irq = sb_irq(sbh) + 2;
-       u32 mask;
-
-       request_irq(irq, button_handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", button_handler);
-
-       for (; b->name; b++)
-               platform.button_mask |= b->gpio;
-
-       mask = platform.button_mask & ~gpiomask;
-
-       sb_gpioouten(sbh, mask, 0);
-       sb_gpiocontrol(sbh, mask, 0);
-       platform.button_polarity = sb_gpioin(sbh) & mask;
-       sb_gpiointpolarity(sbh, mask, platform.button_polarity);
-       sb_gpiointmask(sbh, mask, mask);
-
-       set_irqenable(1);
-}
-
-static void __exit unregister_buttons(struct button_t *b)
-{
-       int irq = sb_irq(sbh) + 2;
-
-       sb_gpiointmask(sbh, platform.button_mask, 0);
-
-       free_irq(irq, button_handler);
-}
-
-static void __init register_leds(struct led_t *l)
+static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-       struct proc_dir_entry *p;
-
-       leds = proc_mkdir("led", diag);
-       if (!leds) 
-               return;
-
-       for(; l->name; l++) {
-               if (l->gpio & gpiomask)
-                       continue;
+#ifdef LINUX_2_4
+       struct inode *inode = file->f_dentry->d_inode;
+       struct proc_dir_entry *dent = inode->u.generic_ip;
+#else
+       struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+#endif
+       char *page;
+       int len = 0;
        
-               if (l->gpio & GPIO_TYPE_EXTIF) {
-                       l->state = 0;
-                       set_led_extif(l);
-               } else {
-                       sb_gpioouten(sbh, l->gpio, l->gpio);
-                       sb_gpiocontrol(sbh, l->gpio, 0);
-                       sb_gpioout(sbh, l->gpio, (l->polarity == NORMAL)?0:l->gpio);
+       if ((page = kmalloc(1024, GFP_KERNEL)) == NULL)
+               return -ENOBUFS;
+       
+       if (dent->data != NULL) {
+               struct prochandler_t *handler = (struct prochandler_t *) dent->data;
+               switch (handler->type) {
+                       case PROC_LED: {
+                               struct led_t * led = (struct led_t *) handler->ptr;
+                               if (led->flash) {
+                                       len = sprintf(page, "f\n");
+                               } else {
+                                       if (led->gpio & GPIO_TYPE_EXTIF) {
+                                               len = sprintf(page, "%d\n", led->state);
+                                       } else {
+                                               u32 in = (sb_gpioin(sbh) & led->gpio ? 1 : 0);
+                                               u8 p = (led->polarity == NORMAL ? 0 : 1);
+                                               len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0));
+                                       }
+                               }
+                               break;
+                       }
+                       case PROC_MODEL:
+                               len = sprintf(page, "%s\n", platform.name);
+                               break;
+                       case PROC_GPIOMASK:
+                               len = sprintf(page, "%d\n", gpiomask);
+                               break;
                }
+       }
+       len += 1;
 
-               if ((p = create_proc_entry(l->name, S_IRUSR, leds))) {
-                       l->proc.type = PROC_LED;
-                       l->proc.ptr = l;
-                       p->data = (void *) &l->proc;
-                       p->proc_fops = &diag_proc_fops;
+       if (*ppos < len) {
+               len = min_t(int, len - *ppos, count);
+               if (copy_to_user(buf, (page + *ppos), len)) {
+                       kfree(page);
+                       return -EFAULT;
                }
+               *ppos += len;
+       } else {
+               len = 0;
        }
-}
-
-static void __exit unregister_leds(struct led_t *l)
-{
-       for(; l->name; l++)
-               remove_proc_entry(l->name, leds);
 
-       remove_proc_entry("led", diag);
+       return len;
 }
 
-static void __exit diag_exit(void)
+
+static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data)
 {
+#ifdef LINUX_2_4
+       struct inode *inode = file->f_dentry->d_inode;
+       struct proc_dir_entry *dent = inode->u.generic_ip;
+#else
+       struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+#endif
+       char *page;
+       int ret = -EINVAL;
 
-       del_timer(&led_timer);
+       if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL)
+               return -ENOBUFS;
 
-       if (platform.buttons)
-               unregister_buttons(platform.buttons);
+       if (copy_from_user(page, buf, count)) {
+               kfree(page);
+               return -EINVAL;
+       }
+       page[count] = 0;
+       
+       if (dent->data != NULL) {
+               struct prochandler_t *handler = (struct prochandler_t *) dent->data;
+               switch (handler->type) {
+                       case PROC_LED: {
+                               struct led_t *led = (struct led_t *) handler->ptr;
+                               int p = (led->polarity == NORMAL ? 0 : 1);
+                               
+                               if (page[0] == 'f') {
+                                       led->flash = 1;
+                                       led_flash(0);
+                               } else {
+                                       led->flash = 0;
+                                       if (led->gpio & GPIO_TYPE_EXTIF) {
+                                               led->state = p ^ ((page[0] == '1') ? 1 : 0);
+                                               set_led_extif(led);
+                                       } else {
+                                               sb_gpioouten(sbh, led->gpio, led->gpio);
+                                               sb_gpiocontrol(sbh, led->gpio, 0);
+                                               sb_gpioout(sbh, led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0));
+                                       }
+                               }
+                               break;
+                       }
+                       case PROC_GPIOMASK:
+                               gpiomask = simple_strtoul(page, NULL, 16);
 
-       if (platform.leds)
-               unregister_leds(platform.leds);
+                               if (platform.buttons) {
+                                       unregister_buttons(platform.buttons);
+                                       register_buttons(platform.buttons);
+                               }
 
-       remove_proc_entry("model", diag);
-       remove_proc_entry("gpiomask", diag);
-       remove_proc_entry("diag", NULL);
-}
+                               if (platform.leds) {
+                                       unregister_leds(platform.leds);
+                                       register_leds(platform.leds);
+                               }
+                               break;
+               }
+               ret = count;
+       }
 
-static struct prochandler_t proc_model = { .type = PROC_MODEL };
-static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK };
+       kfree(page);
+       return ret;
+}
 
 static int __init diag_init(void)
 {
@@ -935,6 +829,22 @@ static int __init diag_init(void)
        return 0;
 }
 
+static void __exit diag_exit(void)
+{
+
+       del_timer(&led_timer);
+
+       if (platform.buttons)
+               unregister_buttons(platform.buttons);
+
+       if (platform.leds)
+               unregister_leds(platform.leds);
+
+       remove_proc_entry("model", diag);
+       remove_proc_entry("gpiomask", diag);
+       remove_proc_entry("diag", NULL);
+}
+
 EXPORT_NO_SYMBOLS;
 
 module_init(diag_init);
@@ -942,37 +852,3 @@ module_exit(diag_exit);
 
 MODULE_AUTHOR("Mike Baker, Felix Fietkau / OpenWrt.org");
 MODULE_LICENSE("GPL");
-
-/* TODO: export existing sb_irq instead */
-static int sb_irq(void *sbh)
-{
-       uint idx;
-       void *regs;
-       sbconfig_t *sb;
-       uint32 flag, sbipsflag;
-       uint irq = 0;
-
-       regs = sb_coreregs(sbh);
-       sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
-       flag = (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
-
-       idx = sb_coreidx(sbh);
-
-       if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
-           (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
-               sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
-
-               /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
-               sbipsflag = R_REG(&sb->sbipsflag);
-               for (irq = 1; irq <= 4; irq++, sbipsflag >>= 8) {
-                       if ((sbipsflag & 0x3f) == flag)
-                               break;
-               }
-               if (irq == 5)
-                       irq = 0;
-       }
-
-       sb_setcoreidx(sbh, idx);
-
-       return irq;
-}
diff --git a/openwrt/target/linux/package/diag/src/diag.h b/openwrt/target/linux/package/diag/src/diag.h
new file mode 100644 (file)
index 0000000..95c31e0
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * diag.h - GPIO interface driver for Broadcom boards
+ *
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ *                    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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * $Id:$
+ */
+
+#define MODULE_NAME "diag"
+
+#define MAX_GPIO 8
+#define FLASH_TIME HZ/6
+
+enum polarity_t {
+       REVERSE = 0,
+       NORMAL = 1,
+};
+
+enum {
+       PROC_BUTTON,
+       PROC_LED,
+       PROC_MODEL,
+       PROC_GPIOMASK
+};
+
+struct prochandler_t {
+       int type;
+       void *ptr;
+};
+
+struct button_t {
+       struct prochandler_t proc;
+       char *name;
+       u32 gpio;
+       unsigned long seen;
+       u8 pressed;
+};
+
+struct led_t {
+       struct prochandler_t proc;
+       char *name;
+       u32 gpio;
+       u8 polarity;
+       u8 flash;
+       u8 state;
+};
+
+struct platform_t {
+       char *name;
+
+       struct button_t buttons[MAX_GPIO];
+       u32 button_mask;
+       u32 button_polarity;
+
+       struct led_t leds[MAX_GPIO];
+};
+
+struct event_t {
+       struct tq_struct tq;
+       char buf[256];
+       char *argv[3];
+       char *envp[6];
+};
+
+#define sbh bcm947xx_sbh
+#define sbh_lock bcm947xx_sbh_lock
+
+extern void *bcm947xx_sbh;
+extern spinlock_t bcm947xx_sbh_lock;
+extern char *nvram_get(char *str);
+
+static struct platform_t platform;
+
+/* buttons */
+
+static void set_irqenable(int enabled);
+
+static void register_buttons(struct button_t *b);
+static void unregister_buttons(struct button_t *b);
+
+static void hotplug_button(struct event_t *event);
+static void button_handler(int irq, void *dev_id, struct pt_regs *regs);
+
+/* leds */
+
+static void register_leds(struct led_t *l);
+static void unregister_leds(struct led_t *l);
+
+#define EXTIF_ADDR 0x1f000000
+#define EXTIF_UART (EXTIF_ADDR + 0x00800000)
+
+#define GPIO_TYPE_NORMAL       (0x0 << 24)
+#define GPIO_TYPE_EXTIF        (0x1 << 24)
+#define GPIO_TYPE_MASK         (0xf << 24)
+
+static void set_led_extif(struct led_t *led);
+static void led_flash(unsigned long dummy);
+
+static struct timer_list led_timer = {
+       function: &led_flash
+};
+
+/* proc */
+
+static struct proc_dir_entry *diag, *leds;
+
+static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos);
+static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data);
+
+static struct file_operations diag_proc_fops = {
+       read: diag_proc_read,
+       write: diag_proc_write
+};
+
+static struct prochandler_t proc_model = { .type = PROC_MODEL };
+static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK };
+
+/* TODO: export existing sb_irq instead */
+static int sb_irq(void *sbh)
+{
+       uint idx;
+       void *regs;
+       sbconfig_t *sb;
+       uint32 flag, sbipsflag;
+       uint irq = 0;
+
+       regs = sb_coreregs(sbh);
+       sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
+       flag = (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
+
+       idx = sb_coreidx(sbh);
+
+       if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
+           (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
+               sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
+
+               /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
+               sbipsflag = R_REG(&sb->sbipsflag);
+               for (irq = 1; irq <= 4; irq++, sbipsflag >>= 8) {
+                       if ((sbipsflag & 0x3f) == flag)
+                               break;
+               }
+               if (irq == 5)
+                       irq = 0;
+       }
+
+       sb_setcoreidx(sbh, idx);
+
+       return irq;
+}