11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 51da177e4SLinus Torvalds * License. See the file COPYING in the main directory of this archive 61da177e4SLinus Torvalds * for more details. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * 07/03/96: Timer initialization, and thus mach_sched_init(), 91da177e4SLinus Torvalds * removed from request_irq() and moved to init_time(). 101da177e4SLinus Torvalds * We should therefore consider renaming our add_isr() and 111da177e4SLinus Torvalds * remove_isr() to request_irq() and free_irq() 121da177e4SLinus Torvalds * respectively, so they are compliant with the other 131da177e4SLinus Torvalds * architectures. /Jes 141da177e4SLinus Torvalds * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls. 151da177e4SLinus Torvalds * Removed irq list support, if any machine needs an irq server 161da177e4SLinus Torvalds * it must implement this itself (as it's already done), instead 171da177e4SLinus Torvalds * only default handler are used with mach_default_handler. 181da177e4SLinus Torvalds * request_irq got some flags different from other architectures: 191da177e4SLinus Torvalds * - IRQ_FLG_REPLACE : Replace an existing handler (the default one 201da177e4SLinus Torvalds * can be replaced without this flag) 211da177e4SLinus Torvalds * - IRQ_FLG_LOCK : handler can't be replaced 221da177e4SLinus Torvalds * There are other machine depending flags, see there 231da177e4SLinus Torvalds * If you want to replace a default handler you should know what 241da177e4SLinus Torvalds * you're doing, since it might handle different other irq sources 251da177e4SLinus Torvalds * which must be served /Roman Zippel 261da177e4SLinus Torvalds */ 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <linux/module.h> 291da177e4SLinus Torvalds #include <linux/types.h> 301da177e4SLinus Torvalds #include <linux/sched.h> 311da177e4SLinus Torvalds #include <linux/kernel_stat.h> 321da177e4SLinus Torvalds #include <linux/errno.h> 331da177e4SLinus Torvalds #include <linux/init.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds #include <asm/setup.h> 361da177e4SLinus Torvalds #include <asm/system.h> 371da177e4SLinus Torvalds #include <asm/irq.h> 381da177e4SLinus Torvalds #include <asm/traps.h> 391da177e4SLinus Torvalds #include <asm/page.h> 401da177e4SLinus Torvalds #include <asm/machdep.h> 4168387c44SRoman Zippel #include <asm/cacheflush.h> 42*2850bc27SAl Viro #include <asm/irq_regs.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #ifdef CONFIG_Q40 451da177e4SLinus Torvalds #include <asm/q40ints.h> 461da177e4SLinus Torvalds #endif 471da177e4SLinus Torvalds 4868387c44SRoman Zippel extern u32 auto_irqhandler_fixup[]; 4968387c44SRoman Zippel extern u32 user_irqhandler_fixup[]; 5068387c44SRoman Zippel extern u16 user_irqvec_fixup[]; 5168387c44SRoman Zippel 521da177e4SLinus Torvalds /* table for system interrupt handlers */ 5368387c44SRoman Zippel static struct irq_node *irq_list[NR_IRQS]; 5468387c44SRoman Zippel static struct irq_controller *irq_controller[NR_IRQS]; 5568387c44SRoman Zippel static int irq_depth[NR_IRQS]; 5668387c44SRoman Zippel 5768387c44SRoman Zippel static int m68k_first_user_vec; 58b5dc7840SRoman Zippel 59b5dc7840SRoman Zippel static struct irq_controller auto_irq_controller = { 60b5dc7840SRoman Zippel .name = "auto", 61b5dc7840SRoman Zippel .lock = SPIN_LOCK_UNLOCKED, 62b5dc7840SRoman Zippel .startup = m68k_irq_startup, 63b5dc7840SRoman Zippel .shutdown = m68k_irq_shutdown, 64b5dc7840SRoman Zippel }; 651da177e4SLinus Torvalds 6668387c44SRoman Zippel static struct irq_controller user_irq_controller = { 6768387c44SRoman Zippel .name = "user", 6868387c44SRoman Zippel .lock = SPIN_LOCK_UNLOCKED, 6968387c44SRoman Zippel .startup = m68k_irq_startup, 7068387c44SRoman Zippel .shutdown = m68k_irq_shutdown, 711da177e4SLinus Torvalds }; 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds #define NUM_IRQ_NODES 100 741da177e4SLinus Torvalds static irq_node_t nodes[NUM_IRQ_NODES]; 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds /* 771da177e4SLinus Torvalds * void init_IRQ(void) 781da177e4SLinus Torvalds * 791da177e4SLinus Torvalds * Parameters: None 801da177e4SLinus Torvalds * 811da177e4SLinus Torvalds * Returns: Nothing 821da177e4SLinus Torvalds * 831da177e4SLinus Torvalds * This function should be called during kernel startup to initialize 841da177e4SLinus Torvalds * the IRQ handling routines. 851da177e4SLinus Torvalds */ 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds void __init init_IRQ(void) 881da177e4SLinus Torvalds { 891da177e4SLinus Torvalds int i; 901da177e4SLinus Torvalds 916d2f16a8SRoman Zippel /* assembly irq entry code relies on this... */ 926d2f16a8SRoman Zippel if (HARDIRQ_MASK != 0x00ff0000) { 936d2f16a8SRoman Zippel extern void hardirq_mask_is_broken(void); 946d2f16a8SRoman Zippel hardirq_mask_is_broken(); 956d2f16a8SRoman Zippel } 966d2f16a8SRoman Zippel 9768387c44SRoman Zippel for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) 98b5dc7840SRoman Zippel irq_controller[i] = &auto_irq_controller; 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds mach_init_IRQ(); 1011da177e4SLinus Torvalds } 1021da177e4SLinus Torvalds 10368387c44SRoman Zippel /** 10468387c44SRoman Zippel * m68k_setup_auto_interrupt 10568387c44SRoman Zippel * @handler: called from auto vector interrupts 10668387c44SRoman Zippel * 10768387c44SRoman Zippel * setup the handler to be called from auto vector interrupts instead of the 108*2850bc27SAl Viro * standard __m68k_handle_int(), it will be called with irq numbers in the range 10968387c44SRoman Zippel * from IRQ_AUTO_1 - IRQ_AUTO_7. 11068387c44SRoman Zippel */ 11168387c44SRoman Zippel void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) 11268387c44SRoman Zippel { 11368387c44SRoman Zippel if (handler) 11468387c44SRoman Zippel *auto_irqhandler_fixup = (u32)handler; 11568387c44SRoman Zippel flush_icache(); 11668387c44SRoman Zippel } 11768387c44SRoman Zippel 11868387c44SRoman Zippel /** 11968387c44SRoman Zippel * m68k_setup_user_interrupt 12068387c44SRoman Zippel * @vec: first user vector interrupt to handle 12168387c44SRoman Zippel * @cnt: number of active user vector interrupts 12268387c44SRoman Zippel * @handler: called from user vector interrupts 12368387c44SRoman Zippel * 12468387c44SRoman Zippel * setup user vector interrupts, this includes activating the specified range 12568387c44SRoman Zippel * of interrupts, only then these interrupts can be requested (note: this is 12668387c44SRoman Zippel * different from auto vector interrupts). An optional handler can be installed 127*2850bc27SAl Viro * to be called instead of the default __m68k_handle_int(), it will be called 12868387c44SRoman Zippel * with irq numbers starting from IRQ_USER. 12968387c44SRoman Zippel */ 13068387c44SRoman Zippel void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, 13168387c44SRoman Zippel void (*handler)(unsigned int, struct pt_regs *)) 13268387c44SRoman Zippel { 13368387c44SRoman Zippel int i; 13468387c44SRoman Zippel 13568387c44SRoman Zippel m68k_first_user_vec = vec; 13668387c44SRoman Zippel for (i = 0; i < cnt; i++) 13768387c44SRoman Zippel irq_controller[IRQ_USER + i] = &user_irq_controller; 13868387c44SRoman Zippel *user_irqvec_fixup = vec - IRQ_USER; 13968387c44SRoman Zippel if (handler) 14068387c44SRoman Zippel *user_irqhandler_fixup = (u32)handler; 14168387c44SRoman Zippel flush_icache(); 14268387c44SRoman Zippel } 14368387c44SRoman Zippel 14468387c44SRoman Zippel /** 14568387c44SRoman Zippel * m68k_setup_irq_controller 14668387c44SRoman Zippel * @contr: irq controller which controls specified irq 14768387c44SRoman Zippel * @irq: first irq to be managed by the controller 14868387c44SRoman Zippel * 14968387c44SRoman Zippel * Change the controller for the specified range of irq, which will be used to 15068387c44SRoman Zippel * manage these irq. auto/user irq already have a default controller, which can 15168387c44SRoman Zippel * be changed as well, but the controller probably should use m68k_irq_startup/ 15268387c44SRoman Zippel * m68k_irq_shutdown. 15368387c44SRoman Zippel */ 15468387c44SRoman Zippel void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, 15568387c44SRoman Zippel unsigned int cnt) 15668387c44SRoman Zippel { 15768387c44SRoman Zippel int i; 15868387c44SRoman Zippel 15968387c44SRoman Zippel for (i = 0; i < cnt; i++) 16068387c44SRoman Zippel irq_controller[irq + i] = contr; 16168387c44SRoman Zippel } 16268387c44SRoman Zippel 1631da177e4SLinus Torvalds irq_node_t *new_irq_node(void) 1641da177e4SLinus Torvalds { 1651da177e4SLinus Torvalds irq_node_t *node; 1661da177e4SLinus Torvalds short i; 1671da177e4SLinus Torvalds 168b5dc7840SRoman Zippel for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { 169b5dc7840SRoman Zippel if (!node->handler) { 170b5dc7840SRoman Zippel memset(node, 0, sizeof(*node)); 1711da177e4SLinus Torvalds return node; 172b5dc7840SRoman Zippel } 173b5dc7840SRoman Zippel } 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds printk ("new_irq_node: out of nodes\n"); 1761da177e4SLinus Torvalds return NULL; 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 179b5dc7840SRoman Zippel int setup_irq(unsigned int irq, struct irq_node *node) 180b5dc7840SRoman Zippel { 181b5dc7840SRoman Zippel struct irq_controller *contr; 182b5dc7840SRoman Zippel struct irq_node **prev; 183b5dc7840SRoman Zippel unsigned long flags; 184b5dc7840SRoman Zippel 18568387c44SRoman Zippel if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 186b5dc7840SRoman Zippel printk("%s: Incorrect IRQ %d from %s\n", 187b5dc7840SRoman Zippel __FUNCTION__, irq, node->devname); 188b5dc7840SRoman Zippel return -ENXIO; 189b5dc7840SRoman Zippel } 190b5dc7840SRoman Zippel 191b5dc7840SRoman Zippel spin_lock_irqsave(&contr->lock, flags); 192b5dc7840SRoman Zippel 193b5dc7840SRoman Zippel prev = irq_list + irq; 194b5dc7840SRoman Zippel if (*prev) { 195b5dc7840SRoman Zippel /* Can't share interrupts unless both agree to */ 196b0b9fdc1SThomas Gleixner if (!((*prev)->flags & node->flags & IRQF_SHARED)) { 197b5dc7840SRoman Zippel spin_unlock_irqrestore(&contr->lock, flags); 198b5dc7840SRoman Zippel return -EBUSY; 199b5dc7840SRoman Zippel } 200b5dc7840SRoman Zippel while (*prev) 201b5dc7840SRoman Zippel prev = &(*prev)->next; 202b5dc7840SRoman Zippel } 203b5dc7840SRoman Zippel 204b5dc7840SRoman Zippel if (!irq_list[irq]) { 205b5dc7840SRoman Zippel if (contr->startup) 206b5dc7840SRoman Zippel contr->startup(irq); 207b5dc7840SRoman Zippel else 208b5dc7840SRoman Zippel contr->enable(irq); 209b5dc7840SRoman Zippel } 210b5dc7840SRoman Zippel node->next = NULL; 211b5dc7840SRoman Zippel *prev = node; 212b5dc7840SRoman Zippel 213b5dc7840SRoman Zippel spin_unlock_irqrestore(&contr->lock, flags); 214b5dc7840SRoman Zippel 215b5dc7840SRoman Zippel return 0; 216b5dc7840SRoman Zippel } 217b5dc7840SRoman Zippel 21868387c44SRoman Zippel int request_irq(unsigned int irq, 219*2850bc27SAl Viro irqreturn_t (*handler) (int, void *), 2201da177e4SLinus Torvalds unsigned long flags, const char *devname, void *dev_id) 2211da177e4SLinus Torvalds { 222b5dc7840SRoman Zippel struct irq_node *node; 223b5dc7840SRoman Zippel int res; 2241da177e4SLinus Torvalds 225b5dc7840SRoman Zippel node = new_irq_node(); 226b5dc7840SRoman Zippel if (!node) 227b5dc7840SRoman Zippel return -ENOMEM; 2281da177e4SLinus Torvalds 229b5dc7840SRoman Zippel node->handler = handler; 230b5dc7840SRoman Zippel node->flags = flags; 231b5dc7840SRoman Zippel node->dev_id = dev_id; 232b5dc7840SRoman Zippel node->devname = devname; 233b5dc7840SRoman Zippel 234b5dc7840SRoman Zippel res = setup_irq(irq, node); 235b5dc7840SRoman Zippel if (res) 236b5dc7840SRoman Zippel node->handler = NULL; 237b5dc7840SRoman Zippel 238b5dc7840SRoman Zippel return res; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds 24168387c44SRoman Zippel EXPORT_SYMBOL(request_irq); 24268387c44SRoman Zippel 24368387c44SRoman Zippel void free_irq(unsigned int irq, void *dev_id) 2441da177e4SLinus Torvalds { 245b5dc7840SRoman Zippel struct irq_controller *contr; 246b5dc7840SRoman Zippel struct irq_node **p, *node; 247b5dc7840SRoman Zippel unsigned long flags; 248b5dc7840SRoman Zippel 24968387c44SRoman Zippel if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 2501da177e4SLinus Torvalds printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 2511da177e4SLinus Torvalds return; 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 254b5dc7840SRoman Zippel spin_lock_irqsave(&contr->lock, flags); 2551da177e4SLinus Torvalds 256b5dc7840SRoman Zippel p = irq_list + irq; 257b5dc7840SRoman Zippel while ((node = *p)) { 258b5dc7840SRoman Zippel if (node->dev_id == dev_id) 259b5dc7840SRoman Zippel break; 260b5dc7840SRoman Zippel p = &node->next; 2611da177e4SLinus Torvalds } 2621da177e4SLinus Torvalds 263b5dc7840SRoman Zippel if (node) { 264b5dc7840SRoman Zippel *p = node->next; 265b5dc7840SRoman Zippel node->handler = NULL; 266b5dc7840SRoman Zippel } else 267b5dc7840SRoman Zippel printk("%s: Removing probably wrong IRQ %d\n", 268b5dc7840SRoman Zippel __FUNCTION__, irq); 269b5dc7840SRoman Zippel 27068387c44SRoman Zippel if (!irq_list[irq]) { 27168387c44SRoman Zippel if (contr->shutdown) 272b5dc7840SRoman Zippel contr->shutdown(irq); 27368387c44SRoman Zippel else 27468387c44SRoman Zippel contr->disable(irq); 27568387c44SRoman Zippel } 276b5dc7840SRoman Zippel 277b5dc7840SRoman Zippel spin_unlock_irqrestore(&contr->lock, flags); 278b5dc7840SRoman Zippel } 279b5dc7840SRoman Zippel 28068387c44SRoman Zippel EXPORT_SYMBOL(free_irq); 28168387c44SRoman Zippel 28268387c44SRoman Zippel void enable_irq(unsigned int irq) 28368387c44SRoman Zippel { 28468387c44SRoman Zippel struct irq_controller *contr; 28568387c44SRoman Zippel unsigned long flags; 28668387c44SRoman Zippel 28768387c44SRoman Zippel if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 28868387c44SRoman Zippel printk("%s: Incorrect IRQ %d\n", 28968387c44SRoman Zippel __FUNCTION__, irq); 29068387c44SRoman Zippel return; 29168387c44SRoman Zippel } 29268387c44SRoman Zippel 29368387c44SRoman Zippel spin_lock_irqsave(&contr->lock, flags); 29468387c44SRoman Zippel if (irq_depth[irq]) { 29568387c44SRoman Zippel if (!--irq_depth[irq]) { 29668387c44SRoman Zippel if (contr->enable) 29768387c44SRoman Zippel contr->enable(irq); 29868387c44SRoman Zippel } 29968387c44SRoman Zippel } else 30068387c44SRoman Zippel WARN_ON(1); 30168387c44SRoman Zippel spin_unlock_irqrestore(&contr->lock, flags); 30268387c44SRoman Zippel } 30368387c44SRoman Zippel 30468387c44SRoman Zippel EXPORT_SYMBOL(enable_irq); 30568387c44SRoman Zippel 30668387c44SRoman Zippel void disable_irq(unsigned int irq) 30768387c44SRoman Zippel { 30868387c44SRoman Zippel struct irq_controller *contr; 30968387c44SRoman Zippel unsigned long flags; 31068387c44SRoman Zippel 31168387c44SRoman Zippel if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 31268387c44SRoman Zippel printk("%s: Incorrect IRQ %d\n", 31368387c44SRoman Zippel __FUNCTION__, irq); 31468387c44SRoman Zippel return; 31568387c44SRoman Zippel } 31668387c44SRoman Zippel 31768387c44SRoman Zippel spin_lock_irqsave(&contr->lock, flags); 31868387c44SRoman Zippel if (!irq_depth[irq]++) { 31968387c44SRoman Zippel if (contr->disable) 32068387c44SRoman Zippel contr->disable(irq); 32168387c44SRoman Zippel } 32268387c44SRoman Zippel spin_unlock_irqrestore(&contr->lock, flags); 32368387c44SRoman Zippel } 32468387c44SRoman Zippel 32568387c44SRoman Zippel EXPORT_SYMBOL(disable_irq); 32668387c44SRoman Zippel 327b5dc7840SRoman Zippel int m68k_irq_startup(unsigned int irq) 328b5dc7840SRoman Zippel { 329b5dc7840SRoman Zippel if (irq <= IRQ_AUTO_7) 330b5dc7840SRoman Zippel vectors[VEC_SPUR + irq] = auto_inthandler; 33168387c44SRoman Zippel else 33268387c44SRoman Zippel vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler; 333b5dc7840SRoman Zippel return 0; 334b5dc7840SRoman Zippel } 335b5dc7840SRoman Zippel 336b5dc7840SRoman Zippel void m68k_irq_shutdown(unsigned int irq) 337b5dc7840SRoman Zippel { 338b5dc7840SRoman Zippel if (irq <= IRQ_AUTO_7) 339b5dc7840SRoman Zippel vectors[VEC_SPUR + irq] = bad_inthandler; 34068387c44SRoman Zippel else 34168387c44SRoman Zippel vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; 342b5dc7840SRoman Zippel } 343b5dc7840SRoman Zippel 344b5dc7840SRoman Zippel 3451da177e4SLinus Torvalds /* 3461da177e4SLinus Torvalds * Do we need these probe functions on the m68k? 3471da177e4SLinus Torvalds * 3481da177e4SLinus Torvalds * ... may be useful with ISA devices 3491da177e4SLinus Torvalds */ 3501da177e4SLinus Torvalds unsigned long probe_irq_on (void) 3511da177e4SLinus Torvalds { 3521da177e4SLinus Torvalds #ifdef CONFIG_Q40 3531da177e4SLinus Torvalds if (MACH_IS_Q40) 3541da177e4SLinus Torvalds return q40_probe_irq_on(); 3551da177e4SLinus Torvalds #endif 3561da177e4SLinus Torvalds return 0; 3571da177e4SLinus Torvalds } 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds EXPORT_SYMBOL(probe_irq_on); 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds int probe_irq_off (unsigned long irqs) 3621da177e4SLinus Torvalds { 3631da177e4SLinus Torvalds #ifdef CONFIG_Q40 3641da177e4SLinus Torvalds if (MACH_IS_Q40) 3651da177e4SLinus Torvalds return q40_probe_irq_off(irqs); 3661da177e4SLinus Torvalds #endif 3671da177e4SLinus Torvalds return 0; 3681da177e4SLinus Torvalds } 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds EXPORT_SYMBOL(probe_irq_off); 3711da177e4SLinus Torvalds 37268387c44SRoman Zippel unsigned int irq_canonicalize(unsigned int irq) 3731da177e4SLinus Torvalds { 37468387c44SRoman Zippel #ifdef CONFIG_Q40 37568387c44SRoman Zippel if (MACH_IS_Q40 && irq == 11) 37668387c44SRoman Zippel irq = 10; 37768387c44SRoman Zippel #endif 37868387c44SRoman Zippel return irq; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds 38168387c44SRoman Zippel EXPORT_SYMBOL(irq_canonicalize); 3821da177e4SLinus Torvalds 383*2850bc27SAl Viro asmlinkage void m68k_handle_int(unsigned int irq) 3841da177e4SLinus Torvalds { 385b5dc7840SRoman Zippel struct irq_node *node; 38692445eaaSRoman Zippel kstat_cpu(0).irqs[irq]++; 387b5dc7840SRoman Zippel node = irq_list[irq]; 388b5dc7840SRoman Zippel do { 389*2850bc27SAl Viro node->handler(irq, node->dev_id); 390b5dc7840SRoman Zippel node = node->next; 391b5dc7840SRoman Zippel } while (node); 3921da177e4SLinus Torvalds } 39392445eaaSRoman Zippel 394*2850bc27SAl Viro asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs) 395*2850bc27SAl Viro { 396*2850bc27SAl Viro struct pt_regs *old_regs; 397*2850bc27SAl Viro old_regs = set_irq_regs(regs); 398*2850bc27SAl Viro m68k_handle_int(irq); 399*2850bc27SAl Viro set_irq_regs(old_regs); 400*2850bc27SAl Viro } 401*2850bc27SAl Viro 40292445eaaSRoman Zippel asmlinkage void handle_badint(struct pt_regs *regs) 40392445eaaSRoman Zippel { 40492445eaaSRoman Zippel kstat_cpu(0).irqs[0]++; 40592445eaaSRoman Zippel printk("unexpected interrupt from %u\n", regs->vector); 4061da177e4SLinus Torvalds } 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds int show_interrupts(struct seq_file *p, void *v) 4091da177e4SLinus Torvalds { 410b5dc7840SRoman Zippel struct irq_controller *contr; 411b5dc7840SRoman Zippel struct irq_node *node; 4121da177e4SLinus Torvalds int i = *(loff_t *) v; 4131da177e4SLinus Torvalds 4141da177e4SLinus Torvalds /* autovector interrupts */ 41568387c44SRoman Zippel if (irq_list[i]) { 416b5dc7840SRoman Zippel contr = irq_controller[i]; 417b5dc7840SRoman Zippel node = irq_list[i]; 41868387c44SRoman Zippel seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); 419b5dc7840SRoman Zippel while ((node = node->next)) 420b5dc7840SRoman Zippel seq_printf(p, ", %s", node->devname); 421b5dc7840SRoman Zippel seq_puts(p, "\n"); 42268387c44SRoman Zippel } 4231da177e4SLinus Torvalds return 0; 4241da177e4SLinus Torvalds } 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds void init_irq_proc(void) 4271da177e4SLinus Torvalds { 4281da177e4SLinus Torvalds /* Insert /proc/irq driver here */ 4291da177e4SLinus Torvalds } 4301da177e4SLinus Torvalds 431