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