The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/isa/atpic.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/5.4/sys/amd64/isa/atpic.c 142759 2005-02-28 07:40:00Z obrien $");
   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 #include <sys/proc.h>
   49 
   50 #include <machine/cpufunc.h>
   51 #include <machine/frame.h>
   52 #include <machine/intr_machdep.h>
   53 #include <machine/md_var.h>
   54 #include <machine/resource.h>
   55 #include <machine/segments.h>
   56 
   57 #include <dev/ic/i8259.h>
   58 #include <amd64/isa/icu.h>
   59 #include <amd64/isa/isa.h>
   60 
   61 #include <isa/isavar.h>
   62 
   63 #define MASTER  0
   64 #define SLAVE   1
   65 
   66 /*
   67  * PC-AT machines wire the slave PIC to pin 2 on the master PIC.
   68  */
   69 #define ICU_SLAVEID     2
   70 
   71 /*
   72  * Determine the base master and slave modes not including auto EOI support.
   73  * All machines that FreeBSD supports use 8086 mode.
   74  */
   75 #define BASE_MASTER_MODE        ICW4_8086
   76 #define BASE_SLAVE_MODE         ICW4_8086
   77 
   78 /* Enable automatic EOI if requested. */
   79 #ifdef AUTO_EOI_1
   80 #define MASTER_MODE             (BASE_MASTER_MODE | ICW4_AEOI)
   81 #else
   82 #define MASTER_MODE             BASE_MASTER_MODE
   83 #endif
   84 #ifdef AUTO_EOI_2
   85 #define SLAVE_MODE              (BASE_SLAVE_MODE | ICW4_AEOI)
   86 #else
   87 #define SLAVE_MODE              BASE_SLAVE_MODE
   88 #endif
   89 
   90 #define IRQ_MASK(irq)           (1 << (irq))
   91 #define IMEN_MASK(ai)           (IRQ_MASK((ai)->at_irq))
   92 
   93 #define NUM_ISA_IRQS            16
   94 
   95 static void     atpic_init(void *dummy);
   96 
   97 unsigned int imen;      /* XXX */
   98 
   99 inthand_t
  100         IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2),
  101         IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5),
  102         IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8),
  103         IDTVEC(atpic_intr9), IDTVEC(atpic_intr10), IDTVEC(atpic_intr11),
  104         IDTVEC(atpic_intr12), IDTVEC(atpic_intr13), IDTVEC(atpic_intr14),
  105         IDTVEC(atpic_intr15);
  106 
  107 #define IRQ(ap, ai)     ((ap)->at_irqbase + (ai)->at_irq)
  108 
  109 #define ATPIC(io, base, eoi, imenptr)                                   \
  110         { { atpic_enable_source, atpic_disable_source, (eoi),           \
  111             atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \
  112             atpic_resume, atpic_config_intr }, (io), (base),            \
  113             IDT_IO_INTS + (base), (imenptr) }
  114 
  115 #define INTSRC(irq)                                                     \
  116         { { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ),    \
  117             (irq) % 8 }
  118 
  119 struct atpic {
  120         struct pic at_pic;
  121         int     at_ioaddr;
  122         int     at_irqbase;
  123         uint8_t at_intbase;
  124         uint8_t *at_imen;
  125 };
  126 
  127 struct atpic_intsrc {
  128         struct intsrc at_intsrc;
  129         inthand_t *at_intr;
  130         int     at_irq;                 /* Relative to PIC base. */
  131         enum intr_trigger at_trigger;
  132         u_long  at_count;
  133         u_long  at_straycount;
  134 };
  135 
  136 static void atpic_enable_source(struct intsrc *isrc);
  137 static void atpic_disable_source(struct intsrc *isrc, int eoi);
  138 static void atpic_eoi_master(struct intsrc *isrc);
  139 static void atpic_eoi_slave(struct intsrc *isrc);
  140 static void atpic_enable_intr(struct intsrc *isrc);
  141 static int atpic_vector(struct intsrc *isrc);
  142 static void atpic_resume(struct intsrc *isrc);
  143 static int atpic_source_pending(struct intsrc *isrc);
  144 static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
  145     enum intr_polarity pol);
  146 static void i8259_init(struct atpic *pic, int slave);
  147 
  148 static struct atpic atpics[] = {
  149         ATPIC(IO_ICU1, 0, atpic_eoi_master, (uint8_t *)&imen),
  150         ATPIC(IO_ICU2, 8, atpic_eoi_slave, ((uint8_t *)&imen) + 1)
  151 };
  152 
  153 static struct atpic_intsrc atintrs[] = {
  154         INTSRC(0),
  155         INTSRC(1),
  156         INTSRC(2),
  157         INTSRC(3),
  158         INTSRC(4),
  159         INTSRC(5),
  160         INTSRC(6),
  161         INTSRC(7),
  162         INTSRC(8),
  163         INTSRC(9),
  164         INTSRC(10),
  165         INTSRC(11),
  166         INTSRC(12),
  167         INTSRC(13),
  168         INTSRC(14),
  169         INTSRC(15),
  170 };
  171 
  172 CTASSERT(sizeof(atintrs) / sizeof(atintrs[0]) == NUM_ISA_IRQS);
  173 
  174 static __inline void
  175 _atpic_eoi_master(struct intsrc *isrc)
  176 {
  177 
  178         KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
  179             ("%s: mismatched pic", __func__));
  180 #ifndef AUTO_EOI_1
  181         outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
  182 #endif
  183 }
  184 
  185 /*
  186  * The data sheet says no auto-EOI on slave, but it sometimes works.
  187  * So, if AUTO_EOI_2 is enabled, we use it.
  188  */
  189 static __inline void
  190 _atpic_eoi_slave(struct intsrc *isrc)
  191 {
  192 
  193         KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
  194             ("%s: mismatched pic", __func__));
  195 #ifndef AUTO_EOI_2
  196         outb(atpics[SLAVE].at_ioaddr, OCW2_EOI);
  197 #ifndef AUTO_EOI_1
  198         outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
  199 #endif
  200 #endif
  201 }
  202 
  203 static void
  204 atpic_enable_source(struct intsrc *isrc)
  205 {
  206         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
  207         struct atpic *ap = (struct atpic *)isrc->is_pic;
  208 
  209         mtx_lock_spin(&icu_lock);
  210         if (*ap->at_imen & IMEN_MASK(ai)) {
  211                 *ap->at_imen &= ~IMEN_MASK(ai);
  212                 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
  213         }
  214         mtx_unlock_spin(&icu_lock);
  215 }
  216 
  217 static void
  218 atpic_disable_source(struct intsrc *isrc, int eoi)
  219 {
  220         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
  221         struct atpic *ap = (struct atpic *)isrc->is_pic;
  222 
  223         mtx_lock_spin(&icu_lock);
  224         if (ai->at_trigger != INTR_TRIGGER_EDGE) {
  225                 *ap->at_imen |= IMEN_MASK(ai);
  226                 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
  227         }
  228 
  229         /*
  230          * Take care to call these functions directly instead of through
  231          * a function pointer.  All of the referenced variables should
  232          * still be hot in the cache.
  233          */
  234         if (eoi == PIC_EOI) {
  235                 if (isrc->is_pic == &atpics[MASTER].at_pic)
  236                         _atpic_eoi_master(isrc);
  237                 else
  238                         _atpic_eoi_slave(isrc);
  239         }
  240 
  241         mtx_unlock_spin(&icu_lock);
  242 }
  243 
  244 static void
  245 atpic_eoi_master(struct intsrc *isrc)
  246 {
  247 #ifndef AUTO_EOI_1
  248         mtx_lock_spin(&icu_lock);
  249         _atpic_eoi_master(isrc);
  250         mtx_unlock_spin(&icu_lock);
  251 #endif
  252 }
  253 
  254 static void
  255 atpic_eoi_slave(struct intsrc *isrc)
  256 {
  257 #ifndef AUTO_EOI_2
  258         mtx_lock_spin(&icu_lock);
  259         _atpic_eoi_slave(isrc);
  260         mtx_unlock_spin(&icu_lock);
  261 #endif
  262 }
  263 
  264 static void
  265 atpic_enable_intr(struct intsrc *isrc)
  266 {
  267 }
  268 
  269 static int
  270 atpic_vector(struct intsrc *isrc)
  271 {
  272         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
  273         struct atpic *ap = (struct atpic *)isrc->is_pic;
  274 
  275         return (IRQ(ap, ai));
  276 }
  277 
  278 static int
  279 atpic_source_pending(struct intsrc *isrc)
  280 {
  281         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
  282         struct atpic *ap = (struct atpic *)isrc->is_pic;
  283 
  284         return (inb(ap->at_ioaddr) & IMEN_MASK(ai));
  285 }
  286 
  287 static void
  288 atpic_resume(struct intsrc *isrc)
  289 {
  290         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
  291         struct atpic *ap = (struct atpic *)isrc->is_pic;
  292 
  293         if (ai->at_irq == 0) {
  294                 i8259_init(ap, ap == &atpics[SLAVE]);
  295                 if (ap == &atpics[SLAVE] && elcr_found)
  296                         elcr_resume();
  297         }
  298 }
  299 
  300 static int
  301 atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
  302     enum intr_polarity pol)
  303 {
  304         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
  305         u_int vector;
  306 
  307         /* Map conforming values to edge/hi and sanity check the values. */
  308         if (trig == INTR_TRIGGER_CONFORM)
  309                 trig = INTR_TRIGGER_EDGE;
  310         if (pol == INTR_POLARITY_CONFORM)
  311                 pol = INTR_POLARITY_HIGH;
  312         vector = atpic_vector(isrc);
  313         if ((trig == INTR_TRIGGER_EDGE && pol == INTR_POLARITY_LOW) ||
  314             (trig == INTR_TRIGGER_LEVEL && pol == INTR_POLARITY_HIGH)) {
  315                 printf(
  316                 "atpic: Mismatched config for IRQ%u: trigger %s, polarity %s\n",
  317                     vector, trig == INTR_TRIGGER_EDGE ? "edge" : "level",
  318                     pol == INTR_POLARITY_HIGH ? "high" : "low");
  319                 return (EINVAL);
  320         }
  321 
  322         /* If there is no change, just return. */
  323         if (ai->at_trigger == trig)
  324                 return (0);
  325 
  326         /*
  327          * Certain IRQs can never be level/lo, so don't try to set them
  328          * that way if asked.  At least some ELCR registers ignore setting
  329          * these bits as well.
  330          */
  331         if ((vector == 0 || vector == 1 || vector == 2 || vector == 13) &&
  332             trig == INTR_TRIGGER_LEVEL) {
  333                 if (bootverbose)
  334                         printf(
  335                 "atpic: Ignoring invalid level/low configuration for IRQ%u\n",
  336                             vector);
  337                 return (EINVAL);
  338         }
  339         if (!elcr_found) {
  340                 if (bootverbose)
  341                         printf("atpic: No ELCR to configure IRQ%u as %s\n",
  342                             vector, trig == INTR_TRIGGER_EDGE ? "edge/high" :
  343                             "level/low");
  344                 return (ENXIO);
  345         }
  346         if (bootverbose)
  347                 printf("atpic: Programming IRQ%u as %s\n", vector,
  348                     trig == INTR_TRIGGER_EDGE ? "edge/high" : "level/low");
  349         mtx_lock_spin(&icu_lock);
  350         elcr_write_trigger(atpic_vector(isrc), trig);
  351         ai->at_trigger = trig;
  352         mtx_unlock_spin(&icu_lock);
  353         return (0);
  354 }
  355 
  356 static void
  357 i8259_init(struct atpic *pic, int slave)
  358 {
  359         int imr_addr;
  360 
  361         /* Reset the PIC and program with next four bytes. */
  362         mtx_lock_spin(&icu_lock);
  363         outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4);
  364         imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET;
  365 
  366         /* Start vector. */
  367         outb(imr_addr, pic->at_intbase);
  368 
  369         /*
  370          * Setup slave links.  For the master pic, indicate what line
  371          * the slave is configured on.  For the slave indicate
  372          * which line on the master we are connected to.
  373          */
  374         if (slave)
  375                 outb(imr_addr, ICU_SLAVEID);
  376         else
  377                 outb(imr_addr, IRQ_MASK(ICU_SLAVEID));
  378 
  379         /* Set mode. */
  380         if (slave)
  381                 outb(imr_addr, SLAVE_MODE);
  382         else
  383                 outb(imr_addr, MASTER_MODE);
  384 
  385         /* Set interrupt enable mask. */
  386         outb(imr_addr, *pic->at_imen);
  387 
  388         /* Reset is finished, default to IRR on read. */
  389         outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR);
  390 
  391         /* OCW2_L1 sets priority order to 3-7, 0-2 (com2 first). */
  392         if (!slave)
  393                 outb(pic->at_ioaddr, OCW2_R | OCW2_SL | OCW2_L1);
  394         mtx_unlock_spin(&icu_lock);
  395 }
  396 
  397 void
  398 atpic_startup(void)
  399 {
  400         struct atpic_intsrc *ai;
  401         int i;
  402 
  403         /* Start off with all interrupts disabled. */
  404         imen = 0xffff;
  405         i8259_init(&atpics[MASTER], 0);
  406         i8259_init(&atpics[SLAVE], 1);
  407         atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
  408 
  409         /* Install low-level interrupt handlers for all of our IRQs. */
  410         for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
  411                 if (i == ICU_SLAVEID)
  412                         continue;
  413                 ai->at_intsrc.is_count = &ai->at_count;
  414                 ai->at_intsrc.is_straycount = &ai->at_straycount;
  415                 setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
  416                     ai->at_irq, ai->at_intr, SDT_SYSIGT, SEL_KPL, 0);
  417         }
  418 
  419         /*
  420          * Look for an ELCR.  If we find one, update the trigger modes.
  421          * If we don't find one, assume that IRQs 0, 1, 2, and 13 are
  422          * edge triggered and that everything else is level triggered.
  423          * We only use the trigger information to reprogram the ELCR if
  424          * we have one and as an optimization to avoid masking edge
  425          * triggered interrupts.  For the case that we don't have an ELCR,
  426          * it doesn't hurt to mask an edge triggered interrupt, so we
  427          * assume level trigger for any interrupt that we aren't sure is
  428          * edge triggered.
  429          */
  430         if (elcr_found) {
  431                 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
  432                         ai->at_trigger = elcr_read_trigger(i);
  433         } else {
  434                 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
  435                         switch (i) {
  436                         case 0:
  437                         case 1:
  438                         case 2:
  439                         case 8:
  440                         case 13:
  441                                 ai->at_trigger = INTR_TRIGGER_EDGE;
  442                                 break;
  443                         default:
  444                                 ai->at_trigger = INTR_TRIGGER_LEVEL;
  445                                 break;
  446                         }
  447         }
  448 }
  449 
  450 static void
  451 atpic_init(void *dummy __unused)
  452 {
  453         struct atpic_intsrc *ai;
  454         int i;
  455 
  456         /* Loop through all interrupt sources and add them. */
  457         for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
  458                 if (i == ICU_SLAVEID)
  459                         continue;
  460                 intr_register_source(&ai->at_intsrc);
  461         }
  462 }
  463 SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL)
  464 
  465 void
  466 atpic_handle_intr(void *cookie, struct intrframe iframe)
  467 {
  468         struct intsrc *isrc;
  469         int vec = (uintptr_t)cookie;
  470 
  471         KASSERT(vec < NUM_ISA_IRQS, ("unknown int %d\n", vec));
  472         isrc = &atintrs[vec].at_intsrc;
  473 
  474         /*
  475          * If we don't have an ithread, see if this is a spurious
  476          * interrupt.
  477          */
  478         if (isrc->is_ithread == NULL && (vec == 7 || vec == 15)) {
  479                 int port, isr;
  480 
  481                 /*
  482                  * Read the ISR register to see if IRQ 7/15 is really
  483                  * pending.  Reset read register back to IRR when done.
  484                  */
  485                 port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
  486                 mtx_lock_spin(&icu_lock);
  487                 outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
  488                 isr = inb(port);
  489                 outb(port, OCW3_SEL | OCW3_RR);
  490                 mtx_unlock_spin(&icu_lock);
  491                 if ((isr & IRQ_MASK(7)) == 0)
  492                         return;
  493         }
  494         intr_execute_handlers(isrc, &iframe);
  495 }
  496 
  497 #ifdef DEV_ISA
  498 /*
  499  * Bus attachment for the ISA PIC.
  500  */
  501 static struct isa_pnp_id atpic_ids[] = {
  502         { 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
  503         { 0 }
  504 };
  505 
  506 static int
  507 atpic_probe(device_t dev)
  508 {
  509         int result;
  510         
  511         result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
  512         if (result <= 0)
  513                 device_quiet(dev);
  514         return (result);
  515 }
  516 
  517 /*
  518  * We might be granted IRQ 2, as this is typically consumed by chaining
  519  * between the two PIC components.  If we're using the APIC, however,
  520  * this may not be the case, and as such we should free the resource.
  521  * (XXX untested)
  522  *
  523  * The generic ISA attachment code will handle allocating any other resources
  524  * that we don't explicitly claim here.
  525  */
  526 static int
  527 atpic_attach(device_t dev)
  528 {
  529         struct resource *res;
  530         int rid;
  531 
  532         /* Try to allocate our IRQ and then free it. */
  533         rid = 0;
  534         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0);
  535         if (res != NULL)
  536                 bus_release_resource(dev, SYS_RES_IRQ, rid, res);
  537         return (0);
  538 }
  539 
  540 static device_method_t atpic_methods[] = {
  541         /* Device interface */
  542         DEVMETHOD(device_probe,         atpic_probe),
  543         DEVMETHOD(device_attach,        atpic_attach),
  544         DEVMETHOD(device_detach,        bus_generic_detach),
  545         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  546         DEVMETHOD(device_suspend,       bus_generic_suspend),
  547         DEVMETHOD(device_resume,        bus_generic_resume),
  548         { 0, 0 }
  549 };
  550 
  551 static driver_t atpic_driver = {
  552         "atpic",
  553         atpic_methods,
  554         1,              /* no softc */
  555 };
  556 
  557 static devclass_t atpic_devclass;
  558 
  559 DRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0);
  560 DRIVER_MODULE(atpic, acpi, atpic_driver, atpic_devclass, 0, 0);
  561 
  562 /*
  563  * Return a bitmap of the current interrupt requests.  This is 8259-specific
  564  * and is only suitable for use at probe time.
  565  */
  566 intrmask_t
  567 isa_irq_pending(void)
  568 {
  569         u_char irr1;
  570         u_char irr2;
  571 
  572         irr1 = inb(IO_ICU1);
  573         irr2 = inb(IO_ICU2);
  574         return ((irr2 << 8) | irr1);
  575 }
  576 #endif /* DEV_ISA */

Cache object: 848047581681528bc95fd6dc6a567b66


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.