atpic.c revision 127135
1121985Sjhb/*-
2121985Sjhb * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3121985Sjhb * All rights reserved.
4121985Sjhb *
5121985Sjhb * Redistribution and use in source and binary forms, with or without
6121985Sjhb * modification, are permitted provided that the following conditions
7121985Sjhb * are met:
8121985Sjhb * 1. Redistributions of source code must retain the above copyright
9121985Sjhb *    notice, this list of conditions and the following disclaimer.
10121985Sjhb * 2. Redistributions in binary form must reproduce the above copyright
11121985Sjhb *    notice, this list of conditions and the following disclaimer in the
12121985Sjhb *    documentation and/or other materials provided with the distribution.
13121985Sjhb * 3. Neither the name of the author nor the names of any co-contributors
14121985Sjhb *    may be used to endorse or promote products derived from this software
15121985Sjhb *    without specific prior written permission.
16121985Sjhb *
17121985Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18121985Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19121985Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20121985Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21121985Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22121985Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23121985Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24121985Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25121985Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26121985Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27121985Sjhb * SUCH DAMAGE.
28121985Sjhb */
29121985Sjhb
30121985Sjhb/*
31121985Sjhb * PIC driver for the 8259A Master and Slave PICs in PC/AT machines.
32121985Sjhb */
33121985Sjhb
34121985Sjhb#include <sys/cdefs.h>
35121985Sjhb__FBSDID("$FreeBSD: head/sys/i386/isa/atpic.c 127135 2004-03-17 17:50:55Z njl $");
36121985Sjhb
37121985Sjhb#include "opt_auto_eoi.h"
38121985Sjhb#include "opt_isa.h"
39121985Sjhb
40121985Sjhb#include <sys/param.h>
41121985Sjhb#include <sys/systm.h>
42121985Sjhb#include <sys/bus.h>
43121985Sjhb#include <sys/interrupt.h>
44121985Sjhb#include <sys/kernel.h>
45121985Sjhb#include <sys/lock.h>
46121985Sjhb#include <sys/mutex.h>
47121985Sjhb
48121985Sjhb#include <machine/cpufunc.h>
49121985Sjhb#include <machine/frame.h>
50121985Sjhb#include <machine/intr_machdep.h>
51121985Sjhb#include <machine/md_var.h>
52121985Sjhb#include <machine/resource.h>
53121985Sjhb#include <machine/segments.h>
54121985Sjhb
55124188Sjhb#include <dev/ic/i8259.h>
56121985Sjhb#include <i386/isa/icu.h>
57122051Snyan#ifdef PC98
58122051Snyan#include <pc98/pc98/pc98.h>
59122051Snyan#else
60121985Sjhb#include <i386/isa/isa.h>
61122051Snyan#endif
62121985Sjhb#include <isa/isavar.h>
63121985Sjhb
64121985Sjhb#define	MASTER	0
65121985Sjhb#define	SLAVE	1
66121985Sjhb
67124188Sjhb/*
68124188Sjhb * Determine the base master and slave modes not including auto EOI support.
69124188Sjhb * All machines that FreeBSD supports use 8086 mode.
70124188Sjhb */
71121985Sjhb#ifdef PC98
72124188Sjhb/*
73124188Sjhb * PC-98 machines do not support auto EOI on the second PIC.  Also, it
74124188Sjhb * seems that PC-98 machine PICs use buffered mode, and the master PIC
75124188Sjhb * uses special fully nested mode.
76124188Sjhb */
77124188Sjhb#define	BASE_MASTER_MODE	(ICW4_SFNM | ICW4_BUF | ICW4_MS | ICW4_8086)
78124188Sjhb#define	BASE_SLAVE_MODE		(ICW4_BUF | ICW4_8086)
79121985Sjhb#else
80124188Sjhb#define	BASE_MASTER_MODE	ICW4_8086
81124188Sjhb#define	BASE_SLAVE_MODE		ICW4_8086
82121985Sjhb#endif
83124188Sjhb
84124188Sjhb/* Enable automatic EOI if requested. */
85121985Sjhb#ifdef AUTO_EOI_1
86124188Sjhb#define	MASTER_MODE		(BASE_MASTER_MODE | ICW4_AEOI)
87121985Sjhb#else
88124188Sjhb#define	MASTER_MODE		BASE_MASTER_MODE
89121985Sjhb#endif
90121985Sjhb#ifdef AUTO_EOI_2
91124188Sjhb#define	SLAVE_MODE		(BASE_SLAVE_MODE | ICW4_AEOI)
92121985Sjhb#else
93124188Sjhb#define	SLAVE_MODE		BASE_SLAVE_MODE
94121985Sjhb#endif
95121985Sjhb
96121985Sjhbstatic void	atpic_init(void *dummy);
97121985Sjhb
98121985Sjhbunsigned int imen;	/* XXX */
99121985Sjhb
100121985Sjhbinthand_t
101121985Sjhb	IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2),
102121985Sjhb	IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5),
103121985Sjhb	IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8),
104121985Sjhb	IDTVEC(atpic_intr9), IDTVEC(atpic_intr10), IDTVEC(atpic_intr11),
105121985Sjhb	IDTVEC(atpic_intr12), IDTVEC(atpic_intr13), IDTVEC(atpic_intr14),
106121985Sjhb	IDTVEC(atpic_intr15);
107121985Sjhb
108121985Sjhb#define	IRQ(ap, ai)	((ap)->at_irqbase + (ai)->at_irq)
109121985Sjhb
110121985Sjhb#define	ATPIC(io, base, eoi, imenptr)				\
111121985Sjhb     	{ { atpic_enable_source, atpic_disable_source, (eoi),		\
112121985Sjhb	    atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \
113121985Sjhb	    atpic_resume }, (io), (base), IDT_IO_INTS + (base), (imenptr) }
114121985Sjhb
115121985Sjhb#define	INTSRC(irq)							\
116121985Sjhb	{ { &atpics[(irq) / 8].at_pic }, (irq) % 8,			\
117121985Sjhb	    IDTVEC(atpic_intr ## irq ) }
118121985Sjhb
119121985Sjhbstruct atpic {
120121985Sjhb	struct pic at_pic;
121121985Sjhb	int	at_ioaddr;
122121985Sjhb	int	at_irqbase;
123121985Sjhb	uint8_t	at_intbase;
124121985Sjhb	uint8_t	*at_imen;
125121985Sjhb};
126121985Sjhb
127121985Sjhbstruct atpic_intsrc {
128121985Sjhb	struct intsrc at_intsrc;
129121985Sjhb	int	at_irq;		/* Relative to PIC base. */
130121985Sjhb	inthand_t *at_intr;
131122897Sjhb	u_long	at_count;
132122897Sjhb	u_long	at_straycount;
133121985Sjhb};
134121985Sjhb
135121985Sjhbstatic void atpic_enable_source(struct intsrc *isrc);
136121985Sjhbstatic void atpic_disable_source(struct intsrc *isrc);
137121985Sjhbstatic void atpic_eoi_master(struct intsrc *isrc);
138121985Sjhbstatic void atpic_eoi_slave(struct intsrc *isrc);
139121985Sjhbstatic void atpic_enable_intr(struct intsrc *isrc);
140121985Sjhbstatic int atpic_vector(struct intsrc *isrc);
141121985Sjhbstatic void atpic_resume(struct intsrc *isrc);
142121985Sjhbstatic int atpic_source_pending(struct intsrc *isrc);
143121985Sjhbstatic void i8259_init(struct atpic *pic, int slave);
144121985Sjhb
145121985Sjhbstatic struct atpic atpics[] = {
146121985Sjhb	ATPIC(IO_ICU1, 0, atpic_eoi_master, (uint8_t *)&imen),
147121985Sjhb	ATPIC(IO_ICU2, 8, atpic_eoi_slave, ((uint8_t *)&imen) + 1)
148121985Sjhb};
149121985Sjhb
150121985Sjhbstatic struct atpic_intsrc atintrs[] = {
151121985Sjhb	INTSRC(0),
152121985Sjhb	INTSRC(1),
153121985Sjhb	INTSRC(2),
154121985Sjhb	INTSRC(3),
155121985Sjhb	INTSRC(4),
156121985Sjhb	INTSRC(5),
157121985Sjhb	INTSRC(6),
158121985Sjhb	INTSRC(7),
159121985Sjhb	INTSRC(8),
160121985Sjhb	INTSRC(9),
161121985Sjhb	INTSRC(10),
162121985Sjhb	INTSRC(11),
163121985Sjhb	INTSRC(12),
164121985Sjhb	INTSRC(13),
165121985Sjhb	INTSRC(14),
166121985Sjhb	INTSRC(15),
167121985Sjhb};
168121985Sjhb
169121985Sjhbstatic void
170121985Sjhbatpic_enable_source(struct intsrc *isrc)
171121985Sjhb{
172121985Sjhb	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
173121985Sjhb	struct atpic *ap = (struct atpic *)isrc->is_pic;
174121985Sjhb
175121985Sjhb	mtx_lock_spin(&icu_lock);
176121985Sjhb	*ap->at_imen &= ~(1 << ai->at_irq);
177121985Sjhb	outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
178121985Sjhb	mtx_unlock_spin(&icu_lock);
179121985Sjhb}
180121985Sjhb
181121985Sjhbstatic void
182121985Sjhbatpic_disable_source(struct intsrc *isrc)
183121985Sjhb{
184121985Sjhb	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
185121985Sjhb	struct atpic *ap = (struct atpic *)isrc->is_pic;
186121985Sjhb
187121985Sjhb	mtx_lock_spin(&icu_lock);
188121985Sjhb	*ap->at_imen |= (1 << ai->at_irq);
189121985Sjhb	outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
190121985Sjhb	mtx_unlock_spin(&icu_lock);
191121985Sjhb}
192121985Sjhb
193121985Sjhbstatic void
194121985Sjhbatpic_eoi_master(struct intsrc *isrc)
195121985Sjhb{
196121985Sjhb
197121985Sjhb	KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
198121985Sjhb	    ("%s: mismatched pic", __func__));
199121985Sjhb#ifndef AUTO_EOI_1
200121985Sjhb	mtx_lock_spin(&icu_lock);
201121985Sjhb	outb(atpics[MASTER].at_ioaddr, ICU_EOI);
202121985Sjhb	mtx_unlock_spin(&icu_lock);
203121985Sjhb#endif
204121985Sjhb}
205121985Sjhb
206122572Sjhb/*
207122572Sjhb * The data sheet says no auto-EOI on slave, but it sometimes works.
208122572Sjhb * So, if AUTO_EOI_2 is enabled, we use it.
209122572Sjhb */
210121985Sjhbstatic void
211121985Sjhbatpic_eoi_slave(struct intsrc *isrc)
212121985Sjhb{
213121985Sjhb
214121985Sjhb	KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
215121985Sjhb	    ("%s: mismatched pic", __func__));
216121985Sjhb#ifndef AUTO_EOI_2
217121985Sjhb	mtx_lock_spin(&icu_lock);
218121985Sjhb	outb(atpics[SLAVE].at_ioaddr, ICU_EOI);
219121985Sjhb#ifndef AUTO_EOI_1
220121985Sjhb	outb(atpics[MASTER].at_ioaddr, ICU_EOI);
221121985Sjhb#endif
222121985Sjhb	mtx_unlock_spin(&icu_lock);
223121985Sjhb#endif
224121985Sjhb}
225121985Sjhb
226121985Sjhbstatic void
227121985Sjhbatpic_enable_intr(struct intsrc *isrc)
228121985Sjhb{
229121985Sjhb}
230121985Sjhb
231121985Sjhbstatic int
232121985Sjhbatpic_vector(struct intsrc *isrc)
233121985Sjhb{
234121985Sjhb	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
235121985Sjhb	struct atpic *ap = (struct atpic *)isrc->is_pic;
236121985Sjhb
237121985Sjhb	return (IRQ(ap, ai));
238121985Sjhb}
239121985Sjhb
240121985Sjhbstatic int
241121985Sjhbatpic_source_pending(struct intsrc *isrc)
242121985Sjhb{
243121985Sjhb	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
244121985Sjhb	struct atpic *ap = (struct atpic *)isrc->is_pic;
245121985Sjhb
246121985Sjhb	return (inb(ap->at_ioaddr) & (1 << ai->at_irq));
247121985Sjhb}
248121985Sjhb
249121985Sjhbstatic void
250121985Sjhbatpic_resume(struct intsrc *isrc)
251121985Sjhb{
252121985Sjhb	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
253121985Sjhb	struct atpic *ap = (struct atpic *)isrc->is_pic;
254121985Sjhb
255121985Sjhb	if (ai->at_irq == 0)
256121985Sjhb		i8259_init(ap, ap == &atpics[SLAVE]);
257121985Sjhb}
258121985Sjhb
259121985Sjhbstatic void
260121985Sjhbi8259_init(struct atpic *pic, int slave)
261121985Sjhb{
262121985Sjhb	int imr_addr;
263121985Sjhb
264121985Sjhb	/* Reset the PIC and program with next four bytes. */
265121985Sjhb	mtx_lock_spin(&icu_lock);
266121985Sjhb#ifdef DEV_MCA
267122692Sjhb	/* MCA uses level triggered interrupts. */
268121985Sjhb	if (MCA_system)
269122692Sjhb		outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4 | ICW1_LTIM);
270121985Sjhb	else
271121985Sjhb#endif
272122692Sjhb		outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4);
273121985Sjhb	imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET;
274121985Sjhb
275121985Sjhb	/* Start vector. */
276121985Sjhb	outb(imr_addr, pic->at_intbase);
277121985Sjhb
278121985Sjhb	/*
279121985Sjhb	 * Setup slave links.  For the master pic, indicate what line
280121985Sjhb	 * the slave is configured on.  For the slave indicate
281121985Sjhb	 * which line on the master we are connected to.
282121985Sjhb	 */
283121985Sjhb	if (slave)
284121985Sjhb		outb(imr_addr, ICU_SLAVEID);	/* my slave id is 7 */
285121985Sjhb	else
286121985Sjhb		outb(imr_addr, IRQ_SLAVE);	/* slave on line 7 */
287121985Sjhb
288121985Sjhb	/* Set mode. */
289121985Sjhb	if (slave)
290121985Sjhb		outb(imr_addr, SLAVE_MODE);
291121985Sjhb	else
292121985Sjhb		outb(imr_addr, MASTER_MODE);
293121985Sjhb
294121985Sjhb	/* Set interrupt enable mask. */
295121985Sjhb	outb(imr_addr, *pic->at_imen);
296121985Sjhb
297121985Sjhb	/* Reset is finished, default to IRR on read. */
298122692Sjhb	outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR);
299121985Sjhb
300121985Sjhb#ifndef PC98
301122692Sjhb	/* OCW2_L1 sets priority order to 3-7, 0-2 (com2 first). */
302121985Sjhb	if (!slave)
303122692Sjhb		outb(pic->at_ioaddr, OCW2_R | OCW2_SL | OCW2_L1);
304121985Sjhb#endif
305121985Sjhb	mtx_unlock_spin(&icu_lock);
306121985Sjhb}
307121985Sjhb
308121985Sjhbvoid
309121985Sjhbatpic_startup(void)
310121985Sjhb{
311122897Sjhb	struct atpic_intsrc *ai;
312122897Sjhb	int i;
313121985Sjhb
314121985Sjhb	/* Start off with all interrupts disabled. */
315121985Sjhb	imen = 0xffff;
316121985Sjhb	i8259_init(&atpics[MASTER], 0);
317121985Sjhb	i8259_init(&atpics[SLAVE], 1);
318121985Sjhb	atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
319122897Sjhb
320122897Sjhb	/* Install low-level interrupt handlers for all of our IRQs. */
321122897Sjhb	for (i = 0; i < sizeof(atintrs) / sizeof(struct atpic_intsrc); i++) {
322122897Sjhb		if (i == ICU_SLAVEID)
323122897Sjhb			continue;
324122897Sjhb		ai = &atintrs[i];
325122897Sjhb		ai->at_intsrc.is_count = &ai->at_count;
326122897Sjhb		ai->at_intsrc.is_straycount = &ai->at_straycount;
327122897Sjhb		setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
328122897Sjhb		    ai->at_irq, ai->at_intr, SDT_SYS386IGT, SEL_KPL,
329122897Sjhb		    GSEL(GCODE_SEL, SEL_KPL));
330122897Sjhb	}
331121985Sjhb}
332121985Sjhb
333121985Sjhbstatic void
334121985Sjhbatpic_init(void *dummy __unused)
335121985Sjhb{
336121985Sjhb	int i;
337121985Sjhb
338121985Sjhb	/* Loop through all interrupt sources and add them. */
339121985Sjhb	for (i = 0; i < sizeof(atintrs) / sizeof(struct atpic_intsrc); i++) {
340121985Sjhb		if (i == ICU_SLAVEID)
341121985Sjhb			continue;
342122897Sjhb		intr_register_source(&atintrs[i].at_intsrc);
343121985Sjhb	}
344121985Sjhb}
345121985SjhbSYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL)
346121985Sjhb
347121985Sjhbvoid
348122572Sjhbatpic_handle_intr(struct intrframe iframe)
349121985Sjhb{
350121985Sjhb	struct intsrc *isrc;
351121985Sjhb
352121985Sjhb	KASSERT((uint)iframe.if_vec < ICU_LEN,
353121985Sjhb	    ("unknown int %d\n", iframe.if_vec));
354121985Sjhb	isrc = &atintrs[iframe.if_vec].at_intsrc;
355122898Sjhb
356122898Sjhb	/*
357122898Sjhb	 * If we don't have an ithread, see if this is a spurious
358122898Sjhb	 * interrupt.
359122898Sjhb	 */
360122898Sjhb	if (isrc->is_ithread == NULL &&
361122898Sjhb	    (iframe.if_vec == 7 || iframe.if_vec == 15)) {
362122898Sjhb		int port, isr;
363122898Sjhb
364122898Sjhb		/*
365122898Sjhb		 * Read the ISR register to see if IRQ 7/15 is really
366122898Sjhb		 * pending.  Reset read register back to IRR when done.
367122898Sjhb		 */
368122898Sjhb		port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
369122898Sjhb		mtx_lock_spin(&icu_lock);
370122898Sjhb		outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
371122898Sjhb		isr = inb(port);
372122898Sjhb		outb(port, OCW3_SEL | OCW3_RR);
373122898Sjhb		mtx_unlock_spin(&icu_lock);
374122898Sjhb		if ((isr & IRQ7) == 0)
375122898Sjhb			return;
376122898Sjhb	}
377121985Sjhb	intr_execute_handlers(isrc, &iframe);
378121985Sjhb}
379121985Sjhb
380121985Sjhb#ifdef DEV_ISA
381121985Sjhb/*
382121985Sjhb * Bus attachment for the ISA PIC.
383121985Sjhb */
384121985Sjhbstatic struct isa_pnp_id atpic_ids[] = {
385121985Sjhb	{ 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
386121985Sjhb	{ 0 }
387121985Sjhb};
388121985Sjhb
389121985Sjhbstatic int
390121985Sjhbatpic_probe(device_t dev)
391121985Sjhb{
392121985Sjhb	int result;
393121985Sjhb
394121985Sjhb	result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
395121985Sjhb	if (result <= 0)
396121985Sjhb		device_quiet(dev);
397121985Sjhb	return (result);
398121985Sjhb}
399121985Sjhb
400121985Sjhb/*
401121985Sjhb * We might be granted IRQ 2, as this is typically consumed by chaining
402121985Sjhb * between the two PIC components.  If we're using the APIC, however,
403121985Sjhb * this may not be the case, and as such we should free the resource.
404121985Sjhb * (XXX untested)
405121985Sjhb *
406121985Sjhb * The generic ISA attachment code will handle allocating any other resources
407121985Sjhb * that we don't explicitly claim here.
408121985Sjhb */
409121985Sjhbstatic int
410121985Sjhbatpic_attach(device_t dev)
411121985Sjhb{
412121985Sjhb	struct resource *res;
413121985Sjhb	int rid;
414121985Sjhb
415121985Sjhb	/* Try to allocate our IRQ and then free it. */
416121985Sjhb	rid = 0;
417127135Snjl	res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0);
418121985Sjhb	if (res != NULL)
419121985Sjhb		bus_release_resource(dev, SYS_RES_IRQ, rid, res);
420121985Sjhb	return (0);
421121985Sjhb}
422121985Sjhb
423121985Sjhbstatic device_method_t atpic_methods[] = {
424121985Sjhb	/* Device interface */
425121985Sjhb	DEVMETHOD(device_probe,		atpic_probe),
426121985Sjhb	DEVMETHOD(device_attach,	atpic_attach),
427121985Sjhb	DEVMETHOD(device_detach,	bus_generic_detach),
428121985Sjhb	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
429121985Sjhb	DEVMETHOD(device_suspend,	bus_generic_suspend),
430121985Sjhb	DEVMETHOD(device_resume,	bus_generic_resume),
431121985Sjhb	{ 0, 0 }
432121985Sjhb};
433121985Sjhb
434121985Sjhbstatic driver_t atpic_driver = {
435121985Sjhb	"atpic",
436121985Sjhb	atpic_methods,
437121985Sjhb	1,		/* no softc */
438121985Sjhb};
439121985Sjhb
440121985Sjhbstatic devclass_t atpic_devclass;
441121985Sjhb
442121985SjhbDRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0);
443122051Snyan#ifndef PC98
444121985SjhbDRIVER_MODULE(atpic, acpi, atpic_driver, atpic_devclass, 0, 0);
445122051Snyan#endif
446121985Sjhb
447121985Sjhb/*
448121985Sjhb * Return a bitmap of the current interrupt requests.  This is 8259-specific
449121985Sjhb * and is only suitable for use at probe time.
450121985Sjhb */
451121985Sjhbintrmask_t
452121985Sjhbisa_irq_pending(void)
453121985Sjhb{
454121985Sjhb	u_char irr1;
455121985Sjhb	u_char irr2;
456121985Sjhb
457121985Sjhb	irr1 = inb(IO_ICU1);
458121985Sjhb	irr2 = inb(IO_ICU2);
459121985Sjhb	return ((irr2 << 8) | irr1);
460121985Sjhb}
461121985Sjhb#endif /* DEV_ISA */
462