xref: /freebsd/sys/x86/isa/atpic.c (revision 38a52bd3)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * PIC driver for the 8259A Master and Slave PICs in PC/AT machines.
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 
35 #include "opt_auto_eoi.h"
36 #include "opt_isa.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/asan.h>
41 #include <sys/bus.h>
42 #include <sys/interrupt.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/module.h>
46 #include <sys/msan.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 #include <isa/isareg.h>
58 #include <isa/isavar.h>
59 
60 #ifdef __amd64__
61 #define	SDT_ATPIC	SDT_SYSIGT
62 #define	GSEL_ATPIC	0
63 #else
64 #define	SDT_ATPIC	SDT_SYS386IGT
65 #define	GSEL_ATPIC	GSEL(GCODE_SEL, SEL_KPL)
66 #endif
67 
68 #define	MASTER	0
69 #define	SLAVE	1
70 
71 #define	IMEN_MASK(ai)		(IRQ_MASK((ai)->at_irq))
72 
73 #define	NUM_ISA_IRQS		16
74 
75 static void	atpic_init(void *dummy);
76 
77 inthand_t
78 	IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2),
79 	IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5),
80 	IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8),
81 	IDTVEC(atpic_intr9), IDTVEC(atpic_intr10), IDTVEC(atpic_intr11),
82 	IDTVEC(atpic_intr12), IDTVEC(atpic_intr13), IDTVEC(atpic_intr14),
83 	IDTVEC(atpic_intr15);
84 /* XXXKIB i386 uses stubs until pti comes */
85 inthand_t
86 	IDTVEC(atpic_intr0_pti), IDTVEC(atpic_intr1_pti),
87 	IDTVEC(atpic_intr2_pti), IDTVEC(atpic_intr3_pti),
88 	IDTVEC(atpic_intr4_pti), IDTVEC(atpic_intr5_pti),
89 	IDTVEC(atpic_intr6_pti), IDTVEC(atpic_intr7_pti),
90 	IDTVEC(atpic_intr8_pti), IDTVEC(atpic_intr9_pti),
91 	IDTVEC(atpic_intr10_pti), IDTVEC(atpic_intr11_pti),
92 	IDTVEC(atpic_intr12_pti), IDTVEC(atpic_intr13_pti),
93 	IDTVEC(atpic_intr14_pti), IDTVEC(atpic_intr15_pti);
94 
95 #define	IRQ(ap, ai)	((ap)->at_irqbase + (ai)->at_irq)
96 
97 #define	ATPIC(io, base, eoi) {						\
98 		.at_pic = {						\
99 			.pic_register_sources = atpic_register_sources,	\
100 			.pic_enable_source = atpic_enable_source,	\
101 			.pic_disable_source = atpic_disable_source,	\
102 			.pic_eoi_source = (eoi),			\
103 			.pic_enable_intr = atpic_enable_intr,		\
104 			.pic_disable_intr = atpic_disable_intr,		\
105 			.pic_vector = atpic_vector,			\
106 			.pic_source_pending = atpic_source_pending,	\
107 			.pic_resume = atpic_resume,			\
108 			.pic_config_intr = atpic_config_intr,		\
109 			.pic_assign_cpu = atpic_assign_cpu		\
110 		},							\
111 		.at_ioaddr = (io),					\
112 		.at_irqbase = (base),					\
113 		.at_intbase = IDT_IO_INTS + (base),			\
114 		.at_imen = 0xff,					\
115 	}
116 
117 #define	INTSRC(irq)							\
118 	{ { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ),	\
119 	    IDTVEC(atpic_intr ## irq ## _pti), (irq) % 8 }
120 
121 struct atpic {
122 	struct pic at_pic;
123 	int	at_ioaddr;
124 	int	at_irqbase;
125 	uint8_t	at_intbase;
126 	uint8_t	at_imen;
127 };
128 
129 struct atpic_intsrc {
130 	struct intsrc at_intsrc;
131 	inthand_t *at_intr, *at_intr_pti;
132 	int	at_irq;			/* Relative to PIC base. */
133 	enum intr_trigger at_trigger;
134 	u_long	at_count;
135 	u_long	at_straycount;
136 };
137 
138 static void atpic_register_sources(struct pic *pic);
139 static void atpic_enable_source(struct intsrc *isrc);
140 static void atpic_disable_source(struct intsrc *isrc, int eoi);
141 static void atpic_eoi_master(struct intsrc *isrc);
142 static void atpic_eoi_slave(struct intsrc *isrc);
143 static void atpic_enable_intr(struct intsrc *isrc);
144 static void atpic_disable_intr(struct intsrc *isrc);
145 static int atpic_vector(struct intsrc *isrc);
146 static void atpic_resume(struct pic *pic, bool suspend_cancelled);
147 static int atpic_source_pending(struct intsrc *isrc);
148 static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
149     enum intr_polarity pol);
150 static int atpic_assign_cpu(struct intsrc *isrc, u_int apic_id);
151 static void i8259_init(struct atpic *pic, int slave);
152 
153 static struct atpic atpics[] = {
154 	ATPIC(IO_ICU1, 0, atpic_eoi_master),
155 	ATPIC(IO_ICU2, 8, atpic_eoi_slave)
156 };
157 
158 static struct atpic_intsrc atintrs[] = {
159 	INTSRC(0),
160 	INTSRC(1),
161 	INTSRC(2),
162 	INTSRC(3),
163 	INTSRC(4),
164 	INTSRC(5),
165 	INTSRC(6),
166 	INTSRC(7),
167 	INTSRC(8),
168 	INTSRC(9),
169 	INTSRC(10),
170 	INTSRC(11),
171 	INTSRC(12),
172 	INTSRC(13),
173 	INTSRC(14),
174 	INTSRC(15),
175 };
176 
177 CTASSERT(nitems(atintrs) == NUM_ISA_IRQS);
178 
179 static __inline void
180 _atpic_eoi_master(struct intsrc *isrc)
181 {
182 
183 	KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
184 	    ("%s: mismatched pic", __func__));
185 #ifndef AUTO_EOI_1
186 	outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
187 #endif
188 }
189 
190 /*
191  * The data sheet says no auto-EOI on slave, but it sometimes works.
192  * So, if AUTO_EOI_2 is enabled, we use it.
193  */
194 static __inline void
195 _atpic_eoi_slave(struct intsrc *isrc)
196 {
197 
198 	KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
199 	    ("%s: mismatched pic", __func__));
200 #ifndef AUTO_EOI_2
201 	outb(atpics[SLAVE].at_ioaddr, OCW2_EOI);
202 #ifndef AUTO_EOI_1
203 	outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
204 #endif
205 #endif
206 }
207 
208 static void
209 atpic_register_sources(struct pic *pic)
210 {
211 	struct atpic *ap = (struct atpic *)pic;
212 	struct atpic_intsrc *ai;
213 	int i;
214 
215 	/*
216 	 * If any of the ISA IRQs have an interrupt source already, then
217 	 * assume that the I/O APICs are being used and don't register any
218 	 * of our interrupt sources.  This makes sure we don't accidentally
219 	 * use mixed mode.  The "accidental" use could otherwise occur on
220 	 * machines that route the ACPI SCI interrupt to a different ISA
221 	 * IRQ (at least one machine routes it to IRQ 13) thus disabling
222 	 * that APIC ISA routing and allowing the ATPIC source for that IRQ
223 	 * to leak through.  We used to depend on this feature for routing
224 	 * IRQ0 via mixed mode, but now we don't use mixed mode at all.
225 	 *
226 	 * To avoid the slave not register sources after the master
227 	 * registers its sources, register all IRQs when this function is
228 	 * called on the master.
229 	 */
230 	if (ap != &atpics[MASTER])
231 		return;
232 	for (i = 0; i < NUM_ISA_IRQS; i++)
233 		if (intr_lookup_source(i) != NULL)
234 			return;
235 
236 	/* Loop through all interrupt sources and add them. */
237 	for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
238 		if (i == ICU_SLAVEID)
239 			continue;
240 		intr_register_source(&ai->at_intsrc);
241 	}
242 }
243 
244 static void
245 atpic_enable_source(struct intsrc *isrc)
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 (ap->at_imen & IMEN_MASK(ai)) {
252 		ap->at_imen &= ~IMEN_MASK(ai);
253 		outb(ap->at_ioaddr + ICU_IMR_OFFSET, ap->at_imen);
254 	}
255 	spinlock_exit();
256 }
257 
258 static void
259 atpic_disable_source(struct intsrc *isrc, int eoi)
260 {
261 	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
262 	struct atpic *ap = (struct atpic *)isrc->is_pic;
263 
264 	spinlock_enter();
265 	if (ai->at_trigger != INTR_TRIGGER_EDGE) {
266 		ap->at_imen |= IMEN_MASK(ai);
267 		outb(ap->at_ioaddr + ICU_IMR_OFFSET, ap->at_imen);
268 	}
269 
270 	/*
271 	 * Take care to call these functions directly instead of through
272 	 * a function pointer.  All of the referenced variables should
273 	 * still be hot in the cache.
274 	 */
275 	if (eoi == PIC_EOI) {
276 		if (isrc->is_pic == &atpics[MASTER].at_pic)
277 			_atpic_eoi_master(isrc);
278 		else
279 			_atpic_eoi_slave(isrc);
280 	}
281 
282 	spinlock_exit();
283 }
284 
285 static void
286 atpic_eoi_master(struct intsrc *isrc)
287 {
288 #ifndef AUTO_EOI_1
289 	spinlock_enter();
290 	_atpic_eoi_master(isrc);
291 	spinlock_exit();
292 #endif
293 }
294 
295 static void
296 atpic_eoi_slave(struct intsrc *isrc)
297 {
298 #ifndef AUTO_EOI_2
299 	spinlock_enter();
300 	_atpic_eoi_slave(isrc);
301 	spinlock_exit();
302 #endif
303 }
304 
305 static void
306 atpic_enable_intr(struct intsrc *isrc)
307 {
308 }
309 
310 static void
311 atpic_disable_intr(struct intsrc *isrc)
312 {
313 }
314 
315 static int
316 atpic_vector(struct intsrc *isrc)
317 {
318 	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
319 	struct atpic *ap = (struct atpic *)isrc->is_pic;
320 
321 	return (IRQ(ap, ai));
322 }
323 
324 static int
325 atpic_source_pending(struct intsrc *isrc)
326 {
327 	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
328 	struct atpic *ap = (struct atpic *)isrc->is_pic;
329 
330 	return (inb(ap->at_ioaddr) & IMEN_MASK(ai));
331 }
332 
333 static void
334 atpic_resume(struct pic *pic, bool suspend_cancelled)
335 {
336 	struct atpic *ap = (struct atpic *)pic;
337 
338 	i8259_init(ap, ap == &atpics[SLAVE]);
339 	if (ap == &atpics[SLAVE] && elcr_found)
340 		elcr_resume();
341 }
342 
343 static int
344 atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
345     enum intr_polarity pol)
346 {
347 	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
348 	u_int vector;
349 
350 	/* Map conforming values to edge/hi and sanity check the values. */
351 	if (trig == INTR_TRIGGER_CONFORM)
352 		trig = INTR_TRIGGER_EDGE;
353 	if (pol == INTR_POLARITY_CONFORM)
354 		pol = INTR_POLARITY_HIGH;
355 	vector = atpic_vector(isrc);
356 	if ((trig == INTR_TRIGGER_EDGE && pol == INTR_POLARITY_LOW) ||
357 	    (trig == INTR_TRIGGER_LEVEL && pol == INTR_POLARITY_HIGH)) {
358 		printf(
359 		"atpic: Mismatched config for IRQ%u: trigger %s, polarity %s\n",
360 		    vector, trig == INTR_TRIGGER_EDGE ? "edge" : "level",
361 		    pol == INTR_POLARITY_HIGH ? "high" : "low");
362 		return (EINVAL);
363 	}
364 
365 	/* If there is no change, just return. */
366 	if (ai->at_trigger == trig)
367 		return (0);
368 
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 }
398 
399 static int
400 atpic_assign_cpu(struct intsrc *isrc, u_int apic_id)
401 {
402 
403 	/*
404 	 * 8259A's are only used in UP in which case all interrupts always
405 	 * go to the sole CPU and this function shouldn't even be called.
406 	 */
407 	panic("%s: bad cookie", __func__);
408 }
409 
410 static void
411 i8259_init(struct atpic *pic, int slave)
412 {
413 	int imr_addr;
414 
415 	/* Reset the PIC and program with next four bytes. */
416 	spinlock_enter();
417 	outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4);
418 	imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET;
419 
420 	/* Start vector. */
421 	outb(imr_addr, pic->at_intbase);
422 
423 	/*
424 	 * Setup slave links.  For the master pic, indicate what line
425 	 * the slave is configured on.  For the slave indicate
426 	 * which line on the master we are connected to.
427 	 */
428 	if (slave)
429 		outb(imr_addr, ICU_SLAVEID);
430 	else
431 		outb(imr_addr, IRQ_MASK(ICU_SLAVEID));
432 
433 	/* Set mode. */
434 	if (slave)
435 		outb(imr_addr, SLAVE_MODE);
436 	else
437 		outb(imr_addr, MASTER_MODE);
438 
439 	/* Set interrupt enable mask. */
440 	outb(imr_addr, pic->at_imen);
441 
442 	/* Reset is finished, default to IRR on read. */
443 	outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR);
444 
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 
449 	spinlock_exit();
450 }
451 
452 void
453 atpic_startup(void)
454 {
455 	struct atpic_intsrc *ai;
456 	int i;
457 
458 	/* Start off with all interrupts disabled. */
459 	i8259_init(&atpics[MASTER], 0);
460 	i8259_init(&atpics[SLAVE], 1);
461 	atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
462 
463 	/* Install low-level interrupt handlers for all of our IRQs. */
464 	for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
465 		if (i == ICU_SLAVEID)
466 			continue;
467 		ai->at_intsrc.is_count = &ai->at_count;
468 		ai->at_intsrc.is_straycount = &ai->at_straycount;
469 		setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
470 		    ai->at_irq, pti ? ai->at_intr_pti : ai->at_intr, SDT_ATPIC,
471 		    SEL_KPL, GSEL_ATPIC);
472 	}
473 
474 	/*
475 	 * Look for an ELCR.  If we find one, update the trigger modes.
476 	 * If we don't find one, assume that IRQs 0, 1, 2, and 13 are
477 	 * edge triggered and that everything else is level triggered.
478 	 * We only use the trigger information to reprogram the ELCR if
479 	 * we have one and as an optimization to avoid masking edge
480 	 * triggered interrupts.  For the case that we don't have an ELCR,
481 	 * it doesn't hurt to mask an edge triggered interrupt, so we
482 	 * assume level trigger for any interrupt that we aren't sure is
483 	 * edge triggered.
484 	 */
485 	if (elcr_found) {
486 		for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
487 			ai->at_trigger = elcr_read_trigger(i);
488 	} else {
489 		for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
490 			switch (i) {
491 			case 0:
492 			case 1:
493 			case 2:
494 			case 8:
495 			case 13:
496 				ai->at_trigger = INTR_TRIGGER_EDGE;
497 				break;
498 			default:
499 				ai->at_trigger = INTR_TRIGGER_LEVEL;
500 				break;
501 			}
502 	}
503 }
504 
505 static void
506 atpic_init(void *dummy __unused)
507 {
508 
509 	/*
510 	 * Register our PICs, even if we aren't going to use any of their
511 	 * pins so that they are suspended and resumed.
512 	 */
513 	if (intr_register_pic(&atpics[0].at_pic) != 0 ||
514 	    intr_register_pic(&atpics[1].at_pic) != 0)
515 		panic("Unable to register ATPICs");
516 
517 	if (num_io_irqs == 0)
518 		num_io_irqs = NUM_ISA_IRQS;
519 }
520 SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_FOURTH, atpic_init, NULL);
521 
522 void
523 atpic_handle_intr(u_int vector, struct trapframe *frame)
524 {
525 	struct intsrc *isrc;
526 
527 	kasan_mark(frame, sizeof(*frame), sizeof(*frame), 0);
528 	kmsan_mark(frame, sizeof(*frame), KMSAN_STATE_INITED);
529 	trap_check_kstack();
530 
531 	KASSERT(vector < NUM_ISA_IRQS, ("unknown int %u\n", vector));
532 	isrc = &atintrs[vector].at_intsrc;
533 
534 	/*
535 	 * If we don't have an event, see if this is a spurious
536 	 * interrupt.
537 	 */
538 	if (isrc->is_event == NULL && (vector == 7 || vector == 15)) {
539 		int port, isr;
540 
541 		/*
542 		 * Read the ISR register to see if IRQ 7/15 is really
543 		 * pending.  Reset read register back to IRR when done.
544 		 */
545 		port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
546 		spinlock_enter();
547 		outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
548 		isr = inb(port);
549 		outb(port, OCW3_SEL | OCW3_RR);
550 		spinlock_exit();
551 		if ((isr & IRQ_MASK(7)) == 0)
552 			return;
553 	}
554 	intr_execute_handlers(isrc, frame);
555 }
556 
557 #ifdef DEV_ISA
558 /*
559  * Bus attachment for the ISA PIC.
560  */
561 static struct isa_pnp_id atpic_ids[] = {
562 	{ 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
563 	{ 0 }
564 };
565 
566 static int
567 atpic_probe(device_t dev)
568 {
569 	int result;
570 
571 	result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
572 	if (result <= 0)
573 		device_quiet(dev);
574 	return (result);
575 }
576 
577 /*
578  * We might be granted IRQ 2, as this is typically consumed by chaining
579  * between the two PIC components.  If we're using the APIC, however,
580  * this may not be the case, and as such we should free the resource.
581  * (XXX untested)
582  *
583  * The generic ISA attachment code will handle allocating any other resources
584  * that we don't explicitly claim here.
585  */
586 static int
587 atpic_attach(device_t dev)
588 {
589 	struct resource *res;
590 	int rid;
591 
592 	/* Try to allocate our IRQ and then free it. */
593 	rid = 0;
594 	res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0);
595 	if (res != NULL)
596 		bus_release_resource(dev, SYS_RES_IRQ, rid, res);
597 	return (0);
598 }
599 
600 static device_method_t atpic_methods[] = {
601 	/* Device interface */
602 	DEVMETHOD(device_probe,		atpic_probe),
603 	DEVMETHOD(device_attach,	atpic_attach),
604 	DEVMETHOD(device_detach,	bus_generic_detach),
605 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
606 	DEVMETHOD(device_suspend,	bus_generic_suspend),
607 	DEVMETHOD(device_resume,	bus_generic_resume),
608 	{ 0, 0 }
609 };
610 
611 static driver_t atpic_driver = {
612 	"atpic",
613 	atpic_methods,
614 	1,		/* no softc */
615 };
616 
617 DRIVER_MODULE(atpic, isa, atpic_driver, 0, 0);
618 DRIVER_MODULE(atpic, acpi, atpic_driver, 0, 0);
619 ISA_PNP_INFO(atpic_ids);
620 #endif /* DEV_ISA */
621