[BACK]Return to pci_machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / x86 / pci

Annotation of src/sys/arch/x86/pci/pci_machdep.c, Revision 1.19

1.19    ! jmcneill    1: /*     $NetBSD: pci_machdep.c,v 1.18 2006/11/16 01:32:39 christos Exp $        */
1.1       fvdl        2:
                      3: /*-
                      4:  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                      9:  * NASA Ames Research Center.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
                     42:  * Copyright (c) 1994 Charles M. Hannum.  All rights reserved.
                     43:  *
                     44:  * Redistribution and use in source and binary forms, with or without
                     45:  * modification, are permitted provided that the following conditions
                     46:  * are met:
                     47:  * 1. Redistributions of source code must retain the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer.
                     49:  * 2. Redistributions in binary form must reproduce the above copyright
                     50:  *    notice, this list of conditions and the following disclaimer in the
                     51:  *    documentation and/or other materials provided with the distribution.
                     52:  * 3. All advertising materials mentioning features or use of this software
                     53:  *    must display the following acknowledgement:
                     54:  *     This product includes software developed by Charles M. Hannum.
                     55:  * 4. The name of the author may not be used to endorse or promote products
                     56:  *    derived from this software without specific prior written permission.
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     59:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     60:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     61:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     62:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     63:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     64:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     65:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     66:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     67:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     68:  */
                     69:
                     70: /*
                     71:  * Machine-specific functions for PCI autoconfiguration.
                     72:  *
                     73:  * On PCs, there are two methods of generating PCI configuration cycles.
                     74:  * We try to detect the appropriate mechanism for this machine and set
                     75:  * up a few function pointers to access the correct method directly.
                     76:  *
                     77:  * The configuration method can be hard-coded in the config file by
                     78:  * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
                     79:  * as defined section 3.6.4.1, `Generating Configuration Cycles'.
                     80:  */
                     81:
                     82: #include <sys/cdefs.h>
1.19    ! jmcneill   83: __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.18 2006/11/16 01:32:39 christos Exp $");
1.1       fvdl       84:
                     85: #include <sys/types.h>
                     86: #include <sys/param.h>
                     87: #include <sys/time.h>
                     88: #include <sys/systm.h>
                     89: #include <sys/errno.h>
                     90: #include <sys/device.h>
                     91: #include <sys/lock.h>
                     92:
                     93: #include <uvm/uvm_extern.h>
                     94:
                     95: #include <machine/bus.h>
1.10      yamt       96: #include <machine/bus_private.h>
1.1       fvdl       97:
                     98: #include <machine/pio.h>
                     99:
1.3       fvdl      100: #include <dev/isa/isareg.h>
1.1       fvdl      101: #include <dev/isa/isavar.h>
                    102: #include <dev/pci/pcivar.h>
                    103: #include <dev/pci/pcireg.h>
                    104: #include <dev/pci/pcidevs.h>
                    105:
1.16      christos  106: #include "acpi.h"
1.14      bouyer    107: #include "opt_mpbios.h"
1.16      christos  108: #include "opt_acpi.h"
1.14      bouyer    109:
                    110: #ifdef MPBIOS
                    111: #include <machine/mpbiosvar.h>
                    112: #endif
                    113:
1.16      christos  114: #if NACPI > 0
1.14      bouyer    115: #include <machine/mpacpi.h>
                    116: #endif
                    117:
1.16      christos  118: #include <machine/mpconfig.h>
                    119:
1.1       fvdl      120: #include "opt_pci_conf_mode.h"
                    121:
1.19    ! jmcneill  122: #ifdef __i386__
        !           123: #include "opt_xbox.h"
        !           124: #ifdef XBOX
        !           125: #include <machine/xbox.h>
        !           126: #endif
        !           127: #endif
        !           128:
1.1       fvdl      129: int pci_mode = -1;
                    130:
1.11      sekiya    131: static void pci_bridge_hook(pci_chipset_tag_t, pcitag_t, void *);
                    132: struct pci_bridge_hook_arg {
                    133:        void (*func)(pci_chipset_tag_t, pcitag_t, void *);
                    134:        void *arg;
                    135: };
                    136:
                    137:
1.1       fvdl      138: struct simplelock pci_conf_slock = SIMPLELOCK_INITIALIZER;
                    139:
                    140: #define        PCI_CONF_LOCK(s)                                                \
                    141: do {                                                                   \
                    142:        (s) = splhigh();                                                \
                    143:        simple_lock(&pci_conf_slock);                                   \
                    144: } while (0)
                    145:
                    146: #define        PCI_CONF_UNLOCK(s)                                              \
                    147: do {                                                                   \
                    148:        simple_unlock(&pci_conf_slock);                                 \
                    149:        splx((s));                                                      \
                    150: } while (0)
                    151:
                    152: #define        PCI_MODE1_ENABLE        0x80000000UL
                    153: #define        PCI_MODE1_ADDRESS_REG   0x0cf8
                    154: #define        PCI_MODE1_DATA_REG      0x0cfc
                    155:
                    156: #define        PCI_MODE2_ENABLE_REG    0x0cf8
                    157: #define        PCI_MODE2_FORWARD_REG   0x0cfa
                    158:
                    159: #define _m1tag(b, d, f) \
                    160:        (PCI_MODE1_ENABLE | ((b) << 16) | ((d) << 11) | ((f) << 8))
                    161: #define _qe(bus, dev, fcn, vend, prod) \
                    162:        {_m1tag(bus, dev, fcn), PCI_ID_CODE(vend, prod)}
                    163: struct {
                    164:        u_int32_t tag;
                    165:        pcireg_t id;
                    166: } pcim1_quirk_tbl[] = {
                    167:        _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX1),
                    168:        /* XXX Triflex2 not tested */
                    169:        _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX2),
                    170:        _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX4),
                    171:        /* Triton needed for Connectix Virtual PC */
                    172:        _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437FX),
                    173:        /* Connectix Virtual PC 5 has a 440BX */
                    174:        _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX_NOAGP),
1.15      soren     175:        /* Parallels Desktop for Mac */
                    176:        _qe(0, 2, 0, PCI_VENDOR_PARALLELS, PCI_PRODUCT_PARALLELS_VIDEO),
                    177:        _qe(0, 3, 0, PCI_VENDOR_PARALLELS, PCI_PRODUCT_PARALLELS_TOOLS),
1.12      christos  178:        /* SIS 741 */
                    179:        _qe(0, 0, 0, PCI_VENDOR_SIS, PCI_PRODUCT_SIS_741),
1.1       fvdl      180:        {0, 0xffffffff} /* patchable */
                    181: };
                    182: #undef _m1tag
                    183: #undef _id
                    184: #undef _qe
                    185:
                    186: /*
                    187:  * PCI doesn't have any special needs; just use the generic versions
                    188:  * of these functions.
                    189:  */
                    190: struct x86_bus_dma_tag pci_bus_dma_tag = {
1.3       fvdl      191: #if defined(_LP64) || defined(PAE)
                    192:        PCI32_DMA_BOUNCE_THRESHOLD,     /* bounce_thresh */
                    193:        ISA_DMA_BOUNCE_THRESHOLD,       /* bounce_alloclo */
                    194:        PCI32_DMA_BOUNCE_THRESHOLD,     /* bounce_allochi */
                    195: #else
                    196:        0,
                    197:        0,
                    198:        0,
                    199: #endif
                    200:        NULL,                   /* _may_bounce */
1.1       fvdl      201:        _bus_dmamap_create,
                    202:        _bus_dmamap_destroy,
                    203:        _bus_dmamap_load,
                    204:        _bus_dmamap_load_mbuf,
                    205:        _bus_dmamap_load_uio,
                    206:        _bus_dmamap_load_raw,
                    207:        _bus_dmamap_unload,
1.3       fvdl      208: #if defined(_LP64) || defined(PAE)
                    209:        _bus_dmamap_sync,
                    210: #else
                    211:        NULL,
                    212: #endif
1.1       fvdl      213:        _bus_dmamem_alloc,
                    214:        _bus_dmamem_free,
                    215:        _bus_dmamem_map,
                    216:        _bus_dmamem_unmap,
                    217:        _bus_dmamem_mmap,
                    218: };
1.5       fvdl      219:
                    220: #ifdef _LP64
                    221: struct x86_bus_dma_tag pci_bus_dma64_tag = {
                    222:        0,
                    223:        0,
                    224:        0,
                    225:        NULL,                   /* _may_bounce */
                    226:        _bus_dmamap_create,
                    227:        _bus_dmamap_destroy,
                    228:        _bus_dmamap_load,
                    229:        _bus_dmamap_load_mbuf,
                    230:        _bus_dmamap_load_uio,
                    231:        _bus_dmamap_load_raw,
                    232:        _bus_dmamap_unload,
                    233:        NULL,
                    234:        _bus_dmamem_alloc,
                    235:        _bus_dmamem_free,
                    236:        _bus_dmamem_map,
                    237:        _bus_dmamem_unmap,
                    238:        _bus_dmamem_mmap,
                    239: };
                    240: #endif
1.1       fvdl      241:
                    242: void
1.18      christos  243: pci_attach_hook(struct device *parent, struct device *self,
1.17      christos  244:     struct pcibus_attach_args *pba)
1.1       fvdl      245: {
                    246:
                    247:        if (pba->pba_bus == 0)
                    248:                printf(": configuration mode %d", pci_mode);
1.4       fvdl      249: #ifdef MPBIOS
                    250:        mpbios_pci_attach_hook(parent, self, pba);
                    251: #endif
1.16      christos  252: #if NACPI > 0
1.4       fvdl      253:        mpacpi_pci_attach_hook(parent, self, pba);
                    254: #endif
1.1       fvdl      255: }
                    256:
                    257: int
1.18      christos  258: pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
1.1       fvdl      259: {
                    260:
1.19    ! jmcneill  261: #if defined(__i386__) && defined(XBOX)
        !           262:        /*
        !           263:         * Scanning above the first device is fatal on the Microsoft Xbox.
        !           264:         * If busno=1, only allow for one device.
        !           265:         */
        !           266:        if (arch_i386_is_xbox) {
        !           267:                if (busno == 1)
        !           268:                        return 1;
        !           269:                else if (busno > 1)
        !           270:                        return 0;
        !           271:        }
        !           272: #endif
        !           273:
1.1       fvdl      274:        /*
                    275:         * Bus number is irrelevant.  If Configuration Mechanism 2 is in
                    276:         * use, can only have devices 0-15 on any bus.  If Configuration
                    277:         * Mechanism 1 is in use, can have devices 0-32 (i.e. the `normal'
                    278:         * range).
                    279:         */
                    280:        if (pci_mode == 2)
                    281:                return (16);
                    282:        else
                    283:                return (32);
                    284: }
                    285:
                    286: pcitag_t
1.18      christos  287: pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
1.1       fvdl      288: {
                    289:        pcitag_t tag;
                    290:
                    291: #ifndef PCI_CONF_MODE
                    292:        switch (pci_mode) {
                    293:        case 1:
                    294:                goto mode1;
                    295:        case 2:
                    296:                goto mode2;
                    297:        default:
                    298:                panic("pci_make_tag: mode not configured");
                    299:        }
                    300: #endif
                    301:
                    302: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
                    303: #ifndef PCI_CONF_MODE
                    304: mode1:
                    305: #endif
                    306:        if (bus >= 256 || device >= 32 || function >= 8)
                    307:                panic("pci_make_tag: bad request");
                    308:
                    309:        tag.mode1 = PCI_MODE1_ENABLE |
                    310:                    (bus << 16) | (device << 11) | (function << 8);
                    311:        return tag;
                    312: #endif
                    313:
                    314: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
                    315: #ifndef PCI_CONF_MODE
                    316: mode2:
                    317: #endif
                    318:        if (bus >= 256 || device >= 16 || function >= 8)
                    319:                panic("pci_make_tag: bad request");
                    320:
                    321:        tag.mode2.port = 0xc000 | (device << 8);
                    322:        tag.mode2.enable = 0xf0 | (function << 1);
                    323:        tag.mode2.forward = bus;
                    324:        return tag;
                    325: #endif
                    326: }
                    327:
                    328: void
1.18      christos  329: pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag,
1.17      christos  330:     int *bp, int *dp, int *fp)
1.1       fvdl      331: {
                    332:
                    333: #ifndef PCI_CONF_MODE
                    334:        switch (pci_mode) {
                    335:        case 1:
                    336:                goto mode1;
                    337:        case 2:
                    338:                goto mode2;
                    339:        default:
                    340:                panic("pci_decompose_tag: mode not configured");
                    341:        }
                    342: #endif
                    343:
                    344: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
                    345: #ifndef PCI_CONF_MODE
                    346: mode1:
                    347: #endif
                    348:        if (bp != NULL)
                    349:                *bp = (tag.mode1 >> 16) & 0xff;
                    350:        if (dp != NULL)
                    351:                *dp = (tag.mode1 >> 11) & 0x1f;
                    352:        if (fp != NULL)
                    353:                *fp = (tag.mode1 >> 8) & 0x7;
                    354:        return;
                    355: #endif
                    356:
                    357: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
                    358: #ifndef PCI_CONF_MODE
                    359: mode2:
                    360: #endif
                    361:        if (bp != NULL)
                    362:                *bp = tag.mode2.forward & 0xff;
                    363:        if (dp != NULL)
                    364:                *dp = (tag.mode2.port >> 8) & 0xf;
                    365:        if (fp != NULL)
                    366:                *fp = (tag.mode2.enable >> 1) & 0x7;
                    367: #endif
                    368: }
                    369:
                    370: pcireg_t
1.18      christos  371: pci_conf_read( pci_chipset_tag_t pc, pcitag_t tag,
                    372:     int reg)
1.1       fvdl      373: {
                    374:        pcireg_t data;
                    375:        int s;
                    376:
                    377: #ifndef PCI_CONF_MODE
                    378:        switch (pci_mode) {
                    379:        case 1:
                    380:                goto mode1;
                    381:        case 2:
                    382:                goto mode2;
                    383:        default:
                    384:                panic("pci_conf_read: mode not configured");
                    385:        }
                    386: #endif
                    387:
                    388: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
                    389: #ifndef PCI_CONF_MODE
                    390: mode1:
                    391: #endif
                    392:        PCI_CONF_LOCK(s);
                    393:        outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
                    394:        data = inl(PCI_MODE1_DATA_REG);
                    395:        outl(PCI_MODE1_ADDRESS_REG, 0);
                    396:        PCI_CONF_UNLOCK(s);
                    397:        return data;
                    398: #endif
                    399:
                    400: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
                    401: #ifndef PCI_CONF_MODE
                    402: mode2:
                    403: #endif
                    404:        PCI_CONF_LOCK(s);
                    405:        outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
                    406:        outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
                    407:        data = inl(tag.mode2.port | reg);
                    408:        outb(PCI_MODE2_ENABLE_REG, 0);
                    409:        PCI_CONF_UNLOCK(s);
                    410:        return data;
                    411: #endif
                    412: }
                    413:
                    414: void
1.18      christos  415: pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg,
1.17      christos  416:     pcireg_t data)
1.1       fvdl      417: {
                    418:        int s;
                    419:
                    420: #ifndef PCI_CONF_MODE
                    421:        switch (pci_mode) {
                    422:        case 1:
                    423:                goto mode1;
                    424:        case 2:
                    425:                goto mode2;
                    426:        default:
                    427:                panic("pci_conf_write: mode not configured");
                    428:        }
                    429: #endif
                    430:
                    431: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
                    432: #ifndef PCI_CONF_MODE
                    433: mode1:
                    434: #endif
                    435:        PCI_CONF_LOCK(s);
                    436:        outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
                    437:        outl(PCI_MODE1_DATA_REG, data);
                    438:        outl(PCI_MODE1_ADDRESS_REG, 0);
                    439:        PCI_CONF_UNLOCK(s);
                    440:        return;
                    441: #endif
                    442:
                    443: #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
                    444: #ifndef PCI_CONF_MODE
                    445: mode2:
                    446: #endif
                    447:        PCI_CONF_LOCK(s);
                    448:        outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
                    449:        outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
                    450:        outl(tag.mode2.port | reg, data);
                    451:        outb(PCI_MODE2_ENABLE_REG, 0);
                    452:        PCI_CONF_UNLOCK(s);
                    453: #endif
                    454: }
                    455:
                    456: int
                    457: pci_mode_detect()
                    458: {
                    459:
                    460: #ifdef PCI_CONF_MODE
                    461: #if (PCI_CONF_MODE == 1) || (PCI_CONF_MODE == 2)
                    462:        return (pci_mode = PCI_CONF_MODE);
                    463: #else
                    464: #error Invalid PCI configuration mode.
                    465: #endif
                    466: #else
                    467:        u_int32_t sav, val;
                    468:        int i;
                    469:        pcireg_t idreg;
                    470:
                    471:        if (pci_mode != -1)
                    472:                return pci_mode;
                    473:
                    474:        /*
                    475:         * We try to divine which configuration mode the host bridge wants.
                    476:         */
                    477:
                    478:        sav = inl(PCI_MODE1_ADDRESS_REG);
                    479:
                    480:        pci_mode = 1; /* assume this for now */
                    481:        /*
                    482:         * catch some known buggy implementations of mode 1
                    483:         */
                    484:        for (i = 0; i < sizeof(pcim1_quirk_tbl) / sizeof(pcim1_quirk_tbl[0]);
                    485:             i++) {
                    486:                pcitag_t t;
                    487:
                    488:                if (!pcim1_quirk_tbl[i].tag)
                    489:                        break;
                    490:                t.mode1 = pcim1_quirk_tbl[i].tag;
                    491:                idreg = pci_conf_read(0, t, PCI_ID_REG); /* needs "pci_mode" */
                    492:                if (idreg == pcim1_quirk_tbl[i].id) {
                    493: #ifdef DEBUG
                    494:                        printf("known mode 1 PCI chipset (%08x)\n",
                    495:                               idreg);
                    496: #endif
                    497:                        return (pci_mode);
                    498:                }
                    499:        }
                    500:
                    501:        /*
                    502:         * Strong check for standard compliant mode 1:
                    503:         * 1. bit 31 ("enable") can be set
                    504:         * 2. byte/word access does not affect register
                    505:         */
                    506:        outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE);
                    507:        outb(PCI_MODE1_ADDRESS_REG + 3, 0);
                    508:        outw(PCI_MODE1_ADDRESS_REG + 2, 0);
                    509:        val = inl(PCI_MODE1_ADDRESS_REG);
                    510:        if ((val & 0x80fffffc) != PCI_MODE1_ENABLE) {
                    511: #ifdef DEBUG
                    512:                printf("pci_mode_detect: mode 1 enable failed (%x)\n",
                    513:                       val);
                    514: #endif
                    515:                goto not1;
                    516:        }
                    517:        outl(PCI_MODE1_ADDRESS_REG, 0);
                    518:        val = inl(PCI_MODE1_ADDRESS_REG);
                    519:        if ((val & 0x80fffffc) != 0)
                    520:                goto not1;
                    521:        return (pci_mode);
                    522: not1:
                    523:        outl(PCI_MODE1_ADDRESS_REG, sav);
                    524:
                    525:        /*
                    526:         * This mode 2 check is quite weak (and known to give false
                    527:         * positives on some Compaq machines).
                    528:         * However, this doesn't matter, because this is the
                    529:         * last test, and simply no PCI devices will be found if
                    530:         * this happens.
                    531:         */
                    532:        outb(PCI_MODE2_ENABLE_REG, 0);
                    533:        outb(PCI_MODE2_FORWARD_REG, 0);
                    534:        if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
                    535:            inb(PCI_MODE2_FORWARD_REG) != 0)
                    536:                goto not2;
                    537:        return (pci_mode = 2);
                    538: not2:
                    539:
                    540:        return (pci_mode = 0);
                    541: #endif
                    542: }
                    543:
                    544: /*
                    545:  * Determine which flags should be passed to the primary PCI bus's
                    546:  * autoconfiguration node.  We use this to detect broken chipsets
                    547:  * which cannot safely use memory-mapped device access.
                    548:  */
                    549: int
                    550: pci_bus_flags()
                    551: {
                    552:        int rval = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
                    553:            PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
                    554:        int device, maxndevs;
                    555:        pcitag_t tag;
                    556:        pcireg_t id;
                    557:
                    558:        maxndevs = pci_bus_maxdevs(NULL, 0);
                    559:
                    560:        for (device = 0; device < maxndevs; device++) {
                    561:                tag = pci_make_tag(NULL, 0, device, 0);
                    562:                id = pci_conf_read(NULL, tag, PCI_ID_REG);
                    563:
                    564:                /* Invalid vendor ID value? */
                    565:                if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
                    566:                        continue;
                    567:                /* XXX Not invalid, but we've done this ~forever. */
                    568:                if (PCI_VENDOR(id) == 0)
                    569:                        continue;
                    570:
                    571:                switch (PCI_VENDOR(id)) {
                    572:                case PCI_VENDOR_SIS:
                    573:                        switch (PCI_PRODUCT(id)) {
                    574:                        case PCI_PRODUCT_SIS_85C496:
                    575:                                goto disable_mem;
                    576:                        }
                    577:                        break;
                    578:                }
                    579:        }
                    580:
                    581:        return (rval);
                    582:
                    583:  disable_mem:
                    584:        printf("Warning: broken PCI-Host bridge detected; "
                    585:            "disabling memory-mapped access\n");
                    586:        rval &= ~(PCI_FLAGS_MEM_ENABLED|PCI_FLAGS_MRL_OKAY|PCI_FLAGS_MRM_OKAY|
                    587:            PCI_FLAGS_MWI_OKAY);
                    588:        return (rval);
                    589: }
1.11      sekiya    590:
                    591: void
                    592: pci_device_foreach(pci_chipset_tag_t pc, int maxbus,
                    593:        void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *context)
                    594: {
                    595:        pci_device_foreach_min(pc, 0, maxbus, func, context);
                    596: }
                    597:
                    598: void
                    599: pci_device_foreach_min(pci_chipset_tag_t pc, int minbus, int maxbus,
                    600:        void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *context)
                    601: {
                    602:        const struct pci_quirkdata *qd;
                    603:        int bus, device, function, maxdevs, nfuncs;
                    604:        pcireg_t id, bhlcr;
                    605:        pcitag_t tag;
                    606:
                    607:        for (bus = minbus; bus <= maxbus; bus++) {
                    608:                maxdevs = pci_bus_maxdevs(pc, bus);
                    609:                for (device = 0; device < maxdevs; device++) {
                    610:                        tag = pci_make_tag(pc, bus, device, 0);
                    611:                        id = pci_conf_read(pc, tag, PCI_ID_REG);
                    612:
                    613:                        /* Invalid vendor ID value? */
                    614:                        if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
                    615:                                continue;
                    616:                        /* XXX Not invalid, but we've done this ~forever. */
                    617:                        if (PCI_VENDOR(id) == 0)
                    618:                                continue;
                    619:
                    620:                        qd = pci_lookup_quirkdata(PCI_VENDOR(id),
                    621:                                PCI_PRODUCT(id));
                    622:
                    623:                        bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
                    624:                        if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
                    625:                             (qd != NULL &&
                    626:                             (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
                    627:                                nfuncs = 8;
                    628:                        else
                    629:                                nfuncs = 1;
                    630:
                    631:                        for (function = 0; function < nfuncs; function++) {
                    632:                                tag = pci_make_tag(pc, bus, device, function);
                    633:                                id = pci_conf_read(pc, tag, PCI_ID_REG);
                    634:
                    635:                                /* Invalid vendor ID value? */
                    636:                                if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
                    637:                                        continue;
                    638:                                /*
                    639:                                 * XXX Not invalid, but we've done this
                    640:                                 * ~forever.
                    641:                                 */
                    642:                                if (PCI_VENDOR(id) == 0)
                    643:                                        continue;
                    644:                                (*func)(pc, tag, context);
                    645:                        }
                    646:                }
                    647:        }
                    648: }
                    649:
                    650: void
                    651: pci_bridge_foreach(pci_chipset_tag_t pc, int minbus, int maxbus,
                    652:        void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *ctx)
                    653: {
                    654:        struct pci_bridge_hook_arg bridge_hook;
                    655:
                    656:        bridge_hook.func = func;
                    657:        bridge_hook.arg = ctx;
                    658:
                    659:        pci_device_foreach_min(pc, minbus, maxbus, pci_bridge_hook,
                    660:                &bridge_hook);
                    661: }
                    662:
                    663: static void
                    664: pci_bridge_hook(pci_chipset_tag_t pc, pcitag_t tag, void *ctx)
                    665: {
                    666:        struct pci_bridge_hook_arg *bridge_hook = (void *)ctx;
                    667:        pcireg_t reg;
                    668:
                    669:        reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
                    670:        if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
                    671:             (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI ||
                    672:                PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) {
                    673:                (*bridge_hook->func)(pc, tag, bridge_hook->arg);
                    674:        }
                    675: }

CVSweb <webmaster@jp.NetBSD.org>