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