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