xref: /netbsd/sys/arch/sun2/sun2/obio.c (revision c4a72b64)
1 /*	$NetBSD: obio.c,v 1.11 2002/10/02 16:02:24 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Adam Glass, Gordon W. Ross, and Matthew Fredette.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 
43 #include <uvm/uvm_extern.h>
44 
45 #include <machine/autoconf.h>
46 #include <machine/pmap.h>
47 #include <machine/pte.h>
48 
49 #include <sun2/sun2/control.h>
50 #include <sun2/sun2/machdep.h>
51 
52 /* Does this machine have a Multibus? */
53 extern int cpu_has_multibus;
54 
55 static int  obio_match __P((struct device *, struct cfdata *, void *));
56 static void obio_attach __P((struct device *, struct device *, void *));
57 
58 struct obio_softc {
59 	struct device	sc_dev;		/* base device */
60 	bus_space_tag_t	sc_bustag;	/* parent bus tag */
61 	bus_dma_tag_t	sc_dmatag;	/* parent bus dma tag */
62 };
63 
64 CFATTACH_DECL(obio, sizeof(struct obio_softc),
65     obio_match, obio_attach, NULL, NULL);
66 
67 static	paddr_t obio_bus_mmap __P((bus_space_tag_t, bus_type_t, bus_addr_t,
68 			       off_t, int, int));
69 static	int _obio_bus_map __P((bus_space_tag_t, bus_type_t, bus_addr_t,
70 			       bus_size_t, int,
71 			       vaddr_t, bus_space_handle_t *));
72 static	int _obio_addr_bad __P((bus_space_tag_t, bus_space_handle_t,
73 				bus_size_t, size_t));
74 static	int _obio_bus_peek __P((bus_space_tag_t, bus_space_handle_t,
75 				bus_size_t, size_t, void *));
76 static	int _obio_bus_poke __P((bus_space_tag_t, bus_space_handle_t,
77 				bus_size_t, size_t, u_int32_t));
78 
79 static struct sun68k_bus_space_tag obio_space_tag = {
80 	NULL,				/* cookie */
81 	NULL,				/* parent bus tag */
82 	_obio_bus_map,			/* bus_space_map */
83 	NULL,				/* bus_space_unmap */
84 	NULL,				/* bus_space_subregion */
85 	NULL,				/* bus_space_barrier */
86 	obio_bus_mmap,			/* bus_space_mmap */
87 	NULL,				/* bus_intr_establish */
88 	_obio_bus_peek,			/* bus_space_peek_N */
89 	_obio_bus_poke			/* bus_space_poke_N */
90 };
91 
92 static int
93 obio_match(parent, cf, aux)
94 	struct device *parent;
95 	struct cfdata *cf;
96 	void *aux;
97 {
98 	struct mainbus_attach_args *ma = aux;
99 
100 	return (ma->ma_name == NULL || strcmp(cf->cf_name, ma->ma_name) == 0);
101 }
102 
103 static void
104 obio_attach(parent, self, aux)
105 	struct device *parent;
106 	struct device *self;
107 	void *aux;
108 {
109 	struct mainbus_attach_args *ma = aux;
110 	struct obio_softc *sc = (struct obio_softc *)self;
111 	struct obio_attach_args oba;
112 	const char *const *cpp;
113 	static const char *const special[] = {
114 		/* find these first */
115 		NULL
116 	};
117 
118 	/*
119 	 * There is only one obio bus
120 	 */
121 	if (self->dv_unit > 0) {
122 		printf(" unsupported\n");
123 		return;
124 	}
125 	printf("\n");
126 
127 	sc->sc_bustag = ma->ma_bustag;
128 	sc->sc_dmatag = ma->ma_dmatag;
129 
130 	obio_space_tag.cookie = sc;
131 	obio_space_tag.parent = sc->sc_bustag;
132 
133 	/*
134 	 * Prepare the skeleton attach arguments for our devices.
135 	 * The values we give in the locators are indications to
136 	 * sun68k_bus_search about which locators must and must not
137 	 * be defined.
138 	 */
139 	oba = *ma;
140 	oba.oba_bustag = &obio_space_tag;
141 	oba.oba_paddr = LOCATOR_REQUIRED;
142 	oba.oba_pri = LOCATOR_OPTIONAL;
143 
144 	/* Find all `early' obio devices */
145 	for (cpp = special; *cpp != NULL; cpp++) {
146 		oba.oba_name = *cpp;
147 		(void)config_search(sun68k_bus_search, self, &oba);
148 	}
149 
150 	/* Find all other obio devices */
151 	oba.oba_name = NULL;
152 	(void)config_search(sun68k_bus_search, self, &oba);
153 }
154 
155 int
156 _obio_bus_map(t, btype, paddr, size, flags, vaddr, hp)
157 	bus_space_tag_t t;
158 	bus_type_t btype;
159 	bus_addr_t paddr;
160 	bus_size_t size;
161 	vaddr_t vaddr;
162 	int	flags;
163 
164 	bus_space_handle_t *hp;
165 {
166 	struct obio_softc *sc = t->cookie;
167 
168 	return (bus_space_map2(sc->sc_bustag, PMAP_OBIO, paddr,
169 				size, flags | _SUN68K_BUS_MAP_USE_PROM, vaddr, hp));
170 }
171 
172 paddr_t
173 obio_bus_mmap(t, btype, paddr, off, prot, flags)
174 	bus_space_tag_t t;
175 	bus_type_t btype;
176 	bus_addr_t paddr;
177 	off_t off;
178 	int prot;
179 	int flags;
180 {
181 	struct obio_softc *sc = t->cookie;
182 
183 	return (bus_space_mmap2(sc->sc_bustag, PMAP_OBIO, paddr, off,
184 				prot, flags));
185 }
186 
187 /*
188  * The sun2 obio bus doesn't give bus errors, so we check on
189  * probed obio physical addresses to make sure they're ok.
190  */
191 int
192 _obio_addr_bad(t, h, o, s)
193 	bus_space_tag_t t;
194 	bus_space_handle_t h;
195 	bus_size_t o;
196 	size_t s;
197 {
198 	u_int pte;
199 	paddr_t pa;
200 
201 	/* Get the physical address for this page. */
202 	pte = get_pte((vaddr_t) (h + o));
203 	if (!(pte & PG_VALID))
204 		return (-1);
205 	pa = PG_PA(pte);
206 
207 	/*
208 	 * Return nonzero if it's bad.  All sun2 Multibus
209 	 * machines have all obio devices between 0x2000
210 	 * and 0x4000, and all sun2 VME machines have all
211 	 * obio devices outside of this range.
212 	 */
213 	return ((!!cpu_has_multibus) != (pa >= 0x2000 && pa < 0x4000));
214 }
215 
216 int
217 _obio_bus_peek(t, h, o, s, vp)
218 	bus_space_tag_t t;
219 	bus_space_handle_t h;
220 	bus_size_t o;
221 	size_t s;
222 	void *vp;
223 {
224 	struct obio_softc *sc = t->cookie;
225 
226 	return (_obio_addr_bad(t, h, o, s) ||
227 		_bus_space_peek(sc->sc_bustag, h, o, s, vp));
228 }
229 
230 int
231 _obio_bus_poke(t, h, o, s, v)
232 	bus_space_tag_t t;
233 	bus_space_handle_t h;
234 	bus_size_t o;
235 	size_t s;
236 	u_int32_t v;
237 {
238 	struct obio_softc *sc = t->cookie;
239 
240 	return (_obio_addr_bad(t, h, o, s) ||
241 		_bus_space_poke(sc->sc_bustag, h, o, s, v));
242 }
243