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

Cache object: 9e760afca25e26a511f9ccb8788b0b79


[ 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.