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