xref: /netbsd/sys/arch/mvme68k/mvme68k/bus_space.c (revision bf9ec67e)
1 /*	$NetBSD: bus_space.c,v 1.4 2000/11/24 09:36:40 scw Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Steve C. Woodford and Jason R. Thorpe.
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 /*
40  * Implementation of bus_space mapping for the mvme68k.
41  * Derived from the hp300 bus_space implementation by Jason Thorpe.
42  */
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/malloc.h>
47 
48 #include <machine/cpu.h>
49 #include <machine/pte.h>
50 #define _MVME68K_BUS_DMA_PRIVATE    /* For _bus_dmamem_map/_bus_dmamem_unmap */
51 #define _MVME68K_BUS_SPACE_PRIVATE
52 #include <machine/bus.h>
53 #undef _MVME68K_BUS_DMA_PRIVATE
54 #undef _MVME68K_BUS_SPACE_PRIVATE
55 
56 static	void	peek1(void *, void *);
57 static	void	peek2(void *, void *);
58 static	void	peek4(void *, void *);
59 static	void	poke1(void *, u_int);
60 static	void	poke2(void *, u_int);
61 static	void	poke4(void *, u_int);
62 static	int	do_peek(void (*)(void *, void *), void *, void *);
63 static	int	do_poke(void (*)(void *, u_int), void *, u_int);
64 
65 /*
66  * Used in locore.s/trap.c to determine if faults are being trapped.
67  */
68 label_t *nofault;
69 
70 
71 /* ARGSUSED */
72 int
73 _bus_space_map(cookie, addr, size, flags, bushp)
74 	void *cookie;
75 	bus_addr_t addr;
76 	bus_size_t size;
77 	int flags;
78 	bus_space_handle_t *bushp;
79 {
80 	bus_dma_segment_t seg;
81 	caddr_t va;
82 
83 	if (addr >= intiobase_phys && addr < intiotop_phys) {
84 #ifdef DEBUG
85 		if ((addr + size) >= intiotop_phys)
86 			panic("mvme68k_bus_space_map: Invalid INTIO range!");
87 #endif
88 		/*
89 		 * Intio space is direct-mapped in pmap_bootstrap(); just
90 		 * do the translation.
91 		 */
92 		addr -= intiobase_phys;
93 		*bushp = (bus_space_handle_t) &(intiobase[addr]);
94 		return (0);
95 	}
96 
97 	/*
98 	 * Otherwise, set up a VM mapping for the requested address range
99 	 */
100 	seg.ds_addr = seg._ds_cpuaddr = m68k_trunc_page(addr);
101 	seg.ds_len = m68k_round_page(size);
102 
103 	if (_bus_dmamem_map(NULL, &seg, 1, seg.ds_len, &va,
104 	    flags | BUS_DMA_COHERENT))
105 		return EIO;
106 
107 	/*
108 	 * The handle is really the virtual address we just mapped
109 	 */
110 	*bushp = (bus_space_handle_t) (va + m68k_page_offset(addr));
111 
112 	return (0);
113 }
114 
115 /* ARGSUSED */
116 void
117 _bus_space_unmap(cookie, bush, size)
118 	void *cookie;
119 	bus_space_handle_t bush;
120 	bus_size_t size;
121 {
122 	/* Nothing to do for INTIO space */
123 	if ((char *)bush >= intiobase && (char *)bush < intiolimit)
124 		return;
125 
126 	bush = m68k_trunc_page(bush);
127 	size = m68k_round_page(size);
128 
129 	_bus_dmamem_unmap(NULL, (caddr_t) bush, size);
130 }
131 
132 /* ARGSUSED */
133 int
134 _bus_space_peek_1(cookie, bush, offset, valuep)
135 	void *cookie;
136 	bus_space_handle_t bush;
137 	bus_size_t offset;
138 	u_int8_t *valuep;
139 {
140 	u_int8_t v;
141 
142 	if (valuep == NULL)
143 		valuep = &v;
144 
145 	return (do_peek(&peek1, (void *)(bush + offset), (void *)valuep));
146 }
147 
148 /* ARGSUSED */
149 int
150 _bus_space_peek_2(cookie, bush, offset, valuep)
151 	void *cookie;
152 	bus_space_handle_t bush;
153 	bus_size_t offset;
154 	u_int16_t *valuep;
155 {
156 	u_int16_t v;
157 
158 	if (valuep == NULL)
159 		valuep = &v;
160 
161 	return (do_peek(&peek2, (void *)(bush + offset), (void *)valuep));
162 }
163 
164 /* ARGSUSED */
165 int
166 _bus_space_peek_4(cookie, bush, offset, valuep)
167 	void *cookie;
168 	bus_space_handle_t bush;
169 	bus_size_t offset;
170 	u_int32_t *valuep;
171 {
172 	u_int32_t v;
173 
174 	if (valuep == NULL)
175 		valuep = &v;
176 
177 	return (do_peek(&peek4, (void *)(bush + offset), (void *)valuep));
178 }
179 
180 /* ARGSUSED */
181 int
182 _bus_space_poke_1(cookie, bush, offset, value)
183 	void *cookie;
184 	bus_space_handle_t bush;
185 	bus_size_t offset;
186 	u_int8_t value;
187 {
188 	return (do_poke(&poke1, (void *)(bush + offset), (u_int)value));
189 }
190 
191 /* ARGSUSED */
192 int
193 _bus_space_poke_2(cookie, bush, offset, value)
194 	void *cookie;
195 	bus_space_handle_t bush;
196 	bus_size_t offset;
197 	u_int16_t value;
198 {
199 	return (do_poke(&poke2, (void *)(bush + offset), (u_int)value));
200 }
201 
202 /* ARGSUSED */
203 int
204 _bus_space_poke_4(cookie, bush, offset, value)
205 	void *cookie;
206 	bus_space_handle_t bush;
207 	bus_size_t offset;
208 	u_int32_t value;
209 {
210 	return (do_poke(&poke4, (void *)(bush + offset), (u_int)value));
211 }
212 
213 static void
214 peek1(addr, vp)
215 	void *addr;
216 	void *vp;
217 {
218 	*((u_int8_t *)vp) =  *((u_int8_t *)addr);
219 }
220 
221 static void
222 peek2(addr, vp)
223 	void *addr;
224 	void *vp;
225 {
226 	*((u_int16_t *)vp) = *((u_int16_t *)addr);
227 }
228 
229 static void
230 peek4(addr, vp)
231 	void *addr;
232 	void *vp;
233 {
234 	*((u_int32_t *)vp) = *((u_int32_t *)addr);
235 }
236 
237 static void
238 poke1(addr, value)
239 	void *addr;
240 	u_int value;
241 {
242 	*((u_int8_t *)addr) = value;
243 }
244 
245 static void
246 poke2(addr, value)
247 	void *addr;
248 	u_int value;
249 {
250 	*((u_int16_t *)addr) = value;
251 }
252 
253 static void
254 poke4(addr, value)
255 	void *addr;
256 	u_int value;
257 {
258 	*((u_int32_t *)addr) = value;
259 }
260 
261 static int
262 do_peek(peekfn, addr, valuep)
263 	void (*peekfn)(void *, void *);
264 	void *addr;
265 	void *valuep;
266 {
267 	label_t faultbuf;
268 
269 	nofault = &faultbuf;
270 	if (setjmp(&faultbuf)) {
271 		nofault = NULL;
272 		return (1);
273 	}
274 
275 	(*peekfn)(addr, valuep);
276 
277 	nofault = NULL;
278 	return (0);
279 }
280 
281 static int
282 do_poke(pokefn, addr, value)
283 	void (*pokefn)(void *, u_int);
284 	void *addr;
285 	u_int value;
286 {
287 	label_t faultbuf;
288 
289 	nofault = &faultbuf;
290 	if (setjmp(&faultbuf)) {
291 		nofault = NULL;
292 		return (1);
293 	}
294 
295 	(*pokefn)(addr, value);
296 
297 	nofault = NULL;
298 	return (0);
299 }
300