xref: /netbsd/sys/arch/x68k/include/bus.h (revision bf9ec67e)
1 /*	$NetBSD: bus.h,v 1.9 2001/11/11 01:38:00 isaki Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998, 2001 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  * bus_space(9) and bus_dma(9) interface for NetBSD/x68k.
42  */
43 
44 #ifndef _X68K_BUS_H_
45 #define _X68K_BUS_H_
46 
47 #ifndef X68K_BUS_PERFORMANCE_HACK
48 #if defined(__GNUC__) && defined(__STDC__)
49 #define X68K_BUS_PERFORMANCE_HACK	1
50 #else
51 #define X68K_BUS_PERFORMANCE_HACK	0
52 #endif
53 #endif
54 
55 /*
56  * Bus address and size types
57  */
58 typedef u_long	bus_addr_t;
59 typedef u_long	bus_size_t;
60 typedef	u_long	bus_space_handle_t;
61 
62 /*
63  * Bus space descripter
64  */
65 typedef struct x68k_bus_space *bus_space_tag_t;
66 
67 struct x68k_bus_space {
68 #if 0
69 	enum {
70 		X68K_INTIO_BUS,
71 		X68K_PCI_BUS,
72 		X68K_NEPTUNE_BUS
73 	}	x68k_bus_type;
74 #endif
75 
76 	int	(*x68k_bus_space_map) __P((
77 				bus_space_tag_t,
78 				bus_addr_t,
79 				bus_size_t,
80 				int,			/* flags */
81 				bus_space_handle_t *));
82 	void	(*x68k_bus_space_unmap) __P((
83 				bus_space_tag_t,
84 				bus_space_handle_t,
85 				bus_size_t));
86 	int	(*x68k_bus_space_subregion) __P((
87 				bus_space_tag_t,
88 				bus_space_handle_t,
89 				bus_size_t,		/* offset */
90 				bus_size_t,		/* size */
91 				bus_space_handle_t *));
92 
93 	int	(*x68k_bus_space_alloc) __P((
94 				bus_space_tag_t,
95 				bus_addr_t,		/* reg_start */
96 				bus_addr_t,		/* reg_end */
97 				bus_size_t,
98 				bus_size_t,		/* alignment */
99 				bus_size_t,		/* boundary */
100 				int,			/* flags */
101 				bus_addr_t *,
102 				bus_space_handle_t *));
103 	void	(*x68k_bus_space_free) __P((
104 				bus_space_tag_t,
105 				bus_space_handle_t,
106 				bus_size_t));
107 
108 #if 0
109 	void	(*x68k_bus_space_barrier) __P((
110 				bus_space_tag_t,
111 				bus_space_handle_t,
112 				bus_size_t,		/* offset */
113 				bus_size_t,		/* length */
114 				int));			/* flags */
115 #endif
116 
117 	struct device *x68k_bus_device;
118 };
119 
120 int x68k_bus_space_alloc __P((bus_space_tag_t, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *));
121 void x68k_bus_space_free __P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
122 
123 /*
124  * bus_space(9) interface
125  */
126 
127 #define bus_space_map(t,a,s,f,h) \
128 		((*((t)->x68k_bus_space_map)) ((t),(a),(s),(f),(h)))
129 #define bus_space_unmap(t,h,s) \
130 		((*((t)->x68k_bus_space_unmap)) ((t),(h),(s)))
131 #define bus_space_subregion(t,h,o,s,p) \
132 		((*((t)->x68k_bus_space_subregion)) ((t),(h),(o),(s),(p)))
133 #define BUS_SPACE_MAP_CACHEABLE		0x0001
134 #define BUS_SPACE_MAP_LINEAR		0x0002
135 #define BUS_SPACE_MAP_PREFETCHABLE	0x0004
136 /*
137  * For simpler hadware, many x68k devices are mapped with shifted address
138  * i.e. only on even or odd addresses.
139  */
140 #define BUS_SPACE_MAP_SHIFTED_MASK	0x1001
141 #define BUS_SPACE_MAP_SHIFTED_ODD	0x1001
142 #define BUS_SPACE_MAP_SHIFTED_EVEN	0x1000
143 #define BUS_SPACE_MAP_SHIFTED		BUS_SPACE_MAP_SHIFTED_ODD
144 
145 #define bus_space_alloc(t,rs,re,s,a,b,f,r,h) \
146 		((*((t)->x68k_bus_space_alloc)) ((t),(rs),(re),(s),(a),(b),(f),(r),(h)))
147 #define bus_space_free(t,h,s) \
148 		((*((t)->x68k_bus_space_free)) ((t),(h),(s)))
149 
150 /*
151  * Note: the 680x0 does not currently require barriers, but we must
152  * provide the flags to MI code.
153  */
154 #define	bus_space_barrier(t, h, o, l, f)	\
155 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
156 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
157 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
158 
159 #define bus_space_read_1(t,h,o) _bus_space_read_1(t,h,o)
160 #define bus_space_read_2(t,h,o) _bus_space_read_2(t,h,o)
161 #define bus_space_read_4(t,h,o) _bus_space_read_4(t,h,o)
162 
163 #define bus_space_read_multi_1(t,h,o,p,c) _bus_space_read_multi_1(t,h,o,p,c)
164 #define bus_space_read_multi_2(t,h,o,p,c) _bus_space_read_multi_2(t,h,o,p,c)
165 #define bus_space_read_multi_4(t,h,o,p,c) _bus_space_read_multi_4(t,h,o,p,c)
166 
167 #define bus_space_read_region_1(t,h,o,p,c) _bus_space_read_region_1(t,h,o,p,c)
168 #define bus_space_read_region_2(t,h,o,p,c) _bus_space_read_region_2(t,h,o,p,c)
169 #define bus_space_read_region_4(t,h,o,p,c) _bus_space_read_region_4(t,h,o,p,c)
170 
171 #define bus_space_write_1(t,h,o,v) _bus_space_write_1(t,h,o,v)
172 #define bus_space_write_2(t,h,o,v) _bus_space_write_2(t,h,o,v)
173 #define bus_space_write_4(t,h,o,v) _bus_space_write_4(t,h,o,v)
174 
175 #define bus_space_write_multi_1(t,h,o,p,c) _bus_space_write_multi_1(t,h,o,p,c)
176 #define bus_space_write_multi_2(t,h,o,p,c) _bus_space_write_multi_2(t,h,o,p,c)
177 #define bus_space_write_multi_4(t,h,o,p,c) _bus_space_write_multi_4(t,h,o,p,c)
178 
179 #define bus_space_write_region_1(t,h,o,p,c) \
180 		_bus_space_write_region_1(t,h,o,p,c)
181 #define bus_space_write_region_2(t,h,o,p,c) \
182 		_bus_space_write_region_2(t,h,o,p,c)
183 #define bus_space_write_region_4(t,h,o,p,c) \
184 		_bus_space_write_region_4(t,h,o,p,c)
185 
186 #define bus_space_set_region_1(t,h,o,v,c) _bus_space_set_region_1(t,h,o,v,c)
187 #define bus_space_set_region_2(t,h,o,v,c) _bus_space_set_region_2(t,h,o,v,c)
188 #define bus_space_set_region_4(t,h,o,v,c) _bus_space_set_region_4(t,h,o,v,c)
189 
190 #define bus_space_copy_region_1(t,sh,so,dh,do,c) \
191 		_bus_space_copy_region_1(t,sh,so,dh,do,c)
192 #define bus_space_copy_region_2(t,sh,so,dh,do,c) \
193 		_bus_space_copy_region_2(t,sh,so,dh,do,c)
194 #define bus_space_copy_region_4(t,sh,so,dh,do,c) \
195 		_bus_space_copy_region_4(t,sh,so,dh,do,c)
196 
197 static inline u_int8_t _bus_space_read_1
198 	__P((bus_space_tag_t, bus_space_handle_t bsh, bus_size_t offset));
199 static inline u_int16_t _bus_space_read_2
200 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
201 static inline u_int32_t _bus_space_read_4
202 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
203 
204 static inline void _bus_space_read_multi_1
205 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
206 	     u_int8_t *, bus_size_t));
207 static inline void _bus_space_read_multi_2
208 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
209 	     u_int16_t *, bus_size_t));
210 static inline void _bus_space_read_multi_4
211 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
212 	     u_int32_t *, bus_size_t));
213 
214 static inline void _bus_space_read_region_1
215 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
216 	     u_int8_t *, bus_size_t));
217 static inline void _bus_space_read_region_2
218 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
219 	     u_int16_t *, bus_size_t));
220 static inline void _bus_space_read_region_4
221 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
222 	     u_int32_t *, bus_size_t));
223 
224 static inline void _bus_space_write_1
225 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t));
226 static inline void _bus_space_write_2
227 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t));
228 static inline void _bus_space_write_4
229 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t));
230 
231 static inline void _bus_space_write_multi_1
232 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
233 	     u_int8_t *, bus_size_t));
234 static inline void _bus_space_write_multi_2
235 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
236 	     u_int16_t *, bus_size_t));
237 static inline void _bus_space_write_multi_4
238 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
239 	     u_int32_t *, bus_size_t));
240 
241 static inline void _bus_space_write_region_1
242 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
243 	     u_int8_t *, bus_size_t));
244 static inline void _bus_space_write_region_2
245 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
246 	     u_int16_t *, bus_size_t));
247 static inline void _bus_space_write_region_4
248 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
249 	     u_int32_t *, bus_size_t));
250 
251 static inline void _bus_space_set_region_1
252 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
253 	     u_int8_t, bus_size_t));
254 static inline void _bus_space_set_region_2
255 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
256 	     u_int16_t, bus_size_t));
257 static inline void _bus_space_set_region_4
258 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
259 	     u_int32_t, bus_size_t));
260 
261 static inline void _bus_space_copy_region_1
262 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
263 	     bus_space_handle_t, bus_size_t, bus_size_t));
264 static inline void _bus_space_copy_region_2
265 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
266 	     bus_space_handle_t, bus_size_t, bus_size_t));
267 static inline void _bus_space_copy_region_4
268 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
269 	     bus_space_handle_t, bus_size_t, bus_size_t));
270 
271 
272 #define __X68K_BUS_ADDR(tag, handle, offset)	\
273 	(((long)(handle) < 0 ? (offset) * 2 : (offset))	\
274 		+ ((handle) & 0x7fffffff))
275 
276 static inline u_int8_t
277 _bus_space_read_1(t, bsh, offset)
278 	bus_space_tag_t t;
279 	bus_space_handle_t bsh;
280 	bus_size_t offset;
281 {
282 	return (*((volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset)));
283 }
284 
285 static inline u_int16_t
286 _bus_space_read_2(t, bsh, offset)
287 	bus_space_tag_t t;
288 	bus_space_handle_t bsh;
289 	bus_size_t offset;
290 {
291 	return (*((volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset)));
292 }
293 
294 static inline u_int32_t
295 _bus_space_read_4(t, bsh, offset)
296 	bus_space_tag_t t;
297 	bus_space_handle_t bsh;
298 	bus_size_t offset;
299 {
300 	return (*((volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset)));
301 }
302 
303 static inline void
304 _bus_space_read_multi_1(t, bsh, offset, datap, count)
305 	bus_space_tag_t t;
306 	bus_space_handle_t bsh;
307 	bus_size_t offset;
308 	u_int8_t *datap;
309 	bus_size_t count;
310 {
311 #if X68K_BUS_PERFORMANCE_HACK
312 	u_int8_t *regadr = (u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset);
313 	for (; count; count--) {
314 		__asm("| avoid optim. _bus_space_read_multi_1" : : : "memory");
315 		*datap++ = *regadr;
316 	}
317 #else
318 	while (count-- > 0) {
319 		*datap++ = *(volatile u_int8_t *)
320 				__X68K_BUS_ADDR(t, bsh, offset);
321 	}
322 #endif
323 }
324 
325 static inline void
326 _bus_space_read_multi_2(t, bsh, offset, datap, count)
327 	bus_space_tag_t t;
328 	bus_space_handle_t bsh;
329 	bus_size_t offset;
330 	u_int16_t *datap;
331 	bus_size_t count;
332 {
333 #if X68K_BUS_PERFORMANCE_HACK
334 	u_int16_t *regadr = (u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset);
335 	for (; count; count--) {
336 		__asm("| avoid optim. _bus_space_read_multi_2" : : : "memory");
337 		*datap++ = *regadr;
338 	}
339 #else
340 	while (count-- > 0) {
341 		*datap++ = *(volatile u_int16_t *)
342 				__X68K_BUS_ADDR(t, bsh, offset);
343 	}
344 #endif
345 }
346 
347 static inline void
348 _bus_space_read_multi_4(t, bsh, offset, datap, count)
349 	bus_space_tag_t t;
350 	bus_space_handle_t bsh;
351 	bus_size_t offset;
352 	u_int32_t *datap;
353 	bus_size_t count;
354 {
355 #if X68K_BUS_PERFORMANCE_HACK
356 	u_int32_t *regadr = (u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset);
357 	for (; count; count--) {
358 		__asm("| avoid optim. _bus_space_read_multi_4" : : : "memory");
359 		*datap++ = *regadr;
360 	}
361 #else
362 	while (count-- > 0) {
363 		*datap++ = *(volatile u_int32_t *)
364 				__X68K_BUS_ADDR(t, bsh, offset);
365 	}
366 #endif
367 }
368 
369 static inline void
370 _bus_space_read_region_1(t, bsh, offset, datap, count)
371 	bus_space_tag_t t;
372 	bus_space_handle_t bsh;
373 	bus_size_t offset;
374 	u_int8_t *datap;
375 	bus_size_t count;
376 {
377 #if X68K_BUS_PERFORMANCE_HACK
378 	u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
379 
380 	for (; count; count--) {
381 		__asm("| avoid optim. _bus_space_read_region_1" : : : "memory");
382 		*datap++ = *addr++;
383 	}
384 #else
385 	volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
386 
387 	while (count-- > 0) {
388 		*datap++ = *addr++;
389 	}
390 #endif
391 }
392 
393 static inline void
394 _bus_space_read_region_2(t, bsh, offset, datap, count)
395 	bus_space_tag_t t;
396 	bus_space_handle_t bsh;
397 	bus_size_t offset;
398 	u_int16_t *datap;
399 	bus_size_t count;
400 {
401 #if X68K_BUS_PERFORMANCE_HACK
402 	u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
403 
404 	for (; count; count--) {
405 		__asm("| avoid optim. _bus_space_read_region_2" : : : "memory");
406 		*datap++ = *addr++;
407 	}
408 #else
409 	volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
410 
411 	while (count-- > 0) {
412 		*datap++ = *addr++;
413 	}
414 #endif
415 }
416 
417 static inline void
418 _bus_space_read_region_4(t, bsh, offset, datap, count)
419 	bus_space_tag_t t;
420 	bus_space_handle_t bsh;
421 	bus_size_t offset;
422 	u_int32_t *datap;
423 	bus_size_t count;
424 {
425 #if X68K_BUS_PERFORMANCE_HACK
426 	u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
427 
428 	for (; count; count--) {
429 		__asm("| avoid optim. _bus_space_read_region_4" : : : "memory");
430 		*datap++ = *addr++;
431 	}
432 #else
433 	volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
434 
435 	while (count-- > 0) {
436 		*datap++ = *addr++;
437 	}
438 #endif
439 }
440 
441 static inline void
442 _bus_space_write_1(t, bsh, offset, value)
443 	bus_space_tag_t t;
444 	bus_space_handle_t bsh;
445 	bus_size_t offset;
446 	u_int8_t value;
447 {
448 	*(volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
449 }
450 
451 static inline void
452 _bus_space_write_2(t, bsh, offset, value)
453 	bus_space_tag_t t;
454 	bus_space_handle_t bsh;
455 	bus_size_t offset;
456 	u_int16_t value;
457 {
458 	*(volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
459 }
460 
461 static inline void
462 _bus_space_write_4(t, bsh, offset, value)
463 	bus_space_tag_t t;
464 	bus_space_handle_t bsh;
465 	bus_size_t offset;
466 	u_int32_t value;
467 {
468 	*(volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
469 }
470 
471 static inline void
472 _bus_space_write_multi_1(t, bsh, offset, datap, count)
473 	bus_space_tag_t t;
474 	bus_space_handle_t bsh;
475 	bus_size_t offset;
476 	u_int8_t *datap;
477 	bus_size_t count;
478 {
479 #if X68K_BUS_PERFORMANCE_HACK
480 	u_int8_t *regadr = (u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset);
481 	for (; count; count--) {
482 		__asm("| avoid optim. _bus_space_write_multi_1" : : : "memory");
483 		*regadr = *datap++;
484 	}
485 #else
486 	while (count-- > 0) {
487 		*(volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset)
488 		    = *datap++;
489 	}
490 #endif
491 }
492 
493 static inline void
494 _bus_space_write_multi_2(t, bsh, offset, datap, count)
495 	bus_space_tag_t t;
496 	bus_space_handle_t bsh;
497 	bus_size_t offset;
498 	u_int16_t *datap;
499 	bus_size_t count;
500 {
501 #if X68K_BUS_PERFORMANCE_HACK
502 	u_int16_t *regadr = (u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset);
503 	for (; count; count--) {
504 		__asm("| avoid optim. _bus_space_write_multi_2" : : : "memory");
505 		*regadr = *datap++;
506 	}
507 #else
508 	while (count-- > 0) {
509 		*(volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset)
510 		    = *datap++;
511 	}
512 #endif
513 }
514 
515 static inline void
516 _bus_space_write_multi_4(t, bsh, offset, datap, count)
517 	bus_space_tag_t t;
518 	bus_space_handle_t bsh;
519 	bus_size_t offset;
520 	u_int32_t *datap;
521 	bus_size_t count;
522 {
523 #if X68K_BUS_PERFORMANCE_HACK
524 	u_int32_t *regadr = (u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset);
525 	for (; count; count--) {
526 		__asm("| avoid optim. _bus_space_write_multi_4" : : : "memory");
527 		*regadr = *datap++;
528 	}
529 #else
530 	while (count-- > 0) {
531 		*(volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset)
532 		    = *datap++;
533 	}
534 #endif
535 }
536 
537 static inline void
538 _bus_space_write_region_1(t, bsh, offset, datap, count)
539 	bus_space_tag_t t;
540 	bus_space_handle_t bsh;
541 	bus_size_t offset;
542 	u_int8_t *datap;
543 	bus_size_t count;
544 {
545 #if X68K_BUS_PERFORMANCE_HACK
546 	u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
547 
548 	for (; count; count--) {
549 		__asm("| avoid optim. _bus_space_write_region_1": : : "memory");
550 		*addr++ = *datap++;
551 	}
552 #else
553 	volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
554 
555 	while (count-- > 0) {
556 		*addr++ = *datap++;
557 	}
558 #endif
559 }
560 
561 static inline void
562 _bus_space_write_region_2(t, bsh, offset, datap, count)
563 	bus_space_tag_t t;
564 	bus_space_handle_t bsh;
565 	bus_size_t offset;
566 	u_int16_t *datap;
567 	bus_size_t count;
568 {
569 #if X68K_BUS_PERFORMANCE_HACK
570 	u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
571 
572 	for (; count; count--) {
573 		__asm("| avoid optim. _bus_space_write_region_2": : : "memory");
574 		*addr++ = *datap++;
575 	}
576 #else
577 	volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
578 
579 	while (count-- > 0) {
580 		*addr++ = *datap++;
581 	}
582 #endif
583 }
584 
585 static inline void
586 _bus_space_write_region_4(t, bsh, offset, datap, count)
587 	bus_space_tag_t t;
588 	bus_space_handle_t bsh;
589 	bus_size_t offset;
590 	u_int32_t *datap;
591 	bus_size_t count;
592 {
593 #if X68K_BUS_PERFORMANCE_HACK
594 	u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
595 
596 	for (; count; count--) {
597 		__asm("| avoid optim. _bus_space_write_region_4": : : "memory");
598 		*addr++ = *datap++;
599 	}
600 #else
601 	volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
602 
603 	while (count-- > 0) {
604 		*addr++ = *datap++;
605 	}
606 #endif
607 }
608 
609 static inline void
610 _bus_space_set_region_1(t, bsh, offset, value, count)
611 	bus_space_tag_t t;
612 	bus_space_handle_t bsh;
613 	bus_size_t offset;
614 	u_int8_t value;
615 	bus_size_t count;
616 {
617 #if X68K_BUS_PERFORMANCE_HACK
618 	u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
619 
620 	for (; count; count--) {
621 		__asm("| avoid optim. _bus_space_set_region_1" : : : "memory");
622 		*addr++ = value;
623 	}
624 #else
625 	volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
626 
627 	while (count-- > 0) {
628 		*addr++ = value;
629 	}
630 #endif
631 }
632 
633 static inline void
634 _bus_space_set_region_2(t, bsh, offset, value, count)
635 	bus_space_tag_t t;
636 	bus_space_handle_t bsh;
637 	bus_size_t offset;
638 	u_int16_t value;
639 	bus_size_t count;
640 {
641 #if X68K_BUS_PERFORMANCE_HACK
642 	u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
643 
644 	for (; count; count--) {
645 		__asm("| avoid optim. _bus_space_set_region_2" : : : "memory");
646 		*addr++ = value;
647 	}
648 #else
649 	volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
650 
651 	while (count-- > 0) {
652 		*addr++ = value;
653 	}
654 #endif
655 }
656 
657 static inline void
658 _bus_space_set_region_4(t, bsh, offset, value, count)
659 	bus_space_tag_t t;
660 	bus_space_handle_t bsh;
661 	bus_size_t offset;
662 	u_int32_t value;
663 	bus_size_t count;
664 {
665 #if X68K_BUS_PERFORMANCE_HACK
666 	u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
667 
668 	for (; count; count--) {
669 		__asm("| avoid optim. _bus_space_set_region_4" : : : "memory");
670 		*addr++ = value;
671 	}
672 #else
673 	volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
674 
675 	while (count-- > 0) {
676 		*addr++ = value;
677 	}
678 #endif
679 }
680 
681 static inline void
682 _bus_space_copy_region_1(t, sbsh, soffset, dbsh, doffset, count)
683 	bus_space_tag_t t;
684 	bus_space_handle_t sbsh;
685 	bus_size_t soffset;
686 	bus_space_handle_t dbsh;
687 	bus_size_t doffset;
688 	bus_size_t count;
689 {
690 	volatile u_int8_t *saddr = (void *) (sbsh + soffset);
691 	volatile u_int8_t *daddr = (void *) (dbsh + doffset);
692 
693 	if ((u_int32_t) saddr >= (u_int32_t) daddr)
694 		while (count-- > 0)
695 			*daddr++ = *saddr++;
696 	else {
697 		saddr += count;
698 		daddr += count;
699 		while (count-- > 0)
700 			*--daddr = *--saddr;
701 	}
702 }
703 
704 static inline void
705 _bus_space_copy_region_2(t, sbsh, soffset, dbsh, doffset, count)
706 	bus_space_tag_t t;
707 	bus_space_handle_t sbsh;
708 	bus_size_t soffset;
709 	bus_space_handle_t dbsh;
710 	bus_size_t doffset;
711 	bus_size_t count;
712 {
713 	volatile u_int16_t *saddr = (void *) (sbsh + soffset);
714 	volatile u_int16_t *daddr = (void *) (dbsh + doffset);
715 
716 	if ((u_int32_t) saddr >= (u_int32_t) daddr)
717 		while (count-- > 0)
718 			*daddr++ = *saddr++;
719 	else {
720 		saddr += count;
721 		daddr += count;
722 		while (count-- > 0)
723 			*--daddr = *--saddr;
724 	}
725 }
726 
727 static inline void
728 _bus_space_copy_region_4(t, sbsh, soffset, dbsh, doffset, count)
729 	bus_space_tag_t t;
730 	bus_space_handle_t sbsh;
731 	bus_size_t soffset;
732 	bus_space_handle_t dbsh;
733 	bus_size_t doffset;
734 	bus_size_t count;
735 {
736 	volatile u_int32_t *saddr = (void *) (sbsh + soffset);
737 	volatile u_int32_t *daddr = (void *) (dbsh + doffset);
738 
739 	if ((u_int32_t) saddr >= (u_int32_t) daddr)
740 		while (count-- > 0)
741 			*daddr++ = *saddr++;
742 	else {
743 		saddr += count;
744 		daddr += count;
745 		while (count-- > 0)
746 			*--daddr = *--saddr;
747 	}
748 }
749 
750 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
751 
752 /*
753  * DMA segment
754  */
755 struct x68k_bus_dma_segment {
756 	bus_addr_t	ds_addr;
757 	bus_size_t	ds_len;
758 };
759 typedef struct x68k_bus_dma_segment	bus_dma_segment_t;
760 
761 /*
762  * DMA descriptor
763  */
764 /* Forwards needed by prototypes below. */
765 struct mbuf;
766 struct uio;
767 
768 typedef struct x68k_bus_dma		*bus_dma_tag_t;
769 typedef struct x68k_bus_dmamap		*bus_dmamap_t;
770 struct x68k_bus_dma {
771 	/*
772 	 * The `bounce threshold' is checked while we are loading
773 	 * the DMA map.  If the physical address of the segment
774 	 * exceeds the threshold, an error will be returned.  The
775 	 * caller can then take whatever action is necessary to
776 	 * bounce the transfer.  If this value is 0, it will be
777 	 * ignored.
778 	 */
779 	bus_addr_t _bounce_thresh;
780 
781 	/*
782 	 * DMA mapping methods.
783 	 */
784 	int	(*x68k_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int,
785 		    bus_size_t, bus_size_t, int, bus_dmamap_t *));
786 	void	(*x68k_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t));
787 	int	(*x68k_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *,
788 		    bus_size_t, struct proc *, int));
789 	int	(*x68k_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t,
790 		    struct mbuf *, int));
791 	int	(*x68k_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t,
792 		    struct uio *, int));
793 	int	(*x68k_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t,
794 		    bus_dma_segment_t *, int, bus_size_t, int));
795 	void	(*x68k_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t));
796 	void	(*x68k_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t,
797 		    bus_addr_t, bus_size_t, int));
798 
799 	/*
800 	 * DMA memory utility functions.
801 	 */
802 	int	(*x68k_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t,
803 		    bus_size_t, bus_dma_segment_t *, int, int *, int));
804 	void	(*x68k_dmamem_free) __P((bus_dma_tag_t,
805 		    bus_dma_segment_t *, int));
806 	int	(*x68k_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *,
807 		    int, size_t, caddr_t *, int));
808 	void	(*x68k_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t));
809 	paddr_t	(*x68k_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *,
810 		    int, off_t, int, int));
811 };
812 
813 /*
814  *	bus_dmamap_t
815  *
816  *	Describes a DMA mapping.
817  */
818 struct x68k_bus_dmamap {
819 	/*
820 	 * PRIVATE MEMBERS: not for use my machine-independent code.
821 	 */
822 	bus_size_t	x68k_dm_size;	/* largest DMA transfer mappable */
823 	int		x68k_dm_segcnt;	/* number of segs this map can map */
824 	bus_size_t	x68k_dm_maxsegsz; /* largest possible segment */
825 	bus_size_t	x68k_dm_boundary; /* don't cross this */
826 	bus_addr_t	x68k_dm_bounce_thresh; /* bounce threshold */
827 	int		x68k_dm_flags;	/* misc. flags */
828 
829 	void		*x68k_dm_cookie; /* cookie for bus-specific functions */
830 
831 	/*
832 	 * PUBLIC MEMBERS: these are used by machine-independent code.
833 	 */
834 	bus_size_t	dm_mapsize;	/* size of the mapping */
835 	int		dm_nsegs;	/* # valid segments in mapping */
836 	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
837 };
838 
839 int	x68k_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t,
840 	    bus_size_t, int, bus_dmamap_t *));
841 void	x68k_bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
842 int	x68k_bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
843 	    bus_size_t, struct proc *, int));
844 int	x68k_bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
845 	    struct mbuf *, int));
846 int	x68k_bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t,
847 	    struct uio *, int));
848 int	x68k_bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
849 	    bus_dma_segment_t *, int, bus_size_t, int));
850 void	x68k_bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
851 void	x68k_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
852 	    bus_size_t, int));
853 
854 int	x68k_bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size,
855 	    bus_size_t alignment, bus_size_t boundary,
856 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags));
857 void	x68k_bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
858 	    int nsegs));
859 int	x68k_bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
860 	    int nsegs, size_t size, caddr_t *kvap, int flags));
861 void	x68k_bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva,
862 	    size_t size));
863 paddr_t	x68k_bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
864 	    int nsegs, off_t off, int prot, int flags));
865 
866 int	x68k_bus_dmamap_load_buffer __P((bus_dmamap_t, void *,
867 	    bus_size_t buflen, struct proc *, int, paddr_t *, int *, int));
868 int	x68k_bus_dmamem_alloc_range __P((bus_dma_tag_t tag, bus_size_t size,
869 	    bus_size_t alignment, bus_size_t boundary,
870 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
871 	    paddr_t low, paddr_t high));
872 
873 #define	bus_dmamap_create(t,s,n,m,b,f,p) \
874 	((*((t)->x68k_dmamap_create)) ((t),(s),(n),(m),(b),(f),(p)))
875 #define	bus_dmamap_destroy(t,p) \
876 	((*((t)->x68k_dmamap_destroy)) ((t),(p)))
877 #define	bus_dmamap_load(t,m,b,s,p,f) \
878 	((*((t)->x68k_dmamap_load)) ((t),(m),(b),(s),(p),(f)))
879 #define	bus_dmamap_load_mbuf(t,m,b,f) \
880 	((*((t)->x68k_dmamap_load_mbuf)) ((t),(m),(b),(f)))
881 #define	bus_dmamap_load_uio(t,m,u,f) \
882 	((*((t)->x68k_dmamap_load_uio)) ((t),(m),(u),(f)))
883 #define	bus_dmamap_load_raw(t,m,sg,n,s,f) \
884 	((*((t)->x68k_dmamap_load_raw)) ((t),(m),(sg),(n),(s),(f)))
885 #define	bus_dmamap_unload(t,p) \
886 	((*((t)->x68k_dmamap_unload)) ((t),(p)))
887 #define	bus_dmamap_sync(t,p,o,l,ops) \
888 	((*((t)->x68k_dmamap_sync)) ((t),(p),(o),(l),(ops)))
889 
890 #define	bus_dmamem_alloc(t,s,a,b,sg,n,r,f) \
891 	((*((t)->x68k_dmamem_alloc)) ((t),(s),(a),(b),(sg),(n),(r),(f)))
892 #define	bus_dmamem_free(t,sg,n) \
893 	((*((t)->x68k_dmamem_free)) ((t),(sg),(n)))
894 #define	bus_dmamem_map(t,sg,n,s,k,f) \
895 	((*((t)->x68k_dmamem_map)) ((t),(sg),(n),(s),(k),(f)))
896 #define	bus_dmamem_unmap(t,k,s) \
897 	((*((t)->x68k_dmamem_unmap)) ((t),(k),(s)))
898 #define	bus_dmamem_mmap(t,sg,n,o,p,f) \
899 	((*((t)->x68k_dmamem_mmap)) ((t),(sg),(n),(o),(p),(f)))
900 
901 /*
902  * Flags used in various bus DMA methods.
903  */
904 #define	BUS_DMA_WAITOK		0x000	/* safe to sleep (pseudo-flag) */
905 #define	BUS_DMA_NOWAIT		0x001	/* not safe to sleep */
906 #define	BUS_DMA_ALLOCNOW	0x002	/* perform resource allocation now */
907 #define	BUS_DMA_COHERENT	0x004	/* hint: map memory DMA coherent */
908 #define	BUS_DMA_STREAMING	0x008	/* hint: sequential, unidirectional */
909 #define	BUS_DMA_BUS1		0x010	/* placeholders for bus functions... */
910 #define	BUS_DMA_BUS2		0x020
911 #define	BUS_DMA_BUS3		0x040
912 #define	BUS_DMA_BUS4		0x080
913 #define	BUS_DMA_READ		0x100	/* mapping is device -> memory only */
914 #define	BUS_DMA_WRITE		0x200	/* mapping is memory -> device only */
915 
916 /*
917  * Operations performed by bus_dmamap_sync().
918  */
919 #define	BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
920 #define	BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
921 #define	BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
922 #define	BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
923 
924 #endif /* _X68K_BUS_H_ */
925