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

Cache object: 5d02e138ec2ca001429438fad8fd291e


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