FreeBSD/Linux Kernel Cross Reference
sys/x86/isa/atpic.c
1 /*-
2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 /*
28 * PIC driver for the 8259A Master and Slave PICs in PC/AT machines.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: releng/10.4/sys/x86/isa/atpic.c 262192 2014-02-18 20:27:17Z jhb $");
33
34 #include "opt_auto_eoi.h"
35 #include "opt_isa.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/bus.h>
40 #include <sys/interrupt.h>
41 #include <sys/kernel.h>
42 #include <sys/lock.h>
43 #include <sys/module.h>
44
45 #include <machine/cpufunc.h>
46 #include <machine/frame.h>
47 #include <machine/intr_machdep.h>
48 #include <machine/md_var.h>
49 #include <machine/resource.h>
50 #include <machine/segments.h>
51
52 #include <dev/ic/i8259.h>
53 #include <x86/isa/icu.h>
54 #ifdef PC98
55 #include <pc98/cbus/cbus.h>
56 #else
57 #include <x86/isa/isa.h>
58 #endif
59 #include <isa/isavar.h>
60
61 #ifdef __amd64__
62 #define SDT_ATPIC SDT_SYSIGT
63 #define GSEL_ATPIC 0
64 #else
65 #define SDT_ATPIC SDT_SYS386IGT
66 #define GSEL_ATPIC GSEL(GCODE_SEL, SEL_KPL)
67 #endif
68
69 #define MASTER 0
70 #define SLAVE 1
71
72 #define NUM_ISA_IRQS 16
73
74 static void atpic_init(void *dummy);
75
76 unsigned int imen; /* XXX */
77
78 inthand_t
79 IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2),
80 IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5),
81 IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8),
82 IDTVEC(atpic_intr9), IDTVEC(atpic_intr10), IDTVEC(atpic_intr11),
83 IDTVEC(atpic_intr12), IDTVEC(atpic_intr13), IDTVEC(atpic_intr14),
84 IDTVEC(atpic_intr15);
85
86 #define IRQ(ap, ai) ((ap)->at_irqbase + (ai)->at_irq)
87
88 #define ATPIC(io, base, eoi, imenptr) \
89 { { atpic_enable_source, atpic_disable_source, (eoi), \
90 atpic_enable_intr, atpic_disable_intr, atpic_vector, \
91 atpic_source_pending, NULL, atpic_resume, atpic_config_intr,\
92 atpic_assign_cpu }, (io), (base), IDT_IO_INTS + (base), \
93 (imenptr) }
94
95 #define INTSRC(irq) \
96 { { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ), \
97 (irq) % 8 }
98
99 struct atpic {
100 struct pic at_pic;
101 int at_ioaddr;
102 int at_irqbase;
103 uint8_t at_intbase;
104 uint8_t *at_imen;
105 };
106
107 struct atpic_intsrc {
108 struct intsrc at_intsrc;
109 inthand_t *at_intr;
110 int at_irq; /* Relative to PIC base. */
111 enum intr_trigger at_trigger;
112 u_long at_count;
113 u_long at_straycount;
114 };
115
116 static void atpic_enable_source(struct intsrc *isrc);
117 static void atpic_disable_source(struct intsrc *isrc, int eoi);
118 static void atpic_eoi_master(struct intsrc *isrc);
119 static void atpic_eoi_slave(struct intsrc *isrc);
120 static void atpic_enable_intr(struct intsrc *isrc);
121 static void atpic_disable_intr(struct intsrc *isrc);
122 static int atpic_vector(struct intsrc *isrc);
123 static void atpic_resume(struct pic *pic, bool suspend_cancelled);
124 static int atpic_source_pending(struct intsrc *isrc);
125 static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
126 enum intr_polarity pol);
127 static int atpic_assign_cpu(struct intsrc *isrc, u_int apic_id);
128 static void i8259_init(struct atpic *pic, int slave);
129
130 static struct atpic atpics[] = {
131 ATPIC(IO_ICU1, 0, atpic_eoi_master, (uint8_t *)&imen),
132 ATPIC(IO_ICU2, 8, atpic_eoi_slave, ((uint8_t *)&imen) + 1)
133 };
134
135 static struct atpic_intsrc atintrs[] = {
136 INTSRC(0),
137 INTSRC(1),
138 INTSRC(2),
139 INTSRC(3),
140 INTSRC(4),
141 INTSRC(5),
142 INTSRC(6),
143 INTSRC(7),
144 INTSRC(8),
145 INTSRC(9),
146 INTSRC(10),
147 INTSRC(11),
148 INTSRC(12),
149 INTSRC(13),
150 INTSRC(14),
151 INTSRC(15),
152 };
153
154 CTASSERT(sizeof(atintrs) / sizeof(atintrs[0]) == NUM_ISA_IRQS);
155
156 static __inline void
157 _atpic_eoi_master(struct intsrc *isrc)
158 {
159
160 KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
161 ("%s: mismatched pic", __func__));
162 #ifndef AUTO_EOI_1
163 outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
164 #endif
165 }
166
167 /*
168 * The data sheet says no auto-EOI on slave, but it sometimes works.
169 * So, if AUTO_EOI_2 is enabled, we use it.
170 */
171 static __inline void
172 _atpic_eoi_slave(struct intsrc *isrc)
173 {
174
175 KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
176 ("%s: mismatched pic", __func__));
177 #ifndef AUTO_EOI_2
178 outb(atpics[SLAVE].at_ioaddr, OCW2_EOI);
179 #ifndef AUTO_EOI_1
180 outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
181 #endif
182 #endif
183 }
184
185 static void
186 atpic_enable_source(struct intsrc *isrc)
187 {
188 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
189 struct atpic *ap = (struct atpic *)isrc->is_pic;
190
191 spinlock_enter();
192 if (*ap->at_imen & IMEN_MASK(ai)) {
193 *ap->at_imen &= ~IMEN_MASK(ai);
194 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
195 }
196 spinlock_exit();
197 }
198
199 static void
200 atpic_disable_source(struct intsrc *isrc, int eoi)
201 {
202 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
203 struct atpic *ap = (struct atpic *)isrc->is_pic;
204
205 spinlock_enter();
206 if (ai->at_trigger != INTR_TRIGGER_EDGE) {
207 *ap->at_imen |= IMEN_MASK(ai);
208 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
209 }
210
211 /*
212 * Take care to call these functions directly instead of through
213 * a function pointer. All of the referenced variables should
214 * still be hot in the cache.
215 */
216 if (eoi == PIC_EOI) {
217 if (isrc->is_pic == &atpics[MASTER].at_pic)
218 _atpic_eoi_master(isrc);
219 else
220 _atpic_eoi_slave(isrc);
221 }
222
223 spinlock_exit();
224 }
225
226 static void
227 atpic_eoi_master(struct intsrc *isrc)
228 {
229 #ifndef AUTO_EOI_1
230 spinlock_enter();
231 _atpic_eoi_master(isrc);
232 spinlock_exit();
233 #endif
234 }
235
236 static void
237 atpic_eoi_slave(struct intsrc *isrc)
238 {
239 #ifndef AUTO_EOI_2
240 spinlock_enter();
241 _atpic_eoi_slave(isrc);
242 spinlock_exit();
243 #endif
244 }
245
246 static void
247 atpic_enable_intr(struct intsrc *isrc)
248 {
249 }
250
251 static void
252 atpic_disable_intr(struct intsrc *isrc)
253 {
254 }
255
256
257 static int
258 atpic_vector(struct intsrc *isrc)
259 {
260 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
261 struct atpic *ap = (struct atpic *)isrc->is_pic;
262
263 return (IRQ(ap, ai));
264 }
265
266 static int
267 atpic_source_pending(struct intsrc *isrc)
268 {
269 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
270 struct atpic *ap = (struct atpic *)isrc->is_pic;
271
272 return (inb(ap->at_ioaddr) & IMEN_MASK(ai));
273 }
274
275 static void
276 atpic_resume(struct pic *pic, bool suspend_cancelled)
277 {
278 struct atpic *ap = (struct atpic *)pic;
279
280 i8259_init(ap, ap == &atpics[SLAVE]);
281 #ifndef PC98
282 if (ap == &atpics[SLAVE] && elcr_found)
283 elcr_resume();
284 #endif
285 }
286
287 static int
288 atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
289 enum intr_polarity pol)
290 {
291 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
292 u_int vector;
293
294 /* Map conforming values to edge/hi and sanity check the values. */
295 if (trig == INTR_TRIGGER_CONFORM)
296 trig = INTR_TRIGGER_EDGE;
297 if (pol == INTR_POLARITY_CONFORM)
298 pol = INTR_POLARITY_HIGH;
299 vector = atpic_vector(isrc);
300 if ((trig == INTR_TRIGGER_EDGE && pol == INTR_POLARITY_LOW) ||
301 (trig == INTR_TRIGGER_LEVEL && pol == INTR_POLARITY_HIGH)) {
302 printf(
303 "atpic: Mismatched config for IRQ%u: trigger %s, polarity %s\n",
304 vector, trig == INTR_TRIGGER_EDGE ? "edge" : "level",
305 pol == INTR_POLARITY_HIGH ? "high" : "low");
306 return (EINVAL);
307 }
308
309 /* If there is no change, just return. */
310 if (ai->at_trigger == trig)
311 return (0);
312
313 #ifdef PC98
314 if ((vector == 0 || vector == 1 || vector == 7 || vector == 8) &&
315 trig == INTR_TRIGGER_LEVEL) {
316 if (bootverbose)
317 printf(
318 "atpic: Ignoring invalid level/low configuration for IRQ%u\n",
319 vector);
320 return (EINVAL);
321 }
322 return (ENXIO);
323 #else
324 /*
325 * Certain IRQs can never be level/lo, so don't try to set them
326 * that way if asked. At least some ELCR registers ignore setting
327 * these bits as well.
328 */
329 if ((vector == 0 || vector == 1 || vector == 2 || vector == 13) &&
330 trig == INTR_TRIGGER_LEVEL) {
331 if (bootverbose)
332 printf(
333 "atpic: Ignoring invalid level/low configuration for IRQ%u\n",
334 vector);
335 return (EINVAL);
336 }
337 if (!elcr_found) {
338 if (bootverbose)
339 printf("atpic: No ELCR to configure IRQ%u as %s\n",
340 vector, trig == INTR_TRIGGER_EDGE ? "edge/high" :
341 "level/low");
342 return (ENXIO);
343 }
344 if (bootverbose)
345 printf("atpic: Programming IRQ%u as %s\n", vector,
346 trig == INTR_TRIGGER_EDGE ? "edge/high" : "level/low");
347 spinlock_enter();
348 elcr_write_trigger(atpic_vector(isrc), trig);
349 ai->at_trigger = trig;
350 spinlock_exit();
351 return (0);
352 #endif /* PC98 */
353 }
354
355 static int
356 atpic_assign_cpu(struct intsrc *isrc, u_int apic_id)
357 {
358
359 /*
360 * 8259A's are only used in UP in which case all interrupts always
361 * go to the sole CPU and this function shouldn't even be called.
362 */
363 panic("%s: bad cookie", __func__);
364 }
365
366 static void
367 i8259_init(struct atpic *pic, int slave)
368 {
369 int imr_addr;
370
371 /* Reset the PIC and program with next four bytes. */
372 spinlock_enter();
373 #ifdef DEV_MCA
374 /* MCA uses level triggered interrupts. */
375 if (MCA_system)
376 outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4 | ICW1_LTIM);
377 else
378 #endif
379 outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4);
380 imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET;
381
382 /* Start vector. */
383 outb(imr_addr, pic->at_intbase);
384
385 /*
386 * Setup slave links. For the master pic, indicate what line
387 * the slave is configured on. For the slave indicate
388 * which line on the master we are connected to.
389 */
390 if (slave)
391 outb(imr_addr, ICU_SLAVEID);
392 else
393 outb(imr_addr, IRQ_MASK(ICU_SLAVEID));
394
395 /* Set mode. */
396 if (slave)
397 outb(imr_addr, SLAVE_MODE);
398 else
399 outb(imr_addr, MASTER_MODE);
400
401 /* Set interrupt enable mask. */
402 outb(imr_addr, *pic->at_imen);
403
404 /* Reset is finished, default to IRR on read. */
405 outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR);
406
407 #ifndef PC98
408 /* OCW2_L1 sets priority order to 3-7, 0-2 (com2 first). */
409 if (!slave)
410 outb(pic->at_ioaddr, OCW2_R | OCW2_SL | OCW2_L1);
411 #endif
412 spinlock_exit();
413 }
414
415 void
416 atpic_startup(void)
417 {
418 struct atpic_intsrc *ai;
419 int i;
420
421 /* Start off with all interrupts disabled. */
422 imen = 0xffff;
423 i8259_init(&atpics[MASTER], 0);
424 i8259_init(&atpics[SLAVE], 1);
425 atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
426
427 /* Install low-level interrupt handlers for all of our IRQs. */
428 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
429 if (i == ICU_SLAVEID)
430 continue;
431 ai->at_intsrc.is_count = &ai->at_count;
432 ai->at_intsrc.is_straycount = &ai->at_straycount;
433 setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
434 ai->at_irq, ai->at_intr, SDT_ATPIC, SEL_KPL, GSEL_ATPIC);
435 }
436
437 #ifdef DEV_MCA
438 /* For MCA systems, all interrupts are level triggered. */
439 if (MCA_system)
440 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
441 ai->at_trigger = INTR_TRIGGER_LEVEL;
442 else
443 #endif
444
445 #ifdef PC98
446 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
447 switch (i) {
448 case 0:
449 case 1:
450 case 7:
451 case 8:
452 ai->at_trigger = INTR_TRIGGER_EDGE;
453 break;
454 default:
455 ai->at_trigger = INTR_TRIGGER_LEVEL;
456 break;
457 }
458 #else
459 /*
460 * Look for an ELCR. If we find one, update the trigger modes.
461 * If we don't find one, assume that IRQs 0, 1, 2, and 13 are
462 * edge triggered and that everything else is level triggered.
463 * We only use the trigger information to reprogram the ELCR if
464 * we have one and as an optimization to avoid masking edge
465 * triggered interrupts. For the case that we don't have an ELCR,
466 * it doesn't hurt to mask an edge triggered interrupt, so we
467 * assume level trigger for any interrupt that we aren't sure is
468 * edge triggered.
469 */
470 if (elcr_found) {
471 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
472 ai->at_trigger = elcr_read_trigger(i);
473 } else {
474 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
475 switch (i) {
476 case 0:
477 case 1:
478 case 2:
479 case 8:
480 case 13:
481 ai->at_trigger = INTR_TRIGGER_EDGE;
482 break;
483 default:
484 ai->at_trigger = INTR_TRIGGER_LEVEL;
485 break;
486 }
487 }
488 #endif /* PC98 */
489 }
490
491 static void
492 atpic_init(void *dummy __unused)
493 {
494 struct atpic_intsrc *ai;
495 int i;
496
497 /*
498 * Register our PICs, even if we aren't going to use any of their
499 * pins so that they are suspended and resumed.
500 */
501 if (intr_register_pic(&atpics[0].at_pic) != 0 ||
502 intr_register_pic(&atpics[1].at_pic) != 0)
503 panic("Unable to register ATPICs");
504
505 /*
506 * If any of the ISA IRQs have an interrupt source already, then
507 * assume that the APICs are being used and don't register any
508 * of our interrupt sources. This makes sure we don't accidentally
509 * use mixed mode. The "accidental" use could otherwise occur on
510 * machines that route the ACPI SCI interrupt to a different ISA
511 * IRQ (at least one machines routes it to IRQ 13) thus disabling
512 * that APIC ISA routing and allowing the ATPIC source for that IRQ
513 * to leak through. We used to depend on this feature for routing
514 * IRQ0 via mixed mode, but now we don't use mixed mode at all.
515 */
516 for (i = 0; i < NUM_ISA_IRQS; i++)
517 if (intr_lookup_source(i) != NULL)
518 return;
519
520 /* Loop through all interrupt sources and add them. */
521 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
522 if (i == ICU_SLAVEID)
523 continue;
524 intr_register_source(&ai->at_intsrc);
525 }
526 }
527 SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL);
528
529 void
530 atpic_handle_intr(u_int vector, struct trapframe *frame)
531 {
532 struct intsrc *isrc;
533
534 KASSERT(vector < NUM_ISA_IRQS, ("unknown int %u\n", vector));
535 isrc = &atintrs[vector].at_intsrc;
536
537 /*
538 * If we don't have an event, see if this is a spurious
539 * interrupt.
540 */
541 if (isrc->is_event == NULL && (vector == 7 || vector == 15)) {
542 int port, isr;
543
544 /*
545 * Read the ISR register to see if IRQ 7/15 is really
546 * pending. Reset read register back to IRR when done.
547 */
548 port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
549 spinlock_enter();
550 outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
551 isr = inb(port);
552 outb(port, OCW3_SEL | OCW3_RR);
553 spinlock_exit();
554 if ((isr & IRQ_MASK(7)) == 0)
555 return;
556 }
557 intr_execute_handlers(isrc, frame);
558 }
559
560 #ifdef DEV_ISA
561 /*
562 * Bus attachment for the ISA PIC.
563 */
564 static struct isa_pnp_id atpic_ids[] = {
565 { 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
566 { 0 }
567 };
568
569 static int
570 atpic_probe(device_t dev)
571 {
572 int result;
573
574 result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
575 if (result <= 0)
576 device_quiet(dev);
577 return (result);
578 }
579
580 /*
581 * We might be granted IRQ 2, as this is typically consumed by chaining
582 * between the two PIC components. If we're using the APIC, however,
583 * this may not be the case, and as such we should free the resource.
584 * (XXX untested)
585 *
586 * The generic ISA attachment code will handle allocating any other resources
587 * that we don't explicitly claim here.
588 */
589 static int
590 atpic_attach(device_t dev)
591 {
592 struct resource *res;
593 int rid;
594
595 /* Try to allocate our IRQ and then free it. */
596 rid = 0;
597 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0);
598 if (res != NULL)
599 bus_release_resource(dev, SYS_RES_IRQ, rid, res);
600 return (0);
601 }
602
603 static device_method_t atpic_methods[] = {
604 /* Device interface */
605 DEVMETHOD(device_probe, atpic_probe),
606 DEVMETHOD(device_attach, atpic_attach),
607 DEVMETHOD(device_detach, bus_generic_detach),
608 DEVMETHOD(device_shutdown, bus_generic_shutdown),
609 DEVMETHOD(device_suspend, bus_generic_suspend),
610 DEVMETHOD(device_resume, bus_generic_resume),
611 { 0, 0 }
612 };
613
614 static driver_t atpic_driver = {
615 "atpic",
616 atpic_methods,
617 1, /* no softc */
618 };
619
620 static devclass_t atpic_devclass;
621
622 DRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0);
623 #ifndef PC98
624 DRIVER_MODULE(atpic, acpi, atpic_driver, atpic_devclass, 0, 0);
625 #endif
626
627 /*
628 * Return a bitmap of the current interrupt requests. This is 8259-specific
629 * and is only suitable for use at probe time.
630 */
631 intrmask_t
632 isa_irq_pending(void)
633 {
634 u_char irr1;
635 u_char irr2;
636
637 irr1 = inb(IO_ICU1);
638 irr2 = inb(IO_ICU2);
639 return ((irr2 << 8) | irr1);
640 }
641 #endif /* DEV_ISA */
Cache object: 5d02e138ec2ca001429438fad8fd291e
|