[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

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