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