root/dev/sbus/uperf_sbus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uperf_sbus_match
  2. uperf_sbus_attach
  3. uperf_sbus_read_reg
  4. uperf_sbus_write_reg
  5. uperf_sbus_clrcnt
  6. uperf_sbus_setcntsrc
  7. uperf_sbus_getcntsrc
  8. uperf_sbus_getcnt

    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 }

/* [<][>][^][v][top][bottom][index][help] */