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