[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     ! 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