root/arch/i386/pci/pci_machdep.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pci_attach_hook
  2. pci_bus_maxdevs
  3. pci_make_tag
  4. pci_decompose_tag
  5. pci_conf_read
  6. pci_conf_write
  7. pci_mode_detect
  8. pci_intr_map
  9. pci_intr_string
  10. pci_intr_establish
  11. pci_intr_disestablish

    1 /*      $OpenBSD: pci_machdep.c,v 1.39 2007/05/21 22:10:45 kettenis Exp $       */
    2 /*      $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
   43  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
   44  *
   45  * Redistribution and use in source and binary forms, with or without
   46  * modification, are permitted provided that the following conditions
   47  * are met:
   48  * 1. Redistributions of source code must retain the above copyright
   49  *    notice, this list of conditions and the following disclaimer.
   50  * 2. Redistributions in binary form must reproduce the above copyright
   51  *    notice, this list of conditions and the following disclaimer in the
   52  *    documentation and/or other materials provided with the distribution.
   53  * 3. All advertising materials mentioning features or use of this software
   54  *    must display the following acknowledgement:
   55  *      This product includes software developed by Charles Hannum.
   56  * 4. The name of the author may not be used to endorse or promote products
   57  *    derived from this software without specific prior written permission.
   58  *
   59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   69  */
   70 
   71 /*
   72  * Machine-specific functions for PCI autoconfiguration.
   73  *
   74  * On PCs, there are two methods of generating PCI configuration cycles.
   75  * We try to detect the appropriate mechanism for this machine and set
   76  * up a few function pointers to access the correct method directly.
   77  *
   78  * The configuration method can be hard-coded in the config file by
   79  * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
   80  * as defined section 3.6.4.1, `Generating Configuration Cycles'.
   81  */
   82 
   83 #include <sys/types.h>
   84 #include <sys/param.h>
   85 #include <sys/time.h>
   86 #include <sys/systm.h>
   87 #include <sys/errno.h>
   88 #include <sys/device.h>
   89 
   90 #include <uvm/uvm_extern.h>
   91 
   92 #define _I386_BUS_DMA_PRIVATE
   93 #include <machine/bus.h>
   94 #include <machine/pio.h>
   95 #include <machine/i8259.h>
   96 
   97 #include "bios.h"
   98 #if NBIOS > 0
   99 #include <machine/biosvar.h>
  100 extern bios_pciinfo_t *bios_pciinfo;
  101 #endif
  102 
  103 #include <dev/isa/isavar.h>
  104 #include <dev/pci/pcivar.h>
  105 #include <dev/pci/pcireg.h>
  106 #include <dev/pci/pcidevs.h>
  107 #include <dev/pci/ppbreg.h>
  108 
  109 #include "ioapic.h"
  110 
  111 #include <machine/i82093var.h>
  112 #if NIOAPIC > 0
  113 #include <machine/mpbiosvar.h>
  114 #endif
  115 
  116 #include "pcibios.h"
  117 #if NPCIBIOS > 0
  118 #include <i386/pci/pcibiosvar.h>
  119 #endif
  120 
  121 int pci_mode = -1;
  122 
  123 #define PCI_MODE1_ENABLE        0x80000000UL
  124 #define PCI_MODE1_ADDRESS_REG   0x0cf8
  125 #define PCI_MODE1_DATA_REG      0x0cfc
  126 
  127 #define PCI_MODE2_ENABLE_REG    0x0cf8
  128 #define PCI_MODE2_FORWARD_REG   0x0cfa
  129 
  130 #define _m1tag(b, d, f) \
  131         (PCI_MODE1_ENABLE | ((b) << 16) | ((d) << 11) | ((f) << 8))
  132 #define _qe(bus, dev, fcn, vend, prod) \
  133         {_m1tag(bus, dev, fcn), PCI_ID_CODE(vend, prod)}
  134 struct {
  135         u_int32_t tag;
  136         pcireg_t id;
  137 } pcim1_quirk_tbl[] = {
  138         _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX1),
  139         /* XXX Triflex2 not tested */
  140         _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX2),
  141         _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX4),
  142         /* Triton needed for Connectix Virtual PC */
  143         _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437FX),
  144         /* Connectix Virtual PC 5 has a 440BX */
  145         _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX_NOAGP),
  146         {0, 0xffffffff} /* patchable */
  147 };
  148 #undef _m1tag
  149 #undef _qe
  150 
  151 /*
  152  * PCI doesn't have any special needs; just use the generic versions
  153  * of these functions.
  154  */
  155 struct i386_bus_dma_tag pci_bus_dma_tag = {
  156         NULL,                   /* _cookie */
  157         _bus_dmamap_create, 
  158         _bus_dmamap_destroy,
  159         _bus_dmamap_load,
  160         _bus_dmamap_load_mbuf,
  161         _bus_dmamap_load_uio,
  162         _bus_dmamap_load_raw,
  163         _bus_dmamap_unload,
  164         NULL,                   /* _dmamap_sync */
  165         _bus_dmamem_alloc,
  166         _bus_dmamem_free,
  167         _bus_dmamem_map,
  168         _bus_dmamem_unmap,
  169         _bus_dmamem_mmap,
  170 };
  171 
  172 void
  173 pci_attach_hook(struct device *parent, struct device *self,
  174     struct pcibus_attach_args *pba)
  175 {
  176 
  177 #if NBIOS > 0
  178         if (pba->pba_bus == 0)
  179                 printf(": configuration mode %d (%s)",
  180                         pci_mode, (bios_pciinfo?"bios":"no bios"));
  181 #else
  182         if (pba->pba_bus == 0)
  183                 printf(": configuration mode %d", pci_mode);
  184 #endif
  185 }
  186 
  187 int
  188 pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
  189 {
  190 
  191         /*
  192          * Bus number is irrelevant.  If Configuration Mechanism 2 is in
  193          * use, can only have devices 0-15 on any bus.  If Configuration
  194          * Mechanism 1 is in use, can have devices 0-32 (i.e. the `normal'
  195          * range).
  196          */
  197         if (pci_mode == 2)
  198                 return (16);
  199         else
  200                 return (32);
  201 }
  202 
  203 pcitag_t
  204 pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
  205 {
  206         pcitag_t tag;
  207 
  208         switch (pci_mode) {
  209         case 1:
  210                 if (bus >= 256 || device >= 32 || function >= 8)
  211                         panic("pci_make_tag: bad request");
  212 
  213                 tag.mode1 = PCI_MODE1_ENABLE |
  214                         (bus << 16) | (device << 11) | (function << 8);
  215                 break;
  216         case 2:
  217                 if (bus >= 256 || device >= 16 || function >= 8)
  218                         panic("pci_make_tag: bad request");
  219 
  220                 tag.mode2.port = 0xc000 | (device << 8);
  221                 tag.mode2.enable = 0xf0 | (function << 1);
  222                 tag.mode2.forward = bus;
  223                 break;
  224         default:
  225                 panic("pci_make_tag: mode not configured");
  226         }
  227 
  228         return tag;
  229 }
  230 
  231 void
  232 pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
  233 {
  234 
  235         switch (pci_mode) {
  236         case 1:
  237                 if (bp != NULL)
  238                         *bp = (tag.mode1 >> 16) & 0xff;
  239                 if (dp != NULL)
  240                         *dp = (tag.mode1 >> 11) & 0x1f;
  241                 if (fp != NULL)
  242                         *fp = (tag.mode1 >> 8) & 0x7;
  243                 break;
  244         case 2:
  245                 if (bp != NULL)
  246                         *bp = tag.mode2.forward & 0xff;
  247                 if (dp != NULL)
  248                         *dp = (tag.mode2.port >> 8) & 0xf;
  249                 if (fp != NULL)
  250                         *fp = (tag.mode2.enable >> 1) & 0x7;
  251                 break;
  252         default:
  253                 panic("pci_decompose_tag: mode not configured");
  254         }
  255 }
  256 
  257 pcireg_t
  258 pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
  259 {
  260         pcireg_t data;
  261 
  262         switch (pci_mode) {
  263         case 1:
  264                 outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
  265                 data = inl(PCI_MODE1_DATA_REG);
  266                 outl(PCI_MODE1_ADDRESS_REG, 0);
  267                 break;
  268         case 2:
  269                 outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
  270                 outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
  271                 data = inl(tag.mode2.port | reg);
  272                 outb(PCI_MODE2_ENABLE_REG, 0);
  273                 break;
  274         default:
  275                 panic("pci_conf_read: mode not configured");
  276         }
  277 
  278         return data;
  279 }
  280 
  281 void
  282 pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
  283 {
  284 
  285         switch (pci_mode) {
  286         case 1:
  287                 outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
  288                 outl(PCI_MODE1_DATA_REG, data);
  289                 outl(PCI_MODE1_ADDRESS_REG, 0);
  290                 break;
  291         case 2:
  292                 outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
  293                 outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
  294                 outl(tag.mode2.port | reg, data);
  295                 outb(PCI_MODE2_ENABLE_REG, 0);
  296                 break;
  297         default:
  298                 panic("pci_conf_write: mode not configured");
  299         }
  300 }
  301 
  302 int
  303 pci_mode_detect(void)
  304 {
  305 
  306 #ifdef PCI_CONF_MODE
  307 #if (PCI_CONF_MODE == 1) || (PCI_CONF_MODE == 2)
  308         return (pci_mode = PCI_CONF_MODE);
  309 #else
  310 #error Invalid PCI configuration mode.
  311 #endif
  312 #else
  313         u_int32_t sav, val;
  314         int i;
  315         pcireg_t idreg;
  316 
  317         if (pci_mode != -1)
  318                 return (pci_mode);
  319 
  320 #if NBIOS > 0
  321         /*
  322          * If we have PCI info passed from the BIOS, use the mode given there
  323          * for all of this code.  If not, pass on through to the previous tests
  324          * to try and divine the correct mode.
  325          */
  326         if (bios_pciinfo != NULL) {
  327                 if (bios_pciinfo->pci_chars & 0x2)
  328                         return (pci_mode = 2);
  329 
  330                 if (bios_pciinfo->pci_chars & 0x1)
  331                         return (pci_mode = 1);
  332 
  333                 /* We should never get here, but if we do, fall through... */
  334         }
  335 #endif
  336 
  337         /*
  338          * We try to divine which configuration mode the host bridge wants.
  339          *
  340          * This should really be done using the PCI BIOS.  If we get here, the
  341          * PCI BIOS does not exist, or the boot blocks did not provide the
  342          * information.
  343          */
  344 
  345         sav = inl(PCI_MODE1_ADDRESS_REG);
  346 
  347         pci_mode = 1; /* assume this for now */
  348         /*
  349          * catch some known buggy implementations of mode 1
  350          */
  351         for (i = 0; i < sizeof(pcim1_quirk_tbl) / sizeof(pcim1_quirk_tbl[0]);
  352              i++) {
  353                 pcitag_t t;
  354 
  355                 if (!pcim1_quirk_tbl[i].tag)
  356                         break;
  357                 t.mode1 = pcim1_quirk_tbl[i].tag;
  358                 idreg = pci_conf_read(0, t, PCI_ID_REG); /* needs "pci_mode" */
  359                 if (idreg == pcim1_quirk_tbl[i].id) {
  360 #ifdef DEBUG
  361                         printf("known mode 1 PCI chipset (%08x)\n",
  362                                idreg);
  363 #endif
  364                         return (pci_mode);
  365                 }
  366         }
  367 
  368         /*
  369          * Strong check for standard compliant mode 1:
  370          * 1. bit 31 ("enable") can be set
  371          * 2. byte/word access does not affect register
  372          */
  373         outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE);
  374         outb(PCI_MODE1_ADDRESS_REG + 3, 0);
  375         outw(PCI_MODE1_ADDRESS_REG + 2, 0);
  376         val = inl(PCI_MODE1_ADDRESS_REG);
  377         if ((val & 0x80fffffc) != PCI_MODE1_ENABLE) {
  378 #ifdef DEBUG
  379                 printf("pci_mode_detect: mode 1 enable failed (%x)\n",
  380                        val);
  381 #endif
  382                 goto not1;
  383         }
  384         outl(PCI_MODE1_ADDRESS_REG, 0);
  385         val = inl(PCI_MODE1_ADDRESS_REG);
  386         if ((val & 0x80fffffc) != 0)
  387                 goto not1;
  388         return (pci_mode);
  389 not1:
  390         outl(PCI_MODE1_ADDRESS_REG, sav);
  391  
  392         /*
  393          * This mode 2 check is quite weak (and known to give false
  394          * positives on some Compaq machines).
  395          * However, this doesn't matter, because this is the
  396          * last test, and simply no PCI devices will be found if
  397          * this happens.
  398          */
  399         outb(PCI_MODE2_ENABLE_REG, 0);
  400         outb(PCI_MODE2_FORWARD_REG, 0);
  401         if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
  402             inb(PCI_MODE2_FORWARD_REG) != 0)
  403                 goto not2;
  404         return (pci_mode = 2);
  405 not2:
  406         return (pci_mode = 0);
  407 #endif
  408 }
  409 
  410 int
  411 pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
  412 {
  413         int pin = pa->pa_intrpin;
  414         int line = pa->pa_intrline;
  415 #if NIOAPIC > 0
  416         int rawpin = pa->pa_rawintrpin;
  417         struct mp_intr_map *mip;
  418         int bus, dev, func;
  419 #endif
  420 
  421 #if (NPCIBIOS > 0) || (NIOAPIC > 0)
  422         pci_chipset_tag_t pc = pa->pa_pc;
  423         pcitag_t intrtag = pa->pa_intrtag;
  424 #endif
  425 
  426         if (pin == 0) {
  427                 /* No IRQ used. */
  428                 goto bad;
  429         }
  430 
  431         if (pin > PCI_INTERRUPT_PIN_MAX) {
  432                 printf("pci_intr_map: bad interrupt pin %d\n", pin);
  433                 goto bad;
  434         }
  435 
  436         ihp->line = line;
  437         ihp->pin = pin;
  438 
  439 #if NIOAPIC > 0
  440         pci_decompose_tag (pc, intrtag, &bus, &dev, &func);
  441 
  442         if (!(ihp->line & PCI_INT_VIA_ISA) && mp_busses != NULL) {
  443                 /*
  444                  * Assumes 1:1 mapping between PCI bus numbers and
  445                  * the numbers given by the MP bios.
  446                  * XXX Is this a valid assumption?
  447                  */
  448                 int mpspec_pin = (dev<<2)|(pin-1);
  449 
  450                 for (mip = mp_busses[bus].mb_intrs; mip != NULL; mip=mip->next) {
  451                         if (mip->bus_pin == mpspec_pin) {
  452                                 ihp->line = mip->ioapic_ih | line;
  453                                 return 0;
  454                         }
  455                 }
  456 
  457                 if (pa->pa_bridgetag) {
  458                         int pin = PPB_INTERRUPT_SWIZZLE(rawpin, dev);
  459                         if (pa->pa_bridgeih[pin - 1].line != -1) {
  460                                 ihp->line = pa->pa_bridgeih[pin - 1].line;
  461                                 ihp->line |= line;
  462                                 return 0;
  463                         }
  464                 }
  465                 /*
  466                  * No explicit PCI mapping found. This is not fatal,
  467                  * we'll try the ISA (or possibly EISA) mappings next.
  468                  */
  469         }
  470 #endif
  471 
  472 #if NPCIBIOS > 0
  473         pci_intr_header_fixup(pc, intrtag, ihp);
  474         line = ihp->line & APIC_INT_LINE_MASK;
  475 #endif
  476 
  477         /*
  478          * Section 6.2.4, `Miscellaneous Functions', says that 255 means
  479          * `unknown' or `no connection' on a PC.  We assume that a device with
  480          * `no connection' either doesn't have an interrupt (in which case the
  481          * pin number should be 0, and would have been noticed above), or
  482          * wasn't configured by the BIOS (in which case we punt, since there's
  483          * no real way we can know how the interrupt lines are mapped in the
  484          * hardware).
  485          *
  486          * XXX
  487          * Since IRQ 0 is only used by the clock, and we can't actually be sure
  488          * that the BIOS did its job, we also recognize that as meaning that
  489          * the BIOS has not configured the device.
  490          */
  491         if (line == 0 || line == I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
  492                 goto bad;
  493 
  494         if (line >= ICU_LEN) {
  495                 printf("pci_intr_map: bad interrupt line %d\n", line);
  496                 goto bad;
  497         }
  498         if (line == 2) {
  499                 printf("pci_intr_map: changed line 2 to line 9\n");
  500                 line = 9;
  501         }
  502 
  503 #if NIOAPIC > 0
  504         if (!(ihp->line & PCI_INT_VIA_ISA) && mp_busses != NULL) {
  505                 if (mip == NULL && mp_isa_bus) {
  506                         for (mip = mp_isa_bus->mb_intrs; mip != NULL;
  507                             mip = mip->next) {
  508                                 if (mip->bus_pin == line) {
  509                                         ihp->line = mip->ioapic_ih | line;
  510                                         return 0;
  511                                 }
  512                         }
  513                 }
  514                 if (mip == NULL && mp_eisa_bus) {
  515                         for (mip = mp_eisa_bus->mb_intrs;  mip != NULL;
  516                             mip = mip->next) {
  517                                 if (mip->bus_pin == line) {
  518                                         ihp->line = mip->ioapic_ih | line;
  519                                         return 0;
  520                                 }
  521                         }
  522                 }
  523                 if (mip == NULL) {
  524                         printf("pci_intr_map: "
  525                             "bus %d dev %d func %d pin %d; line %d\n",
  526                             bus, dev, func, pin, line);
  527                         printf("pci_intr_map: no MP mapping found\n");
  528                 }
  529         }
  530 #endif
  531 
  532         return 0;
  533 
  534 bad:
  535         ihp->line = -1;
  536         return 1;
  537 }
  538 
  539 const char *
  540 pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih)
  541 {
  542         static char irqstr[64];
  543         int line = ih.line & APIC_INT_LINE_MASK;
  544 
  545 #if NIOAPIC > 0
  546         if (ih.line & APIC_INT_VIA_APIC) {
  547                 snprintf(irqstr, sizeof irqstr, "apic %d int %d (irq %d)",
  548                      APIC_IRQ_APIC(ih.line), APIC_IRQ_PIN(ih.line), line);
  549                 return (irqstr);
  550         }
  551 #endif
  552 
  553         if (line == 0 || line >= ICU_LEN || line == 2)
  554                 panic("pci_intr_string: bogus handle 0x%x", line);
  555 
  556         snprintf(irqstr, sizeof irqstr, "irq %d", line);
  557         return (irqstr);
  558 }
  559 
  560 void *
  561 pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
  562     int (*func)(void *), void *arg, char *what)
  563 {
  564         void *ret;
  565         int l = ih.line & APIC_INT_LINE_MASK;
  566 
  567 #if NIOAPIC > 0
  568         if (l != -1 && ih.line & APIC_INT_VIA_APIC)
  569                 return (apic_intr_establish(ih.line, IST_LEVEL, level, func, 
  570                     arg, what));
  571 #endif
  572         if (l == 0 || l >= ICU_LEN || l == 2)
  573                 panic("pci_intr_establish: bogus handle 0x%x", l);
  574 
  575         ret = isa_intr_establish(NULL, l, IST_LEVEL, level, func, arg, what);
  576 #if NPCIBIOS > 0
  577         if (ret)
  578                 pci_intr_route_link(pc, &ih);
  579 #endif
  580         return (ret);
  581 }
  582 
  583 void
  584 pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
  585 {
  586         /* XXX oh, unroute the pci int link? */
  587         isa_intr_disestablish(NULL, cookie);
  588 }

/* [<][>][^][v][top][bottom][index][help] */