2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
31 * PIC driver for the 8259A Master and Slave PICs in PC/AT machines.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include "opt_auto_eoi.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
43 #include <sys/interrupt.h>
44 #include <sys/kernel.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
49 #include <machine/cpufunc.h>
50 #include <machine/frame.h>
51 #include <machine/intr_machdep.h>
52 #include <machine/md_var.h>
53 #include <machine/resource.h>
54 #include <machine/segments.h>
56 #include <dev/ic/i8259.h>
57 #include <i386/isa/icu.h>
59 #include <pc98/cbus/cbus.h>
61 #include <i386/isa/isa.h>
63 #include <isa/isavar.h>
69 * PC-98 machines wire the slave 8259A to pin 7 on the master PIC, and
70 * PC-AT machines wire the slave PIC to pin 2 on the master PIC.
79 * Determine the base master and slave modes not including auto EOI support.
80 * All machines that FreeBSD supports use 8086 mode.
84 * PC-98 machines do not support auto EOI on the second PIC. Also, it
85 * seems that PC-98 machine PICs use buffered mode, and the master PIC
86 * uses special fully nested mode.
88 #define BASE_MASTER_MODE (ICW4_SFNM | ICW4_BUF | ICW4_MS | ICW4_8086)
89 #define BASE_SLAVE_MODE (ICW4_BUF | ICW4_8086)
91 #define BASE_MASTER_MODE ICW4_8086
92 #define BASE_SLAVE_MODE ICW4_8086
95 /* Enable automatic EOI if requested. */
97 #define MASTER_MODE (BASE_MASTER_MODE | ICW4_AEOI)
99 #define MASTER_MODE BASE_MASTER_MODE
102 #define SLAVE_MODE (BASE_SLAVE_MODE | ICW4_AEOI)
104 #define SLAVE_MODE BASE_SLAVE_MODE
107 #define IRQ_MASK(irq) (1 << (irq))
108 #define IMEN_MASK(ai) (IRQ_MASK((ai)->at_irq))
110 #define NUM_ISA_IRQS 16
112 static void atpic_init(void *dummy);
114 unsigned int imen; /* XXX */
117 IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2),
118 IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5),
119 IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8),
120 IDTVEC(atpic_intr9), IDTVEC(atpic_intr10), IDTVEC(atpic_intr11),
121 IDTVEC(atpic_intr12), IDTVEC(atpic_intr13), IDTVEC(atpic_intr14),
122 IDTVEC(atpic_intr15);
124 #define IRQ(ap, ai) ((ap)->at_irqbase + (ai)->at_irq)
126 #define ATPIC(io, base, eoi, imenptr) \
127 { { atpic_enable_source, atpic_disable_source, (eoi), \
128 atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \
129 atpic_resume, atpic_config_intr }, (io), (base), \
130 IDT_IO_INTS + (base), (imenptr) }
132 #define INTSRC(irq) \
133 { { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ), \
144 struct atpic_intsrc {
145 struct intsrc at_intsrc;
147 int at_irq; /* Relative to PIC base. */
148 enum intr_trigger at_trigger;
150 u_long at_straycount;
153 static void atpic_enable_source(struct intsrc *isrc);
154 static void atpic_disable_source(struct intsrc *isrc, int eoi);
155 static void atpic_eoi_master(struct intsrc *isrc);
156 static void atpic_eoi_slave(struct intsrc *isrc);
157 static void atpic_enable_intr(struct intsrc *isrc);
158 static int atpic_vector(struct intsrc *isrc);
159 static void atpic_resume(struct intsrc *isrc);
160 static int atpic_source_pending(struct intsrc *isrc);
161 static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
162 enum intr_polarity pol);
163 static void i8259_init(struct atpic *pic, int slave);
165 static struct atpic atpics[] = {
166 ATPIC(IO_ICU1, 0, atpic_eoi_master, (uint8_t *)&imen),
167 ATPIC(IO_ICU2, 8, atpic_eoi_slave, ((uint8_t *)&imen) + 1)
170 static struct atpic_intsrc atintrs[] = {
189 CTASSERT(sizeof(atintrs) / sizeof(atintrs[0]) == NUM_ISA_IRQS);
192 _atpic_eoi_master(struct intsrc *isrc)
195 KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
196 ("%s: mismatched pic", __func__));
198 outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
203 * The data sheet says no auto-EOI on slave, but it sometimes works.
204 * So, if AUTO_EOI_2 is enabled, we use it.
207 _atpic_eoi_slave(struct intsrc *isrc)
210 KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
211 ("%s: mismatched pic", __func__));
213 outb(atpics[SLAVE].at_ioaddr, OCW2_EOI);
215 outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
221 atpic_enable_source(struct intsrc *isrc)
223 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
224 struct atpic *ap = (struct atpic *)isrc->is_pic;
226 mtx_lock_spin(&icu_lock);
227 if (*ap->at_imen & IMEN_MASK(ai)) {
228 *ap->at_imen &= ~IMEN_MASK(ai);
229 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
231 mtx_unlock_spin(&icu_lock);
235 atpic_disable_source(struct intsrc *isrc, int eoi)
237 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
238 struct atpic *ap = (struct atpic *)isrc->is_pic;
240 mtx_lock_spin(&icu_lock);
241 if (ai->at_trigger != INTR_TRIGGER_EDGE) {
242 *ap->at_imen |= IMEN_MASK(ai);
243 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
247 * Take care to call these functions directly instead of through
248 * a function pointer. All of the referenced variables should
249 * still be hot in the cache.
251 if (eoi == PIC_EOI) {
252 if (isrc->is_pic == &atpics[MASTER].at_pic)
253 _atpic_eoi_master(isrc);
255 _atpic_eoi_slave(isrc);
258 mtx_unlock_spin(&icu_lock);
262 atpic_eoi_master(struct intsrc *isrc)
265 mtx_lock_spin(&icu_lock);
266 _atpic_eoi_master(isrc);
267 mtx_unlock_spin(&icu_lock);
272 atpic_eoi_slave(struct intsrc *isrc)
275 mtx_lock_spin(&icu_lock);
276 _atpic_eoi_slave(isrc);
277 mtx_unlock_spin(&icu_lock);
282 atpic_enable_intr(struct intsrc *isrc)
287 atpic_vector(struct intsrc *isrc)
289 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
290 struct atpic *ap = (struct atpic *)isrc->is_pic;
292 return (IRQ(ap, ai));
296 atpic_source_pending(struct intsrc *isrc)
298 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
299 struct atpic *ap = (struct atpic *)isrc->is_pic;
301 return (inb(ap->at_ioaddr) & IMEN_MASK(ai));
305 atpic_resume(struct intsrc *isrc)
307 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
308 struct atpic *ap = (struct atpic *)isrc->is_pic;
310 if (ai->at_irq == 0) {
311 i8259_init(ap, ap == &atpics[SLAVE]);
313 if (ap == &atpics[SLAVE] && elcr_found)
320 atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
321 enum intr_polarity pol)
323 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
326 /* Map conforming values to edge/hi and sanity check the values. */
327 if (trig == INTR_TRIGGER_CONFORM)
328 trig = INTR_TRIGGER_EDGE;
329 if (pol == INTR_POLARITY_CONFORM)
330 pol = INTR_POLARITY_HIGH;
331 vector = atpic_vector(isrc);
332 if ((trig == INTR_TRIGGER_EDGE && pol == INTR_POLARITY_LOW) ||
333 (trig == INTR_TRIGGER_LEVEL && pol == INTR_POLARITY_HIGH)) {
335 "atpic: Mismatched config for IRQ%u: trigger %s, polarity %s\n",
336 vector, trig == INTR_TRIGGER_EDGE ? "edge" : "level",
337 pol == INTR_POLARITY_HIGH ? "high" : "low");
341 /* If there is no change, just return. */
342 if (ai->at_trigger == trig)
346 if ((vector == 0 || vector == 1 || vector == 7 || vector == 8) &&
347 trig == INTR_TRIGGER_LEVEL) {
350 "atpic: Ignoring invalid level/low configuration for IRQ%u\n",
357 * Certain IRQs can never be level/lo, so don't try to set them
358 * that way if asked. At least some ELCR registers ignore setting
359 * these bits as well.
361 if ((vector == 0 || vector == 1 || vector == 2 || vector == 13) &&
362 trig == INTR_TRIGGER_LEVEL) {
365 "atpic: Ignoring invalid level/low configuration for IRQ%u\n",
371 printf("atpic: No ELCR to configure IRQ%u as %s\n",
372 vector, trig == INTR_TRIGGER_EDGE ? "edge/high" :
377 printf("atpic: Programming IRQ%u as %s\n", vector,
378 trig == INTR_TRIGGER_EDGE ? "edge/high" : "level/low");
379 mtx_lock_spin(&icu_lock);
380 elcr_write_trigger(atpic_vector(isrc), trig);
381 ai->at_trigger = trig;
382 mtx_unlock_spin(&icu_lock);
388 i8259_init(struct atpic *pic, int slave)
392 /* Reset the PIC and program with next four bytes. */
393 mtx_lock_spin(&icu_lock);
395 /* MCA uses level triggered interrupts. */
397 outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4 | ICW1_LTIM);
400 outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4);
401 imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET;
404 outb(imr_addr, pic->at_intbase);
407 * Setup slave links. For the master pic, indicate what line
408 * the slave is configured on. For the slave indicate
409 * which line on the master we are connected to.
412 outb(imr_addr, ICU_SLAVEID);
414 outb(imr_addr, IRQ_MASK(ICU_SLAVEID));
418 outb(imr_addr, SLAVE_MODE);
420 outb(imr_addr, MASTER_MODE);
422 /* Set interrupt enable mask. */
423 outb(imr_addr, *pic->at_imen);
425 /* Reset is finished, default to IRR on read. */
426 outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR);
429 /* OCW2_L1 sets priority order to 3-7, 0-2 (com2 first). */
431 outb(pic->at_ioaddr, OCW2_R | OCW2_SL | OCW2_L1);
433 mtx_unlock_spin(&icu_lock);
439 struct atpic_intsrc *ai;
442 /* Start off with all interrupts disabled. */
444 i8259_init(&atpics[MASTER], 0);
445 i8259_init(&atpics[SLAVE], 1);
446 atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
448 /* Install low-level interrupt handlers for all of our IRQs. */
449 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
450 if (i == ICU_SLAVEID)
452 ai->at_intsrc.is_count = &ai->at_count;
453 ai->at_intsrc.is_straycount = &ai->at_straycount;
454 setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
455 ai->at_irq, ai->at_intr, SDT_SYS386IGT, SEL_KPL,
456 GSEL(GCODE_SEL, SEL_KPL));
460 /* For MCA systems, all interrupts are level triggered. */
462 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
463 ai->at_trigger = INTR_TRIGGER_LEVEL;
468 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
474 ai->at_trigger = INTR_TRIGGER_EDGE;
477 ai->at_trigger = INTR_TRIGGER_LEVEL;
482 * Look for an ELCR. If we find one, update the trigger modes.
483 * If we don't find one, assume that IRQs 0, 1, 2, and 13 are
484 * edge triggered and that everything else is level triggered.
485 * We only use the trigger information to reprogram the ELCR if
486 * we have one and as an optimization to avoid masking edge
487 * triggered interrupts. For the case that we don't have an ELCR,
488 * it doesn't hurt to mask an edge triggered interrupt, so we
489 * assume level trigger for any interrupt that we aren't sure is
493 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
494 ai->at_trigger = elcr_read_trigger(i);
496 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
503 ai->at_trigger = INTR_TRIGGER_EDGE;
506 ai->at_trigger = INTR_TRIGGER_LEVEL;
514 atpic_init(void *dummy __unused)
516 struct atpic_intsrc *ai;
520 * If any of the ISA IRQs have an interrupt source already, then
521 * assume that the APICs are being used and don't register any
522 * of our interrupt sources. This makes sure we don't accidentally
523 * use mixed mode. The "accidental" use could otherwise occur on
524 * machines that route the ACPI SCI interrupt to a different ISA
525 * IRQ (at least one machines routes it to IRQ 13) thus disabling
526 * that APIC ISA routing and allowing the ATPIC source for that IRQ
527 * to leak through. We used to depend on this feature for routing
528 * IRQ0 via mixed mode, but now we don't use mixed mode at all.
530 for (i = 0; i < NUM_ISA_IRQS; i++)
531 if (intr_lookup_source(i) != NULL)
534 /* Loop through all interrupt sources and add them. */
535 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
536 if (i == ICU_SLAVEID)
538 intr_register_source(&ai->at_intsrc);
541 SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL)
544 atpic_handle_intr(u_int vector, struct trapframe frame)
548 KASSERT(vector < NUM_ISA_IRQS, ("unknown int %u\n", vector));
549 isrc = &atintrs[vector].at_intsrc;
552 * If we don't have an event, see if this is a spurious
555 if (isrc->is_event == NULL && (vector == 7 || vector == 15)) {
559 * Read the ISR register to see if IRQ 7/15 is really
560 * pending. Reset read register back to IRR when done.
562 port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
563 mtx_lock_spin(&icu_lock);
564 outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
566 outb(port, OCW3_SEL | OCW3_RR);
567 mtx_unlock_spin(&icu_lock);
568 if ((isr & IRQ_MASK(7)) == 0)
571 intr_execute_handlers(isrc, &frame);
576 * Bus attachment for the ISA PIC.
578 static struct isa_pnp_id atpic_ids[] = {
579 { 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
584 atpic_probe(device_t dev)
588 result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
595 * We might be granted IRQ 2, as this is typically consumed by chaining
596 * between the two PIC components. If we're using the APIC, however,
597 * this may not be the case, and as such we should free the resource.
600 * The generic ISA attachment code will handle allocating any other resources
601 * that we don't explicitly claim here.
604 atpic_attach(device_t dev)
606 struct resource *res;
609 /* Try to allocate our IRQ and then free it. */
611 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0);
613 bus_release_resource(dev, SYS_RES_IRQ, rid, res);
617 static device_method_t atpic_methods[] = {
618 /* Device interface */
619 DEVMETHOD(device_probe, atpic_probe),
620 DEVMETHOD(device_attach, atpic_attach),
621 DEVMETHOD(device_detach, bus_generic_detach),
622 DEVMETHOD(device_shutdown, bus_generic_shutdown),
623 DEVMETHOD(device_suspend, bus_generic_suspend),
624 DEVMETHOD(device_resume, bus_generic_resume),
628 static driver_t atpic_driver = {
634 static devclass_t atpic_devclass;
636 DRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0);
638 DRIVER_MODULE(atpic, acpi, atpic_driver, atpic_devclass, 0, 0);
642 * Return a bitmap of the current interrupt requests. This is 8259-specific
643 * and is only suitable for use at probe time.
646 isa_irq_pending(void)
653 return ((irr2 << 8) | irr1);