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