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