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