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/i386/isa/pci_cfgreg.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) 1997, Stefan Esser <se@freebsd.org>
    3  * Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
    4  * Copyright (c) 2000, BSDi
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  *
   30  */
   31 
   32 #include <sys/param.h>          /* XXX trim includes */
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/kernel.h>
   36 #include <sys/module.h>
   37 #include <sys/malloc.h>
   38 #include <vm/vm.h>
   39 #include <vm/pmap.h>
   40 #include <machine/md_var.h>
   41 #include <pci/pcivar.h>
   42 #include <pci/pcireg.h>
   43 #include <isa/isavar.h>
   44 #include <i386/isa/pcibus.h>
   45 /* #include <machine/nexusvar.h> */
   46 #include <machine/clock.h>
   47 #include <machine/pci_cfgreg.h>
   48 #include <machine/segments.h>
   49 #include <machine/pc/bios.h>
   50 
   51 #ifdef APIC_IO
   52 #include <machine/smp.h>
   53 #endif /* APIC_IO */
   54 
   55 static int cfgmech;
   56 static int devmax;
   57 
   58 #define PRVERB(a) printf a
   59 static int      pci_cfgintr_unique(struct PIR_entry *pe, int pin);
   60 static int      pci_cfgintr_linked(struct PIR_entry *pe, int pin);
   61 static int      pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
   62 static int      pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
   63 
   64 static int      pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
   65 static void     pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
   66 static int      pcireg_cfgopen(void);
   67 
   68 static struct PIR_table *pci_route_table;
   69 static int              pci_route_count;
   70 
   71 static u_int16_t
   72 pcibios_get_version(void)
   73 {
   74     struct bios_regs args;
   75 
   76     if (PCIbios.entry == 0) {
   77         PRVERB(("pcibios: No call entry point\n"));
   78         return (0);
   79     }
   80     args.eax = PCIBIOS_BIOS_PRESENT;
   81     if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
   82         PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
   83         return (0);
   84     }
   85     if (args.edx != 0x20494350) {
   86         PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
   87         return (0);
   88     }
   89     return (args.ebx & 0xffff);
   90 }
   91 
   92 /* 
   93  * Initialise access to PCI configuration space 
   94  */
   95 int
   96 pci_cfgregopen(void)
   97 {
   98     static int                  opened = 0;
   99     u_long                      sigaddr;
  100     static struct PIR_table     *pt;
  101     u_int8_t                    ck, *cv;
  102     int                         i;
  103 
  104     if (opened)
  105         return(1);
  106 
  107     if (pcireg_cfgopen() == 0)
  108         return(0);
  109 
  110     /*
  111      * Look for the interrupt routing table.
  112      */
  113     /* We use PCI BIOS's PIR table if it's available */
  114     if (pcibios_get_version() >= 0x0210 && pt == NULL && 
  115       (sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0)) != 0) {
  116         pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
  117         for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < (pt->pt_header.ph_length); i++) {
  118             ck += cv[i];
  119         }
  120         if (ck == 0) {
  121             pci_route_table = pt;
  122             pci_route_count = (pt->pt_header.ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry);
  123             printf("Using $PIR table, %d entries at %p\n", pci_route_count, pci_route_table);
  124         }
  125     }
  126 
  127     opened = 1;
  128     return(1);
  129 }
  130 
  131 /* 
  132  * Read configuration space register
  133  */
  134 static u_int32_t
  135 pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
  136 {
  137     return(pcireg_cfgread(bus, slot, func, reg, bytes));
  138 }
  139 
  140 u_int32_t
  141 pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
  142 {
  143 #ifdef APIC_IO
  144     /*
  145      * If we are using the APIC, the contents of the intline register will probably
  146      * be wrong (since they are set up for use with the PIC.
  147      * Rather than rewrite these registers (maybe that would be smarter) we trap
  148      * attempts to read them and translate to our private vector numbers.
  149      */
  150     if ((reg == PCIR_INTLINE) && (bytes == 1)) {
  151         int     pin, line;
  152 
  153         pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
  154         line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
  155 
  156         if (pin != 0) {
  157             int airq;
  158 
  159             airq = pci_apic_irq(bus, slot, pin, NULL);
  160             if (airq >= 0) {
  161                 /* PCI specific entry found in MP table */
  162                 if (airq != line)
  163                     undirect_pci_irq(line);
  164                 return(airq);
  165             } else {
  166                 /* 
  167                  * PCI interrupts might be redirected to the
  168                  * ISA bus according to some MP tables. Use the
  169                  * same methods as used by the ISA devices
  170                  * devices to find the proper IOAPIC int pin.
  171                  */
  172                 airq = isa_apic_irq(line);
  173                 if ((airq >= 0) && (airq != line)) {
  174                     /* XXX: undirect_pci_irq() ? */
  175                     undirect_isa_irq(line);
  176                     return(airq);
  177                 }
  178             }
  179         }
  180         return(line);
  181     }
  182 #endif /* APIC_IO */
  183     return(pci_do_cfgregread(bus, slot, func, reg, bytes));
  184 }
  185 
  186 /* 
  187  * Write configuration space register 
  188  */
  189 void
  190 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
  191 {
  192     return(pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
  193 }
  194 
  195 int
  196 pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
  197 {
  198         return(pci_cfgregread(cfg->bus, cfg->slot, cfg->func, reg, bytes));
  199 }
  200 
  201 void
  202 pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
  203 {
  204         pci_cfgregwrite(cfg->bus, cfg->slot, cfg->func, reg, data, bytes);
  205 }
  206 
  207 
  208 /*
  209  * Route a PCI interrupt
  210  *
  211  * XXX we don't do anything "right" with the function number in the PIR table
  212  *     (because the consumer isn't currently passing it in).  We don't care
  213  *     anyway, due to the way PCI interrupts are assigned.
  214  */
  215 int
  216 pci_cfgintr(int bus, int device, int pin)
  217 {
  218     struct PIR_entry    *pe;
  219     int                 i, irq;
  220     struct bios_regs    args;
  221     u_int16_t           v;
  222     int already = 0;
  223     
  224     v = pcibios_get_version();
  225     if (v < 0x0210) {
  226         PRVERB((
  227           "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
  228           (v & 0xff00) >> 8, v & 0xff));
  229         return (255);
  230     }
  231     if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
  232       (pin < 1) || (pin > 4))
  233         return(255);
  234 
  235     /*
  236      * Scan the entry table for a contender
  237      */
  238     for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, pe++) {
  239         if ((bus != pe->pe_bus) || (device != pe->pe_device))
  240             continue;
  241 
  242         irq = pci_cfgintr_linked(pe, pin);
  243         if (irq != 255)
  244              already = 1;
  245         if (irq == 255)
  246             irq = pci_cfgintr_unique(pe, pin);
  247         if (irq == 255)
  248             irq = pci_cfgintr_virgin(pe, pin);
  249 
  250         if (irq == 255)
  251             break;
  252 
  253         /*
  254          * Ask the BIOS to route the interrupt
  255          */
  256         args.eax = PCIBIOS_ROUTE_INTERRUPT;
  257         args.ebx = (bus << 8) | (device << 3);
  258         args.ecx = (irq << 8) | (0xa + pin - 1);        /* pin value is 0xa - 0xd */
  259         if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)) && !already) {
  260             /*
  261              * XXX if it fails, we should try to smack the router
  262              * hardware directly.
  263              * XXX Also, there may be other choices that we can try that
  264              * will work.
  265              */
  266             PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n"));
  267             return(255);
  268         }
  269         printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, device, 'A' + pin - 1, irq);
  270         return(irq);
  271     }
  272 
  273     PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1));
  274     return(255);
  275 }
  276 
  277 /*
  278  * Look to see if the routing table claims this pin is uniquely routed.
  279  */
  280 static int
  281 pci_cfgintr_unique(struct PIR_entry *pe, int pin)
  282 {
  283     int         irq;
  284     
  285     if (powerof2(pe->pe_intpin[pin - 1].irqs)) {
  286         irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1;
  287         PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
  288         return(irq);
  289     }
  290     return(255);
  291 }
  292 
  293 /*
  294  * Look for another device which shares the same link byte and
  295  * already has a unique IRQ, or which has had one routed already.
  296  */
  297 static int
  298 pci_cfgintr_linked(struct PIR_entry *pe, int pin)
  299 {
  300     struct PIR_entry    *oe;
  301     struct PIR_intpin   *pi;
  302     int                 i, j, irq;
  303 
  304     /*
  305      * Scan table slots.
  306      */
  307     for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, oe++) {
  308 
  309         /* scan interrupt pins */
  310         for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
  311 
  312             /* don't look at the entry we're trying to match with */
  313             if ((pe == oe) && (i == (pin - 1)))
  314                 continue;
  315 
  316             /* compare link bytes */
  317             if (pi->link != pe->pe_intpin[pin - 1].link)
  318                 continue;
  319             
  320             /* link destination mapped to a unique interrupt? */
  321             if (powerof2(pi->irqs)) {
  322                 irq = ffs(pi->irqs) - 1;
  323                 PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
  324                        pi->link, irq));
  325                 return(irq);
  326             } 
  327 
  328             /* look for the real PCI device that matches this table entry */
  329             if ((irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, j, pin)) != 255)
  330                 return(irq);
  331         }
  332     }
  333     return(255);
  334 }
  335 
  336 /*
  337  * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and
  338  * see if it has already been assigned an interrupt.
  339  */
  340 static int
  341 pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin)
  342 {
  343     devclass_t          pci_devclass;
  344     device_t            *pci_devices;
  345     int                 pci_count;
  346     device_t            *pci_children;
  347     int                 pci_childcount;
  348     device_t            *busp, *childp;
  349     int                 i, j, irq;
  350 
  351     /*
  352      * Find all the PCI busses.
  353      */
  354     pci_count = 0;
  355     if ((pci_devclass = devclass_find("pci")) != NULL)
  356         devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
  357 
  358     /*
  359      * Scan all the PCI busses/devices looking for this one.
  360      */
  361     irq = 255;
  362     for (i = 0, busp = pci_devices; (i < pci_count) && (irq == 255); i++, busp++) {
  363         pci_childcount = 0;
  364         device_get_children(*busp, &pci_children, &pci_childcount);
  365                 
  366         for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) {
  367             if ((pci_get_bus(*childp) == bus) &&
  368                 (pci_get_slot(*childp) == device) &&
  369                 (pci_get_intpin(*childp) == matchpin)) {
  370                 irq = pci_get_irq(*childp);
  371                 /*
  372                  * Some BIOS writers seem to want to ignore the spec and put
  373                  * 0 in the intline rather than 255 to indicate none.  Once
  374                  * we've found one that matches, we break because there can
  375                  * be no others (which is why test looks a little odd).
  376                  */
  377                 if (irq == 0)
  378                     irq = 255;
  379                 if (irq != 255)
  380                     PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
  381                       pe->pe_intpin[pin - 1].link, irq,
  382                       pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp)));
  383                 break;
  384             }
  385         }
  386         if (pci_children != NULL)
  387             free(pci_children, M_TEMP);
  388     }
  389     if (pci_devices != NULL)
  390         free(pci_devices, M_TEMP);
  391     return(irq);
  392 }
  393 
  394 /*
  395  * Pick a suitable IRQ from those listed as routable to this device.
  396  */
  397 static int
  398 pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
  399 {
  400     int         irq, ibit;
  401     
  402     /* first scan the set of PCI-only interrupts and see if any of these are routable */
  403     for (irq = 0; irq < 16; irq++) {
  404         ibit = (1 << irq);
  405 
  406         /* can we use this interrupt? */
  407         if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
  408             (pe->pe_intpin[pin - 1].irqs & ibit)) {
  409             PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
  410             return(irq);
  411         }
  412     }
  413     
  414     /* life is tough, so just pick an interrupt */
  415     for (irq = 0; irq < 16; irq++) {
  416         ibit = (1 << irq);
  417     
  418         if (pe->pe_intpin[pin - 1].irqs & ibit) {
  419             PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
  420             return(irq);
  421         }
  422     }
  423     return(255);
  424 }
  425 
  426 /* 
  427  * Configuration space access using direct register operations
  428  */
  429 
  430 /* enable configuration space accesses and return data port address */
  431 static int
  432 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
  433 {
  434     int dataport = 0;
  435 
  436     if (bus <= PCI_BUSMAX
  437         && slot < devmax
  438         && func <= PCI_FUNCMAX
  439         && reg <= PCI_REGMAX
  440         && bytes != 3
  441         && (unsigned) bytes <= 4
  442         && (reg & (bytes -1)) == 0) {
  443         switch (cfgmech) {
  444         case 1:
  445             outl(CONF1_ADDR_PORT, (1 << 31)
  446                  | (bus << 16) | (slot << 11) 
  447                  | (func << 8) | (reg & ~0x03));
  448             dataport = CONF1_DATA_PORT + (reg & 0x03);
  449             break;
  450         case 2:
  451             outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
  452             outb(CONF2_FORWARD_PORT, bus);
  453             dataport = 0xc000 | (slot << 8) | reg;
  454             break;
  455         }
  456     }
  457     return (dataport);
  458 }
  459 
  460 /* disable configuration space accesses */
  461 static void
  462 pci_cfgdisable(void)
  463 {
  464     switch (cfgmech) {
  465     case 1:
  466         /*
  467          * Do nothing for the config mechanism 1 case.
  468          * Writing a 0 to the address port can apparently
  469          * confuse some bridges and cause spurious
  470          * access failures.
  471          */
  472         break;
  473     case 2:
  474         outb(CONF2_ENABLE_PORT, 0);
  475         break;
  476     }
  477 }
  478 
  479 static int
  480 pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
  481 {
  482     int data = -1;
  483     int port;
  484 
  485     port = pci_cfgenable(bus, slot, func, reg, bytes);
  486 
  487     if (port != 0) {
  488         switch (bytes) {
  489         case 1:
  490             data = inb(port);
  491             break;
  492         case 2:
  493             data = inw(port);
  494             break;
  495         case 4:
  496             data = inl(port);
  497             break;
  498         }
  499         pci_cfgdisable();
  500     }
  501     return (data);
  502 }
  503 
  504 static void
  505 pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
  506 {
  507     int port;
  508 
  509     port = pci_cfgenable(bus, slot, func, reg, bytes);
  510     if (port != 0) {
  511         switch (bytes) {
  512         case 1:
  513             outb(port, data);
  514             break;
  515         case 2:
  516             outw(port, data);
  517             break;
  518         case 4:
  519             outl(port, data);
  520             break;
  521         }
  522         pci_cfgdisable();
  523     }
  524 }
  525 
  526 /* check whether the configuration mechanism has been correctly identified */
  527 static int
  528 pci_cfgcheck(int maxdev)
  529 {
  530     u_char device;
  531 
  532     if (bootverbose) 
  533         printf("pci_cfgcheck:\tdevice ");
  534 
  535     for (device = 0; device < maxdev; device++) {
  536         unsigned id, class, header;
  537         if (bootverbose) 
  538             printf("%d ", device);
  539 
  540         id = inl(pci_cfgenable(0, device, 0, 0, 4));
  541         if (id == 0 || id == -1)
  542             continue;
  543 
  544         class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
  545         if (bootverbose)
  546             printf("[class=%06x] ", class);
  547         if (class == 0 || (class & 0xf870ff) != 0)
  548             continue;
  549 
  550         header = inb(pci_cfgenable(0, device, 0, 14, 1));
  551         if (bootverbose) 
  552             printf("[hdr=%02x] ", header);
  553         if ((header & 0x7e) != 0)
  554             continue;
  555 
  556         if (bootverbose)
  557             printf("is there (id=%08x)\n", id);
  558 
  559         pci_cfgdisable();
  560         return (1);
  561     }
  562     if (bootverbose) 
  563         printf("-- nothing found\n");
  564 
  565     pci_cfgdisable();
  566     return (0);
  567 }
  568 
  569 static int
  570 pcireg_cfgopen(void)
  571 {
  572     unsigned long mode1res,oldval1;
  573     unsigned char mode2res,oldval2;
  574 
  575     /* Check for type #1 first. */
  576     oldval1 = inl(CONF1_ADDR_PORT);
  577 
  578     if (bootverbose) {
  579         printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
  580                oldval1);
  581     }
  582 
  583     cfgmech = 1;
  584     devmax = 32;
  585 
  586     outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
  587     DELAY(1);
  588     mode1res = inl(CONF1_ADDR_PORT);
  589     outl(CONF1_ADDR_PORT, oldval1);
  590 
  591     if (bootverbose)
  592         printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 
  593             mode1res, CONF1_ENABLE_CHK);
  594 
  595     if (mode1res) {
  596         if (pci_cfgcheck(32)) 
  597             return (cfgmech);
  598     }
  599 
  600     outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
  601     mode1res = inl(CONF1_ADDR_PORT);
  602     outl(CONF1_ADDR_PORT, oldval1);
  603 
  604     if (bootverbose)
  605         printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 
  606             mode1res, CONF1_ENABLE_CHK1);
  607 
  608     if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
  609         if (pci_cfgcheck(32)) 
  610             return (cfgmech);
  611     }
  612 
  613     /* Type #1 didn't work, so try type #2. */
  614     oldval2 = inb(CONF2_ENABLE_PORT);
  615 
  616     if (bootverbose) {
  617         printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
  618                oldval2);
  619     }
  620 
  621     if ((oldval2 & 0xf0) == 0) {
  622 
  623         cfgmech = 2;
  624         devmax = 16;
  625 
  626         outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
  627         mode2res = inb(CONF2_ENABLE_PORT);
  628         outb(CONF2_ENABLE_PORT, oldval2);
  629 
  630         if (bootverbose)
  631             printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 
  632                    mode2res, CONF2_ENABLE_CHK);
  633 
  634         if (mode2res == CONF2_ENABLE_RES) {
  635             if (bootverbose)
  636                 printf("pci_open(2a):\tnow trying mechanism 2\n");
  637 
  638             if (pci_cfgcheck(16)) 
  639                 return (cfgmech);
  640         }
  641     }
  642 
  643     /* Nothing worked, so punt. */
  644     cfgmech = 0;
  645     devmax = 0;
  646     return (cfgmech);
  647 }

Cache object: 8276bb8e577a194a698b3c82262b155d


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