atpic.c revision 255726
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: head/sys/x86/isa/atpic.c 255726 2013-09-20 05:06:03Z gibbs $");
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
77static void	atpic_init(void *dummy);
78
79unsigned int imen;	/* XXX */
80
81inthand_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
102struct 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
110struct 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
119static void atpic_enable_source(struct intsrc *isrc);
120static void atpic_disable_source(struct intsrc *isrc, int eoi);
121static void atpic_eoi_master(struct intsrc *isrc);
122static void atpic_eoi_slave(struct intsrc *isrc);
123static void atpic_enable_intr(struct intsrc *isrc);
124static void atpic_disable_intr(struct intsrc *isrc);
125static int atpic_vector(struct intsrc *isrc);
126static void atpic_resume(struct pic *pic, bool suspend_cancelled);
127static int atpic_source_pending(struct intsrc *isrc);
128static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
129    enum intr_polarity pol);
130static int atpic_assign_cpu(struct intsrc *isrc, u_int apic_id);
131static void i8259_init(struct atpic *pic, int slave);
132
133static 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
138static 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
157CTASSERT(sizeof(atintrs) / sizeof(atintrs[0]) == NUM_ISA_IRQS);
158
159static __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 */
174static __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
188static void
189atpic_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
202static void
203atpic_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
229static void
230atpic_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
239static void
240atpic_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
249static void
250atpic_enable_intr(struct intsrc *isrc)
251{
252}
253
254static void
255atpic_disable_intr(struct intsrc *isrc)
256{
257}
258
259
260static int
261atpic_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
269static int
270atpic_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
278static void
279atpic_resume(struct pic *pic, bool suspend_cancelled)
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
290static int
291atpic_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
358static int
359atpic_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
369static void
370i8259_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
418void
419atpic_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
494static void
495atpic_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}
530SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL);
531
532void
533atpic_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 */
567static struct isa_pnp_id atpic_ids[] = {
568	{ 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
569	{ 0 }
570};
571
572static int
573atpic_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 */
592static int
593atpic_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
606static 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
617static driver_t atpic_driver = {
618	"atpic",
619	atpic_methods,
620	1,		/* no softc */
621};
622
623static devclass_t atpic_devclass;
624
625DRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0);
626#ifndef PC98
627DRIVER_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 */
634intrmask_t
635isa_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 */
645