1 /*	$NetBSD: bus_space.c,v 1.2 2002/09/27 15:36:35 provos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
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  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *        This product includes software developed by the NetBSD
18  *        Foundation, Inc. and its contributors.
19  * 4. Neither the name of The NetBSD Foundation nor the names of its
20  *    contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/extent.h>
40 
41 #define _PLAYSTATION2_BUS_SPACE_PRIVATE
42 #include <machine/bus.h>
43 
44 #ifdef BUS_SPACE_DEBUG
45 int	bus_space_debug = 0;
46 #define	DPRINTF(fmt, args...)						\
47 	if (bus_space_debug)						\
48 		printf("%s: " fmt, __FUNCTION__ , ##args)
49 #define	DPRINTFN(n, arg)						\
50 	if (bus_space_debug > (n))					\
51 		printf("%s: " fmt, __FUNCTION__ , ##args)
52 #else
53 #define	DPRINTF(arg...)		((void)0)
54 #define DPRINTFN(n, arg...)	((void)0)
55 #endif
56 
57 #define VADDR(h, o)	(h + o)
58 _BUS_SPACE_READ(_default, 1, 8)
59 _BUS_SPACE_READ(_default, 2, 16)
60 _BUS_SPACE_READ(_default, 4, 32)
61 _BUS_SPACE_READ(_default, 8, 64)
62 _BUS_SPACE_READ_MULTI(_default, 1, 8)
63 _BUS_SPACE_READ_MULTI(_default, 2, 16)
64 _BUS_SPACE_READ_MULTI(_default, 4, 32)
65 _BUS_SPACE_READ_MULTI(_default, 8, 64)
66 _BUS_SPACE_READ_REGION(_default, 1, 8)
67 _BUS_SPACE_READ_REGION(_default, 2, 16)
68 _BUS_SPACE_READ_REGION(_default, 4, 32)
69 _BUS_SPACE_READ_REGION(_default, 8, 64)
70 _BUS_SPACE_WRITE(_default, 1, 8)
71 _BUS_SPACE_WRITE(_default, 2, 16)
72 _BUS_SPACE_WRITE(_default, 4, 32)
73 _BUS_SPACE_WRITE(_default, 8, 64)
74 _BUS_SPACE_WRITE_MULTI(_default, 1, 8)
75 _BUS_SPACE_WRITE_MULTI(_default, 2, 16)
76 _BUS_SPACE_WRITE_MULTI(_default, 4, 32)
77 _BUS_SPACE_WRITE_MULTI(_default, 8, 64)
78 _BUS_SPACE_WRITE_REGION(_default, 1, 8)
79 _BUS_SPACE_WRITE_REGION(_default, 2, 16)
80 _BUS_SPACE_WRITE_REGION(_default, 4, 32)
81 _BUS_SPACE_WRITE_REGION(_default, 8, 64)
82 _BUS_SPACE_SET_MULTI(_default, 1, 8)
83 _BUS_SPACE_SET_MULTI(_default, 2, 16)
84 _BUS_SPACE_SET_MULTI(_default, 4, 32)
85 _BUS_SPACE_SET_MULTI(_default, 8, 64)
86 _BUS_SPACE_SET_REGION(_default, 1, 8)
87 _BUS_SPACE_SET_REGION(_default, 2, 16)
88 _BUS_SPACE_SET_REGION(_default, 4, 32)
89 _BUS_SPACE_SET_REGION(_default, 8, 64)
90 _BUS_SPACE_COPY_REGION(_default, 1, 8)
91 _BUS_SPACE_COPY_REGION(_default, 2, 16)
92 _BUS_SPACE_COPY_REGION(_default, 4, 32)
93 _BUS_SPACE_COPY_REGION(_default, 8, 64)
94 #undef VADDR
95 
96 static int _default_map(void *, bus_addr_t, bus_size_t, int,
97     bus_space_handle_t *);
98 static void _default_unmap(void *, bus_space_handle_t, bus_size_t);
99 static int _default_subregion(void *, bus_space_handle_t, bus_size_t,
100     bus_size_t, bus_space_handle_t *);
101 static int _default_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t,
102     bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
103 static void _default_free(void *, bus_space_handle_t, bus_size_t);
104 static void *_default_vaddr(void *, bus_space_handle_t);
105 
106 static const struct playstation2_bus_space _default_bus_space = {
107 	pbs_map		: _default_map,
108 	pbs_unmap	: _default_unmap,
109 	pbs_subregion	: _default_subregion,
110 	pbs_alloc	: _default_alloc,
111 	pbs_free	: _default_free,
112 	pbs_vaddr	: _default_vaddr,
113 	pbs_r_1		: _default_read_1,
114 	pbs_r_2		: _default_read_2,
115 	pbs_r_4		: _default_read_4,
116 	pbs_r_8		: _default_read_8,
117 	pbs_rm_1	: _default_read_multi_1,
118 	pbs_rm_2	: _default_read_multi_2,
119 	pbs_rm_4	: _default_read_multi_4,
120 	pbs_rm_8	: _default_read_multi_8,
121 	pbs_rr_1	: _default_read_region_1,
122 	pbs_rr_2	: _default_read_region_2,
123 	pbs_rr_4	: _default_read_region_4,
124 	pbs_rr_8	: _default_read_region_8,
125 	pbs_w_1		: _default_write_1,
126 	pbs_w_2		: _default_write_2,
127 	pbs_w_4		: _default_write_4,
128 	pbs_w_8		: _default_write_8,
129 	pbs_wm_1	: _default_write_multi_1,
130 	pbs_wm_2	: _default_write_multi_2,
131 	pbs_wm_4	: _default_write_multi_4,
132 	pbs_wm_8	: _default_write_multi_8,
133 	pbs_wr_1	: _default_write_region_1,
134 	pbs_wr_2	: _default_write_region_2,
135 	pbs_wr_4	: _default_write_region_4,
136 	pbs_wr_8	: _default_write_region_8,
137 	pbs_sm_1	: _default_set_multi_1,
138 	pbs_sm_2	: _default_set_multi_2,
139 	pbs_sm_4	: _default_set_multi_4,
140 	pbs_sm_8	: _default_set_multi_8,
141 	pbs_sr_1	: _default_set_region_1,
142 	pbs_sr_2	: _default_set_region_2,
143 	pbs_sr_4	: _default_set_region_4,
144 	pbs_sr_8	: _default_set_region_8,
145 	pbs_c_1		: _default_copy_region_1,
146 	pbs_c_2		: _default_copy_region_2,
147 	pbs_c_4		: _default_copy_region_4,
148 	pbs_c_8		: _default_copy_region_8
149 };
150 
151 /* create default bus_space_tag */
152 bus_space_tag_t
153 bus_space_create(bus_space_tag_t t, const char *name,
154     bus_addr_t addr, bus_size_t size)
155 {
156 	struct playstation2_bus_space *pbs = (void *)t; /* discard const */
157 
158 	if (pbs == 0)
159 		pbs = malloc(sizeof(*pbs), M_DEVBUF, M_NOWAIT);
160 	KDASSERT(pbs);
161 
162 	memset(pbs, 0, sizeof(*pbs));
163 
164 	/* set default method */
165 	*pbs = _default_bus_space;
166 	pbs->pbs_cookie = pbs;
167 
168 	/* set access region */
169 	if (size == 0) {
170 		pbs->pbs_base_addr = addr; /* no extent */
171 	} else {
172 		pbs->pbs_extent = extent_create(name, addr, addr + size - 1,
173 		    M_DEVBUF, 0, 0, EX_NOWAIT);
174 		if (pbs->pbs_extent == 0) {
175 			panic("%s:: unable to create bus_space for "
176 			    "0x%08lx-%#lx", __FUNCTION__, addr, size);
177 		}
178 	}
179 
180 	return (pbs);
181 }
182 
183 void
184 bus_space_destroy(bus_space_tag_t t)
185 {
186 	struct playstation2_bus_space *pbs = (void *)t;  /* discard const */
187 	struct extent *ex = pbs->pbs_extent;
188 
189 	if (ex != 0)
190 		extent_destroy(ex);
191 
192 	free(pbs, M_DEVBUF);
193 }
194 
195 void
196 _bus_space_invalid_access(void)
197 {
198 	panic("invalid bus space access.");
199 }
200 
201 /* default bus_space tag */
202 static int
203 _default_map(void *t, bus_addr_t bpa, bus_size_t size, int flags,
204     bus_space_handle_t *bshp)
205 {
206 	struct playstation2_bus_space *pbs = t;
207 	struct extent *ex = pbs->pbs_extent;
208 	int error;
209 
210 	if (ex == 0) {
211 		*bshp = (bus_space_handle_t)(bpa + pbs->pbs_base_addr);
212 		return (0);
213 	}
214 
215 	bpa += ex->ex_start;
216 	error = extent_alloc_region(ex, bpa, size, EX_NOWAIT | EX_MALLOCOK);
217 
218 	if (error) {
219 		DPRINTF("failed.\n");
220 		return (error);
221 	}
222 
223 	*bshp = (bus_space_handle_t)bpa;
224 
225 	DPRINTF("success.\n");
226 
227 	return (0);
228 }
229 
230 static int
231 _default_subregion(void *t, bus_space_handle_t bsh,
232     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
233 {
234 	*nbshp = bsh + offset;
235 
236 	return (0);
237 }
238 
239 static int
240 _default_alloc(void *t, bus_addr_t rstart, bus_addr_t rend,
241     bus_size_t size, bus_size_t alignment, bus_size_t boundary,
242     int flags, bus_addr_t *bpap, bus_space_handle_t *bshp)
243 {
244 	struct playstation2_bus_space *pbs = t;
245 	struct extent *ex = pbs->pbs_extent;
246 	u_long bpa, base;
247 	int error;
248 
249 	if (ex == 0) {
250 		*bshp = *bpap = rstart + pbs->pbs_base_addr;
251 		return (0);
252 	}
253 
254 	base = ex->ex_start;
255 
256 	error = extent_alloc_subregion(ex, rstart + base, rend + base, size,
257 	    alignment, boundary,
258 	    EX_FAST | EX_NOWAIT | EX_MALLOCOK,
259 	    &bpa);
260 
261 	if (error) {
262 		DPRINTF("failed.\n");
263 		return (error);
264 	}
265 
266 	*bshp = (bus_space_handle_t)bpa;
267 
268 	if (bpap)
269 		*bpap = bpa;
270 
271 	DPRINTF("success.\n");
272 
273 	return (0);
274 }
275 
276 static void
277 _default_free(void *t, bus_space_handle_t bsh, bus_size_t size)
278 {
279 	struct playstation2_bus_space *pbs = t;
280 	struct extent *ex = pbs->pbs_extent;
281 
282 	if (ex != 0)
283 		_default_unmap(t, bsh, size);
284 }
285 
286 static void
287 _default_unmap(void *t, bus_space_handle_t bsh, bus_size_t size)
288 {
289 	struct playstation2_bus_space *pbs = t;
290 	struct extent *ex = pbs->pbs_extent;
291 	int error;
292 
293 	if (ex == 0)
294 		return;
295 
296 	error = extent_free(ex, bsh, size, EX_NOWAIT);
297 
298 	if (error) {
299 		DPRINTF("%#lx-%#lx of %s space lost\n", bsh, bsh + size,
300 		    ex->ex_name);
301 	}
302 }
303 
304 void *
305 _default_vaddr(void *t, bus_space_handle_t h)
306 {
307 	return (void *)h;
308 }
309