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