1 // SPDX-License-Identifier: GPL-2.0 1 2 #include <linux/linkage.h> 3 #include <linux/errno.h> 4 #include <linux/signal.h> 5 #include <linux/sched.h> 6 #include <linux/ioport.h> 7 #include <linux/interrupt.h> 8 #include <linux/irq.h> 9 #include <linux/timex.h> 10 #include <linux/random.h> 11 #include <linux/init.h> 12 #include <linux/kernel_stat.h> 13 #include <linux/syscore_ops.h> 14 #include <linux/bitops.h> 15 #include <linux/acpi.h> 16 #include <linux/io.h> 17 #include <linux/delay.h> 18 #include <linux/pgtable.h> 19 20 #include <linux/atomic.h> 21 #include <asm/timer.h> 22 #include <asm/hw_irq.h> 23 #include <asm/desc.h> 24 #include <asm/apic.h> 25 #include <asm/i8259.h> 26 27 /* 28 * This is the 'legacy' 8259A Programmable Int 29 * present in the majority of PC/AT boxes. 30 * plus some generic x86 specific things if ge 31 * any sense at all. 32 */ 33 static void init_8259A(int auto_eoi); 34 35 static bool pcat_compat __ro_after_init; 36 static int i8259A_auto_eoi; 37 DEFINE_RAW_SPINLOCK(i8259A_lock); 38 39 /* 40 * 8259A PIC functions to handle ISA devices: 41 */ 42 43 /* 44 * This contains the irq mask for both 8259A i 45 */ 46 unsigned int cached_irq_mask = 0xffff; 47 48 /* 49 * Not all IRQs can be routed through the IO-A 50 * boards the timer interrupt is not really co 51 * it's fed to the master 8259A's IR0 line onl 52 * 53 * Any '1' bit in this mask means the IRQ is r 54 * this 'mixed mode' IRQ handling costs nothin 55 * at IRQ setup time. 56 */ 57 unsigned long io_apic_irqs; 58 59 static void mask_8259A_irq(unsigned int irq) 60 { 61 unsigned int mask = 1 << irq; 62 unsigned long flags; 63 64 raw_spin_lock_irqsave(&i8259A_lock, fl 65 cached_irq_mask |= mask; 66 if (irq & 8) 67 outb(cached_slave_mask, PIC_SL 68 else 69 outb(cached_master_mask, PIC_M 70 raw_spin_unlock_irqrestore(&i8259A_loc 71 } 72 73 static void disable_8259A_irq(struct irq_data 74 { 75 mask_8259A_irq(data->irq); 76 } 77 78 static void unmask_8259A_irq(unsigned int irq) 79 { 80 unsigned int mask = ~(1 << irq); 81 unsigned long flags; 82 83 raw_spin_lock_irqsave(&i8259A_lock, fl 84 cached_irq_mask &= mask; 85 if (irq & 8) 86 outb(cached_slave_mask, PIC_SL 87 else 88 outb(cached_master_mask, PIC_M 89 raw_spin_unlock_irqrestore(&i8259A_loc 90 } 91 92 static void enable_8259A_irq(struct irq_data * 93 { 94 unmask_8259A_irq(data->irq); 95 } 96 97 static int i8259A_irq_pending(unsigned int irq 98 { 99 unsigned int mask = 1<<irq; 100 unsigned long flags; 101 int ret; 102 103 raw_spin_lock_irqsave(&i8259A_lock, fl 104 if (irq < 8) 105 ret = inb(PIC_MASTER_CMD) & ma 106 else 107 ret = inb(PIC_SLAVE_CMD) & (ma 108 raw_spin_unlock_irqrestore(&i8259A_loc 109 110 return ret; 111 } 112 113 static void make_8259A_irq(unsigned int irq) 114 { 115 disable_irq_nosync(irq); 116 io_apic_irqs &= ~(1<<irq); 117 irq_set_chip_and_handler(irq, &i8259A_ 118 irq_set_status_flags(irq, IRQ_LEVEL); 119 enable_irq(irq); 120 lapic_assign_legacy_vector(irq, true); 121 } 122 123 /* 124 * This function assumes to be called rarely. 125 * 8259A registers is slow. 126 * This has to be protected by the irq control 127 * before being called. 128 */ 129 static inline int i8259A_irq_real(unsigned int 130 { 131 int value; 132 int irqmask = 1<<irq; 133 134 if (irq < 8) { 135 outb(0x0B, PIC_MASTER_CMD); 136 value = inb(PIC_MASTER_CMD) & 137 outb(0x0A, PIC_MASTER_CMD); 138 return value; 139 } 140 outb(0x0B, PIC_SLAVE_CMD); /* ISR 141 value = inb(PIC_SLAVE_CMD) & (irqmask 142 outb(0x0A, PIC_SLAVE_CMD); /* bac 143 return value; 144 } 145 146 /* 147 * Careful! The 8259A is a fragile beast, it p 148 * much _has_ to be done exactly like this (ma 149 * first, _then_ send the EOI, and the order o 150 * to the two 8259s is important! 151 */ 152 static void mask_and_ack_8259A(struct irq_data 153 { 154 unsigned int irq = data->irq; 155 unsigned int irqmask = 1 << irq; 156 unsigned long flags; 157 158 raw_spin_lock_irqsave(&i8259A_lock, fl 159 /* 160 * Lightweight spurious IRQ detection. 161 * to overdo spurious IRQ handling - i 162 * of hardware problems, so we only do 163 * do without slowing down good hardwa 164 * 165 * Note that IRQ7 and IRQ15 (the two s 166 * usually resulting from the 8259A-1| 167 * even if the IRQ is masked in the 82 168 * can check spurious 8259A IRQs witho 169 * quite slow i8259A_irq_real() call f 170 * This does not cover 100% of spuriou 171 * but should be enough to warn the us 172 * is something bad going on ... 173 */ 174 if (cached_irq_mask & irqmask) 175 goto spurious_8259A_irq; 176 cached_irq_mask |= irqmask; 177 178 handle_real_irq: 179 if (irq & 8) { 180 inb(PIC_SLAVE_IMR); /* DUM 181 outb(cached_slave_mask, PIC_SL 182 /* 'Specific EOI' to slave */ 183 outb(0x60+(irq&7), PIC_SLAVE_C 184 /* 'Specific EOI' to master-I 185 outb(0x60+PIC_CASCADE_IR, PIC_ 186 } else { 187 inb(PIC_MASTER_IMR); /* DUM 188 outb(cached_master_mask, PIC_M 189 outb(0x60+irq, PIC_MASTER_CMD) 190 } 191 raw_spin_unlock_irqrestore(&i8259A_loc 192 return; 193 194 spurious_8259A_irq: 195 /* 196 * this is the slow path - should happ 197 */ 198 if (i8259A_irq_real(irq)) 199 /* 200 * oops, the IRQ _is_ in servi 201 * 8259A - not spurious, go ha 202 */ 203 goto handle_real_irq; 204 205 { 206 static int spurious_irq_mask; 207 /* 208 * At this point we can be sur 209 * lets ACK and report it. [on 210 */ 211 if (!(spurious_irq_mask & irqm 212 printk_deferred(KERN_D 213 "spurious 8259A 214 spurious_irq_mask |= i 215 } 216 atomic_inc(&irq_err_count); 217 /* 218 * Theoretically we do not hav 219 * but in Linux this does not 220 * simpler for us. 221 */ 222 goto handle_real_irq; 223 } 224 } 225 226 struct irq_chip i8259A_chip = { 227 .name = "XT-PIC", 228 .irq_mask = disable_8259A_irq, 229 .irq_disable = disable_8259A_irq, 230 .irq_unmask = enable_8259A_irq, 231 .irq_mask_ack = mask_and_ack_8259A, 232 }; 233 234 static char irq_trigger[2]; 235 /* ELCR registers (0x4d0, 0x4d1) control edge/ 236 static void restore_ELCR(char *trigger) 237 { 238 outb(trigger[0], PIC_ELCR1); 239 outb(trigger[1], PIC_ELCR2); 240 } 241 242 static void save_ELCR(char *trigger) 243 { 244 /* IRQ 0,1,2,8,13 are marked as reserv 245 trigger[0] = inb(PIC_ELCR1) & 0xF8; 246 trigger[1] = inb(PIC_ELCR2) & 0xDE; 247 } 248 249 static void i8259A_resume(void) 250 { 251 init_8259A(i8259A_auto_eoi); 252 restore_ELCR(irq_trigger); 253 } 254 255 static int i8259A_suspend(void) 256 { 257 save_ELCR(irq_trigger); 258 return 0; 259 } 260 261 static void i8259A_shutdown(void) 262 { 263 /* Put the i8259A into a quiescent sta 264 * the kernel initialization code can 265 * out of. 266 */ 267 outb(0xff, PIC_MASTER_IMR); /* mas 268 outb(0xff, PIC_SLAVE_IMR); /* mas 269 } 270 271 static struct syscore_ops i8259_syscore_ops = 272 .suspend = i8259A_suspend, 273 .resume = i8259A_resume, 274 .shutdown = i8259A_shutdown, 275 }; 276 277 static void mask_8259A(void) 278 { 279 unsigned long flags; 280 281 raw_spin_lock_irqsave(&i8259A_lock, fl 282 283 outb(0xff, PIC_MASTER_IMR); /* mas 284 outb(0xff, PIC_SLAVE_IMR); /* mas 285 286 raw_spin_unlock_irqrestore(&i8259A_loc 287 } 288 289 static void unmask_8259A(void) 290 { 291 unsigned long flags; 292 293 raw_spin_lock_irqsave(&i8259A_lock, fl 294 295 outb(cached_master_mask, PIC_MASTER_IM 296 outb(cached_slave_mask, PIC_SLAVE_IMR) 297 298 raw_spin_unlock_irqrestore(&i8259A_loc 299 } 300 301 static int probe_8259A(void) 302 { 303 unsigned char new_val, probe_val = ~(1 304 unsigned long flags; 305 306 /* 307 * If MADT has the PCAT_COMPAT flag se 308 * for the PIC. Some BIOSes leave the 309 * fails. 310 * 311 * Right now this causes problems as q 312 * nr_legacy_irqs() > 0 or has_legacy_ 313 * when the system has an IO/APIC beca 314 * at all, except for really old machi 315 * must be routed through the PIC. So 316 * there and let legacy_pic->init() in 317 * 318 * Alternatively this could just try t 319 * repeat the probe, but for cases whe 320 * just pointless. 321 */ 322 if (pcat_compat) 323 return nr_legacy_irqs(); 324 325 /* 326 * Check to see if we have a PIC. Mas 327 * read back the value we just wrote. 328 * will read 0xff as opposed to the va 329 */ 330 raw_spin_lock_irqsave(&i8259A_lock, fl 331 332 outb(0xff, PIC_SLAVE_IMR); /* mas 333 outb(probe_val, PIC_MASTER_IMR); 334 new_val = inb(PIC_MASTER_IMR); 335 if (new_val != probe_val) { 336 printk(KERN_INFO "Using NULL l 337 legacy_pic = &null_legacy_pic; 338 } 339 340 raw_spin_unlock_irqrestore(&i8259A_loc 341 return nr_legacy_irqs(); 342 } 343 344 static void init_8259A(int auto_eoi) 345 { 346 unsigned long flags; 347 348 i8259A_auto_eoi = auto_eoi; 349 350 raw_spin_lock_irqsave(&i8259A_lock, fl 351 352 outb(0xff, PIC_MASTER_IMR); /* mas 353 354 /* 355 * outb_pic - this has to work on a wi 356 */ 357 outb_pic(0x11, PIC_MASTER_CMD); /* ICW 358 359 /* ICW2: 8259A-1 IR0-7 mapped to ISA_I 360 outb_pic(ISA_IRQ_VECTOR(0), PIC_MASTER 361 362 /* 8259A-1 (the master) has a slave on 363 outb_pic(1U << PIC_CASCADE_IR, PIC_MAS 364 365 if (auto_eoi) /* master does Auto EO 366 outb_pic(MASTER_ICW4_DEFAULT | 367 else /* master expects norm 368 outb_pic(MASTER_ICW4_DEFAULT, 369 370 outb_pic(0x11, PIC_SLAVE_CMD); /* ICW 371 372 /* ICW2: 8259A-2 IR0-7 mapped to ISA_I 373 outb_pic(ISA_IRQ_VECTOR(8), PIC_SLAVE_ 374 /* 8259A-2 is a slave on master's IR2 375 outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR 376 /* (slave's support for AEOI in flat m 377 outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE 378 379 if (auto_eoi) 380 /* 381 * In AEOI mode we just have t 382 * when acking. 383 */ 384 i8259A_chip.irq_mask_ack = dis 385 else 386 i8259A_chip.irq_mask_ack = mas 387 388 udelay(100); /* wait for 82 389 390 outb(cached_master_mask, PIC_MASTER_IM 391 outb(cached_slave_mask, PIC_SLAVE_IMR) 392 393 raw_spin_unlock_irqrestore(&i8259A_loc 394 } 395 396 /* 397 * make i8259 a driver so that we can select p 398 * is to make x86 binary compatible among pc c 399 * platforms, such as x86 MID. 400 */ 401 402 static void legacy_pic_noop(void) { }; 403 static void legacy_pic_uint_noop(unsigned int 404 static void legacy_pic_int_noop(int unused) { 405 static int legacy_pic_irq_pending_noop(unsigne 406 { 407 return 0; 408 } 409 static int legacy_pic_probe(void) 410 { 411 return 0; 412 } 413 414 struct legacy_pic null_legacy_pic = { 415 .nr_legacy_irqs = 0, 416 .chip = &dummy_irq_chip, 417 .mask = legacy_pic_uint_noop, 418 .unmask = legacy_pic_uint_noop, 419 .mask_all = legacy_pic_noop, 420 .restore_mask = legacy_pic_noop, 421 .init = legacy_pic_int_noop, 422 .probe = legacy_pic_probe, 423 .irq_pending = legacy_pic_irq_pending_ 424 .make_irq = legacy_pic_uint_noop, 425 }; 426 427 static struct legacy_pic default_legacy_pic = 428 .nr_legacy_irqs = NR_IRQS_LEGACY, 429 .chip = &i8259A_chip, 430 .mask = mask_8259A_irq, 431 .unmask = unmask_8259A_irq, 432 .mask_all = mask_8259A, 433 .restore_mask = unmask_8259A, 434 .init = init_8259A, 435 .probe = probe_8259A, 436 .irq_pending = i8259A_irq_pending, 437 .make_irq = make_8259A_irq, 438 }; 439 440 struct legacy_pic *legacy_pic = &default_legac 441 EXPORT_SYMBOL(legacy_pic); 442 443 static int __init i8259A_init_ops(void) 444 { 445 if (legacy_pic == &default_legacy_pic) 446 register_syscore_ops(&i8259_sy 447 448 return 0; 449 } 450 device_initcall(i8259A_init_ops); 451 452 void __init legacy_pic_pcat_compat(void) 453 { 454 pcat_compat = true; 455 } 456
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.