Annotation of sys/dev/sbus/uperf_sbus.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: uperf_sbus.c,v 1.7 2003/06/27 01:50:52 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/errno.h>
! 39: #include <sys/device.h>
! 40: #include <sys/malloc.h>
! 41:
! 42: #include <machine/bus.h>
! 43: #include <machine/intr.h>
! 44: #include <machine/autoconf.h>
! 45:
! 46: #include <arch/sparc64/dev/uperfvar.h>
! 47: #include <dev/sun/uperfio.h>
! 48: #include <dev/sbus/sbusvar.h>
! 49: #include <dev/sbus/uperf_sbusreg.h>
! 50:
! 51: int uperf_sbus_match(struct device *, void *, void *);
! 52: void uperf_sbus_attach(struct device *, struct device *, void *);
! 53:
! 54: struct uperf_sbus_softc {
! 55: struct uperf_softc sc_usc;
! 56: bus_space_tag_t sc_bus_t; /* direct register tag */
! 57: bus_space_handle_t sc_bus_h; /* direct register handle */
! 58: };
! 59:
! 60: struct cfattach uperf_sbus_ca = {
! 61: sizeof(struct uperf_sbus_softc), uperf_sbus_match, uperf_sbus_attach
! 62: };
! 63:
! 64: u_int32_t uperf_sbus_read_reg(struct uperf_sbus_softc *, bus_size_t);
! 65: void uperf_sbus_write_reg(struct uperf_sbus_softc *,
! 66: bus_size_t, u_int32_t);
! 67:
! 68: int uperf_sbus_getcnt(void *, int, u_int32_t *, u_int32_t *);
! 69: int uperf_sbus_clrcnt(void *, int);
! 70: int uperf_sbus_getcntsrc(void *, int, u_int *, u_int *);
! 71: int uperf_sbus_setcntsrc(void *, int, u_int, u_int);
! 72:
! 73: struct uperf_src uperf_sbus_srcs[] = {
! 74: { UPERFSRC_SYSCK, UPERF_CNT0|UPERF_CNT1, SEL0_SYSCK },
! 75: { UPERFSRC_PRALL, UPERF_CNT0|UPERF_CNT1, SEL0_PRALL },
! 76: { UPERFSRC_PRP0, UPERF_CNT0|UPERF_CNT1, SEL0_PRP0 },
! 77: { UPERFSRC_PRU2S, UPERF_CNT0|UPERF_CNT1, SEL0_PRUS },
! 78: { UPERFSRC_UPA128, UPERF_CNT0, SEL0_128BUSY },
! 79: { UPERFSRC_RP0, UPERF_CNT1, SEL1_RDP0 },
! 80: { UPERFSRC_UPA64, UPERF_CNT0, SEL0_64BUSY },
! 81: { UPERFSRC_P0CRMR, UPERF_CNT1, SEL1_CRMP0 },
! 82: { UPERFSRC_PIOS, UPERF_CNT0, SEL0_PIOSTALL },
! 83: { UPERFSRC_P0PIO, UPERF_CNT1, SEL1_PIOP0 },
! 84: { UPERFSRC_MEMRI, UPERF_CNT0|UPERF_CNT0, SEL0_MEMREQ },
! 85: { UPERFSRC_MCBUSY, UPERF_CNT0, SEL0_MCBUSY },
! 86: { UPERFSRC_MEMRC, UPERF_CNT1, SEL1_MRC},
! 87: { UPERFSRC_PXSH, UPERF_CNT0, SEL0_PENDSTALL },
! 88: { UPERFSRC_RDP0, UPERF_CNT0, SEL1_RDP1 },
! 89: { UPERFSRC_P0CWMR, UPERF_CNT0, SEL0_CWMRP0 },
! 90: { UPERFSRC_CRMP1, UPERF_CNT1, SEL1_CRMP1 },
! 91: { UPERFSRC_P1CWMR, UPERF_CNT0, SEL0_CWMRP1 },
! 92: { UPERFSRC_PIOP1, UPERF_CNT1, SEL1_PIOP1 },
! 93: { UPERFSRC_CIT, UPERF_CNT0, SEL0_CIT },
! 94: { UPERFSRC_CWXI, UPERF_CNT1, SEL1_CWXI },
! 95: { UPERFSRC_U2SDAT, UPERF_CNT0|UPERF_CNT1, SEL0_DACT },
! 96: { UPERFSRC_CRXI, UPERF_CNT0, SEL0_CRXI },
! 97: { -1, -1, 0 }
! 98: };
! 99:
! 100: int
! 101: uperf_sbus_match(struct device *parent, void *vcf, void *aux)
! 102: {
! 103: struct sbus_attach_args *sa = aux;
! 104:
! 105: return (strcmp(sa->sa_name, "sc") == 0);
! 106: }
! 107:
! 108: void
! 109: uperf_sbus_attach(struct device *parent, struct device *self, void *aux)
! 110: {
! 111: struct sbus_attach_args *sa = aux;
! 112: struct uperf_sbus_softc *sc = (struct uperf_sbus_softc *)self;
! 113: char *model;
! 114: u_int32_t id;
! 115:
! 116: sc->sc_bus_t = sa->sa_bustag;
! 117: sc->sc_usc.usc_cookie = sc;
! 118: sc->sc_usc.usc_getcntsrc = uperf_sbus_getcntsrc;
! 119: sc->sc_usc.usc_setcntsrc = uperf_sbus_setcntsrc;
! 120: sc->sc_usc.usc_clrcnt = uperf_sbus_clrcnt;
! 121: sc->sc_usc.usc_getcnt = uperf_sbus_getcnt;
! 122: sc->sc_usc.usc_srcs = uperf_sbus_srcs;
! 123:
! 124: if (sa->sa_nreg != 1) {
! 125: printf(": expected 1 register, got %d\n", sa->sa_nreg);
! 126: return;
! 127: }
! 128:
! 129: if (sbus_bus_map(sc->sc_bus_t, sa->sa_reg[0].sbr_slot,
! 130: sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 0, 0,
! 131: &sc->sc_bus_h) != 0) {
! 132: printf(": couldn't map registers\n");
! 133: return;
! 134: }
! 135:
! 136: id = uperf_sbus_read_reg(sc, USC_ID);
! 137: model = getpropstring(sa->sa_node, "model");
! 138: if (model == NULL || strlen(model) == 0)
! 139: model = "unknown";
! 140:
! 141: printf(": model %s (%x/%x) ports %d\n", model,
! 142: (id & USC_ID_IMPL_M) >> USC_ID_IMPL_S,
! 143: (id & USC_ID_VERS_M) >> USC_ID_VERS_S,
! 144: (id & USC_ID_UPANUM_M) >> USC_ID_UPANUM_S);
! 145: }
! 146:
! 147: /*
! 148: * Read from an indirect register
! 149: */
! 150: u_int32_t
! 151: uperf_sbus_read_reg(struct uperf_sbus_softc *sc, bus_size_t r)
! 152: {
! 153: u_int32_t v;
! 154: int s;
! 155:
! 156: s = splhigh();
! 157: bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, r);
! 158: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, 1,
! 159: BUS_SPACE_BARRIER_WRITE);
! 160:
! 161: /* Can't use multi reads because we have to gaurantee order */
! 162:
! 163: v = bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0);
! 164: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0, 1,
! 165: BUS_SPACE_BARRIER_READ);
! 166:
! 167: v <<= 8;
! 168: v |= bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1);
! 169: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1, 1,
! 170: BUS_SPACE_BARRIER_READ);
! 171:
! 172: v <<= 8;
! 173: v |= bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2);
! 174: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2, 1,
! 175: BUS_SPACE_BARRIER_READ);
! 176:
! 177: v <<= 8;
! 178: v |= bus_space_read_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3);
! 179: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3, 1,
! 180: BUS_SPACE_BARRIER_READ);
! 181:
! 182: splx(s);
! 183: return (v);
! 184: }
! 185:
! 186: /*
! 187: * Write to an indirect register
! 188: */
! 189: void
! 190: uperf_sbus_write_reg(struct uperf_sbus_softc *sc, bus_size_t r, u_int32_t v)
! 191: {
! 192: int s;
! 193:
! 194: s = splhigh();
! 195: bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, r);
! 196: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_ADDR, 1,
! 197: BUS_SPACE_BARRIER_WRITE);
! 198:
! 199: /* Can't use multi writes because we have to gaurantee order */
! 200:
! 201: bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0,
! 202: (v >> 24) & 0xff);
! 203: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 0, 1,
! 204: BUS_SPACE_BARRIER_WRITE);
! 205:
! 206: bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1,
! 207: (v >> 16) & 0xff);
! 208: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 1, 1,
! 209: BUS_SPACE_BARRIER_WRITE);
! 210:
! 211: bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2,
! 212: (v >> 8) & 0xff);
! 213: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 2, 1,
! 214: BUS_SPACE_BARRIER_WRITE);
! 215:
! 216: bus_space_write_1(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3,
! 217: (v >> 0) & 0xff);
! 218: bus_space_barrier(sc->sc_bus_t, sc->sc_bus_h, USC_DATA + 3, 1,
! 219: BUS_SPACE_BARRIER_WRITE);
! 220: splx(s);
! 221: }
! 222:
! 223: int
! 224: uperf_sbus_clrcnt(void *vsc, int flags)
! 225: {
! 226: struct uperf_sbus_softc *sc = vsc;
! 227: u_int32_t clr = 0, oldsrc;
! 228:
! 229: if (flags & UPERF_CNT0)
! 230: clr |= USC_PCTRL_CLR0;
! 231: if (flags & UPERF_CNT1)
! 232: clr |= USC_PCTRL_CLR1;
! 233: if (clr) {
! 234: oldsrc = uperf_sbus_read_reg(sc, USC_PERFCTRL);
! 235: uperf_sbus_write_reg(sc, USC_PERFCTRL, clr | oldsrc);
! 236: }
! 237: return (0);
! 238: }
! 239:
! 240: int
! 241: uperf_sbus_setcntsrc(void *vsc, int flags, u_int src0, u_int src1)
! 242: {
! 243: struct uperf_sbus_softc *sc = vsc;
! 244: u_int32_t src;
! 245:
! 246: src = uperf_sbus_read_reg(sc, USC_PERFCTRL);
! 247: if (flags & UPERF_CNT0) {
! 248: src &= ~USC_PCTRL_SEL0;
! 249: src |= ((src0 << 0) & USC_PCTRL_SEL0) | USC_PCTRL_CLR0;
! 250: }
! 251: if (flags & UPERF_CNT1) {
! 252: src &= ~USC_PCTRL_SEL1;
! 253: src |= ((src1 << 8) & USC_PCTRL_SEL1) | USC_PCTRL_CLR1;
! 254: }
! 255: uperf_sbus_write_reg(sc, USC_PERFCTRL, src);
! 256: return (0);
! 257: }
! 258:
! 259: int
! 260: uperf_sbus_getcntsrc(void *vsc, int flags, u_int *srcp0, u_int *srcp1)
! 261: {
! 262: struct uperf_sbus_softc *sc = vsc;
! 263: u_int32_t src;
! 264:
! 265: src = uperf_sbus_read_reg(sc, USC_PERFCTRL);
! 266: if (flags & UPERF_CNT0)
! 267: *srcp0 = (src & USC_PCTRL_SEL0) >> 0;
! 268: if (flags & UPERF_CNT1)
! 269: *srcp1 = (src & USC_PCTRL_SEL1) >> 8;
! 270: return (0);
! 271: }
! 272:
! 273: int
! 274: uperf_sbus_getcnt(void *vsc, int flags, u_int32_t *cntp0, u_int32_t *cntp1)
! 275: {
! 276: struct uperf_sbus_softc *sc = vsc;
! 277: u_int32_t c0, c1;
! 278:
! 279: c0 = uperf_sbus_read_reg(sc, USC_PERF0);
! 280: c1 = uperf_sbus_read_reg(sc, USC_PERFSHAD);
! 281: if (flags & UPERF_CNT0)
! 282: *cntp0 = c0;
! 283: if (flags & UPERF_CNT1)
! 284: *cntp1 = c1;
! 285: return (0);
! 286: }
CVSweb