atpic.c revision 156124
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 156124 2006-02-28 22:24:55Z 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 112static void atpic_init(void *dummy); 113 114unsigned int imen; /* XXX */ 115 116inthand_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 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 int atpic_vector(struct intsrc *isrc); 159static void atpic_resume(struct intsrc *isrc); 160static int atpic_source_pending(struct intsrc *isrc); 161static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig, 162 enum intr_polarity pol); 163static void atpic_assign_cpu(struct intsrc *isrc, u_int apic_id); 164static void i8259_init(struct atpic *pic, int slave); 165 166static 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 171static 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 190CTASSERT(sizeof(atintrs) / sizeof(atintrs[0]) == NUM_ISA_IRQS); 191 192static __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 */ 207static __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 221static void 222atpic_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 235static void 236atpic_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 262static void 263atpic_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 272static void 273atpic_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 282static void 283atpic_enable_intr(struct intsrc *isrc) 284{ 285} 286 287static int 288atpic_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 296static int 297atpic_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 305static void 306atpic_resume(struct intsrc *isrc) 307{ 308 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc; 309 struct atpic *ap = (struct atpic *)isrc->is_pic; 310 311 if (ai->at_irq == 0) { 312 i8259_init(ap, ap == &atpics[SLAVE]); 313#ifndef PC98 314 if (ap == &atpics[SLAVE] && elcr_found) 315 elcr_resume(); 316#endif 317 } 318} 319 320static int 321atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig, 322 enum intr_polarity pol) 323{ 324 struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc; 325 u_int vector; 326 327 /* Map conforming values to edge/hi and sanity check the values. */ 328 if (trig == INTR_TRIGGER_CONFORM) 329 trig = INTR_TRIGGER_EDGE; 330 if (pol == INTR_POLARITY_CONFORM) 331 pol = INTR_POLARITY_HIGH; 332 vector = atpic_vector(isrc); 333 if ((trig == INTR_TRIGGER_EDGE && pol == INTR_POLARITY_LOW) || 334 (trig == INTR_TRIGGER_LEVEL && pol == INTR_POLARITY_HIGH)) { 335 printf( 336 "atpic: Mismatched config for IRQ%u: trigger %s, polarity %s\n", 337 vector, trig == INTR_TRIGGER_EDGE ? "edge" : "level", 338 pol == INTR_POLARITY_HIGH ? "high" : "low"); 339 return (EINVAL); 340 } 341 342 /* If there is no change, just return. */ 343 if (ai->at_trigger == trig) 344 return (0); 345 346#ifdef PC98 347 if ((vector == 0 || vector == 1 || vector == 7 || vector == 8) && 348 trig == INTR_TRIGGER_LEVEL) { 349 if (bootverbose) 350 printf( 351 "atpic: Ignoring invalid level/low configuration for IRQ%u\n", 352 vector); 353 return (EINVAL); 354 } 355 return (ENXIO); 356#else 357 /* 358 * Certain IRQs can never be level/lo, so don't try to set them 359 * that way if asked. At least some ELCR registers ignore setting 360 * these bits as well. 361 */ 362 if ((vector == 0 || vector == 1 || vector == 2 || vector == 13) && 363 trig == INTR_TRIGGER_LEVEL) { 364 if (bootverbose) 365 printf( 366 "atpic: Ignoring invalid level/low configuration for IRQ%u\n", 367 vector); 368 return (EINVAL); 369 } 370 if (!elcr_found) { 371 if (bootverbose) 372 printf("atpic: No ELCR to configure IRQ%u as %s\n", 373 vector, trig == INTR_TRIGGER_EDGE ? "edge/high" : 374 "level/low"); 375 return (ENXIO); 376 } 377 if (bootverbose) 378 printf("atpic: Programming IRQ%u as %s\n", vector, 379 trig == INTR_TRIGGER_EDGE ? "edge/high" : "level/low"); 380 mtx_lock_spin(&icu_lock); 381 elcr_write_trigger(atpic_vector(isrc), trig); 382 ai->at_trigger = trig; 383 mtx_unlock_spin(&icu_lock); 384 return (0); 385#endif /* PC98 */ 386} 387 388static void 389atpic_assign_cpu(struct intsrc *isrc, u_int apic_id) 390{ 391 392 /* 393 * 8259A's are only used in UP in which case all interrupts always 394 * go to the sole CPU and this function shouldn't even be called. 395 */ 396 panic("%s: bad cookie", __func__); 397} 398 399static void 400i8259_init(struct atpic *pic, int slave) 401{ 402 int imr_addr; 403 404 /* Reset the PIC and program with next four bytes. */ 405 mtx_lock_spin(&icu_lock); 406#ifdef DEV_MCA 407 /* MCA uses level triggered interrupts. */ 408 if (MCA_system) 409 outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4 | ICW1_LTIM); 410 else 411#endif 412 outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4); 413 imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET; 414 415 /* Start vector. */ 416 outb(imr_addr, pic->at_intbase); 417 418 /* 419 * Setup slave links. For the master pic, indicate what line 420 * the slave is configured on. For the slave indicate 421 * which line on the master we are connected to. 422 */ 423 if (slave) 424 outb(imr_addr, ICU_SLAVEID); 425 else 426 outb(imr_addr, IRQ_MASK(ICU_SLAVEID)); 427 428 /* Set mode. */ 429 if (slave) 430 outb(imr_addr, SLAVE_MODE); 431 else 432 outb(imr_addr, MASTER_MODE); 433 434 /* Set interrupt enable mask. */ 435 outb(imr_addr, *pic->at_imen); 436 437 /* Reset is finished, default to IRR on read. */ 438 outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR); 439 440#ifndef PC98 441 /* OCW2_L1 sets priority order to 3-7, 0-2 (com2 first). */ 442 if (!slave) 443 outb(pic->at_ioaddr, OCW2_R | OCW2_SL | OCW2_L1); 444#endif 445 mtx_unlock_spin(&icu_lock); 446} 447 448void 449atpic_startup(void) 450{ 451 struct atpic_intsrc *ai; 452 int i; 453 454 /* Start off with all interrupts disabled. */ 455 imen = 0xffff; 456 i8259_init(&atpics[MASTER], 0); 457 i8259_init(&atpics[SLAVE], 1); 458 atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]); 459 460 /* Install low-level interrupt handlers for all of our IRQs. */ 461 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) { 462 if (i == ICU_SLAVEID) 463 continue; 464 ai->at_intsrc.is_count = &ai->at_count; 465 ai->at_intsrc.is_straycount = &ai->at_straycount; 466 setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase + 467 ai->at_irq, ai->at_intr, SDT_SYS386IGT, SEL_KPL, 468 GSEL(GCODE_SEL, SEL_KPL)); 469 } 470 471#ifdef DEV_MCA 472 /* For MCA systems, all interrupts are level triggered. */ 473 if (MCA_system) 474 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) 475 ai->at_trigger = INTR_TRIGGER_LEVEL; 476 else 477#endif 478 479#ifdef PC98 480 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) 481 switch (i) { 482 case 0: 483 case 1: 484 case 7: 485 case 8: 486 ai->at_trigger = INTR_TRIGGER_EDGE; 487 break; 488 default: 489 ai->at_trigger = INTR_TRIGGER_LEVEL; 490 break; 491 } 492#else 493 /* 494 * Look for an ELCR. If we find one, update the trigger modes. 495 * If we don't find one, assume that IRQs 0, 1, 2, and 13 are 496 * edge triggered and that everything else is level triggered. 497 * We only use the trigger information to reprogram the ELCR if 498 * we have one and as an optimization to avoid masking edge 499 * triggered interrupts. For the case that we don't have an ELCR, 500 * it doesn't hurt to mask an edge triggered interrupt, so we 501 * assume level trigger for any interrupt that we aren't sure is 502 * edge triggered. 503 */ 504 if (elcr_found) { 505 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) 506 ai->at_trigger = elcr_read_trigger(i); 507 } else { 508 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) 509 switch (i) { 510 case 0: 511 case 1: 512 case 2: 513 case 8: 514 case 13: 515 ai->at_trigger = INTR_TRIGGER_EDGE; 516 break; 517 default: 518 ai->at_trigger = INTR_TRIGGER_LEVEL; 519 break; 520 } 521 } 522#endif /* PC98 */ 523} 524 525static void 526atpic_init(void *dummy __unused) 527{ 528 struct atpic_intsrc *ai; 529 int i; 530 531 /* 532 * If any of the ISA IRQs have an interrupt source already, then 533 * assume that the APICs are being used and don't register any 534 * of our interrupt sources. This makes sure we don't accidentally 535 * use mixed mode. The "accidental" use could otherwise occur on 536 * machines that route the ACPI SCI interrupt to a different ISA 537 * IRQ (at least one machines routes it to IRQ 13) thus disabling 538 * that APIC ISA routing and allowing the ATPIC source for that IRQ 539 * to leak through. We used to depend on this feature for routing 540 * IRQ0 via mixed mode, but now we don't use mixed mode at all. 541 */ 542 for (i = 0; i < NUM_ISA_IRQS; i++) 543 if (intr_lookup_source(i) != NULL) 544 return; 545 546 /* Loop through all interrupt sources and add them. */ 547 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) { 548 if (i == ICU_SLAVEID) 549 continue; 550 intr_register_source(&ai->at_intsrc); 551 } 552} 553SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL) 554 555void 556atpic_handle_intr(u_int vector, struct trapframe frame) 557{ 558 struct intsrc *isrc; 559 560 KASSERT(vector < NUM_ISA_IRQS, ("unknown int %u\n", vector)); 561 isrc = &atintrs[vector].at_intsrc; 562 563 /* 564 * If we don't have an event, see if this is a spurious 565 * interrupt. 566 */ 567 if (isrc->is_event == NULL && (vector == 7 || vector == 15)) { 568 int port, isr; 569 570 /* 571 * Read the ISR register to see if IRQ 7/15 is really 572 * pending. Reset read register back to IRR when done. 573 */ 574 port = ((struct atpic *)isrc->is_pic)->at_ioaddr; 575 mtx_lock_spin(&icu_lock); 576 outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS); 577 isr = inb(port); 578 outb(port, OCW3_SEL | OCW3_RR); 579 mtx_unlock_spin(&icu_lock); 580 if ((isr & IRQ_MASK(7)) == 0) 581 return; 582 } 583 intr_execute_handlers(isrc, &frame); 584} 585 586#ifdef DEV_ISA 587/* 588 * Bus attachment for the ISA PIC. 589 */ 590static struct isa_pnp_id atpic_ids[] = { 591 { 0x0000d041 /* PNP0000 */, "AT interrupt controller" }, 592 { 0 } 593}; 594 595static int 596atpic_probe(device_t dev) 597{ 598 int result; 599 600 result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids); 601 if (result <= 0) 602 device_quiet(dev); 603 return (result); 604} 605 606/* 607 * We might be granted IRQ 2, as this is typically consumed by chaining 608 * between the two PIC components. If we're using the APIC, however, 609 * this may not be the case, and as such we should free the resource. 610 * (XXX untested) 611 * 612 * The generic ISA attachment code will handle allocating any other resources 613 * that we don't explicitly claim here. 614 */ 615static int 616atpic_attach(device_t dev) 617{ 618 struct resource *res; 619 int rid; 620 621 /* Try to allocate our IRQ and then free it. */ 622 rid = 0; 623 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0); 624 if (res != NULL) 625 bus_release_resource(dev, SYS_RES_IRQ, rid, res); 626 return (0); 627} 628 629static device_method_t atpic_methods[] = { 630 /* Device interface */ 631 DEVMETHOD(device_probe, atpic_probe), 632 DEVMETHOD(device_attach, atpic_attach), 633 DEVMETHOD(device_detach, bus_generic_detach), 634 DEVMETHOD(device_shutdown, bus_generic_shutdown), 635 DEVMETHOD(device_suspend, bus_generic_suspend), 636 DEVMETHOD(device_resume, bus_generic_resume), 637 { 0, 0 } 638}; 639 640static driver_t atpic_driver = { 641 "atpic", 642 atpic_methods, 643 1, /* no softc */ 644}; 645 646static devclass_t atpic_devclass; 647 648DRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0); 649#ifndef PC98 650DRIVER_MODULE(atpic, acpi, atpic_driver, atpic_devclass, 0, 0); 651#endif 652 653/* 654 * Return a bitmap of the current interrupt requests. This is 8259-specific 655 * and is only suitable for use at probe time. 656 */ 657intrmask_t 658isa_irq_pending(void) 659{ 660 u_char irr1; 661 u_char irr2; 662 663 irr1 = inb(IO_ICU1); 664 irr2 = inb(IO_ICU2); 665 return ((irr2 << 8) | irr1); 666} 667#endif /* DEV_ISA */ 668