[BACK]Return to pcibios.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / pci

Annotation of sys/arch/i386/pci/pcibios.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pcibios.c,v 1.37 2007/03/19 05:32:05 deraadt Exp $    */
                      2: /*     $NetBSD: pcibios.c,v 1.5 2000/08/01 05:23:59 uch Exp $  */
                      3:
                      4: /*
                      5:  * Copyright (c) 2000 Michael Shalayeff
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following 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 OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
                     21:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     22:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     23:  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     25:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
                     26:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     27:  * THE POSSIBILITY OF SUCH DAMAGE.
                     28:  */
                     29: /*-
                     30:  * Copyright (c) 1999 The NetBSD Foundation, Inc.
                     31:  * All rights reserved.
                     32:  *
                     33:  * This code is derived from software contributed to The NetBSD Foundation
                     34:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                     35:  * NASA Ames Research Center.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer.
                     42:  * 2. Redistributions in binary form must reproduce the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer in the
                     44:  *    documentation and/or other materials provided with the distribution.
                     45:  * 3. All advertising materials mentioning features or use of this software
                     46:  *    must display the following acknowledgement:
                     47:  *     This product includes software developed by the NetBSD
                     48:  *     Foundation, Inc. and its contributors.
                     49:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     50:  *    contributors may be used to endorse or promote products derived
                     51:  *    from this software without specific prior written permission.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     54:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     55:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     56:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     57:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     58:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     59:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     60:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     61:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     62:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     63:  * POSSIBILITY OF SUCH DAMAGE.
                     64:  */
                     65: /*
                     66:  * Copyright (c) 1999, by UCHIYAMA Yasushi
                     67:  * All rights reserved.
                     68:  *
                     69:  * Redistribution and use in source and binary forms, with or without
                     70:  * modification, are permitted provided that the following conditions
                     71:  * are met:
                     72:  * 1. Redistributions of source code must retain the above copyright
                     73:  *    notice, this list of conditions and the following disclaimer.
                     74:  * 2. The name of the developer may NOT be used to endorse or promote products
                     75:  *    derived from this software without specific prior written permission.
                     76:  *
                     77:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     78:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     79:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     80:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     81:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     82:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     83:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     84:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     85:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     86:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     87:  * SUCH DAMAGE.
                     88:  */
                     89:
                     90: /*
                     91:  * Interface to the PCI BIOS and PCI Interrupt Routing table.
                     92:  */
                     93:
                     94: #include <sys/param.h>
                     95: #include <sys/systm.h>
                     96: #include <sys/device.h>
                     97: #include <sys/malloc.h>
                     98:
                     99: #include <dev/isa/isareg.h>
                    100: #include <i386/isa/isa_machdep.h>
                    101:
                    102: #include <dev/pci/pcireg.h>
                    103: #include <dev/pci/pcivar.h>
                    104: #include <dev/pci/pcidevs.h>
                    105:
                    106: #include <i386/pci/pcibiosvar.h>
                    107:
                    108: #include <machine/biosvar.h>
                    109:
                    110: int pcibios_flags;
                    111: int pcibios_present;
                    112:
                    113: struct pcibios_pir_header pcibios_pir_header;
                    114: struct pcibios_intr_routing *pcibios_pir_table;
                    115: int pcibios_pir_table_nentries;
                    116: int pcibios_flags = 0;
                    117:
                    118: struct bios32_entry pcibios_entry;
                    119: struct bios32_entry_info pcibios_entry_info;
                    120:
                    121: struct pcibios_intr_routing *pcibios_pir_init(struct pcibios_softc *);
                    122:
                    123: int    pcibios_get_status(struct pcibios_softc *,
                    124:            u_int32_t *, u_int32_t *, u_int32_t *,
                    125:            u_int32_t *, u_int32_t *, u_int32_t *, u_int32_t *);
                    126: int    pcibios_get_intr_routing(struct pcibios_softc *,
                    127:            struct pcibios_intr_routing *, int *, u_int16_t *);
                    128:
                    129: int    pcibios_return_code(struct pcibios_softc *, u_int16_t, const char *);
                    130:
                    131: void   pcibios_print_exclirq(struct pcibios_softc *);
                    132: void   pcibios_print_pir_table(void);
                    133:
                    134: #define        PCI_IRQ_TABLE_START     0xf0000
                    135: #define        PCI_IRQ_TABLE_END       0xfffff
                    136:
                    137: struct cfdriver pcibios_cd = {
                    138:        NULL, "pcibios", DV_DULL
                    139: };
                    140:
                    141: int pcibiosprobe(struct device *, void *, void *);
                    142: void pcibiosattach(struct device *, struct device *, void *);
                    143:
                    144: struct cfattach pcibios_ca = {
                    145:        sizeof(struct pcibios_softc), pcibiosprobe, pcibiosattach
                    146: };
                    147:
                    148: int
                    149: pcibiosprobe(struct device *parent, void *match, void *aux)
                    150: {
                    151:        struct bios_attach_args *ba = aux;
                    152:        u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2, maxbus;
                    153:        int rv;
                    154:
                    155:        if (strcmp(ba->bios_dev, "pcibios"))
                    156:                return 0;
                    157:
                    158:        rv = bios32_service(PCIBIOS_SIGNATURE, &pcibios_entry,
                    159:                &pcibios_entry_info);
                    160:
                    161:        PCIBIOS_PRINTV(("pcibiosprobe: 0x%lx:0x%lx at 0x%lx[0x%lx]\n",
                    162:            pcibios_entry.segment, pcibios_entry.offset,
                    163:            pcibios_entry_info.bei_base, pcibios_entry_info.bei_size));
                    164:
                    165:        return rv &&
                    166:            pcibios_get_status(NULL, &rev_maj, &rev_min, &mech1, &mech2,
                    167:                &scmech1, &scmech2, &maxbus) == PCIBIOS_SUCCESS;
                    168: }
                    169:
                    170: void
                    171: pcibiosattach(struct device *parent, struct device *self, void *aux)
                    172: {
                    173:        struct pcibios_softc *sc = (struct pcibios_softc *)self;
                    174:        u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2;
                    175:
                    176:        pcibios_flags = sc->sc_dev.dv_cfdata->cf_flags;
                    177:
                    178:        pcibios_get_status((struct pcibios_softc *)self, &rev_maj,
                    179:            &rev_min, &mech1, &mech2,
                    180:            &scmech1, &scmech2, &sc->max_bus);
                    181:
                    182:        printf(": rev %d.%d @ 0x%lx/0x%lx\n",
                    183:            rev_maj, rev_min >> 4, pcibios_entry_info.bei_base,
                    184:            pcibios_entry_info.bei_size);
                    185:
                    186:        PCIBIOS_PRINTV(("%s: config mechanism %s%s, special cycles %s%s, "
                    187:            "last bus %d\n", sc->sc_dev.dv_xname,
                    188:            mech1 ? "[1]" : "[x]", mech2 ? "[2]" : "[x]",
                    189:            scmech1 ? "[1]" : "[x]", scmech2 ? "[2]" : "[x]", sc->max_bus));
                    190:
                    191:        /*
                    192:         * The PCI BIOS tells us the config mechanism; fill it in now
                    193:         * so that pci_mode_detect() doesn't have to look for it.
                    194:         */
                    195:        pci_mode = mech1 ? 1 : 2;
                    196:
                    197:        pcibios_present = 1;
                    198:
                    199:        /*
                    200:         * Find the PCI IRQ Routing table.
                    201:         */
                    202:
                    203:        if (!(pcibios_flags & PCIBIOS_INTR_FIXUP) &&
                    204:            pcibios_pir_init((struct pcibios_softc *)self) != NULL) {
                    205:                int rv;
                    206:
                    207:                /*
                    208:                 * Fixup interrupt routing.
                    209:                 */
                    210:                rv = pci_intr_fixup(sc, NULL, I386_BUS_SPACE_IO);
                    211:                switch (rv) {
                    212:                case -1:
                    213:                        /* Non-fatal error. */
                    214:                        printf("%s: Warning, unable to fix up PCI interrupt "
                    215:                            "routing\n", sc->sc_dev.dv_xname);
                    216:                        break;
                    217:
                    218:                case 1:
                    219:                        /* Fatal error. */
                    220:                        printf("%s: interrupt fixup failed\n", sc->sc_dev.dv_xname);
                    221:                        return;
                    222:                }
                    223:
                    224:                /*
                    225:                 * XXX Clear `pciirq' from the ISA interrupt allocation
                    226:                 * XXX mask.
                    227:                 */
                    228:        }
                    229:
                    230:        if (!(pcibios_flags & PCIBIOS_BUS_FIXUP)) {
                    231:                sc->max_bus = pci_bus_fixup(NULL, 0);
                    232:                printf("%s: PCI bus #%d is the last bus\n",
                    233:                    sc->sc_dev.dv_xname, sc->max_bus);
                    234:        }
                    235:
                    236:        if (!(pcibios_flags & PCIBIOS_ADDR_FIXUP))
                    237:                pci_addr_fixup(sc, NULL, sc->max_bus);
                    238: }
                    239:
                    240: struct pcibios_intr_routing *
                    241: pcibios_pir_init(struct pcibios_softc *sc)
                    242: {
                    243:        paddr_t pa;
                    244:
                    245:        pcibios_pir_table = NULL;
                    246:        for (pa = PCI_IRQ_TABLE_START; pa < PCI_IRQ_TABLE_END; pa += 16) {
                    247:                u_int8_t *p, cksum;
                    248:                struct pcibios_pir_header *pirh;
                    249:                int i;
                    250:
                    251:                p = ISA_HOLE_VADDR(pa);
                    252:                pirh = (struct pcibios_pir_header *)p;
                    253:                /*
                    254:                 * Some laptops (such as the Toshiba Libretto L series)
                    255:                 * use _PIR instead of the standard $PIR for the signature
                    256:                 * so we check for that too.
                    257:                 */
                    258:                if (pirh->signature != BIOS32_MAKESIG('$', 'P', 'I', 'R') &&
                    259:                    pirh->signature != BIOS32_MAKESIG('_', 'P', 'I', 'R'))
                    260:                        continue;
                    261:
                    262:                if (pirh->tablesize < sizeof(*pirh))
                    263:                        continue;
                    264:
                    265:                cksum = 0;
                    266:                for (i = 0; i < pirh->tablesize; i++)
                    267:                        cksum += p[i];
                    268:
                    269:                printf("%s: PCI IRQ Routing Table rev %d.%d @ 0x%lx/%d "
                    270:                    "(%d entries)\n", sc->sc_dev.dv_xname,
                    271:                    pirh->version >> 8, pirh->version & 0xff, pa,
                    272:                    pirh->tablesize, (pirh->tablesize - sizeof(*pirh)) / 16);
                    273:
                    274:                if (cksum != 0) {
                    275:                        printf("%s: bad IRQ table checksum\n",
                    276:                            sc->sc_dev.dv_xname);
                    277:                        continue;
                    278:                }
                    279:
                    280:                if (pirh->tablesize % 16 != 0) {
                    281:                        printf("%s: bad IRQ table size\n", sc->sc_dev.dv_xname);
                    282:                        continue;
                    283:                }
                    284:
                    285:                if (pirh->version != 0x0100) {
                    286:                        printf("%s: unsupported IRQ table version\n",
                    287:                            sc->sc_dev.dv_xname);
                    288:                        continue;
                    289:                }
                    290:
                    291:                /*
                    292:                 * We can handle this table!  Make a copy of it.
                    293:                 */
                    294:                pcibios_pir_header = *pirh;
                    295:                pcibios_pir_table =
                    296:                    malloc(pirh->tablesize - sizeof(*pirh), M_DEVBUF, M_NOWAIT);
                    297:                if (pcibios_pir_table == NULL) {
                    298:                        printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname);
                    299:                        return NULL;
                    300:                }
                    301:                bcopy(p + sizeof(*pirh), pcibios_pir_table,
                    302:                    pirh->tablesize - sizeof(*pirh));
                    303:                pcibios_pir_table_nentries =
                    304:                    (pirh->tablesize - sizeof(*pirh)) / 16;
                    305:
                    306:        }
                    307:
                    308:        /*
                    309:         * If there was no PIR table found, try using the PCI BIOS
                    310:         * Get Interrupt Routing call.
                    311:         *
                    312:         * XXX The interface to this call sucks; just allocate enough
                    313:         * XXX room for 32 entries.
                    314:         */
                    315:        if (pcibios_pir_table == NULL) {
                    316:
                    317:                pcibios_pir_table_nentries = 32;
                    318:                pcibios_pir_table = malloc(pcibios_pir_table_nentries *
                    319:                    sizeof(*pcibios_pir_table), M_DEVBUF, M_NOWAIT);
                    320:                if (pcibios_pir_table == NULL) {
                    321:                        printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname);
                    322:                        return NULL;
                    323:                }
                    324:                if (pcibios_get_intr_routing(sc, pcibios_pir_table,
                    325:                    &pcibios_pir_table_nentries,
                    326:                    &pcibios_pir_header.exclusive_irq) != PCIBIOS_SUCCESS) {
                    327:                        printf("%s: PCI IRQ Routing information unavailable.\n",
                    328:                            sc->sc_dev.dv_xname);
                    329:                        free(pcibios_pir_table, M_DEVBUF);
                    330:                        pcibios_pir_table = NULL;
                    331:                        pcibios_pir_table_nentries = 0;
                    332:                        return NULL;
                    333:                }
                    334:                printf("%s: PCI BIOS has %d Interrupt Routing table entries\n",
                    335:                    sc->sc_dev.dv_xname, pcibios_pir_table_nentries);
                    336:        }
                    337:
                    338:        pcibios_print_exclirq(sc);
                    339:        if (pcibios_flags & PCIBIOS_INTRDEBUG)
                    340:                pcibios_print_pir_table();
                    341:        return pcibios_pir_table;
                    342: }
                    343:
                    344: int
                    345: pcibios_get_status(struct pcibios_softc *sc, u_int32_t *rev_maj,
                    346:     u_int32_t *rev_min, u_int32_t *mech1, u_int32_t *mech2, u_int32_t *scmech1,
                    347:     u_int32_t *scmech2, u_int32_t *maxbus)
                    348: {
                    349:        u_int32_t ax, bx, cx, edx;
                    350:        int rv;
                    351:
                    352:        __asm __volatile("pushl %%es\n\t"
                    353:                         "pushl %%ds\n\t"
                    354:                         "movw  4(%%edi), %%cx\n\t"
                    355:                         "movl  %%ecx, %%ds\n\t"
                    356:                         "lcall %%cs:*(%%edi)\n\t"
                    357:                         "pop   %%ds\n\t"
                    358:                         "pop   %%es\n\t"
                    359:                         "jc    1f\n\t"
                    360:                         "xor   %%ah, %%ah\n"
                    361:                    "1:"
                    362:                : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (edx)
                    363:                : "0" (0xb101), "D" (&pcibios_entry)
                    364:                : "cc", "memory");
                    365:
                    366:        rv = pcibios_return_code(sc, ax, "pcibios_get_status");
                    367:        if (rv != PCIBIOS_SUCCESS)
                    368:                return (rv);
                    369:
                    370:        if (edx != BIOS32_MAKESIG('P', 'C', 'I', ' '))
                    371:                return (PCIBIOS_SERVICE_NOT_PRESENT);   /* XXX */
                    372:
                    373:        /*
                    374:         * Fill in the various pieces of info we're looking for.
                    375:         */
                    376:        *mech1 = ax & 1;
                    377:        *mech2 = ax & (1 << 1);
                    378:        *scmech1 = ax & (1 << 4);
                    379:        *scmech2 = ax & (1 << 5);
                    380:        *rev_maj = (bx >> 8) & 0xff;
                    381:        *rev_min = bx & 0xff;
                    382:        *maxbus = cx & 0xff;
                    383:
                    384:        return (PCIBIOS_SUCCESS);
                    385: }
                    386:
                    387: int
                    388: pcibios_get_intr_routing(struct pcibios_softc *sc,
                    389:     struct pcibios_intr_routing *table, int *nentries, u_int16_t *exclirq)
                    390: {
                    391:        u_int32_t ax, bx;
                    392:        int rv;
                    393:        struct {
                    394:                u_int16_t size;
                    395:                u_int32_t offset;
                    396:                u_int16_t segment;
                    397:        } __attribute__((__packed__)) args;
                    398:
                    399:        args.size = *nentries * sizeof(*table);
                    400:        args.offset = (u_int32_t)table;
                    401:        args.segment = GSEL(GDATA_SEL, SEL_KPL);
                    402:
                    403:        memset(table, 0, args.size);
                    404:
                    405:        __asm __volatile("pushl %%es\n\t"
                    406:                         "pushl %%ds\n\t"
                    407:                         "movw  4(%%esi), %%cx\n\t"
                    408:                         "movl  %%ecx, %%ds\n\t"
                    409:                         "lcall %%cs:*(%%esi)\n\t"
                    410:                         "popl  %%ds\n\t"
                    411:                         "popl  %%es\n\t"
                    412:                         "jc    1f\n\t"
                    413:                         "xor   %%ah, %%ah\n"
                    414:                    "1:\n"
                    415:                : "=a" (ax), "=b" (bx)
                    416:                : "0" (0xb10e), "1" (0), "D" (&args), "S" (&pcibios_entry)
                    417:                : "%ecx", "%edx", "cc", "memory");
                    418:
                    419:        rv = pcibios_return_code(sc, ax, "pcibios_get_intr_routing");
                    420:        if (rv != PCIBIOS_SUCCESS)
                    421:                return (rv);
                    422:
                    423:        *nentries = args.size / sizeof(*table);
                    424:        *exclirq |= bx;
                    425:
                    426:        return (PCIBIOS_SUCCESS);
                    427: }
                    428:
                    429: int
                    430: pcibios_return_code(struct pcibios_softc *sc, u_int16_t ax, const char *func)
                    431: {
                    432:        const char *errstr;
                    433:        int rv = ax >> 8;
                    434:        char *nam;
                    435:
                    436:        if (sc)
                    437:                nam = sc->sc_dev.dv_xname;
                    438:        else
                    439:                nam = "pcibios0";
                    440:
                    441:        switch (rv) {
                    442:        case PCIBIOS_SUCCESS:
                    443:                return (PCIBIOS_SUCCESS);
                    444:
                    445:        case PCIBIOS_SERVICE_NOT_PRESENT:
                    446:                errstr = "service not present";
                    447:                break;
                    448:
                    449:        case PCIBIOS_FUNCTION_NOT_SUPPORTED:
                    450:                errstr = "function not supported";
                    451:                break;
                    452:
                    453:        case PCIBIOS_BAD_VENDOR_ID:
                    454:                errstr = "bad vendor ID";
                    455:                break;
                    456:
                    457:        case PCIBIOS_DEVICE_NOT_FOUND:
                    458:                errstr = "device not found";
                    459:                break;
                    460:
                    461:        case PCIBIOS_BAD_REGISTER_NUMBER:
                    462:                errstr = "bad register number";
                    463:                break;
                    464:
                    465:        case PCIBIOS_SET_FAILED:
                    466:                errstr = "set failed";
                    467:                break;
                    468:
                    469:        case PCIBIOS_BUFFER_TOO_SMALL:
                    470:                errstr = "buffer too small";
                    471:                break;
                    472:
                    473:        default:
                    474:                printf("%s: %s - unknown return code 0x%x\n",
                    475:                    nam, func, rv);
                    476:                return (rv);
                    477:        }
                    478:
                    479:        printf("%s: %s - %s\n", nam, func, errstr);
                    480:        return (rv);
                    481: }
                    482:
                    483: void
                    484: pcibios_print_exclirq(struct pcibios_softc *sc)
                    485: {
                    486:        int i;
                    487:
                    488:        if (pcibios_pir_header.exclusive_irq) {
                    489:                printf("%s: PCI Exclusive IRQs:", sc->sc_dev.dv_xname);
                    490:                for (i = 0; i < 16; i++) {
                    491:                        if (pcibios_pir_header.exclusive_irq & (1 << i))
                    492:                                printf(" %d", i);
                    493:                }
                    494:                printf("\n");
                    495:        }
                    496: }
                    497:
                    498: void
                    499: pcibios_print_pir_table(void)
                    500: {
                    501:        int i, j;
                    502:
                    503:        for (i = 0; i < pcibios_pir_table_nentries; i++) {
                    504:                printf("PIR Entry %d:\n", i);
                    505:                printf("\tBus: %d  Device: %d\n",
                    506:                    pcibios_pir_table[i].bus,
                    507:                    PIR_DEVFUNC_DEVICE(pcibios_pir_table[i].device));
                    508:                for (j = 0; j < 4; j++) {
                    509:                        printf("\t\tINT%c: link 0x%02x bitmap 0x%04x\n",
                    510:                            'A' + j,
                    511:                            pcibios_pir_table[i].linkmap[j].link,
                    512:                            pcibios_pir_table[i].linkmap[j].bitmap);
                    513:                }
                    514:        }
                    515: }
                    516:
                    517: void
                    518: pci_device_foreach(struct pcibios_softc *sc, pci_chipset_tag_t pc, int maxbus,
                    519:     void (*func)(struct pcibios_softc *, pci_chipset_tag_t, pcitag_t))
                    520: {
                    521:        const struct pci_quirkdata *qd;
                    522:        int bus, device, function, maxdevs, nfuncs;
                    523:        pcireg_t id, bhlcr;
                    524:        pcitag_t tag;
                    525:
                    526:        for (bus = 0; bus <= maxbus; bus++) {
                    527:                maxdevs = pci_bus_maxdevs(pc, bus);
                    528:                for (device = 0; device < maxdevs; device++) {
                    529:                        tag = pci_make_tag(pc, bus, device, 0);
                    530:                        id = pci_conf_read(pc, tag, PCI_ID_REG);
                    531:
                    532:                        /* Invalid vendor ID value? */
                    533:                        if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
                    534:                                continue;
                    535:                        /* XXX Not invalid, but we've done this ~forever. */
                    536:                        if (PCI_VENDOR(id) == 0)
                    537:                                continue;
                    538:
                    539:                        qd = pci_lookup_quirkdata(PCI_VENDOR(id),
                    540:                            PCI_PRODUCT(id));
                    541:
                    542:                        bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
                    543:                        if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
                    544:                            (qd != NULL &&
                    545:                             (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
                    546:                                nfuncs = 8;
                    547:                        else
                    548:                                nfuncs = 1;
                    549:
                    550:                        for (function = 0; function < nfuncs; function++) {
                    551:                                tag = pci_make_tag(pc, bus, device, function);
                    552:                                id = pci_conf_read(pc, tag, PCI_ID_REG);
                    553:
                    554:                                /* Invalid vendor ID value? */
                    555:                                if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
                    556:                                        continue;
                    557:                                /*
                    558:                                 * XXX Not invalid, but we've done this
                    559:                                 * ~forever.
                    560:                                 */
                    561:                                if (PCI_VENDOR(id) == 0)
                    562:                                        continue;
                    563:                                (*func)(sc, pc, tag);
                    564:                        }
                    565:                }
                    566:        }
                    567: }

CVSweb