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

Annotation of sys/arch/sparc64/dev/uperf_ebus.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uperf_ebus.c,v 1.4 2003/06/02 20:02:49 jason Exp $    */
                      2:
                      3: /*
                      4:  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     25:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  *
                     28:  * Effort sponsored in part by the Defense Advanced Research Projects
                     29:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     30:  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
                     31:  *
                     32:  */
                     33:
                     34: #include <sys/types.h>
                     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/kernel.h>
                     38: #include <sys/device.h>
                     39: #include <sys/conf.h>
                     40: #include <sys/timeout.h>
                     41:
                     42: #include <machine/bus.h>
                     43: #include <machine/autoconf.h>
                     44: #include <machine/openfirm.h>
                     45:
                     46: #include <sparc64/dev/ebusreg.h>
                     47: #include <sparc64/dev/ebusvar.h>
                     48: #include <dev/sun/uperfio.h>
                     49: #include <dev/sbus/uperf_sbusreg.h>
                     50: #include <sparc64/dev/uperfvar.h>
                     51: #include <sparc64/dev/iommureg.h>
                     52: #include <sparc64/dev/psychoreg.h>
                     53:
                     54: struct uperf_ebus_softc {
                     55:        struct uperf_softc      sc_usc;
                     56:        bus_space_tag_t         sc_bus_t;
                     57:        bus_space_handle_t      sc_bus_h;
                     58: };
                     59:
                     60: int    uperf_ebus_match(struct device *, void *, void *);
                     61: void   uperf_ebus_attach(struct device *, struct device *, void *);
                     62:
                     63: struct cfattach uperf_ebus_ca = {
                     64:        sizeof(struct uperf_ebus_softc), uperf_ebus_match, uperf_ebus_attach
                     65: };
                     66:
                     67: u_int32_t uperf_ebus_read_reg(struct uperf_ebus_softc *, bus_size_t);
                     68: void uperf_ebus_write_reg(struct uperf_ebus_softc *,
                     69:     bus_size_t, u_int32_t);
                     70:
                     71: int uperf_ebus_getcnt(void *, int, u_int32_t *, u_int32_t *);
                     72: int uperf_ebus_clrcnt(void *, int);
                     73: int uperf_ebus_getcntsrc(void *, int, u_int *, u_int *);
                     74: int uperf_ebus_setcntsrc(void *, int, u_int, u_int);
                     75:
                     76: struct uperf_src uperf_ebus_srcs[] = {
                     77:        { UPERFSRC_SDVRA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_SDVRA },
                     78:        { UPERFSRC_SDVWA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_SDVWA },
                     79:        { UPERFSRC_CDVRA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_CDVRA },
                     80:        { UPERFSRC_CDVWA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_CDVWA },
                     81:        { UPERFSRC_SBMA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_SBMA },
                     82:        { UPERFSRC_DVA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_DVA },
                     83:        { UPERFSRC_DVWA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_DVWA },
                     84:        { UPERFSRC_PIOA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_PIOA },
                     85:        { UPERFSRC_SDVRB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_SDVRB },
                     86:        { UPERFSRC_SDVWB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_SDVWB },
                     87:        { UPERFSRC_CDVRB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_CDVRB },
                     88:        { UPERFSRC_CDVWB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_CDVWB },
                     89:        { UPERFSRC_SBMB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_SBMB },
                     90:        { UPERFSRC_DVB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_DVB },
                     91:        { UPERFSRC_DVWB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_DVWB },
                     92:        { UPERFSRC_PIOB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_PIOB },
                     93:        { UPERFSRC_TLBMISS, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_TLBMISS },
                     94:        { UPERFSRC_NINTRS, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_NINTRS },
                     95:        { UPERFSRC_INACK, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_INACK },
                     96:        { UPERFSRC_PIOR, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_PIOR },
                     97:        { UPERFSRC_PIOW, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_PIOW },
                     98:        { UPERFSRC_MERGE, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_MERGE },
                     99:        { UPERFSRC_TBLA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_TBLA },
                    100:        { UPERFSRC_STCA, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_STCA },
                    101:        { UPERFSRC_TBLB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_TBLB },
                    102:        { UPERFSRC_STCB, UPERF_CNT0|UPERF_CNT1, PSY_PMCRSEL_STCB },
                    103:        { -1, -1, 0 }
                    104: };
                    105: int
                    106: uperf_ebus_match(parent, match, aux)
                    107:        struct device *parent;
                    108:        void *match;
                    109:        void *aux;
                    110: {
                    111:        struct ebus_attach_args *ea = aux;
                    112:
                    113:        return (strcmp(ea->ea_name, "sc") == 0);
                    114: }
                    115:
                    116: void
                    117: uperf_ebus_attach(parent, self, aux)
                    118:        struct device *parent, *self;
                    119:        void *aux;
                    120: {
                    121:        struct uperf_ebus_softc *sc = (void *)self;
                    122:        struct ebus_attach_args *ea = aux;
                    123:        char *model;
                    124:        u_int32_t id;
                    125:
                    126:        sc->sc_bus_t = ea->ea_memtag;
                    127:        sc->sc_usc.usc_cookie = sc;
                    128:        sc->sc_usc.usc_getcntsrc = uperf_ebus_getcntsrc;
                    129:        sc->sc_usc.usc_setcntsrc = uperf_ebus_setcntsrc;
                    130:        sc->sc_usc.usc_clrcnt = uperf_ebus_clrcnt;
                    131:        sc->sc_usc.usc_getcnt = uperf_ebus_getcnt;
                    132:        sc->sc_usc.usc_srcs = uperf_ebus_srcs;
                    133:
                    134:        /* Use prom address if available, otherwise map it. */
                    135:        if (ea->ea_nregs != 1) {
                    136:                printf(": expected 1 register, got %d\n", ea->ea_nregs);
                    137:                return;
                    138:        }
                    139:
                    140:        if (ebus_bus_map(sc->sc_bus_t, 0,
                    141:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size,
                    142:            0, 0, &sc->sc_bus_h) != 0) {
                    143:                printf(": can't map register space\n");
                    144:                return;
                    145:        }
                    146:
                    147:        id = uperf_ebus_read_reg(sc, USC_ID);
                    148:        model = getpropstring(ea->ea_node, "model");
                    149:        if (model == NULL || strlen(model) == 0)
                    150:                model = "unknown";
                    151:
                    152:        printf(": model %s (%x/%x) ports %d\n", model,
                    153:            (id & USC_ID_IMPL_M) >> USC_ID_IMPL_S,
                    154:            (id & USC_ID_VERS_M) >> USC_ID_VERS_S,
                    155:            (id & USC_ID_UPANUM_M) >> USC_ID_UPANUM_S);
                    156: }
                    157:
                    158: /*
                    159:  * Read an indirect register.
                    160:  */
                    161: u_int32_t
                    162: uperf_ebus_read_reg(sc, r)
                    163:        struct uperf_ebus_softc *sc;
                    164:        bus_size_t r;
                    165: {
                    166:        u_int32_t v;
                    167:        int s;
                    168:
                    169:        s = splhigh();
                    170:        bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, r);
                    171:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, 1,
                    172:            BUS_SPACE_BARRIER_WRITE);
                    173:
                    174:        /* Can't use multi reads because we have to gaurantee order */
                    175:
                    176:        v = bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0);
                    177:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0, 1,
                    178:            BUS_SPACE_BARRIER_READ);
                    179:
                    180:        v <<= 8;
                    181:        v |= bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1);
                    182:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1, 1,
                    183:            BUS_SPACE_BARRIER_READ);
                    184:
                    185:        v <<= 8;
                    186:        v |= bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2);
                    187:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2, 1,
                    188:            BUS_SPACE_BARRIER_READ);
                    189:
                    190:        v <<= 8;
                    191:        v |= bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3);
                    192:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3, 1,
                    193:            BUS_SPACE_BARRIER_READ);
                    194:
                    195:        splx(s);
                    196:        return (v);
                    197: }
                    198:
                    199: /*
                    200:  * Write an indirect register.
                    201:  */
                    202: void
                    203: uperf_ebus_write_reg(sc, r, v)
                    204:        struct uperf_ebus_softc *sc;
                    205:        bus_size_t r;
                    206:        u_int32_t v;
                    207: {
                    208:        int s;
                    209:
                    210:        s = splhigh();
                    211:        bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, r);
                    212:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, 1,
                    213:            BUS_SPACE_BARRIER_WRITE);
                    214:
                    215:        /* Can't use multi writes because we have to gaurantee order */
                    216:
                    217:        bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0,
                    218:            (v >> 24) & 0xff);
                    219:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0, 1,
                    220:            BUS_SPACE_BARRIER_WRITE);
                    221:
                    222:        bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1,
                    223:            (v >> 16) & 0xff);
                    224:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1, 1,
                    225:            BUS_SPACE_BARRIER_WRITE);
                    226:
                    227:        bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2,
                    228:            (v >> 8) & 0xff);
                    229:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2, 1,
                    230:            BUS_SPACE_BARRIER_WRITE);
                    231:
                    232:        bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3,
                    233:            (v >> 0) & 0xff);
                    234:        bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3, 1,
                    235:            BUS_SPACE_BARRIER_WRITE);
                    236:        splx(s);
                    237: }
                    238:
                    239: int
                    240: uperf_ebus_clrcnt(vsc, flags)
                    241:        void *vsc;
                    242:        int flags;
                    243: {
                    244:        struct uperf_ebus_softc *sc = vsc;
                    245:        u_int32_t clr = 0, oldsrc;
                    246:
                    247:        if (flags & UPERF_CNT0)
                    248:                clr |= USC_PCTRL_CLR0;
                    249:        if (flags & UPERF_CNT1)
                    250:                clr |= USC_PCTRL_CLR1;
                    251:        if (clr) {
                    252:                oldsrc = uperf_ebus_read_reg(sc, USC_PERFCTRL);
                    253:                uperf_ebus_write_reg(sc, USC_PERFCTRL, clr | oldsrc);
                    254:        }
                    255:        return (0);
                    256: }
                    257:
                    258: int
                    259: uperf_ebus_setcntsrc(vsc, flags, src0, src1)
                    260:        void *vsc;
                    261:        int flags;
                    262:        u_int src0, src1;
                    263: {
                    264:        struct uperf_ebus_softc *sc = vsc;
                    265:        u_int32_t src;
                    266:
                    267:        src = uperf_ebus_read_reg(sc, USC_PERFCTRL);
                    268:        if (flags & UPERF_CNT0) {
                    269:                src &= ~USC_PCTRL_SEL0;
                    270:                src |= ((src0 << 0) & USC_PCTRL_SEL0) | USC_PCTRL_CLR0;
                    271:        }
                    272:        if (flags & UPERF_CNT1) {
                    273:                src &= ~USC_PCTRL_SEL1;
                    274:                src |= ((src1 << 8) & USC_PCTRL_SEL1) | USC_PCTRL_CLR1;
                    275:        }
                    276:        uperf_ebus_write_reg(sc, USC_PERFCTRL, src);
                    277:        return (0);
                    278: }
                    279:
                    280: int
                    281: uperf_ebus_getcntsrc(vsc, flags, srcp0, srcp1)
                    282:        void *vsc;
                    283:        int flags;
                    284:        u_int *srcp0, *srcp1;
                    285: {
                    286:        struct uperf_ebus_softc *sc = vsc;
                    287:        u_int32_t src;
                    288:
                    289:        src = uperf_ebus_read_reg(sc, USC_PERFCTRL);
                    290:        if (flags & UPERF_CNT0)
                    291:                *srcp0 = (src & USC_PCTRL_SEL0) >> 0;
                    292:        if (flags & UPERF_CNT1)
                    293:                *srcp1 = (src & USC_PCTRL_SEL1) >> 8;
                    294:        return (0);
                    295: }
                    296:
                    297: int
                    298: uperf_ebus_getcnt(vsc, flags, cntp0, cntp1)
                    299:        void *vsc;
                    300:        int flags;
                    301:        u_int32_t *cntp0, *cntp1;
                    302: {
                    303:        struct uperf_ebus_softc *sc = vsc;
                    304:        u_int32_t c0, c1;
                    305:
                    306:        c0 = uperf_ebus_read_reg(sc, USC_PERF0);
                    307:        c1 = uperf_ebus_read_reg(sc, USC_PERFSHAD);
                    308:        if (flags & UPERF_CNT0)
                    309:                *cntp0 = c0;
                    310:        if (flags & UPERF_CNT1)
                    311:                *cntp1 = c1;
                    312:        return (0);
                    313: }

CVSweb