linux/arch/x86/kernel/i8259.c
<<
>>
Prefs
   1#include <linux/linkage.h>
   2#include <linux/errno.h>
   3#include <linux/signal.h>
   4#include <linux/sched.h>
   5#include <linux/ioport.h>
   6#include <linux/interrupt.h>
   7#include <linux/timex.h>
   8#include <linux/slab.h>
   9#include <linux/random.h>
  10#include <linux/init.h>
  11#include <linux/kernel_stat.h>
  12#include <linux/sysdev.h>
  13#include <linux/bitops.h>
  14
  15#include <asm/acpi.h>
  16#include <asm/atomic.h>
  17#include <asm/system.h>
  18#include <asm/io.h>
  19#include <asm/timer.h>
  20#include <asm/hw_irq.h>
  21#include <asm/pgtable.h>
  22#include <asm/delay.h>
  23#include <asm/desc.h>
  24#include <asm/apic.h>
  25#include <asm/arch_hooks.h>
  26#include <asm/i8259.h>
  27
  28/*
  29 * This is the 'legacy' 8259A Programmable Interrupt Controller,
  30 * present in the majority of PC/AT boxes.
  31 * plus some generic x86 specific things if generic specifics makes
  32 * any sense at all.
  33 */
  34
  35static int i8259A_auto_eoi;
  36DEFINE_SPINLOCK(i8259A_lock);
  37static void mask_and_ack_8259A(unsigned int);
  38
  39struct irq_chip i8259A_chip = {
  40        .name           = "XT-PIC",
  41        .mask           = disable_8259A_irq,
  42        .disable        = disable_8259A_irq,
  43        .unmask         = enable_8259A_irq,
  44        .mask_ack       = mask_and_ack_8259A,
  45};
  46
  47/*
  48 * 8259A PIC functions to handle ISA devices:
  49 */
  50
  51/*
  52 * This contains the irq mask for both 8259A irq controllers,
  53 */
  54unsigned int cached_irq_mask = 0xffff;
  55
  56/*
  57 * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
  58 * boards the timer interrupt is not really connected to any IO-APIC pin,
  59 * it's fed to the master 8259A's IR0 line only.
  60 *
  61 * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
  62 * this 'mixed mode' IRQ handling costs nothing because it's only used
  63 * at IRQ setup time.
  64 */
  65unsigned long io_apic_irqs;
  66
  67void disable_8259A_irq(unsigned int irq)
  68{
  69        unsigned int mask = 1 << irq;
  70        unsigned long flags;
  71
  72        spin_lock_irqsave(&i8259A_lock, flags);
  73        cached_irq_mask |= mask;
  74        if (irq & 8)
  75                outb(cached_slave_mask, PIC_SLAVE_IMR);
  76        else
  77                outb(cached_master_mask, PIC_MASTER_IMR);
  78        spin_unlock_irqrestore(&i8259A_lock, flags);
  79}
  80
  81void enable_8259A_irq(unsigned int irq)
  82{
  83        unsigned int mask = ~(1 << irq);
  84        unsigned long flags;
  85
  86        spin_lock_irqsave(&i8259A_lock, flags);
  87        cached_irq_mask &= mask;
  88        if (irq & 8)
  89                outb(cached_slave_mask, PIC_SLAVE_IMR);
  90        else
  91                outb(cached_master_mask, PIC_MASTER_IMR);
  92        spin_unlock_irqrestore(&i8259A_lock, flags);
  93}
  94
  95int i8259A_irq_pending(unsigned int irq)
  96{
  97        unsigned int mask = 1<<irq;
  98        unsigned long flags;
  99        int ret;
 100
 101        spin_lock_irqsave(&i8259A_lock, flags);
 102        if (irq < 8)
 103                ret = inb(PIC_MASTER_CMD) & mask;
 104        else
 105                ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
 106        spin_unlock_irqrestore(&i8259A_lock, flags);
 107
 108        return ret;
 109}
 110
 111void make_8259A_irq(unsigned int irq)
 112{
 113        disable_irq_nosync(irq);
 114        io_apic_irqs &= ~(1<<irq);
 115        set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
 116                                      "XT");
 117        enable_irq(irq);
 118}
 119
 120/*
 121 * This function assumes to be called rarely. Switching between
 122 * 8259A registers is slow.
 123 * This has to be protected by the irq controller spinlock
 124 * before being called.
 125 */
 126static inline int i8259A_irq_real(unsigned int irq)
 127{
 128        int value;
 129        int irqmask = 1<<irq;
 130
 131        if (irq < 8) {
 132                outb(0x0B, PIC_MASTER_CMD);     /* ISR register */
 133                value = inb(PIC_MASTER_CMD) & irqmask;
 134                outb(0x0A, PIC_MASTER_CMD);     /* back to the IRR register */
 135                return value;
 136        }
 137        outb(0x0B, PIC_SLAVE_CMD);      /* ISR register */
 138        value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
 139        outb(0x0A, PIC_SLAVE_CMD);      /* back to the IRR register */
 140        return value;
 141}
 142
 143/*
 144 * Careful! The 8259A is a fragile beast, it pretty
 145 * much _has_ to be done exactly like this (mask it
 146 * first, _then_ send the EOI, and the order of EOI
 147 * to the two 8259s is important!
 148 */
 149static void mask_and_ack_8259A(unsigned int irq)
 150{
 151        unsigned int irqmask = 1 << irq;
 152        unsigned long flags;
 153
 154        spin_lock_irqsave(&i8259A_lock, flags);
 155        /*
 156         * Lightweight spurious IRQ detection. We do not want
 157         * to overdo spurious IRQ handling - it's usually a sign
 158         * of hardware problems, so we only do the checks we can
 159         * do without slowing down good hardware unnecessarily.
 160         *
 161         * Note that IRQ7 and IRQ15 (the two spurious IRQs
 162         * usually resulting from the 8259A-1|2 PICs) occur
 163         * even if the IRQ is masked in the 8259A. Thus we
 164         * can check spurious 8259A IRQs without doing the
 165         * quite slow i8259A_irq_real() call for every IRQ.
 166         * This does not cover 100% of spurious interrupts,
 167         * but should be enough to warn the user that there
 168         * is something bad going on ...
 169         */
 170        if (cached_irq_mask & irqmask)
 171                goto spurious_8259A_irq;
 172        cached_irq_mask |= irqmask;
 173
 174handle_real_irq:
 175        if (irq & 8) {
 176                inb(PIC_SLAVE_IMR);     /* DUMMY - (do we need this?) */
 177                outb(cached_slave_mask, PIC_SLAVE_IMR);
 178                /* 'Specific EOI' to slave */
 179                outb(0x60+(irq&7), PIC_SLAVE_CMD);
 180                 /* 'Specific EOI' to master-IRQ2 */
 181                outb(0x60+PIC_CASCADE_IR, PIC_MASTER_CMD);
 182        } else {
 183                inb(PIC_MASTER_IMR);    /* DUMMY - (do we need this?) */
 184                outb(cached_master_mask, PIC_MASTER_IMR);
 185                outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */
 186        }
 187        spin_unlock_irqrestore(&i8259A_lock, flags);
 188        return;
 189
 190spurious_8259A_irq:
 191        /*
 192         * this is the slow path - should happen rarely.
 193         */
 194        if (i8259A_irq_real(irq))
 195                /*
 196                 * oops, the IRQ _is_ in service according to the
 197                 * 8259A - not spurious, go handle it.
 198                 */
 199                goto handle_real_irq;
 200
 201        {
 202                static int spurious_irq_mask;
 203                /*
 204                 * At this point we can be sure the IRQ is spurious,
 205                 * lets ACK and report it. [once per IRQ]
 206                 */
 207                if (!(spurious_irq_mask & irqmask)) {
 208                        printk(KERN_DEBUG
 209                               "spurious 8259A interrupt: IRQ%d.\n", irq);
 210                        spurious_irq_mask |= irqmask;
 211                }
 212                atomic_inc(&irq_err_count);
 213                /*
 214                 * Theoretically we do not have to handle this IRQ,
 215                 * but in Linux this does not cause problems and is
 216                 * simpler for us.
 217                 */
 218                goto handle_real_irq;
 219        }
 220}
 221
 222static char irq_trigger[2];
 223/**
 224 * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
 225 */
 226static void restore_ELCR(char *trigger)
 227{
 228        outb(trigger[0], 0x4d0);
 229        outb(trigger[1], 0x4d1);
 230}
 231
 232static void save_ELCR(char *trigger)
 233{
 234        /* IRQ 0,1,2,8,13 are marked as reserved */
 235        trigger[0] = inb(0x4d0) & 0xF8;
 236        trigger[1] = inb(0x4d1) & 0xDE;
 237}
 238
 239static int i8259A_resume(struct sys_device *dev)
 240{
 241        init_8259A(i8259A_auto_eoi);
 242        restore_ELCR(irq_trigger);
 243        return 0;
 244}
 245
 246static int i8259A_suspend(struct sys_device *dev, pm_message_t state)
 247{
 248        save_ELCR(irq_trigger);
 249        return 0;
 250}
 251
 252static int i8259A_shutdown(struct sys_device *dev)
 253{
 254        /* Put the i8259A into a quiescent state that
 255         * the kernel initialization code can get it
 256         * out of.
 257         */
 258        outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
 259        outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-1 */
 260        return 0;
 261}
 262
 263static struct sysdev_class i8259_sysdev_class = {
 264        .name = "i8259",
 265        .suspend = i8259A_suspend,
 266        .resume = i8259A_resume,
 267        .shutdown = i8259A_shutdown,
 268};
 269
 270static struct sys_device device_i8259A = {
 271        .id     = 0,
 272        .cls    = &i8259_sysdev_class,
 273};
 274
 275static int __init i8259A_init_sysfs(void)
 276{
 277        int error = sysdev_class_register(&i8259_sysdev_class);
 278        if (!error)
 279                error = sysdev_register(&device_i8259A);
 280        return error;
 281}
 282
 283device_initcall(i8259A_init_sysfs);
 284
 285void mask_8259A(void)
 286{
 287        unsigned long flags;
 288
 289        spin_lock_irqsave(&i8259A_lock, flags);
 290
 291        outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
 292        outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-2 */
 293
 294        spin_unlock_irqrestore(&i8259A_lock, flags);
 295}
 296
 297void unmask_8259A(void)
 298{
 299        unsigned long flags;
 300
 301        spin_lock_irqsave(&i8259A_lock, flags);
 302
 303        outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
 304        outb(cached_slave_mask, PIC_SLAVE_IMR);   /* restore slave IRQ mask */
 305
 306        spin_unlock_irqrestore(&i8259A_lock, flags);
 307}
 308
 309void init_8259A(int auto_eoi)
 310{
 311        unsigned long flags;
 312
 313        i8259A_auto_eoi = auto_eoi;
 314
 315        spin_lock_irqsave(&i8259A_lock, flags);
 316
 317        outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
 318        outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-2 */
 319
 320        /*
 321         * outb_pic - this has to work on a wide range of PC hardware.
 322         */
 323        outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
 324
 325        /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64,
 326                               to 0x20-0x27 on i386 */
 327        outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);
 328
 329        /* 8259A-1 (the master) has a slave on IR2 */
 330        outb_pic(1U << PIC_CASCADE_IR, PIC_MASTER_IMR);
 331
 332        if (auto_eoi)   /* master does Auto EOI */
 333                outb_pic(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
 334        else            /* master expects normal EOI */
 335                outb_pic(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
 336
 337        outb_pic(0x11, PIC_SLAVE_CMD);  /* ICW1: select 8259A-2 init */
 338
 339        /* ICW2: 8259A-2 IR0-7 mapped to IRQ8_VECTOR */
 340        outb_pic(IRQ8_VECTOR, PIC_SLAVE_IMR);
 341        /* 8259A-2 is a slave on master's IR2 */
 342        outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR);
 343        /* (slave's support for AEOI in flat mode is to be investigated) */
 344        outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR);
 345
 346        if (auto_eoi)
 347                /*
 348                 * In AEOI mode we just have to mask the interrupt
 349                 * when acking.
 350                 */
 351                i8259A_chip.mask_ack = disable_8259A_irq;
 352        else
 353                i8259A_chip.mask_ack = mask_and_ack_8259A;
 354
 355        udelay(100);            /* wait for 8259A to initialize */
 356
 357        outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
 358        outb(cached_slave_mask, PIC_SLAVE_IMR);   /* restore slave IRQ mask */
 359
 360        spin_unlock_irqrestore(&i8259A_lock, flags);
 361}
 362
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.