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