xref: /netbsd/sys/arch/mvme68k/include/bus_space.h (revision bf9ec67e)
1 /*	$NetBSD: bus_space.h,v 1.7 2000/11/29 09:18:32 scw Exp $ */
2 
3 /*-
4  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Copyright (C) 1997 Scott Reynolds.  All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  * 3. The name of the author may not be used to endorse or promote products
52  *    derived from this software without specific prior written permission
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */
65 
66 /*
67  * Lifted from the Next68k port.
68  * Modified for mvme68k by Steve Woodford.
69  *
70  * TODO: Support for VMEbus...
71  * (Do any existing VME card drivers use bus_space_* ?)
72  */
73 
74 #ifndef _MVME68K_BUS_SPACE_H_
75 #define	_MVME68K_BUS_SPACE_H_
76 
77 /*
78  * Addresses (in bus space).
79  */
80 typedef u_long bus_addr_t;
81 typedef u_long bus_size_t;
82 
83 /*
84  * Access methods for bus resources and address space.
85  */
86 struct mvme68k_bus_space_tag;
87 typedef struct mvme68k_bus_space_tag	*bus_space_tag_t;
88 typedef u_long	bus_space_handle_t;
89 
90 struct mvme68k_bus_space_tag {
91 	void		*bs_cookie;
92 	int		(*bs_map)(void *, bus_addr_t, bus_size_t,
93 				  int, bus_space_handle_t *);
94 	void		(*bs_unmap)(void *, bus_space_handle_t, bus_size_t);
95 	int		(*bs_peek_1)(void *, bus_space_handle_t,
96 				     bus_size_t, u_int8_t *);
97 	int		(*bs_peek_2)(void *, bus_space_handle_t,
98 				     bus_size_t, u_int16_t *);
99 	int		(*bs_peek_4)(void *, bus_space_handle_t,
100 				     bus_size_t, u_int32_t *);
101 #if 0
102 	int		(*bs_peek_8)(void *, bus_space_handle_t,
103 				     bus_size_t, u_int64_t *);
104 #endif
105 	int		(*bs_poke_1)(void *, bus_space_handle_t,
106 				     bus_size_t, u_int8_t);
107 	int		(*bs_poke_2)(void *, bus_space_handle_t,
108 				     bus_size_t, u_int16_t);
109 	int		(*bs_poke_4)(void *, bus_space_handle_t,
110 				     bus_size_t, u_int32_t);
111 #if 0
112 	int		(*bs_poke_8)(void *, bus_space_handle_t,
113 				     bus_size_t, u_int64_t);
114 #endif
115 };
116 
117 /*
118  *	int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
119  *	                  bus_size_t size, int flags,
120  *                        bus_space_handle_t *bshp);
121  *
122  * Map a region of bus space.
123  */
124 #define	bus_space_map(tag, offset, size, flags, handlep)		\
125     (*((tag)->bs_map))((tag)->bs_cookie, (offset), (size), (flags), (handlep))
126 
127 /*
128  * Possible values for the 'flags' parameter of bus_space_map()
129  */
130 #define	BUS_SPACE_MAP_CACHEABLE		0x01
131 #define	BUS_SPACE_MAP_LINEAR		0x02
132 #define	BUS_SPACE_MAP_PREFETCHABLE	0x04
133 
134 /*
135  *	void bus_space_unmap(bus_space_tag_t t,
136  *                           bus_space_handle_t bsh, bus_size_t size);
137  *
138  * Unmap a region of bus space.
139  */
140 #define bus_space_unmap(tag, handle, size)				\
141     (*((tag)->bs_unmap))((tag)->bs_cookie, (handle), (size))
142 
143 /*
144  *	int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t h
145  *	    bus_addr_t offset, bus_size_t size, bus_space_handle_t *newh);
146  *
147  * Allocate a sub-region of an existing map
148  */
149 #define	bus_space_subregion(t, h, o, s, hp)				\
150      ((*(hp)=(h)+(o)), 0)
151 
152 /*
153  * Allocation and deallocation operations.
154  */
155 #define	bus_space_alloc(t, rs, re, s, a, b, f, ap, hp)  		\
156      (-1)
157 
158 #define	bus_space_free(t, h, s)
159 
160 /*
161  *	int bus_space_peek_N(bus_space_tag_t tag,
162  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t *valuep);
163  *
164  * Cautiously read 1, 2, 4 or 8 byte quantity from bus space described
165  * by tag/handle/offset.
166  * If no hardware responds to the read access, the function returns a
167  * non-zero value. Otherwise the value read is placed in `valuep'.
168  */
169 #define	bus_space_peek_1(t, h, o, vp)					\
170     (*((t)->bs_peek_1))((t)->bs_cookie, (h), (o), (vp))
171 
172 #define	bus_space_peek_2(t, h, o, vp)					\
173     (*((t)->bs_peek_2))((t)->bs_cookie, (h), (o), (vp))
174 
175 #define	bus_space_peek_4(t, h, o, vp)					\
176     (*((t)->bs_peek_4))((t)->bs_cookie, (h), (o), (vp))
177 
178 #if 0	/* Cause a link error for bus_space_peek_8 */
179 #define	bus_space_peek_8(t, h, o, vp)					\
180     (*((t)->bs_peek_8))((t)->bs_cookie, (h), (o), (vp))
181 #endif
182 
183 /*
184  *	int bus_space_poke_N(bus_space_tag_t tag,
185  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t value);
186  *
187  * Cautiously write 1, 2, 4 or 8 byte quantity to bus space described
188  * by tag/handle/offset.
189  * If no hardware responds to the write access, the function returns a
190  * non-zero value.
191  */
192 #define	bus_space_poke_1(t, h, o, v)					\
193     (*((t)->bs_poke_1))((t)->bs_cookie, (h), (o), (v))
194 
195 #define	bus_space_poke_2(t, h, o, v)					\
196     (*((t)->bs_poke_2))((t)->bs_cookie, (h), (o), (v))
197 
198 #define	bus_space_poke_4(t, h, o, v)					\
199     (*((t)->bs_poke_4))((t)->bs_cookie, (h), (o), (v))
200 
201 #if 0	/* Cause a link error for bus_space_poke_8 */
202 #define	bus_space_poke_8(t, h, o, v)					\
203     (*((t)->bs_poke_8))((t)->bs_cookie, (h), (o), (v))
204 #endif
205 
206 /*
207  *	u_intN_t bus_space_read_N(bus_space_tag_t tag,
208  *	    bus_space_handle_t bsh, bus_size_t offset);
209  *
210  * Read a 1, 2, 4, or 8 byte quantity from bus space
211  * described by tag/handle/offset.
212  */
213 static __inline u_int8_t
214 bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
215 {
216 	u_int8_t rv;
217 
218 	__asm __volatile("movb %1,%0" : "=dm" (rv) :
219 					"g"   (*((u_int8_t *)(h + o))));
220 
221 	return (rv);
222 }
223 
224 static __inline u_int16_t
225 bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
226 {
227 	u_int16_t rv;
228 
229 	__asm __volatile("movw %1,%0" : "=dm" (rv) :
230 					"g"   (*((u_int16_t *)(h + o))));
231 
232 	return (rv);
233 }
234 
235 static __inline u_int32_t
236 bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
237 {
238 	u_int32_t rv;
239 
240 	__asm __volatile("movl %1,%0" : "=rm" (rv) :
241 					"g"   (*((u_int32_t *)(h + o))));
242 
243 	return (rv);
244 }
245 
246 /*
247  *	void bus_space_read_multi_N(bus_space_tag_t tag,
248  *	    bus_space_handle_t bsh, bus_size_t offset,
249  *	    u_intN_t *addr, size_t count);
250  *
251  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
252  * described by tag/handle/offset and copy into buffer provided.
253  */
254 
255 #define	bus_space_read_multi_1(t, h, o, a, c) do {			\
256 	(void) t;							\
257 	__asm __volatile ("						\
258 		movl	%0,%%a0					;	\
259 		movl	%1,%%a1					;	\
260 		movl	%2,%%d0					;	\
261 	1:	movb	%%a0@,%%a1@+				;	\
262 		subql	#1,%%d0					;	\
263 		jne	1b"					:	\
264 								:	\
265 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
266 		    "a0","a1","d0");					\
267 } while (0);
268 
269 #define	bus_space_read_multi_2(t, h, o, a, c) do {			\
270 	(void) t;							\
271 	__asm __volatile ("						\
272 		movl	%0,%%a0					;	\
273 		movl	%1,%%a1					;	\
274 		movl	%2,%%d0					;	\
275 	1:	movw	%%a0@,%%a1@+				;	\
276 		subql	#1,%%d0					;	\
277 		jne	1b"					:	\
278 								:	\
279 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
280 		    "a0","a1","d0");					\
281 } while (0);
282 
283 #define	bus_space_read_multi_4(t, h, o, a, c) do {			\
284 	(void) t;							\
285 	__asm __volatile ("						\
286 		movl	%0,%%a0					;	\
287 		movl	%1,%%a1					;	\
288 		movl	%2,%%d0					;	\
289 	1:	movl	%%a0@,%%a1@+				;	\
290 		subql	#1,%%d0					;	\
291 		jne	1b"					:	\
292 								:	\
293 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
294 		    "a0","a1","d0");					\
295 } while (0);
296 
297 #if 0	/* Cause a link error for bus_space_read_multi_8 */
298 #define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
299 #endif
300 
301 /*
302  *	void bus_space_read_region_N(bus_space_tag_t tag,
303  *	    bus_space_handle_t bsh, bus_size_t offset,
304  *	    u_intN_t *addr, size_t count);
305  *
306  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
307  * described by tag/handle and starting at `offset' and copy into
308  * buffer provided.
309  */
310 
311 #define	bus_space_read_region_1(t, h, o, a, c) do {			\
312 	(void) t;							\
313 	__asm __volatile ("						\
314 		movl	%0,%%a0					;	\
315 		movl	%1,%%a1					;	\
316 		movl	%2,%%d0					;	\
317 	1:	movb	%%a0@+,%%a1@+				;	\
318 		subql	#1,%%d0					;	\
319 		jne	1b"					:	\
320 								:	\
321 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
322 		    "a0","a1","d0");					\
323 } while (0);
324 
325 #define	bus_space_read_region_2(t, h, o, a, c) do {			\
326 	(void) t;							\
327 	__asm __volatile ("						\
328 		movl	%0,%%a0					;	\
329 		movl	%1,%%a1					;	\
330 		movl	%2,%%d0					;	\
331 	1:	movw	%%a0@+,%%a1@+				;	\
332 		subql	#1,%%d0					;	\
333 		jne	1b"					:	\
334 								:	\
335 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
336 		    "a0","a1","d0");					\
337 } while (0);
338 
339 #define	bus_space_read_region_4(t, h, o, a, c) do {			\
340 	(void) t;							\
341 	__asm __volatile ("						\
342 		movl	%0,%%a0					;	\
343 		movl	%1,%%a1					;	\
344 		movl	%2,%%d0					;	\
345 	1:	movl	%%a0@+,%%a1@+				;	\
346 		subql	#1,%%d0					;	\
347 		jne	1b"					:	\
348 								:	\
349 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
350 		    "a0","a1","d0");					\
351 } while (0);
352 
353 #if 0	/* Cause a link error for bus_space_read_region_8 */
354 #define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
355 #endif
356 
357 /*
358  *	void bus_space_write_N(bus_space_tag_t tag,
359  *	    bus_space_handle_t bsh, bus_size_t offset,
360  *	    u_intN_t value);
361  *
362  * Write the 1, 2, 4, or 8 byte value `value' to bus space
363  * described by tag/handle/offset.
364  */
365 static __inline void
366 bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h,
367     bus_size_t o, u_int8_t v)
368 {
369 	__asm __volatile("movb %0,%1" ::
370 	    "dim" (v), "g" (*((u_int8_t *)(h + o))));
371 }
372 
373 static __inline void
374 bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h,
375     bus_size_t o, u_int16_t v)
376 {
377 	__asm __volatile("movw %0,%1" ::
378 	    "dim" (v), "g" (*((u_int16_t *)(h + o))));
379 }
380 
381 static __inline void
382 bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h,
383     bus_size_t o, u_int32_t v)
384 {
385 	__asm __volatile("movl %0,%1" ::
386 	    "g" (v), "g" (*((u_int32_t *)(h + o))));
387 }
388 
389 /*
390  *	void bus_space_write_multi_N(bus_space_tag_t tag,
391  *	    bus_space_handle_t bsh, bus_size_t offset,
392  *	    const u_intN_t *addr, size_t count);
393  *
394  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
395  * provided to bus space described by tag/handle/offset.
396  */
397 
398 #define	bus_space_write_multi_1(t, h, o, a, c) do {			\
399 	(void) t;							\
400 	__asm __volatile ("						\
401 		movl	%0,%%a0					;	\
402 		movl	%1,%%a1					;	\
403 		movl	%2,%%d0					;	\
404 	1:	movb	%%a1@+,%%a0@				;	\
405 		subql	#1,%%d0					;	\
406 		jne	1b"					:	\
407 								:	\
408 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
409 		    "a0","a1","d0");					\
410 } while (0);
411 
412 #define	bus_space_write_multi_2(t, h, o, a, c) do {			\
413 	(void) t;							\
414 	__asm __volatile ("						\
415 		movl	%0,%%a0					;	\
416 		movl	%1,%%a1					;	\
417 		movl	%2,%%d0					;	\
418 	1:	movw	%%a1@+,%%a0@				;	\
419 		subql	#1,%%d0					;	\
420 		jne	1b"					:	\
421 								:	\
422 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
423 		    "a0","a1","d0");					\
424 } while (0);
425 
426 #define	bus_space_write_multi_4(t, h, o, a, c) do {			\
427 	(void) t;							\
428 	__asm __volatile ("						\
429 		movl	%0,%%a0					;	\
430 		movl	%1,%%a1					;	\
431 		movl	%2,%%d0					;	\
432 	1:	movl	a1@+,%%a0@				;	\
433 		subql	#1,%%d0					;	\
434 		jne	1b"					:	\
435 								:	\
436 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
437 		    "a0","a1","d0");					\
438 } while (0);
439 
440 #if 0	/* Cause a link error for bus_space_write_8 */
441 #define	bus_space_write_multi_8(t, h, o, a, c)				\
442 			!!! bus_space_write_multi_8 unimplimented !!!
443 #endif
444 
445 /*
446  *	void bus_space_write_region_N(bus_space_tag_t tag,
447  *	    bus_space_handle_t bsh, bus_size_t offset,
448  *	    const u_intN_t *addr, size_t count);
449  *
450  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
451  * to bus space described by tag/handle starting at `offset'.
452  */
453 
454 #define	bus_space_write_region_1(t, h, o, a, c) do {			\
455 	(void) t;							\
456 	__asm __volatile ("						\
457 		movl	%0,%%a0					;	\
458 		movl	%1,%%a1					;	\
459 		movl	%2,%%d0					;	\
460 	1:	movb	%%a1@+,%%a0@+				;	\
461 		subql	#1,%%d0					;	\
462 		jne	1b"					:	\
463 								:	\
464 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
465 		    "a0","a1","d0");					\
466 } while (0);
467 
468 #define	bus_space_write_region_2(t, h, o, a, c) do {			\
469 	(void) t;							\
470 	__asm __volatile ("						\
471 		movl	%0,%%a0					;	\
472 		movl	%1,%%a1					;	\
473 		movl	%2,%%d0					;	\
474 	1:	movw	%%a1@+,%%a0@+				;	\
475 		subql	#1,%%d0					;	\
476 		jne	1b"					:	\
477 								:	\
478 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
479 		    "a0","a1","d0");					\
480 } while (0);
481 
482 #define	bus_space_write_region_4(t, h, o, a, c) do {			\
483 	(void) t;							\
484 	__asm __volatile ("						\
485 		movl	%0,%%a0					;	\
486 		movl	%1,%%a1					;	\
487 		movl	%2,%%d0					;	\
488 	1:	movl	%%a1@+,%%a0@+				;	\
489 		subql	#1,%%d0					;	\
490 		jne	1b"					:	\
491 								:	\
492 		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
493 		    "a0","a1","d0");					\
494 } while (0);
495 
496 #if 0	/* Cause a link error for bus_space_write_region_8 */
497 #define	bus_space_write_region_8					\
498 			!!! bus_space_write_region_8 unimplemented !!!
499 #endif
500 
501 /*
502  *	void bus_space_set_multi_N(bus_space_tag_t tag,
503  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
504  *	    size_t count);
505  *
506  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
507  * by tag/handle/offset `count' times.
508  */
509 
510 #define	bus_space_set_multi_1(t, h, o, val, c) do {			\
511 	(void) t;							\
512 	__asm __volatile ("						\
513 		movl	%0,%%a0					;	\
514 		movl	%1,%%d1					;	\
515 		movl	%2,%%d0					;	\
516 	1:	movb	%%d1,%%a0@				;	\
517 		subql	#1,%%d0					;	\
518 		jne	1b"					:	\
519 								:	\
520 		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
521 		    "a0","d0","d1");					\
522 } while (0);
523 
524 #define	bus_space_set_multi_2(t, h, o, val, c) do {			\
525 	(void) t;							\
526 	__asm __volatile ("						\
527 		movl	%0,%%a0					;	\
528 		movl	%1,%%d1					;	\
529 		movl	%2,%%d0					;	\
530 	1:	movw	%%d1,%%a0@				;	\
531 		subql	#1,%%d0					;	\
532 		jne	1b"					:	\
533 								:	\
534 		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
535 		    "a0","d0","d1");					\
536 } while (0);
537 
538 #define	bus_space_set_multi_4(t, h, o, val, c) do {			\
539 	(void) t;							\
540 	__asm __volatile ("						\
541 		movl	%0,%%a0					;	\
542 		movl	%1,%%d1					;	\
543 		movl	%2,%%d0					;	\
544 	1:	movl	%%d1,%%a0@				;	\
545 		subql	#1,%%d0					;	\
546 		jne	1b"					:	\
547 								:	\
548 		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
549 		    "a0","d0","d1");					\
550 } while (0);
551 
552 #if 0	/* Cause a link error for bus_space_set_multi_8 */
553 #define	bus_space_set_multi_8						\
554 			!!! bus_space_set_multi_8 unimplemented !!!
555 #endif
556 
557 /*
558  *	void bus_space_set_region_N(bus_space_tag_t tag,
559  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
560  *	    size_t count);
561  *
562  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
563  * by tag/handle starting at `offset'.
564  */
565 
566 #define	bus_space_set_region_1(t, h, o, val, c) do {			\
567 	(void) t;							\
568 	__asm __volatile ("						\
569 		movl	%0,%%a0					;	\
570 		movl	%1,%%d1					;	\
571 		movl	%2,%%d0					;	\
572 	1:	movb	%%d1,%%a0@+				;	\
573 		subql	#1,%%d0					;	\
574 		jne	1b"					:	\
575 								:	\
576 		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
577 		    "a0","d0","d1");					\
578 } while (0);
579 
580 #define	bus_space_set_region_2(t, h, o, val, c) do {			\
581 	(void) t;							\
582 	__asm __volatile ("						\
583 		movl	%0,%%a0					;	\
584 		movl	%1,%%d1					;	\
585 		movl	%2,%%d0					;	\
586 	1:	movw	%%d1,%%a0@+				;	\
587 		subql	#1,%%d0					;	\
588 		jne	1b"					:	\
589 								:	\
590 		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
591 		    "a0","d0","d1");					\
592 } while (0);
593 
594 #define	bus_space_set_region_4(t, h, o, val, c) do {			\
595 	(void) t;							\
596 	__asm __volatile ("						\
597 		movl	%0,%%a0					;	\
598 		movl	%1,%%d1					;	\
599 		movl	%2,%%d0					;	\
600 	1:	movl	d1,%%a0@+				;	\
601 		subql	#1,%%d0					;	\
602 		jne	1b"					:	\
603 								:	\
604 		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
605 		    "a0","d0","d1");					\
606 } while (0);
607 
608 #if 0	/* Cause a link error for bus_space_set_region_8 */
609 #define	bus_space_set_region_8						\
610 			!!! bus_space_set_region_8 unimplemented !!!
611 #endif
612 
613 /*
614  *	void bus_space_copy_N(bus_space_tag_t tag,
615  *	    bus_space_handle_t bsh1, bus_size_t off1,
616  *	    bus_space_handle_t bsh2, bus_size_t off2,
617  *	    size_t count);
618  *
619  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
620  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
621  */
622 
623 #define	__MVME68K_copy_region_N(BYTES)					\
624 static __inline void __CONCAT(bus_space_copy_region_,BYTES)		\
625 	__P((bus_space_tag_t,						\
626 	    bus_space_handle_t bsh1, bus_size_t off1,			\
627 	    bus_space_handle_t bsh2, bus_size_t off2,			\
628 	    bus_size_t count));						\
629 									\
630 static __inline void							\
631 __CONCAT(bus_space_copy_region_,BYTES)(t, h1, o1, h2, o2, c)		\
632 	bus_space_tag_t t;						\
633 	bus_space_handle_t h1, h2;					\
634 	bus_size_t o1, o2, c;						\
635 {									\
636 	bus_size_t o;							\
637 									\
638 	if ((h1 + o1) >= (h2 + o2)) {					\
639 		/* src after dest: copy forward */			\
640 		for (o = 0; c != 0; c--, o += BYTES)			\
641 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
642 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
643 	} else {							\
644 		/* dest after src: copy backwards */			\
645 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
646 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
647 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
648 	}								\
649 }
650 __MVME68K_copy_region_N(1)
651 __MVME68K_copy_region_N(2)
652 __MVME68K_copy_region_N(4)
653 #if 0	/* Cause a link error for bus_space_copy_8 */
654 #define	bus_space_copy_8						\
655 			!!! bus_space_copy_8 unimplemented !!!
656 #endif
657 
658 #undef __MVME68K_copy_region_N
659 
660 /*
661  * Bus read/write barrier methods.
662  *
663  *	void bus_space_barrier(bus_space_tag_t tag,
664  *	    bus_space_handle_t bsh, bus_size_t offset,
665  *	    bus_size_t len, int flags);
666  *
667  * Note: the 680x0 does not currently require barriers, but we must
668  * provide the flags to MI code.
669  */
670 #define	bus_space_barrier(t, h, o, l, f)	\
671 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
672 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
673 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
674 
675 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
676 
677 
678 #ifdef _MVME68K_BUS_SPACE_PRIVATE
679 extern int _bus_space_map(void *, bus_addr_t, bus_size_t,
680     int, bus_space_handle_t *);
681 extern void _bus_space_unmap(void *, bus_space_handle_t, bus_size_t);
682 extern int _bus_space_peek_1(void *, bus_space_handle_t,
683     bus_size_t, u_int8_t *);
684 extern int _bus_space_peek_2(void *, bus_space_handle_t,
685     bus_size_t, u_int16_t *);
686 extern int _bus_space_peek_4(void *, bus_space_handle_t,
687     bus_size_t, u_int32_t *);
688 extern int _bus_space_poke_1(void *, bus_space_handle_t, bus_size_t, u_int8_t);
689 extern int _bus_space_poke_2(void *, bus_space_handle_t, bus_size_t, u_int16_t);
690 extern int _bus_space_poke_4(void *, bus_space_handle_t, bus_size_t, u_int32_t);
691 #endif /* _MVME68K_BUS_SPACE_PRIVATE */
692 
693 #endif /* _MVME68K_BUS_SPACE_H_ */
694