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

Annotation of sys/arch/macppc/pci/mpcpcibus.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: mpcpcibus.c,v 1.36 2006/12/14 17:36:12 kettenis Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 1997 Per Fogelstrom
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     19:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  *
                     27:  */
                     28:
                     29: /*
                     30:  * Generic PCI BUS Bridge driver.
                     31:  * specialized hooks for different config methods.
                     32:  */
                     33:
                     34: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/kernel.h>
                     37: #include <sys/malloc.h>
                     38: #include <sys/device.h>
                     39: #include <sys/proc.h>
                     40: #include <uvm/uvm_extern.h>
                     41:
                     42: #include <machine/autoconf.h>
                     43: #include <machine/pcb.h>
                     44: #include <machine/bat.h>
                     45: #include <machine/powerpc.h>
                     46:
                     47: #include <dev/pci/pcireg.h>
                     48: #include <dev/pci/pcivar.h>
                     49: #include <dev/pci/pcidevs.h>
                     50:
                     51: #include <macppc/pci/pcibrvar.h>
                     52: #include <macppc/pci/mpc106reg.h>
                     53:
                     54: #include <dev/ofw/openfirm.h>
                     55:
                     56: int    mpcpcibrmatch(struct device *, void *, void *);
                     57: void   mpcpcibrattach(struct device *, struct device *, void *);
                     58:
                     59: void   mpc_attach_hook(struct device *, struct device *,
                     60:                                struct pcibus_attach_args *);
                     61: int    mpc_bus_maxdevs(void *, int);
                     62: pcitag_t mpc_make_tag(void *, int, int, int);
                     63: void   mpc_decompose_tag(void *, pcitag_t, int *, int *, int *);
                     64: pcireg_t mpc_conf_read(void *, pcitag_t, int);
                     65: void   mpc_conf_write(void *, pcitag_t, int, pcireg_t);
                     66:
                     67: int      mpc_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *);
                     68: const char *mpc_intr_string(void *, pci_intr_handle_t);
                     69: int    mpc_intr_line(void *, pci_intr_handle_t);
                     70: void     *mpc_intr_establish(void *, pci_intr_handle_t,
                     71:             int, int (*func)(void *), void *, char *);
                     72: void     mpc_intr_disestablish(void *, void *);
                     73: int      mpc_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
                     74: u_int32_t mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset);
                     75: int    of_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
                     76: int    find_node_intr (int parent, u_int32_t *addr, u_int32_t *intr);
                     77: u_int32_t pci_iack(void);
                     78:
                     79: void fix_node_irq(int node, struct pcibus_attach_args *pba);
                     80:
                     81: struct cfattach mpcpcibr_ca = {
                     82:         sizeof(struct pcibr_softc), mpcpcibrmatch, mpcpcibrattach,
                     83: };
                     84:
                     85: struct cfdriver mpcpcibr_cd = {
                     86:        NULL, "mpcpcibr", DV_DULL,
                     87: };
                     88:
                     89: static int      mpcpcibrprint(void *, const char *pnp);
                     90:
                     91: struct pcibr_config mpc_config;
                     92:
                     93: /*
                     94:  * config types
                     95:  * bit meanings
                     96:  * 0 - standard cf8/cfc type configurations,
                     97:  *     sometimes the base addresses for these are different
                     98:  * 1 - Config Method #2 configuration - uni-north
                     99:  *
                    100:  * 2 - 64 bit config bus, data for accesses &4 is at daddr+4;
                    101:  */
                    102: struct config_type{
                    103:        char * compat;
                    104:        u_int32_t addr; /* offset */
                    105:        u_int32_t data; /* offset */
                    106:        int config_type;
                    107: };
                    108: struct config_type config_offsets[] = {
                    109:        {"grackle",             0x00c00cf8, 0x00e00cfc, 0 },
                    110:        {"bandit",              0x00800000, 0x00c00000, 1 },
                    111:        {"uni-north",           0x00800000, 0x00c00000, 3 },
                    112:        {"u3-agp",              0x00800000, 0x00c00000, 3 },
                    113:        {"u3-ht",               0x00000cf8, 0x00000cfc, 3 },
                    114:        {"legacy",              0x00000cf8, 0x00000cfc, 0 },
                    115:        {"IBM,27-82660",        0x00000cf8, 0x00000cfc, 0 },
                    116:        {NULL,                  0x00000000, 0x00000000, 0 },
                    117: };
                    118:
                    119: struct powerpc_bus_dma_tag pci_bus_dma_tag = {
                    120:        NULL,
                    121:        _dmamap_create,
                    122:        _dmamap_destroy,
                    123:        _dmamap_load,
                    124:        _dmamap_load_mbuf,
                    125:        _dmamap_load_uio,
                    126:        _dmamap_load_raw,
                    127:        _dmamap_unload,
                    128:        _dmamap_sync,
                    129:        _dmamem_alloc,
                    130:        _dmamem_free,
                    131:        _dmamem_map,
                    132:        _dmamem_unmap,
                    133:        _dmamem_mmap
                    134: };
                    135:
                    136: int
                    137: mpcpcibrmatch(struct device *parent, void *match, void *aux)
                    138: {
                    139:        struct confargs *ca = aux;
                    140:        int found = 0;
                    141:
                    142:        if (strcmp(ca->ca_name, mpcpcibr_cd.cd_name) != 0)
                    143:                return (found);
                    144:
                    145:        found = 1;
                    146:
                    147:        return found;
                    148: }
                    149:
                    150: int pci_map_a = 0;
                    151:
                    152: struct ranges_32 {
                    153:        u_int32_t flags;
                    154:        u_int32_t pad1;
                    155:        u_int32_t pad2;
                    156:        u_int32_t base;
                    157:        u_int32_t pad3;
                    158:        u_int32_t size;
                    159: };
                    160: void
                    161: mpcpcibus_find_ranges_32 (struct pcibr_softc *sc, u_int32_t *range_store,
                    162:     int rangesize);
                    163: void
                    164: mpcpcibus_find_ranges_64 (struct pcibr_softc *sc, u_int32_t *range_store,
                    165:     int rangesize);
                    166: void
                    167: mpcpcibus_find_ranges_32 (struct pcibr_softc *sc, u_int32_t *range_store,
                    168:     int rangesize)
                    169: {
                    170:        int found;
                    171:        unsigned int base = 0;
                    172:        unsigned int size = 0;
                    173:        struct ranges_32 *prange = (void *)range_store;
                    174:        int rangelen;
                    175:        int i;
                    176:
                    177:        rangelen = rangesize / sizeof (struct ranges_32);
                    178:
                    179:        /* mac configs */
                    180:        sc->sc_membus_space.bus_base = 0;
                    181:        sc->sc_membus_space.bus_io = 0;
                    182:        sc->sc_iobus_space.bus_base = 0;
                    183:        sc->sc_iobus_space.bus_io = 1;
                    184:
                    185:        /* find io(config) base, flag == 0x01000000 */
                    186:        found = 0;
                    187:        for (i = 0; i < rangelen ; i++) {
                    188:                if (prange[i].flags == 0x01000000) {
                    189:                        /* find last? */
                    190:                        found = i;
                    191:                }
                    192:        }
                    193:        /* found the io space ranges */
                    194:        if (prange[found].flags == 0x01000000) {
                    195:                sc->sc_iobus_space.bus_base =
                    196:                    prange[found].base;
                    197:                sc->sc_iobus_space.bus_size =
                    198:                    prange[found].size;
                    199:        }
                    200:
                    201:        /* the mem space ranges
                    202:         * apple openfirmware always puts full
                    203:         * addresses in config information,
                    204:         * it is not necessary to have correct bus
                    205:         * base address, but since 0 is reserved
                    206:         * and all IO and device memory will be in
                    207:         * upper 2G of address space, set to
                    208:         * 0x80000000
                    209:         * start with segment 1 not 0, 0 is config.
                    210:         */
                    211:        for (i = 0; i < rangelen ; i++) {
                    212:                if (prange[i].flags == 0x02000000) {
                    213: #ifdef DEBUG_PCI
                    214:                        printf("\nfound mem %x %x",
                    215:                                prange[i].base,
                    216:                                prange[i].size);
                    217: #endif
                    218:                        if (base != 0) {
                    219:                                if ((base + size) == prange[i].base)
                    220:                                        size += prange[i].size;
                    221:                                else {
                    222:                                        size = prange[i].size;
                    223:                                        base = prange[i].base;
                    224:                                }
                    225:                        } else {
                    226:                                base = prange[i].base;
                    227:                                size = prange[i].size;
                    228:                        }
                    229:                }
                    230:        }
                    231:        sc->sc_membus_space.bus_base = base;
                    232:        sc->sc_membus_space.bus_size = size;
                    233: }
                    234:
                    235: struct ranges_64 {
                    236:        u_int32_t flags;
                    237:        u_int32_t pad1;
                    238:        u_int32_t pad2;
                    239:        u_int32_t pad3;
                    240:        u_int32_t base;
                    241:        u_int32_t pad4;
                    242:        u_int32_t size;
                    243: };
                    244: void
                    245: mpcpcibus_find_ranges_64 (struct pcibr_softc *sc, u_int32_t *range_store,
                    246:     int rangesize)
                    247: {
                    248:        int i, found;
                    249:        unsigned int base = 0;
                    250:        unsigned int size = 0;
                    251:        int rangelen;
                    252:        struct ranges_64 *prange = (void *)range_store;
                    253:
                    254:        rangelen = rangesize / sizeof (struct ranges_64);
                    255:
                    256:        /* mac configs */
                    257:
                    258:        sc->sc_membus_space.bus_base = 0;
                    259:        sc->sc_membus_space.bus_io = 0;
                    260:        sc->sc_iobus_space.bus_base = 0;
                    261:        sc->sc_iobus_space.bus_io = 1;
                    262:
                    263:        if (prange[0].flags == 0xabb10113) { /* appl U3; */
                    264:                prange[0].flags = 0x01000000;
                    265:                prange[0].base = 0xf8070000;
                    266:                prange[0].size = 0x00001000;
                    267:                prange[1].flags = 0x02000000;
                    268:                prange[1].base = 0xf2000000;
                    269:                prange[1].size = 0x02800000;
                    270:                rangelen = 2;
                    271:        }
                    272:
                    273:        /* find io(config) base, flag == 0x01000000 */
                    274:        found = 0;
                    275:        for (i = 0; i < rangelen ; i++) {
                    276:                if (prange[i].flags == 0x01000000) {
                    277:                        /* find last? */
                    278:                        found = i;
                    279:                }
                    280:        }
                    281:        /* found the io space ranges */
                    282:        if (prange[found].flags == 0x01000000) {
                    283:                sc->sc_iobus_space.bus_base = prange[found].base;
                    284:                sc->sc_iobus_space.bus_size = prange[found].size;
                    285:        }
                    286:
                    287:        /* the mem space ranges
                    288:         * apple openfirmware always puts full
                    289:         * addresses in config information,
                    290:         * it is not necessary to have correct bus
                    291:         * base address, but since 0 is reserved
                    292:         * and all IO and device memory will be in
                    293:         * upper 2G of address space, set to
                    294:         * 0x80000000
                    295:         * start with segment 1 not 0, 0 is config.
                    296:         */
                    297:        for (i = 0; i < rangelen ; i++) {
                    298:                if (prange[i].flags == 0x02000000) {
                    299: #ifdef DEBUG_PCI
                    300:                        printf("\nfound mem %x %x",
                    301:                                prange[i].base,
                    302:                                prange[i].size);
                    303: #endif
                    304:
                    305:                        if (base != 0) {
                    306:                                if ((base + size) == prange[i].base) {
                    307:                                        size += prange[i].size;
                    308:                                } else {
                    309:                                        base = prange[i].base;
                    310:                                        size = prange[i].size;
                    311:                                }
                    312:                        } else {
                    313:                                base = prange[i].base;
                    314:                                size = prange[i].size;
                    315:                        }
                    316:                }
                    317:        }
                    318:        sc->sc_membus_space.bus_base = base;
                    319:        sc->sc_membus_space.bus_size = size;
                    320: }
                    321:
                    322: void
                    323: mpcpcibrattach(struct device *parent, struct device *self, void *aux)
                    324: {
                    325:        struct pcibr_softc *sc = (struct pcibr_softc *)self;
                    326:        struct confargs *ca = aux;
                    327:        struct pcibr_config *lcp;
                    328:        struct pcibus_attach_args pba;
                    329:        int node;
                    330:        int of_node = 0;
                    331:        char compat[32];
                    332:        u_int32_t addr_offset;
                    333:        u_int32_t data_offset;
                    334:        int i;
                    335:        int len;
                    336:        int rangesize;
                    337:        u_int32_t range_store[32];
                    338:
                    339:        if (ca->ca_node == 0) {
                    340:                printf("invalid node on mpcpcibr config\n");
                    341:                return;
                    342:        }
                    343:        len=OF_getprop(ca->ca_node, "name", compat, sizeof (compat));
                    344:        compat[len] = '\0';
                    345:        if (len > 0)
                    346:                printf(" %s", compat);
                    347:
                    348:        len=OF_getprop(ca->ca_node, "compatible", compat,
                    349:            sizeof (compat));
                    350:        if (len <= 0 ) {
                    351:                len=OF_getprop(ca->ca_node, "name", compat,
                    352:                        sizeof (compat));
                    353:                if (len <= 0) {
                    354:                        printf(" compatible and name not found\n");
                    355:                        return;
                    356:                }
                    357:                compat[len] = 0;
                    358:                if (strcmp (compat, "bandit") != 0) {
                    359:                        printf(" compatible not found and name %s found\n",
                    360:                            compat);
                    361:                        return;
                    362:                }
                    363:        }
                    364:        compat[len] = 0;
                    365:        if ((rangesize = OF_getprop(ca->ca_node, "ranges",
                    366:            range_store, sizeof (range_store))) <= 0) {
                    367:                if (strcmp(compat, "u3-ht") == 0) {
                    368:                        range_store[0] = 0xabb10113; /* appl U3; */
                    369:                } else
                    370:                        printf("range lookup failed, node %x\n", ca->ca_node);
                    371:        }
                    372:        /* translate byte(s) into item count*/
                    373:
                    374:        lcp = sc->sc_pcibr = &sc->pcibr_config;
                    375:
                    376:        if (ppc_proc_is_64b)
                    377:                mpcpcibus_find_ranges_64 (sc, range_store, rangesize);
                    378:        else
                    379:                mpcpcibus_find_ranges_32 (sc, range_store, rangesize);
                    380:
                    381:        addr_offset = 0;
                    382:        for (i = 0; config_offsets[i].compat != NULL; i++) {
                    383:                struct config_type *co = &config_offsets[i];
                    384:                if (strcmp(co->compat, compat) == 0) {
                    385:                        addr_offset = co->addr;
                    386:                        data_offset = co->data;
                    387:                        lcp->config_type = co->config_type;
                    388:                        break;
                    389:                }
                    390:        }
                    391:        if (addr_offset == 0) {
                    392:                printf("unable to find match for"
                    393:                    " compatible %s\n", compat);
                    394:                return;
                    395:        }
                    396: #ifdef DEBUG_FIXUP
                    397:        printf(" mem base %x sz %x io base %x sz %x\n"
                    398:            " config addr %x config data %x\n",
                    399:            sc->sc_membus_space.bus_base,
                    400:            sc->sc_membus_space.bus_size,
                    401:            sc->sc_iobus_space.bus_base,
                    402:            sc->sc_iobus_space.bus_size,
                    403:            addr_offset, data_offset);
                    404: #endif
                    405:
                    406:        if ( bus_space_map(&(sc->sc_iobus_space), addr_offset,
                    407:                NBPG, 0, &lcp->ioh_cf8) != 0 )
                    408:                panic("mpcpcibus: unable to map self");
                    409:
                    410:        if ( bus_space_map(&(sc->sc_iobus_space), data_offset,
                    411:                NBPG, 0, &lcp->ioh_cfc) != 0 )
                    412:                panic("mpcpcibus: unable to map self");
                    413:
                    414:        of_node = ca->ca_node;
                    415:
                    416:        lcp->node = ca->ca_node;
                    417:        lcp->lc_pc.pc_conf_v = lcp;
                    418:        lcp->lc_pc.pc_attach_hook = mpc_attach_hook;
                    419:        lcp->lc_pc.pc_bus_maxdevs = mpc_bus_maxdevs;
                    420:        lcp->lc_pc.pc_make_tag = mpc_make_tag;
                    421:        lcp->lc_pc.pc_decompose_tag = mpc_decompose_tag;
                    422:        lcp->lc_pc.pc_conf_read = mpc_conf_read;
                    423:        lcp->lc_pc.pc_conf_write = mpc_conf_write;
                    424:        lcp->lc_pc.pc_ether_hw_addr = of_ether_hw_addr;
                    425:        lcp->lc_iot = &sc->sc_iobus_space;
                    426:        lcp->lc_memt = &sc->sc_membus_space;
                    427:
                    428:        lcp->lc_pc.pc_intr_v = lcp;
                    429:        lcp->lc_pc.pc_intr_map = mpc_intr_map;
                    430:        lcp->lc_pc.pc_intr_string = mpc_intr_string;
                    431:        lcp->lc_pc.pc_intr_line = mpc_intr_line;
                    432:        lcp->lc_pc.pc_intr_establish = mpc_intr_establish;
                    433:        lcp->lc_pc.pc_intr_disestablish = mpc_intr_disestablish;
                    434:
                    435:        printf(": %s, Revision 0x%x\n", compat,
                    436:            mpc_cfg_read_1(lcp, MPC106_PCI_REVID));
                    437:
                    438:        if ((strcmp(compat, "bandit")) != 0)
                    439:                pci_addr_fixup(sc, &lcp->lc_pc, 32);
                    440:
                    441:        pba.pba_dmat = &pci_bus_dma_tag;
                    442:
                    443:        pba.pba_busname = "pci";
                    444:        pba.pba_iot = &sc->sc_iobus_space;
                    445:        pba.pba_memt = &sc->sc_membus_space;
                    446:        pba.pba_pc = &lcp->lc_pc;
                    447:        pba.pba_domain = pci_ndomains++;
                    448:        pba.pba_bus = 0;
                    449:        pba.pba_bridgetag = NULL;
                    450:
                    451:        /* we want to check pci irq settings */
                    452:        if (of_node != 0) {
                    453:                int nn;
                    454:
                    455:                for (node = OF_child(of_node); node; node = nn) {
                    456:                        char name[32];
                    457:                        int len;
                    458:                        len = OF_getprop(node, "name", name,
                    459:                            sizeof(name));
                    460:                        name[len] = 0;
                    461:                        fix_node_irq(node, &pba);
                    462:
                    463:                        /* iterate section */
                    464:                        if ((nn = OF_child(node)) != 0)
                    465:                                continue;
                    466:
                    467:                        while ((nn = OF_peer(node)) == 0) {
                    468:                                node = OF_parent(node);
                    469:                                if (node == of_node) {
                    470:                                        nn = 0; /* done */
                    471:                                        break;
                    472:                                }
                    473:                        }
                    474:                }
                    475:        }
                    476:
                    477:        config_found(self, &pba, mpcpcibrprint);
                    478:
                    479: }
                    480:
                    481: #define       OFW_PCI_PHYS_HI_BUSMASK         0x00ff0000
                    482: #define       OFW_PCI_PHYS_HI_BUSSHIFT        16
                    483: #define       OFW_PCI_PHYS_HI_DEVICEMASK      0x0000f800
                    484: #define       OFW_PCI_PHYS_HI_DEVICESHIFT     11
                    485: #define       OFW_PCI_PHYS_HI_FUNCTIONMASK    0x00000700
                    486: #define       OFW_PCI_PHYS_HI_FUNCTIONSHIFT   8
                    487:
                    488: #define pcibus(x) \
                    489:        (((x) & OFW_PCI_PHYS_HI_BUSMASK) >> OFW_PCI_PHYS_HI_BUSSHIFT)
                    490: #define pcidev(x) \
                    491:        (((x) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT)
                    492: #define pcifunc(x) \
                    493:        (((x) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT)
                    494:
                    495: /*
                    496:  * Find PCI IRQ from OF.
                    497:  */
                    498: int
                    499: find_node_intr(int parent, u_int32_t *addr, u_int32_t *intr)
                    500: {
                    501:        int iparent, len, mlen, alen, ilen;
                    502:        int match, i, step;
                    503:        u_int32_t map[144], *mp, *mp1;
                    504:        u_int32_t imask[8], maskedaddr[8];
                    505:        u_int32_t address_cells, interrupt_cells, mask_cells;
                    506:
                    507:        len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
                    508:        mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
                    509:        alen = OF_getprop(parent, "#address-cells",
                    510:            &address_cells, sizeof(address_cells));
                    511:        ilen = OF_getprop(parent, "#interrupt-cells",
                    512:            &interrupt_cells, sizeof(interrupt_cells));
                    513:
                    514:        if (len == -1 || mlen == -1 || alen == -1 || ilen == -1)
                    515:                goto nomap;
                    516:
                    517:        mask_cells = address_cells + interrupt_cells;
                    518:        if (mask_cells != (mlen / sizeof(u_int32_t)))
                    519:                goto nomap;
                    520:        for (i = 0; i < mask_cells; i++)
                    521:                maskedaddr[i] = addr[i] & imask[i];
                    522:
                    523:        /* interrupt-map is formatted as follows
                    524:         * int * #address-cells, int * #interrupt-cells, int, int, int
                    525:         * eg
                    526:         * address-cells = 3
                    527:         * interrupt-cells = 1
                    528:         * 00001000 00000000 00000000 00000000 ff911258 00000034 00000001
                    529:         * 00001800 00000000 00000000 00000000 ff911258 00000035 00000001
                    530:         * 00002000 00000000 00000000 00000000 ff911258 00000036 00000001
                    531:         * | address cells          | | intr | |parent| | irq  | |edge/level|
                    532:         *                            | cells|          | interrupt cells   |
                    533:         *                                              | of parent         |
                    534:         * or at least something close to that.
                    535:         */
                    536:
                    537:        mp = map;
                    538:        while (len > mlen) {
                    539:                mp1 = mp + mask_cells;
                    540:
                    541:                iparent = *mp1;
                    542:                alen = OF_getprop(iparent, "#address-cells",
                    543:                    &address_cells, sizeof(address_cells));
                    544:                if (alen == -1)
                    545:                        address_cells = 0;
                    546:                ilen = OF_getprop(iparent, "#interrupt-cells",
                    547:                    &interrupt_cells, sizeof(interrupt_cells));
                    548:                if (ilen == -1)
                    549:                        goto nomap;
                    550:
                    551:                step = mask_cells + 1 + address_cells + interrupt_cells;
                    552:
                    553:                match = bcmp(maskedaddr, mp, mlen);
                    554:                if (match == 0) {
                    555:                        if (OF_getprop(iparent, "interrupt-controller",
                    556:                                       NULL, 0) == 0) {
                    557:                                *intr = mp1[1];
                    558:                                return 1;
                    559:                        }
                    560:                        /* Recurse with new 'addr'. */
                    561:                        return find_node_intr(iparent, &mp1[1], intr);
                    562:                }
                    563:                len -= step * sizeof(u_int32_t);
                    564:                mp += step;
                    565:        }
                    566: nomap:
                    567:        return -1;
                    568: }
                    569:
                    570: void
                    571: fix_node_irq(int node, struct pcibus_attach_args *pba)
                    572: {
                    573:        struct {
                    574:                u_int32_t phys_hi, phys_mid, phys_lo;
                    575:                u_int32_t size_hi, size_lo;
                    576:        } addr [8];
                    577:        u_int32_t map[144];
                    578:        int len;
                    579:        pcitag_t tag;
                    580:        u_int32_t irq;
                    581:        u_int32_t intr;
                    582:        int parent;
                    583:
                    584:        pci_chipset_tag_t pc = pba->pba_pc;
                    585:
                    586:        len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
                    587:        if (len == -1 || len < sizeof(addr[0]))
                    588:                return;
                    589:
                    590:        /* if this node has a AAPL,interrupts property, firmware
                    591:         * has initialized the register correctly.
                    592:         */
                    593:        len = OF_getprop(node, "AAPL,interrupts", &intr, 4);
                    594:        if (len != 4) {
                    595:
                    596:                parent = OF_parent(node);
                    597:
                    598:                irq = -1;
                    599:
                    600:                /* we want the first interrupt, set size_hi to 1 */
                    601:                addr[0].size_hi = 1;
                    602:                if (find_node_intr(parent, &addr[0].phys_hi, &irq) == -1) {
                    603:                        len = OF_getprop(node, "interrupts", map,
                    604:                            sizeof(map));
                    605:                        if (len != -1 && len != 4) {
                    606:                                irq = map[0];
                    607:                        } else
                    608:                                return;
                    609:                }
                    610:        } else
                    611:                irq = intr;
                    612:        /* program the interrupt line register with the value
                    613:         * found in openfirmware
                    614:         */
                    615:
                    616:        tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
                    617:            pcidev(addr[0].phys_hi), pcifunc(addr[0].phys_hi));
                    618:
                    619:        intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
                    620:        intr &= ~PCI_INTERRUPT_LINE_MASK;
                    621:        intr |= irq & PCI_INTERRUPT_LINE_MASK;
                    622:        pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
                    623: }
                    624:
                    625: static int
                    626: mpcpcibrprint(void *aux, const char *pnp)
                    627: {
                    628:        struct pcibus_attach_args *pba = aux;
                    629:
                    630:        if (pnp)
                    631:                printf("%s at %s", pba->pba_busname, pnp);
                    632:        printf(" bus %d", pba->pba_bus);
                    633:        return(UNCONF);
                    634: }
                    635:
                    636: void
                    637: mpc_attach_hook(struct device *parent, struct device *self,
                    638:     struct pcibus_attach_args *pba)
                    639: {
                    640: }
                    641:
                    642: int
                    643: of_ether_hw_addr(struct ppc_pci_chipset *lcpc, u_int8_t *oaddr)
                    644: {
                    645:        u_int8_t laddr[6];
                    646:        struct pcibr_config *lcp = lcpc->pc_conf_v;
                    647:        int of_node = lcp->node;
                    648:        int node, nn;
                    649:        for (node = OF_child(of_node); node; node = nn) {
                    650:                char name[32];
                    651:                int len;
                    652:                len = OF_getprop(node, "name", name,
                    653:                        sizeof(name));
                    654:                name[len] = 0;
                    655:
                    656:                len = OF_getprop(node, "local-mac-address", laddr,
                    657:                    sizeof laddr);
                    658:                if (sizeof (laddr) == len) {
                    659:                        bcopy (laddr, oaddr, sizeof laddr);
                    660:                        return 1;
                    661:                }
                    662:
                    663:                /* iterate section */
                    664:                if ((nn = OF_child(node)) != 0) {
                    665:                        continue;
                    666:                }
                    667:                while ((nn = OF_peer(node)) == 0) {
                    668:                        node = OF_parent(node);
                    669:                        if (node == of_node) {
                    670:                                nn = 0; /* done */
                    671:                                break;
                    672:                        }
                    673:                }
                    674:        }
                    675:        oaddr[0] = oaddr[1] = oaddr[2] = 0xff;
                    676:        oaddr[3] = oaddr[4] = oaddr[5] = 0xff;
                    677:        return 0;
                    678: }
                    679:
                    680: int
                    681: mpc_ether_hw_addr(struct ppc_pci_chipset *p, u_int8_t *s)
                    682: {
                    683:        printf("mpc_ether_hw_addr not supported\n");
                    684:        return(0);
                    685: }
                    686:
                    687: int
                    688: mpc_bus_maxdevs(void *cpv, int busno)
                    689: {
                    690:        return(32);
                    691: }
                    692:
                    693: #define BUS_SHIFT 16
                    694: #define DEVICE_SHIFT 11
                    695: #define FNC_SHIFT 8
                    696:
                    697: pcitag_t
                    698: mpc_make_tag(void *cpv, int bus, int dev, int fnc)
                    699: {
                    700:        return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT);
                    701: }
                    702:
                    703: void
                    704: mpc_decompose_tag(void *cpv, pcitag_t tag, int *busp, int *devp, int *fncp)
                    705: {
                    706:        if (busp != NULL)
                    707:                *busp = (tag >> BUS_SHIFT) & 0xff;
                    708:        if (devp != NULL)
                    709:                *devp = (tag >> DEVICE_SHIFT) & 0x1f;
                    710:        if (fncp != NULL)
                    711:                *fncp = (tag >> FNC_SHIFT) & 0x7;
                    712: }
                    713:
                    714: u_int32_t
                    715: mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset)
                    716: {
                    717:        struct pcibr_config *cp = cpv;
                    718:        unsigned int bus, dev, fcn;
                    719:        u_int32_t reg;
                    720:
                    721:        mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
                    722:
                    723:        if (cp->config_type & 1) {
                    724:                /* Config Mechanism #2 */
                    725:                if (bus == 0) {
                    726:                        if (dev < 11)
                    727:                                return 0xffffffff;
                    728:                        /*
                    729:                         * Need to do config type 0 operation
                    730:                         *  1 << (11?+dev) | fcn << 8 | reg
                    731:                         * 11? is because pci spec states
                    732:                         * that 11-15 is reserved.
                    733:                         */
                    734:                        reg = 1 << (dev) | fcn << 8 | offset;
                    735:
                    736:                } else {
                    737:                        if (dev > 15)
                    738:                                return 0xffffffff;
                    739:                        /*
                    740:                         * config type 1
                    741:                         */
                    742:                        reg =  tag | offset | 1;
                    743:                }
                    744:        } else {
                    745:                /* config mechanism #2, type 0
                    746:                 * standard cf8/cfc config
                    747:                 */
                    748:                reg =  0x80000000 | tag  | offset;
                    749:        }
                    750:
                    751:        return reg;
                    752: }
                    753:
                    754: /* #define DEBUG_CONFIG  */
                    755: pcireg_t
                    756: mpc_conf_read(void *cpv, pcitag_t tag, int offset)
                    757: {
                    758:        struct pcibr_config *cp = cpv;
                    759:        pcireg_t data;
                    760:        u_int32_t reg;
                    761:        int s;
                    762:        int daddr = 0;
                    763:        faultbuf env;
                    764:        void *oldh;
                    765:
                    766:        if (offset & 3 || offset < 0 || offset >= 0x100) {
                    767: #ifdef DEBUG_CONFIG
                    768:                printf ("pci_conf_read: bad reg %x\n", offset);
                    769: #endif /* DEBUG_CONFIG */
                    770:                return(~0);
                    771:        }
                    772:
                    773:        reg = mpc_gen_config_reg(cpv, tag, offset);
                    774:        /* if invalid tag, return -1 */
                    775:        if (reg == 0xffffffff)
                    776:                return(~0);
                    777:
                    778:        if ((cp->config_type & 2) && (offset & 0x04))
                    779:                daddr += 4;
                    780:
                    781:        s = splhigh();
                    782:
                    783:        oldh = curpcb->pcb_onfault;
                    784:        if (setfault(&env)) {
                    785:                /* we faulted during the read? */
                    786:                curpcb->pcb_onfault = oldh;
                    787:                splx(s);
                    788:                return 0xffffffff;
                    789:        }
                    790:
                    791:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
                    792:        bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
                    793:        data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr);
                    794:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
                    795:        bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
                    796:
                    797:        curpcb->pcb_onfault = oldh;
                    798:
                    799:        splx(s);
                    800: #ifdef DEBUG_CONFIG
                    801:        if (!((offset == 0) && (data == 0xffffffff))) {
                    802:                unsigned int bus, dev, fcn;
                    803:                mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
                    804:                printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn,
                    805:                        offset);
                    806:                printf(" daddr %x reg %x",daddr, reg);
                    807:                printf(" data %x\n", data);
                    808:        }
                    809: #endif
                    810:
                    811:        return(data);
                    812: }
                    813:
                    814: void
                    815: mpc_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
                    816: {
                    817:        struct pcibr_config *cp = cpv;
                    818:        u_int32_t reg;
                    819:        int s;
                    820:        int daddr = 0;
                    821:
                    822:        reg = mpc_gen_config_reg(cpv, tag, offset);
                    823:
                    824:        /* if invalid tag, return ??? */
                    825:        if (reg == 0xffffffff)
                    826:                return;
                    827:
                    828:        if ((cp->config_type & 2) && (offset & 0x04))
                    829:                daddr += 4;
                    830:
                    831: #ifdef DEBUG_CONFIG
                    832:        {
                    833:                unsigned int bus, dev, fcn;
                    834:                mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
                    835:                printf("mpc_conf_write bus %x dev %x fcn %x offset %x", bus,
                    836:                        dev, fcn, offset);
                    837:                printf(" daddr %x reg %x",daddr, reg);
                    838:                printf(" data %x\n", data);
                    839:        }
                    840: #endif
                    841:
                    842:        s = splhigh();
                    843:
                    844:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
                    845:        bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
                    846:        bus_space_write_4(cp->lc_iot, cp->ioh_cfc, daddr, data);
                    847:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
                    848:        bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
                    849:
                    850:        splx(s);
                    851: }
                    852:
                    853:
                    854: /*ARGSUSED*/
                    855: int
                    856: mpc_intr_map(void *lcv, pcitag_t bustag, int buspin, int  line,
                    857:     pci_intr_handle_t *ihp)
                    858: {
                    859:        int error = 0;
                    860:
                    861:        *ihp = -1;
                    862:         if (buspin == 0)
                    863:                 error = 1; /* No IRQ used. */
                    864:         else if (buspin > 4) {
                    865:                 printf("mpc_intr_map: bad interrupt pin %d\n", buspin);
                    866:                 error = 1;
                    867:         }
                    868:
                    869:        if (!error)
                    870:                *ihp = line;
                    871:        return error;
                    872: }
                    873:
                    874: const char *
                    875: mpc_intr_string(void *lcv, pci_intr_handle_t ih)
                    876: {
                    877:        static char str[16];
                    878:
                    879:        snprintf(str, sizeof str, "irq %ld", ih);
                    880:        return(str);
                    881: }
                    882:
                    883: int
                    884: mpc_intr_line(void *lcv, pci_intr_handle_t ih)
                    885: {
                    886:        return (ih);
                    887: }
                    888:
                    889: void *
                    890: mpc_intr_establish(void *lcv, pci_intr_handle_t ih, int level,
                    891:     int (*func)(void *), void *arg, char *name)
                    892: {
                    893:        return (*intr_establish_func)(lcv, ih, IST_LEVEL, level, func, arg,
                    894:                name);
                    895: }
                    896:
                    897: void
                    898: mpc_intr_disestablish(void *lcv, void *cookie)
                    899: {
                    900:        /* XXX We should probably do something clever here.... later */
                    901: }
                    902:
                    903: u_int32_t
                    904: pci_iack()
                    905: {
                    906:        /* do pci IACK cycle */
                    907:        /* this should be bus allocated. */
                    908:        volatile u_int8_t *iack = (u_int8_t *)0xbffffff0;
                    909:        u_int8_t val;
                    910:
                    911:        val = *iack;
                    912:        return val;
                    913: }
                    914:
                    915: void
                    916: mpc_cfg_write_1(struct pcibr_config *cp, u_int32_t reg, u_int8_t val)
                    917: {
                    918:        int s;
                    919:        s = splhigh();
                    920:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
                    921:        bus_space_write_1(cp->lc_iot, cp->ioh_cfc, 0, val);
                    922:        splx(s);
                    923: }
                    924:
                    925: void
                    926: mpc_cfg_write_2(struct pcibr_config *cp, u_int32_t reg, u_int16_t val)
                    927: {
                    928:        int s;
                    929:        s = splhigh();
                    930:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
                    931:        bus_space_write_2(cp->lc_iot, cp->ioh_cfc, 0, val);
                    932:        splx(s);
                    933: }
                    934:
                    935: void
                    936: mpc_cfg_write_4(struct pcibr_config *cp, u_int32_t reg, u_int32_t val)
                    937: {
                    938:
                    939:        int s;
                    940:        s = splhigh();
                    941:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
                    942:        bus_space_write_4(cp->lc_iot, cp->ioh_cfc, 0, val);
                    943:        splx(s);
                    944: }
                    945:
                    946: u_int8_t
                    947: mpc_cfg_read_1(struct pcibr_config *cp, u_int32_t reg)
                    948: {
                    949:        u_int8_t _v_;
                    950:
                    951:        int s;
                    952:        s = splhigh();
                    953:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
                    954:        _v_ = bus_space_read_1(cp->lc_iot, cp->ioh_cfc, 0);
                    955:        splx(s);
                    956:        return(_v_);
                    957: }
                    958:
                    959: u_int16_t
                    960: mpc_cfg_read_2(struct pcibr_config *cp, u_int32_t reg)
                    961: {
                    962:        u_int16_t _v_;
                    963:
                    964:        int s;
                    965:        s = splhigh();
                    966:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
                    967:        _v_ = bus_space_read_2(cp->lc_iot, cp->ioh_cfc, 0);
                    968:        splx(s);
                    969:        return(_v_);
                    970: }
                    971:
                    972: u_int32_t
                    973: mpc_cfg_read_4(struct pcibr_config *cp, u_int32_t reg)
                    974: {
                    975:        u_int32_t _v_;
                    976:
                    977:        int s;
                    978:        s = splhigh();
                    979:        bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
                    980:        _v_ = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, 0);
                    981:        splx(s);
                    982:        return(_v_);
                    983: }

CVSweb