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