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

Cache object: 83d8cab9dc766a5916061d6f7d4c7462


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