[BACK]Return to ebus_mainbus.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc64 / dev

Annotation of sys/arch/sparc64/dev/ebus_mainbus.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ebus_mainbus.c,v 1.3 2007/04/07 20:15:54 kettenis Exp $       */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2007 Mark Kettenis
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: #ifdef DEBUG
        !            20: #define        EDB_PROM        0x01
        !            21: #define EDB_CHILD      0x02
        !            22: #define        EDB_INTRMAP     0x04
        !            23: #define EDB_BUSMAP     0x08
        !            24: #define EDB_BUSDMA     0x10
        !            25: #define EDB_INTR       0x20
        !            26: extern int ebus_debug;
        !            27: #define DPRINTF(l, s)   do { if (ebus_debug & l) printf s; } while (0)
        !            28: #else
        !            29: #define DPRINTF(l, s)
        !            30: #endif
        !            31:
        !            32: #include <sys/param.h>
        !            33: #include <sys/conf.h>
        !            34: #include <sys/device.h>
        !            35: #include <sys/errno.h>
        !            36: #include <sys/extent.h>
        !            37: #include <sys/malloc.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/time.h>
        !            40:
        !            41: #define _SPARC_BUS_DMA_PRIVATE
        !            42: #include <machine/bus.h>
        !            43: #include <machine/autoconf.h>
        !            44: #include <machine/openfirm.h>
        !            45:
        !            46: #include <dev/pci/pcivar.h>
        !            47:
        !            48: #include <sparc64/dev/iommureg.h>
        !            49: #include <sparc64/dev/ebusreg.h>
        !            50: #include <sparc64/dev/ebusvar.h>
        !            51: #include <sparc64/dev/pyrovar.h>
        !            52:
        !            53: extern struct cfdriver pyro_cd;
        !            54:
        !            55: int    ebus_mainbus_match(struct device *, void *, void *);
        !            56: void   ebus_mainbus_attach(struct device *, struct device *, void *);
        !            57:
        !            58: struct cfattach ebus_mainbus_ca = {
        !            59:        sizeof(struct ebus_softc), ebus_mainbus_match, ebus_mainbus_attach
        !            60: };
        !            61:
        !            62:
        !            63: int _ebus_mainbus_bus_map(bus_space_tag_t, bus_space_tag_t,
        !            64:     bus_addr_t, bus_size_t, int, bus_space_handle_t *);
        !            65: void *_ebus_mainbus_intr_establish(bus_space_tag_t, bus_space_tag_t,
        !            66:     int, int, int, int (*)(void *), void *, const char *);
        !            67: bus_space_tag_t ebus_alloc_bus_tag(struct ebus_softc *, bus_space_tag_t);
        !            68:
        !            69:
        !            70: int
        !            71: ebus_mainbus_match(struct device *parent, void *match, void *aux)
        !            72: {
        !            73:        struct mainbus_attach_args *ma = aux;
        !            74:
        !            75:        if (strcmp(ma->ma_name, "ebus") == 0)
        !            76:                return (1);
        !            77:        return (0);
        !            78: }
        !            79:
        !            80: void
        !            81: ebus_mainbus_attach(struct device *parent, struct device *self, void *aux)
        !            82: {
        !            83:        struct ebus_softc *sc = (struct ebus_softc *)self;
        !            84:        struct mainbus_attach_args *ma = aux;
        !            85:        struct ebus_attach_args eba;
        !            86:        struct ebus_interrupt_map_mask *immp;
        !            87:        int node, nmapmask, error;
        !            88:        struct pyro_softc *psc;
        !            89:        int i;
        !            90:
        !            91:        sc->sc_node = node = ma->ma_node;
        !            92:        sc->sc_ign = INTIGN((ma->ma_upaid) << INTMAP_IGN_SHIFT);
        !            93:
        !            94:        printf(": ign %x", sc->sc_ign);
        !            95:
        !            96:        for (i = 0; i < pyro_cd.cd_ndevs; i++) {
        !            97:                psc = pyro_cd.cd_devs[i];
        !            98:                if (psc && psc->sc_ign == sc->sc_ign) {
        !            99:                        sc->sc_bust = psc->sc_bust;
        !           100:                        sc->sc_csr = psc->sc_csr;
        !           101:                        sc->sc_csrh = psc->sc_csrh;
        !           102:                        break;
        !           103:                }
        !           104:        }
        !           105:
        !           106:        if (sc->sc_csr == 0) {
        !           107:                printf(": can't find matching host bridge leaf\n");
        !           108:                return;
        !           109:        }
        !           110:
        !           111:        printf("\n");
        !           112:
        !           113:        sc->sc_memtag = ebus_alloc_bus_tag(sc, ma->ma_bustag);
        !           114:        sc->sc_iotag = ebus_alloc_bus_tag(sc, ma->ma_bustag);
        !           115:        sc->sc_dmatag = ebus_alloc_dma_tag(sc, ma->ma_dmatag);
        !           116:
        !           117:        /*
        !           118:         * fill in our softc with information from the prom
        !           119:         */
        !           120:        sc->sc_intmap = NULL;
        !           121:        sc->sc_range = NULL;
        !           122:        error = getprop(node, "interrupt-map",
        !           123:                        sizeof(struct ebus_interrupt_map),
        !           124:                        &sc->sc_nintmap, (void **)&sc->sc_intmap);
        !           125:        switch (error) {
        !           126:        case 0:
        !           127:                immp = &sc->sc_intmapmask;
        !           128:                error = getprop(node, "interrupt-map-mask",
        !           129:                            sizeof(struct ebus_interrupt_map_mask), &nmapmask,
        !           130:                            (void **)&immp);
        !           131:                if (error)
        !           132:                        panic("could not get ebus interrupt-map-mask");
        !           133:                if (nmapmask != 1)
        !           134:                        panic("ebus interrupt-map-mask is broken");
        !           135:                break;
        !           136:        case ENOENT:
        !           137:                break;
        !           138:        default:
        !           139:                panic("ebus interrupt-map: error %d", error);
        !           140:                break;
        !           141:        }
        !           142:
        !           143:        error = getprop(node, "ranges", sizeof(struct ebus_mainbus_ranges),
        !           144:            &sc->sc_nrange, (void **)&sc->sc_range);
        !           145:        if (error)
        !           146:                panic("ebus ranges: error %d", error);
        !           147:
        !           148:        /*
        !           149:         * now attach all our children
        !           150:         */
        !           151:        DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node));
        !           152:        for (node = firstchild(node); node; node = nextsibling(node)) {
        !           153:                if (ebus_setup_attach_args(sc, node, &eba) != 0) {
        !           154:                        DPRINTF(EDB_CHILD,
        !           155:                            ("ebus_mainbus_attach: %s: incomplete\n",
        !           156:                            getpropstring(node, "name")));
        !           157:                        continue;
        !           158:                } else {
        !           159:                        DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n",
        !           160:                            eba.ea_name));
        !           161:                        (void)config_found(self, &eba, ebus_print);
        !           162:                }
        !           163:                ebus_destroy_attach_args(&eba);
        !           164:        }
        !           165: }
        !           166:
        !           167: bus_space_tag_t
        !           168: ebus_alloc_bus_tag(struct ebus_softc *sc, bus_space_tag_t parent)
        !           169: {
        !           170:        struct sparc_bus_space_tag *bt;
        !           171:
        !           172:        bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT);
        !           173:        if (bt == NULL)
        !           174:                panic("could not allocate ebus bus tag");
        !           175:
        !           176:        bzero(bt, sizeof *bt);
        !           177:        snprintf(bt->name, sizeof(bt->name), "%s", sc->sc_dev.dv_xname);
        !           178:        bt->cookie = sc;
        !           179:        bt->parent = parent;
        !           180:        bt->asi = parent->asi;
        !           181:        bt->sasi = parent->sasi;
        !           182:        bt->sparc_bus_map = _ebus_mainbus_bus_map;
        !           183:        bt->sparc_intr_establish = _ebus_mainbus_intr_establish;
        !           184:
        !           185:        return (bt);
        !           186: }
        !           187:
        !           188: int
        !           189: _ebus_mainbus_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset,
        !           190:     bus_size_t size, int flags, bus_space_handle_t *hp)
        !           191: {
        !           192:        struct ebus_softc *sc = t->cookie;
        !           193:        struct ebus_mainbus_ranges *range;
        !           194:        bus_addr_t hi, lo;
        !           195:        int i;
        !           196:
        !           197:        DPRINTF(EDB_BUSMAP,
        !           198:            ("\n_ebus_mainbus_bus_map: off %016llx sz %x flags %d",
        !           199:            (unsigned long long)offset, (int)size, (int)flags));
        !           200:
        !           201:        if (t->parent == 0 || t->parent->sparc_bus_map == 0) {
        !           202:                printf("\n_ebus_mainbus_bus_map: invalid parent");
        !           203:                return (EINVAL);
        !           204:        }
        !           205:
        !           206:        t = t->parent;
        !           207:
        !           208:        if (flags & BUS_SPACE_MAP_PROMADDRESS) {
        !           209:                return ((*t->sparc_bus_map)
        !           210:                    (t, t0, offset, size, flags, hp));
        !           211:        }
        !           212:
        !           213:        hi = offset >> 32UL;
        !           214:        lo = offset & 0xffffffff;
        !           215:        range = (struct ebus_mainbus_ranges *)sc->sc_range;
        !           216:
        !           217:        DPRINTF(EDB_BUSMAP, (" (hi %08x lo %08x)", (u_int)hi, (u_int)lo));
        !           218:        for (i = 0; i < sc->sc_nrange; i++) {
        !           219:                bus_addr_t addr;
        !           220:
        !           221:                if (hi != range[i].child_hi)
        !           222:                        continue;
        !           223:                if (lo < range[i].child_lo ||
        !           224:                    (lo + size) > (range[i].child_lo + range[i].size))
        !           225:                        continue;
        !           226:
        !           227:                addr = ((bus_addr_t)range[i].phys_hi << 32UL) |
        !           228:                                    range[i].phys_lo;
        !           229:                addr += lo;
        !           230:                DPRINTF(EDB_BUSMAP,
        !           231:                    ("\n_ebus_mainbus_bus_map: paddr offset %qx addr %qx\n",
        !           232:                    (unsigned long long)offset, (unsigned long long)addr));
        !           233:                 return ((*t->sparc_bus_map)(t, t0, addr, size, flags, hp));
        !           234:        }
        !           235:        DPRINTF(EDB_BUSMAP, (": FAILED\n"));
        !           236:        return (EINVAL);
        !           237: }
        !           238:
        !           239: void *
        !           240: _ebus_mainbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
        !           241:     int level, int flags, int (*handler)(void *), void *arg, const char *what)
        !           242: {
        !           243:        struct ebus_softc *sc = t->cookie;
        !           244:        struct intrhand *ih = NULL;
        !           245:        volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL;
        !           246:        int ino;
        !           247:
        !           248:        ihandle |= sc->sc_ign;
        !           249:        ino = INTINO(ihandle);
        !           250:
        !           251:        if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) == 0) {
        !           252:                u_int64_t *imap, *iclr;
        !           253:
        !           254:                /* XXX */
        !           255:                imap = bus_space_vaddr(sc->sc_bust, sc->sc_csrh) + 0x1000;
        !           256:                iclr = bus_space_vaddr(sc->sc_bust, sc->sc_csrh) + 0x1400;
        !           257:                intrmapptr = &imap[ino];
        !           258:                intrclrptr = &iclr[ino];
        !           259:                ino |= INTVEC(ihandle);
        !           260:        }
        !           261:
        !           262:        ih = bus_intr_allocate(t0, handler, arg, ino, level, intrmapptr,
        !           263:            intrclrptr, what);
        !           264:        if (ih == NULL)
        !           265:                return (NULL);
        !           266:
        !           267:        intr_establish(ih->ih_pil, ih);
        !           268:
        !           269:        if (intrmapptr != NULL) {
        !           270:                u_int64_t intrmap;
        !           271:
        !           272:                intrmap = *intrmapptr;
        !           273:                intrmap |= (1LL << 6);
        !           274:                intrmap |= INTMAP_V;
        !           275:                *intrmapptr = intrmap;
        !           276:                intrmap = *intrmapptr;
        !           277:                ih->ih_number |= intrmap & INTMAP_INR;
        !           278:        }
        !           279:
        !           280:        return (ih);
        !           281: }

CVSweb