X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fi386%2Fkernel%2Fi8259.c;h=dec7ebf49a48f61501b229651e4c71da80b377b2;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=0be8d6b87cf799285efe76d5845978bdcf41b8f7;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 0be8d6b87..dec7ebf49 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -12,10 +11,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -225,7 +226,7 @@ spurious_8259A_irq: * lets ACK and report it. [once per IRQ] */ if (!(spurious_irq_mask & irqmask)) { - printk("spurious 8259A interrupt: IRQ%d.\n", irq); + printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } atomic_inc(&irq_err_count); @@ -238,14 +239,39 @@ spurious_8259A_irq: } } +static char irq_trigger[2]; +/** + * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ + */ +static void restore_ELCR(char *trigger) +{ + outb(trigger[0], 0x4d0); + outb(trigger[1], 0x4d1); +} + +static void save_ELCR(char *trigger) +{ + /* IRQ 0,1,2,8,13 are marked as reserved */ + trigger[0] = inb(0x4d0) & 0xF8; + trigger[1] = inb(0x4d1) & 0xDE; +} + static int i8259A_resume(struct sys_device *dev) { init_8259A(0); + restore_ELCR(irq_trigger); + return 0; +} + +static int i8259A_suspend(struct sys_device *dev, u32 state) +{ + save_ELCR(irq_trigger); return 0; } static struct sysdev_class i8259_sysdev_class = { set_kset_name("i8259"), + .suspend = i8259A_suspend, .resume = i8259A_resume, }; @@ -317,19 +343,14 @@ void init_8259A(int auto_eoi) * be shot. */ -/* - * =PC9800NOTE= In NEC PC-9800, we use irq8 instead of irq13! - */ static irqreturn_t math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) { - extern void math_error(void *); -#ifndef CONFIG_X86_PC9800 + extern void math_error(void __user *); outb(0,0xF0); -#endif if (ignore_fpu_irq || !boot_cpu_data.hard_math) return IRQ_NONE; - math_error((void *)regs->eip); + math_error((void __user *)regs->eip); return IRQ_HANDLED; } @@ -337,7 +358,7 @@ static irqreturn_t math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) * New motherboards sometimes make IRQ 13 be a PCI interrupt, * so allow interrupt sharing. */ -static struct irqaction fpu_irq = { math_error_irq, 0, 0, "fpu", NULL, NULL }; +static struct irqaction fpu_irq = { math_error_irq, 0, CPU_MASK_NONE, "fpu", NULL, NULL }; void __init init_ISA_irqs (void) { @@ -350,7 +371,7 @@ void __init init_ISA_irqs (void) for (i = 0; i < NR_IRQS; i++) { irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; + irq_desc[i].action = NULL; irq_desc[i].depth = 1; if (i < 16) { @@ -367,46 +388,6 @@ void __init init_ISA_irqs (void) } } -static void setup_timer(void) -{ - extern spinlock_t i8253_lock; - unsigned long flags; - - spin_lock_irqsave(&i8253_lock, flags); - outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ - udelay(10); - outb_p(LATCH & 0xff , PIT_CH0); /* LSB */ - udelay(10); - outb(LATCH >> 8 , PIT_CH0); /* MSB */ - spin_unlock_irqrestore(&i8253_lock, flags); -} - -static int timer_resume(struct sys_device *dev) -{ - setup_timer(); - return 0; -} - -static struct sysdev_class timer_sysclass = { - set_kset_name("timer"), - .resume = timer_resume, -}; - -static struct sys_device device_timer = { - .id = 0, - .cls = &timer_sysclass, -}; - -static int __init init_timer_sysfs(void) -{ - int error = sysdev_class_register(&timer_sysclass); - if (!error) - error = sysdev_register(&device_timer); - return error; -} - -device_initcall(init_timer_sysfs); - void __init init_IRQ(void) { int i; @@ -436,7 +417,7 @@ void __init init_IRQ(void) * Set the clock to HZ Hz, we already have a valid * vector now: */ - setup_timer(); + setup_pit_timer(); /* * External FPU? Set up irq13 if so, for