Annotation of sys/arch/sparc64/dev/uperf_ebus.c, Revision 1.1.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