0001
0002 #include <linux/linkage.h>
0003 #include <linux/errno.h>
0004 #include <linux/signal.h>
0005 #include <linux/sched.h>
0006 #include <linux/ioport.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/irq.h>
0009 #include <linux/timex.h>
0010 #include <linux/random.h>
0011 #include <linux/init.h>
0012 #include <linux/kernel_stat.h>
0013 #include <linux/syscore_ops.h>
0014 #include <linux/bitops.h>
0015 #include <linux/acpi.h>
0016 #include <linux/io.h>
0017 #include <linux/delay.h>
0018 #include <linux/pgtable.h>
0019
0020 #include <linux/atomic.h>
0021 #include <asm/timer.h>
0022 #include <asm/hw_irq.h>
0023 #include <asm/desc.h>
0024 #include <asm/apic.h>
0025 #include <asm/i8259.h>
0026
0027
0028
0029
0030
0031
0032
0033 static void init_8259A(int auto_eoi);
0034
0035 static int i8259A_auto_eoi;
0036 DEFINE_RAW_SPINLOCK(i8259A_lock);
0037
0038
0039
0040
0041
0042
0043
0044
0045 unsigned int cached_irq_mask = 0xffff;
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 unsigned long io_apic_irqs;
0057
0058 static void mask_8259A_irq(unsigned int irq)
0059 {
0060 unsigned int mask = 1 << irq;
0061 unsigned long flags;
0062
0063 raw_spin_lock_irqsave(&i8259A_lock, flags);
0064 cached_irq_mask |= mask;
0065 if (irq & 8)
0066 outb(cached_slave_mask, PIC_SLAVE_IMR);
0067 else
0068 outb(cached_master_mask, PIC_MASTER_IMR);
0069 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0070 }
0071
0072 static void disable_8259A_irq(struct irq_data *data)
0073 {
0074 mask_8259A_irq(data->irq);
0075 }
0076
0077 static void unmask_8259A_irq(unsigned int irq)
0078 {
0079 unsigned int mask = ~(1 << irq);
0080 unsigned long flags;
0081
0082 raw_spin_lock_irqsave(&i8259A_lock, flags);
0083 cached_irq_mask &= mask;
0084 if (irq & 8)
0085 outb(cached_slave_mask, PIC_SLAVE_IMR);
0086 else
0087 outb(cached_master_mask, PIC_MASTER_IMR);
0088 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0089 }
0090
0091 static void enable_8259A_irq(struct irq_data *data)
0092 {
0093 unmask_8259A_irq(data->irq);
0094 }
0095
0096 static int i8259A_irq_pending(unsigned int irq)
0097 {
0098 unsigned int mask = 1<<irq;
0099 unsigned long flags;
0100 int ret;
0101
0102 raw_spin_lock_irqsave(&i8259A_lock, flags);
0103 if (irq < 8)
0104 ret = inb(PIC_MASTER_CMD) & mask;
0105 else
0106 ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
0107 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0108
0109 return ret;
0110 }
0111
0112 static void make_8259A_irq(unsigned int irq)
0113 {
0114 disable_irq_nosync(irq);
0115 io_apic_irqs &= ~(1<<irq);
0116 irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
0117 enable_irq(irq);
0118 lapic_assign_legacy_vector(irq, true);
0119 }
0120
0121
0122
0123
0124
0125
0126
0127 static inline int i8259A_irq_real(unsigned int irq)
0128 {
0129 int value;
0130 int irqmask = 1<<irq;
0131
0132 if (irq < 8) {
0133 outb(0x0B, PIC_MASTER_CMD);
0134 value = inb(PIC_MASTER_CMD) & irqmask;
0135 outb(0x0A, PIC_MASTER_CMD);
0136 return value;
0137 }
0138 outb(0x0B, PIC_SLAVE_CMD);
0139 value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
0140 outb(0x0A, PIC_SLAVE_CMD);
0141 return value;
0142 }
0143
0144
0145
0146
0147
0148
0149
0150 static void mask_and_ack_8259A(struct irq_data *data)
0151 {
0152 unsigned int irq = data->irq;
0153 unsigned int irqmask = 1 << irq;
0154 unsigned long flags;
0155
0156 raw_spin_lock_irqsave(&i8259A_lock, flags);
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 if (cached_irq_mask & irqmask)
0173 goto spurious_8259A_irq;
0174 cached_irq_mask |= irqmask;
0175
0176 handle_real_irq:
0177 if (irq & 8) {
0178 inb(PIC_SLAVE_IMR);
0179 outb(cached_slave_mask, PIC_SLAVE_IMR);
0180
0181 outb(0x60+(irq&7), PIC_SLAVE_CMD);
0182
0183 outb(0x60+PIC_CASCADE_IR, PIC_MASTER_CMD);
0184 } else {
0185 inb(PIC_MASTER_IMR);
0186 outb(cached_master_mask, PIC_MASTER_IMR);
0187 outb(0x60+irq, PIC_MASTER_CMD);
0188 }
0189 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0190 return;
0191
0192 spurious_8259A_irq:
0193
0194
0195
0196 if (i8259A_irq_real(irq))
0197
0198
0199
0200
0201 goto handle_real_irq;
0202
0203 {
0204 static int spurious_irq_mask;
0205
0206
0207
0208
0209 if (!(spurious_irq_mask & irqmask)) {
0210 printk_deferred(KERN_DEBUG
0211 "spurious 8259A interrupt: IRQ%d.\n", irq);
0212 spurious_irq_mask |= irqmask;
0213 }
0214 atomic_inc(&irq_err_count);
0215
0216
0217
0218
0219
0220 goto handle_real_irq;
0221 }
0222 }
0223
0224 struct irq_chip i8259A_chip = {
0225 .name = "XT-PIC",
0226 .irq_mask = disable_8259A_irq,
0227 .irq_disable = disable_8259A_irq,
0228 .irq_unmask = enable_8259A_irq,
0229 .irq_mask_ack = mask_and_ack_8259A,
0230 };
0231
0232 static char irq_trigger[2];
0233
0234
0235
0236 static void restore_ELCR(char *trigger)
0237 {
0238 outb(trigger[0], PIC_ELCR1);
0239 outb(trigger[1], PIC_ELCR2);
0240 }
0241
0242 static void save_ELCR(char *trigger)
0243 {
0244
0245 trigger[0] = inb(PIC_ELCR1) & 0xF8;
0246 trigger[1] = inb(PIC_ELCR2) & 0xDE;
0247 }
0248
0249 static void i8259A_resume(void)
0250 {
0251 init_8259A(i8259A_auto_eoi);
0252 restore_ELCR(irq_trigger);
0253 }
0254
0255 static int i8259A_suspend(void)
0256 {
0257 save_ELCR(irq_trigger);
0258 return 0;
0259 }
0260
0261 static void i8259A_shutdown(void)
0262 {
0263
0264
0265
0266
0267 outb(0xff, PIC_MASTER_IMR);
0268 outb(0xff, PIC_SLAVE_IMR);
0269 }
0270
0271 static struct syscore_ops i8259_syscore_ops = {
0272 .suspend = i8259A_suspend,
0273 .resume = i8259A_resume,
0274 .shutdown = i8259A_shutdown,
0275 };
0276
0277 static void mask_8259A(void)
0278 {
0279 unsigned long flags;
0280
0281 raw_spin_lock_irqsave(&i8259A_lock, flags);
0282
0283 outb(0xff, PIC_MASTER_IMR);
0284 outb(0xff, PIC_SLAVE_IMR);
0285
0286 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0287 }
0288
0289 static void unmask_8259A(void)
0290 {
0291 unsigned long flags;
0292
0293 raw_spin_lock_irqsave(&i8259A_lock, flags);
0294
0295 outb(cached_master_mask, PIC_MASTER_IMR);
0296 outb(cached_slave_mask, PIC_SLAVE_IMR);
0297
0298 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0299 }
0300
0301 static int probe_8259A(void)
0302 {
0303 unsigned long flags;
0304 unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
0305 unsigned char new_val;
0306
0307
0308
0309
0310
0311
0312
0313 raw_spin_lock_irqsave(&i8259A_lock, flags);
0314
0315 outb(0xff, PIC_SLAVE_IMR);
0316 outb(probe_val, PIC_MASTER_IMR);
0317 new_val = inb(PIC_MASTER_IMR);
0318 if (new_val != probe_val) {
0319 printk(KERN_INFO "Using NULL legacy PIC\n");
0320 legacy_pic = &null_legacy_pic;
0321 }
0322
0323 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0324 return nr_legacy_irqs();
0325 }
0326
0327 static void init_8259A(int auto_eoi)
0328 {
0329 unsigned long flags;
0330
0331 i8259A_auto_eoi = auto_eoi;
0332
0333 raw_spin_lock_irqsave(&i8259A_lock, flags);
0334
0335 outb(0xff, PIC_MASTER_IMR);
0336
0337
0338
0339
0340 outb_pic(0x11, PIC_MASTER_CMD);
0341
0342
0343 outb_pic(ISA_IRQ_VECTOR(0), PIC_MASTER_IMR);
0344
0345
0346 outb_pic(1U << PIC_CASCADE_IR, PIC_MASTER_IMR);
0347
0348 if (auto_eoi)
0349 outb_pic(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
0350 else
0351 outb_pic(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
0352
0353 outb_pic(0x11, PIC_SLAVE_CMD);
0354
0355
0356 outb_pic(ISA_IRQ_VECTOR(8), PIC_SLAVE_IMR);
0357
0358 outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR);
0359
0360 outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR);
0361
0362 if (auto_eoi)
0363
0364
0365
0366
0367 i8259A_chip.irq_mask_ack = disable_8259A_irq;
0368 else
0369 i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
0370
0371 udelay(100);
0372
0373 outb(cached_master_mask, PIC_MASTER_IMR);
0374 outb(cached_slave_mask, PIC_SLAVE_IMR);
0375
0376 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0377 }
0378
0379
0380
0381
0382
0383
0384
0385 static void legacy_pic_noop(void) { };
0386 static void legacy_pic_uint_noop(unsigned int unused) { };
0387 static void legacy_pic_int_noop(int unused) { };
0388 static int legacy_pic_irq_pending_noop(unsigned int irq)
0389 {
0390 return 0;
0391 }
0392 static int legacy_pic_probe(void)
0393 {
0394 return 0;
0395 }
0396
0397 struct legacy_pic null_legacy_pic = {
0398 .nr_legacy_irqs = 0,
0399 .chip = &dummy_irq_chip,
0400 .mask = legacy_pic_uint_noop,
0401 .unmask = legacy_pic_uint_noop,
0402 .mask_all = legacy_pic_noop,
0403 .restore_mask = legacy_pic_noop,
0404 .init = legacy_pic_int_noop,
0405 .probe = legacy_pic_probe,
0406 .irq_pending = legacy_pic_irq_pending_noop,
0407 .make_irq = legacy_pic_uint_noop,
0408 };
0409
0410 struct legacy_pic default_legacy_pic = {
0411 .nr_legacy_irqs = NR_IRQS_LEGACY,
0412 .chip = &i8259A_chip,
0413 .mask = mask_8259A_irq,
0414 .unmask = unmask_8259A_irq,
0415 .mask_all = mask_8259A,
0416 .restore_mask = unmask_8259A,
0417 .init = init_8259A,
0418 .probe = probe_8259A,
0419 .irq_pending = i8259A_irq_pending,
0420 .make_irq = make_8259A_irq,
0421 };
0422
0423 struct legacy_pic *legacy_pic = &default_legacy_pic;
0424 EXPORT_SYMBOL(legacy_pic);
0425
0426 static int __init i8259A_init_ops(void)
0427 {
0428 if (legacy_pic == &default_legacy_pic)
0429 register_syscore_ops(&i8259_syscore_ops);
0430
0431 return 0;
0432 }
0433
0434 device_initcall(i8259A_init_ops);