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