Annotation of sys/dev/sbus/uperf_sbus.c, Revision 1.1.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