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