Annotation of sys/arch/sparc/dev/sbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sbus.c,v 1.16 2007/05/29 09:54:13 sobrado Exp $ */
2: /* $NetBSD: sbus.c,v 1.17 1997/06/01 22:10:39 pk Exp $ */
3:
4: /*
5: * Copyright (c) 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This software was developed by the Computer Systems Engineering group
9: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10: * contributed to Berkeley.
11: *
12: * All advertising materials mentioning features or use of this software
13: * must display the following acknowledgement:
14: * This product includes software developed by the University of
15: * California, Lawrence Berkeley Laboratory.
16: *
17: * Redistribution and use in source and binary forms, with or without
18: * modification, are permitted provided that the following conditions
19: * are met:
20: * 1. Redistributions of source code must retain the above copyright
21: * notice, this list of conditions and the following disclaimer.
22: * 2. Redistributions in binary form must reproduce the above copyright
23: * notice, this list of conditions and the following disclaimer in the
24: * documentation and/or other materials provided with the distribution.
25: * 3. Neither the name of the University nor the names of its contributors
26: * may be used to endorse or promote products derived from this software
27: * without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39: * SUCH DAMAGE.
40: *
41: * @(#)sbus.c 8.1 (Berkeley) 6/11/93
42: */
43:
44: /*
45: * SBus stuff.
46: */
47:
48: #include <sys/param.h>
49: #include <sys/malloc.h>
50: #include <sys/systm.h>
51: #include <sys/device.h>
52: #include <uvm/uvm_extern.h>
53:
54: #include <machine/autoconf.h>
55:
56: #include <sparc/dev/sbusreg.h>
57: #include <sparc/dev/sbusvar.h>
58: #include <sparc/dev/xboxreg.h>
59: #include <sparc/dev/xboxvar.h>
60: #include <sparc/dev/dmareg.h>
61:
62: int sbus_print(void *, const char *);
63:
64: /* autoconfiguration driver */
65: void sbus_attach(struct device *, struct device *, void *);
66: int sbus_match(struct device *, void *, void *);
67:
68: struct cfattach sbus_ca = {
69: sizeof(struct sbus_softc), sbus_match, sbus_attach
70: };
71:
72: struct cfdriver sbus_cd = {
73: NULL, "sbus", DV_DULL
74: };
75:
76: /*
77: * Print the location of some sbus-attached device (called just
78: * before attaching that device). If `sbus' is not NULL, the
79: * device was found but not configured; print the sbus as well.
80: * Return UNCONF (config_find ignores this if the device was configured).
81: */
82: int
83: sbus_print(args, sbus)
84: void *args;
85: const char *sbus;
86: {
87: struct confargs *ca = args;
88: char *class;
89: static char *sl = "slave-only";
90:
91: if (sbus != NULL) {
92: printf("\"%s\" at %s", ca->ca_ra.ra_name, sbus);
93: class = getpropstring(ca->ca_ra.ra_node, "device_type");
94: if (*class != '\0')
95: printf(" class %s", class);
96: }
97: /* Check root node for 'slave-only' property */
98: if (getpropint(0, sl, 0) & (1 << ca->ca_slot))
99: printf(" %s", sl);
100: printf(" slot %d offset 0x%x", ca->ca_slot, ca->ca_offset);
101: return (UNCONF);
102: }
103:
104: int
105: sbus_match(parent, vcf, aux)
106: struct device *parent;
107: void *vcf, *aux;
108: {
109: register struct cfdata *cf = vcf;
110: register struct confargs *ca = aux;
111: register struct romaux *ra = &ca->ca_ra;
112:
113: if (CPU_ISSUN4)
114: return (0);
115:
116: if (ca->ca_bustype == BUS_XBOX) {
117: struct xbox_softc *xsc = (struct xbox_softc *)parent;
118:
119: /* Prevent multiple attachments */
120: if (xsc->sc_attached == 0) {
121: xsc->sc_attached = 1;
122: return (1);
123: }
124:
125: return (0);
126: }
127:
128: return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0);
129: }
130:
131: /*
132: * Attach an SBus.
133: */
134: void
135: sbus_attach(parent, self, aux)
136: struct device *parent;
137: struct device *self;
138: void *aux;
139: {
140: register struct sbus_softc *sc = (struct sbus_softc *)self;
141: struct confargs *ca = aux;
142: register struct romaux *ra = &ca->ca_ra;
143: register int node;
144: register char *name;
145: struct confargs oca;
146: int rlen;
147:
148: /*
149: * XXX there is only one SBus, for now -- do not know how to
150: * address children on others
151: */
152: if (sc->sc_dev.dv_unit > 0 && ca->ca_bustype != BUS_XBOX) {
153: printf(" unsupported\n");
154: return;
155: }
156:
157: /*
158: * Record clock frequency for synchronous SCSI.
159: * IS THIS THE CORRECT DEFAULT??
160: */
161: node = ra->ra_node;
162: sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000);
163: printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq));
164:
165: /*
166: * Get the SBus burst transfer size if burst transfers are supported
167: */
168: sc->sc_burst = getpropint(node, "burst-sizes", 0);
169: sc->sc_burst = sc->sc_burst & ~SBUS_BURST_64;
170:
171: if (ca->ca_bustype == BUS_XBOX) {
172: struct xbox_softc *xsc = (struct xbox_softc *)parent;
173:
174: /* Parent has already done the leg work */
175: sc->sc_nrange = xsc->sc_nrange;
176: sc->sc_range = xsc->sc_range;
177: xsc->sc_attached = 2;
178: }
179: else {
180: if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "sbus") == 0)
181: oca.ca_ra.ra_bp = ra->ra_bp + 1;
182: else
183: oca.ca_ra.ra_bp = NULL;
184:
185: rlen = getproplen(node, "ranges");
186: if (rlen > 0) {
187: sc->sc_nrange = rlen / sizeof(struct rom_range);
188: sc->sc_range =
189: (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT);
190: if (sc->sc_range == 0)
191: panic("sbus: PROM ranges too large: %d", rlen);
192: (void)getprop(node, "ranges", sc->sc_range, rlen);
193: }
194: }
195:
196: /*
197: * Loop through ROM children, fixing any relative addresses
198: * and then configuring each device.
199: */
200: for (node = firstchild(node); node; node = nextsibling(node)) {
201: name = getpropstring(node, "name");
202: if (!romprop(&oca.ca_ra, name, node))
203: continue;
204:
205: sbus_translate(self, &oca);
206: oca.ca_bustype = BUS_SBUS;
207: (void) config_found(&sc->sc_dev, (void *)&oca, sbus_print);
208: }
209: }
210:
211: void
212: sbus_translate(dev, ca)
213: struct device *dev;
214: struct confargs *ca;
215: {
216: struct sbus_softc *sc = (struct sbus_softc *)dev;
217: register int base, slot;
218: register int i;
219:
220: if (sc->sc_nrange == 0) {
221: /* Old-style SBus configuration */
222: base = (int)ca->ca_ra.ra_paddr;
223: if (SBUS_ABS(base)) {
224: ca->ca_slot = SBUS_ABS_TO_SLOT(base);
225: ca->ca_offset = SBUS_ABS_TO_OFFSET(base);
226: } else {
227: if (!CPU_ISSUN4C)
228: panic("relative sbus addressing not supported");
229: ca->ca_slot = slot = ca->ca_ra.ra_iospace;
230: ca->ca_offset = base;
231: ca->ca_ra.ra_paddr = (void *)SBUS_ADDR(slot, base);
232: ca->ca_ra.ra_iospace = PMAP_OBIO;
233:
234: /* Fix any remaining register banks */
235: for (i = 1; i < ca->ca_ra.ra_nreg; i++) {
236: base = (int)ca->ca_ra.ra_reg[i].rr_paddr;
237: ca->ca_ra.ra_reg[i].rr_paddr =
238: (void *)SBUS_ADDR(slot, base);
239: ca->ca_ra.ra_reg[i].rr_iospace = PMAP_OBIO;
240: }
241: }
242:
243: } else {
244:
245: ca->ca_slot = ca->ca_ra.ra_iospace;
246: ca->ca_offset = (int)ca->ca_ra.ra_paddr;
247:
248: /* Translate into parent address spaces */
249: for (i = 0; i < ca->ca_ra.ra_nreg; i++) {
250: int j, cspace = ca->ca_ra.ra_reg[i].rr_iospace;
251:
252: for (j = 0; j < sc->sc_nrange; j++) {
253: if (sc->sc_range[j].cspace == cspace) {
254: (int)ca->ca_ra.ra_reg[i].rr_paddr +=
255: sc->sc_range[j].poffset;
256: (int)ca->ca_ra.ra_reg[i].rr_iospace =
257: sc->sc_range[j].pspace;
258: break;
259: }
260: }
261: }
262: }
263: }
264:
265: /*
266: * Returns true if this sbus slot is capable of dma
267: */
268: int
269: sbus_testdma(sc, ca)
270: struct sbus_softc *sc;
271: struct confargs *ca;
272: {
273: struct romaux *ra = &ca->ca_ra;
274:
275: /*
276: * XXX how to handle more than one sbus?
277: */
278:
279: if (getpropint(0, "slave-only", 0) & (1 << ca->ca_slot)) {
280: printf("%s: dma card found in non-dma sbus slot %d"
281: ": not supported\n", ra->ra_name, ca->ca_slot);
282: return (0);
283: }
284:
285: return (1);
286: }
CVSweb