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