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