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