xref: /freebsd/sys/powerpc/include/bus.h (revision 6af83ee0d2941d18880b6aaa2b4facd1d30c6106)
1 /*-
2  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
7  * NASA Ames Research Center.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the NetBSD
20  *	Foundation, Inc. and its contributors.
21  * 4. Neither the name of The NetBSD Foundation nor the names of its
22  *    contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*-
39  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
40  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *      This product includes software developed by Christopher G. Demetriou
53  *	for the NetBSD Project.
54  * 4. The name of the author may not be used to endorse or promote products
55  *    derived from this software without specific prior written permission
56  *
57  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
63  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
64  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
66  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67  *
68  *	$NetBSD: bus.h,v 1.9.4.1 2000/06/30 16:27:30 simonb Exp $
69  * $FreeBSD$
70  */
71 
72 #ifndef	_MACPPC_BUS_H_
73 #define	_MACPPC_BUS_H_
74 
75 #include <machine/pio.h>
76 
77 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
78 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
79 #define BUS_SPACE_MAXSIZE       0xFFFFFFFF
80 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
81 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
82 #define BUS_SPACE_MAXADDR       0xFFFFFFFF
83 
84 #define BUS_SPACE_UNRESTRICTED  (~0)
85 
86 /*
87  * Values for the macppc bus space tag, not to be used directly by MI code.
88  */
89 
90 #define	__BUS_SPACE_HAS_STREAM_METHODS 1
91 
92 /*
93  * Bus address and size types
94  */
95 typedef u_int32_t bus_addr_t;
96 typedef u_int32_t bus_size_t;
97 
98 /*
99  * Define the PPC tag values
100  */
101 #define PPC_BUS_SPACE_MEM	1	/* space is mem space */
102 #define PPC_BUS_SPACE_IO	2	/* space is io space */
103 
104 /*
105  * Access methods for bus resources and address space.
106  */
107 typedef u_int32_t bus_space_tag_t;
108 typedef u_int32_t bus_space_handle_t;
109 
110 static __inline void *
111 __ppc_ba(bus_space_tag_t tag __unused, bus_space_handle_t handle,
112     bus_size_t offset)
113 {
114 	return ((void *)(handle + offset));
115 }
116 
117 /*
118  *	int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
119  *	    bus_size_t size, int flags, bus_space_handle_t *bshp));
120  *
121  * Map a region of bus space.
122  */
123 #if 0
124 bus_space_map(t, addr, size, flags, bshp) ! not implemented !
125 #endif
126 
127 /*
128  *	int bus_space_unmap(bus_space_tag_t t,
129  *	    bus_space_handle_t bsh, bus_size_t size));
130  *
131  * Unmap a region of bus space.
132  */
133 
134 static __inline void
135 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
136                 bus_size_t size __unused)
137 {
138 }
139 
140 /*
141  *	int bus_space_subregion(bus_space_tag_t t,
142  *	    bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
143  *	    bus_space_handle_t *nbshp));
144  *
145  * Get a new handle for a subregion of an already-mapped area of bus space.
146  */
147 
148 static __inline int
149 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
150     bus_size_t offset, bus_size_t size __unused, bus_space_handle_t *nbshp)
151 {
152 	*nbshp = bsh + offset;
153 	return (0);
154 }
155 
156 /*
157  *	int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
158  *	    bus_addr_t rend, bus_size_t size, bus_size_t align,
159  *	    bus_size_t boundary, int flags, bus_addr_t *addrp,
160  *	    bus_space_handle_t *bshp));
161  *
162  * Allocate a region of bus space.
163  */
164 
165 #if 0
166 #define	bus_space_alloc(t, rs, re, s, a, b, f, ap, hp)	!!! unimplemented !!!
167 #endif
168 
169 /*
170  *	int bus_space_free(bus_space_tag_t t,
171  *	    bus_space_handle_t bsh, bus_size_t size));
172  *
173  * Free a region of bus space.
174  */
175 #if 0
176 #define	bus_space_free(t, h, s)		!!! unimplemented !!!
177 #endif
178 
179 /*
180  *	u_intN_t bus_space_read_N(bus_space_tag_t tag,
181  *	    bus_space_handle_t bsh, bus_size_t offset));
182  *
183  * Read a 1, 2, 4, or 8 byte quantity from bus space
184  * described by tag/handle/offset.
185  */
186 
187 static __inline u_int8_t
188 bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
189 {
190 	return (in8(__ppc_ba(t, h, o)));
191 }
192 
193 static __inline u_int16_t
194 bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
195 {
196 	return (in16rb(__ppc_ba(t, h, o)));
197 }
198 
199 static __inline u_int32_t
200 bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
201 {
202 	return (in32rb(__ppc_ba(t, h, o)));
203 }
204 
205 #if 0	/* Cause a link error for bus_space_read_8 */
206 #define	bus_space_read_8(t, h, o)	!!! unimplemented !!!
207 #endif
208 
209 static __inline u_int8_t
210 bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
211 {
212 	return (in8(__ppc_ba(t, h, o)));
213 }
214 
215 static __inline u_int16_t
216 bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
217 {
218 	return (in16(__ppc_ba(t, h, o)));
219 }
220 
221 static __inline u_int32_t
222 bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
223 {
224 	return (in32(__ppc_ba(t, h, o)));
225 }
226 
227 #if 0	/* Cause a link error for bus_space_read_stream_8 */
228 #define	bus_space_read_stream_8(t, h, o)	!!! unimplemented !!!
229 #endif
230 
231 /*
232  *	void bus_space_read_multi_N(bus_space_tag_t tag,
233  *	    bus_space_handle_t bsh, bus_size_t offset,
234  *	    u_intN_t *addr, size_t count));
235  *
236  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
237  * described by tag/handle/offset and copy into buffer provided.
238  */
239 
240 static __inline void
241 bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
242     u_int8_t *a, size_t c)
243 {
244 	ins8(__ppc_ba(t, h, o), a, c);
245 }
246 
247 static __inline void
248 bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
249     u_int16_t *a, size_t c)
250 {
251 	ins16rb(__ppc_ba(t, h, o), a, c);
252 }
253 
254 static __inline void
255 bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
256     u_int32_t *a, size_t c)
257 {
258 	ins32rb(__ppc_ba(t, h, o), a, c);
259 }
260 
261 #if 0	/* Cause a link error for bus_space_read_multi_8 */
262 #define	bus_space_read_multi_8		!!! unimplemented !!!
263 #endif
264 
265 static __inline void
266 bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
267     bus_size_t o, u_int8_t *a, size_t c)
268 {
269 	ins8(__ppc_ba(t, h, o), a, c);
270 }
271 
272 static __inline void
273 bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
274     bus_size_t o, u_int16_t *a, size_t c)
275 {
276 	ins16(__ppc_ba(t, h, o), a, c);
277 }
278 
279 static __inline void
280 bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
281     bus_size_t o, u_int32_t *a, size_t c)
282 {
283 	ins32(__ppc_ba(t, h, o), a, c);
284 }
285 
286 #if 0	/* Cause a link error for bus_space_read_multi_stream_8 */
287 #define	bus_space_read_multi_stream_8	!!! unimplemented !!!
288 #endif
289 
290 /*
291  *	void bus_space_read_region_N(bus_space_tag_t tag,
292  *	    bus_space_handle_t bsh, bus_size_t offset,
293  *	    u_intN_t *addr, size_t count));
294  *
295  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
296  * described by tag/handle and starting at `offset' and copy into
297  * buffer provided.
298  */
299 
300 static __inline void
301 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
302     bus_size_t offset, u_int8_t *addr, size_t count)
303 {
304 	volatile u_int8_t *s = __ppc_ba(tag, bsh, offset);
305 
306 	while (count--)
307 		*addr++ = *s++;
308 	__asm __volatile("eieio; sync");
309 }
310 
311 static __inline void
312 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
313     bus_size_t offset, u_int16_t *addr, size_t count)
314 {
315 	volatile u_int16_t *s = __ppc_ba(tag, bsh, offset);
316 
317 	while (count--)
318 		__asm __volatile("lhbrx %0, 0, %1" :
319 			"=r"(*addr++) : "r"(s++));
320 	__asm __volatile("eieio; sync");
321 }
322 
323 static __inline void
324 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
325     bus_size_t offset, u_int32_t *addr, size_t count)
326 {
327 	volatile u_int32_t *s = __ppc_ba(tag, bsh, offset);
328 
329 	while (count--)
330 		__asm __volatile("lwbrx %0, 0, %1" :
331 			"=r"(*addr++) : "r"(s++));
332 	__asm __volatile("eieio; sync");
333 }
334 
335 #if 0	/* Cause a link error for bus_space_read_region_8 */
336 #define	bus_space_read_region_8		!!! unimplemented !!!
337 #endif
338 
339 static __inline void
340 bus_space_read_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
341     bus_size_t offset, u_int16_t *addr, size_t count)
342 {
343 	volatile u_int16_t *s = __ppc_ba(tag, bsh, offset);
344 
345 	while (count--)
346 		*addr++ = *s++;
347 	__asm __volatile("eieio; sync");
348 }
349 
350 static __inline void
351 bus_space_read_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
352     bus_size_t offset, u_int32_t *addr, size_t count)
353 {
354 	volatile u_int32_t *s = __ppc_ba(tag, bsh, offset);
355 
356 	while (count--)
357 		*addr++ = *s++;
358 	__asm __volatile("eieio; sync");
359 }
360 
361 #if 0	/* Cause a link error */
362 #define	bus_space_read_region_stream_8		!!! unimplemented !!!
363 #endif
364 
365 /*
366  *	void bus_space_write_N(bus_space_tag_t tag,
367  *	    bus_space_handle_t bsh, bus_size_t offset,
368  *	    u_intN_t value));
369  *
370  * Write the 1, 2, 4, or 8 byte value `value' to bus space
371  * described by tag/handle/offset.
372  */
373 
374 static __inline void
375 bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
376     uint8_t v)
377 {
378 	out8(__ppc_ba(t, h, o), v);
379 }
380 
381 static __inline void
382 bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
383     uint16_t v)
384 {
385 	out16rb(__ppc_ba(t, h, o), v);
386 }
387 
388 static __inline void
389 bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
390     uint32_t v)
391 {
392 	out32rb(__ppc_ba(t, h, o), v);
393 }
394 
395 #if 0	/* Cause a link error for bus_space_write_8 */
396 #define bus_space_write_8		!!! unimplemented !!!
397 #endif
398 
399 static __inline void
400 bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
401     uint8_t v)
402 {
403 	out8(__ppc_ba(t, h, o), v);
404 }
405 
406 static __inline void
407 bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
408     uint16_t v)
409 {
410 	out16(__ppc_ba(t, h, o), v);
411 }
412 
413 static __inline void
414 bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
415     uint32_t v)
416 {
417 	out32(__ppc_ba(t, h, o), v);
418 }
419 
420 #if 0	/* Cause a link error for bus_space_write_stream_8 */
421 #define bus_space_write_stream_8       	!!! unimplemented !!!
422 #endif
423 
424 
425 /*
426  *	void bus_space_write_multi_N(bus_space_tag_t tag,
427  *	    bus_space_handle_t bsh, bus_size_t offset,
428  *	    const u_intN_t *addr, size_t count));
429  *
430  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
431  * provided to bus space described by tag/handle/offset.
432  */
433 
434 static __inline void
435 bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
436     uint8_t *a, size_t c)
437 {
438 	outsb(__ppc_ba(t, h, o), a, c);
439 }
440 
441 static __inline void
442 bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
443     uint16_t *a, size_t c)
444 {
445 	outsw(__ppc_ba(t, h, o), a, c);
446 }
447 
448 static __inline void
449 bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
450     uint32_t *a, size_t c)
451 {
452 	outsl(__ppc_ba(t, h, o), a, c);
453 }
454 
455 #if 0
456 #define bus_space_write_multi_8		!!! unimplemented !!!
457 #endif
458 
459 static __inline void
460 bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
461     bus_size_t o, const u_int8_t *a, size_t c)
462 {
463 	outsb(__ppc_ba(t, h, o), a, c);
464 }
465 
466 static __inline void
467 bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
468     bus_size_t o, const u_int16_t *a, size_t c)
469 {
470 	outsw(__ppc_ba(t, h, o), a, c);
471 }
472 
473 static __inline void
474 bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
475     bus_size_t o, const u_int32_t *a, size_t c)
476 {
477 	outsl(__ppc_ba(t, h, o), a, c);
478 }
479 
480 #if 0
481 #define bus_space_write_multi_stream_8	!!! unimplemented !!!
482 #endif
483 
484 /*
485  *	void bus_space_write_region_N(bus_space_tag_t tag,
486  *	    bus_space_handle_t bsh, bus_size_t offset,
487  *	    const u_intN_t *addr, size_t count));
488  *
489  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
490  * to bus space described by tag/handle starting at `offset'.
491  */
492 
493 static __inline void
494 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
495     bus_size_t offset, const u_int8_t *addr, size_t count)
496 {
497 	volatile u_int8_t *d = __ppc_ba(tag, bsh, offset);
498 
499 	while (count--)
500 		*d++ = *addr++;
501 	__asm __volatile("eieio; sync");
502 }
503 
504 static __inline void
505 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
506     bus_size_t offset, const u_int16_t *addr, size_t count)
507 {
508 	volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
509 
510 	while (count--)
511 		__asm __volatile("sthbrx %0, 0, %1" ::
512 			"r"(*addr++), "r"(d++));
513 	__asm __volatile("eieio; sync");
514 }
515 
516 static __inline void
517 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
518     bus_size_t offset, const u_int32_t *addr, size_t count)
519 {
520 	volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
521 
522 	while (count--)
523 		__asm __volatile("stwbrx %0, 0, %1" ::
524 			"r"(*addr++), "r"(d++));
525 	__asm __volatile("eieio; sync");
526 }
527 
528 #if 0
529 #define	bus_space_write_region_8 !!! bus_space_write_region_8 unimplemented !!!
530 #endif
531 
532 static __inline void
533 bus_space_write_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
534     bus_size_t offset, const u_int16_t *addr, size_t count)
535 {
536 	volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
537 
538 	while (count--)
539 		*d++ = *addr++;
540 	__asm __volatile("eieio; sync");
541 }
542 
543 static __inline void
544 bus_space_write_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
545     bus_size_t offset, const u_int32_t *addr, size_t count)
546 {
547 	volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
548 
549 	while (count--)
550 		*d++ = *addr++;
551 	__asm __volatile("eieio; sync");
552 }
553 
554 #if 0
555 #define	bus_space_write_region_stream_8	!!! unimplemented !!!
556 #endif
557 
558 /*
559  *	void bus_space_set_multi_N(bus_space_tag_t tag,
560  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
561  *	    size_t count));
562  *
563  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
564  * by tag/handle/offset `count' times.
565  */
566 
567 static __inline void
568 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
569     bus_size_t offset, u_int8_t val, size_t count)
570 {
571 	volatile u_int8_t *d = __ppc_ba(tag, bsh, offset);
572 
573 	while (count--)
574 		*d = val;
575 	__asm __volatile("eieio; sync");
576 }
577 
578 static __inline void
579 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
580     bus_size_t offset, u_int16_t val, size_t count)
581 {
582 	volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
583 
584 	while (count--)
585 		__asm __volatile("sthbrx %0, 0, %1" ::
586 			"r"(val), "r"(d));
587 	__asm __volatile("eieio; sync");
588 }
589 
590 static __inline void
591 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
592     bus_size_t offset, u_int32_t val, size_t count)
593 {
594 	volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
595 
596 	while (count--)
597 		__asm __volatile("stwbrx %0, 0, %1" ::
598 			"r"(val), "r"(d));
599 	__asm __volatile("eieio; sync");
600 }
601 
602 #if 0
603 #define	bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
604 #endif
605 
606 static __inline void
607 bus_space_set_multi_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
608     bus_size_t offset, u_int16_t val, size_t count)
609 {
610 	volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
611 
612 	while (count--)
613 		*d = val;
614 	__asm __volatile("eieio; sync");
615 }
616 
617 static __inline void
618 bus_space_set_multi_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
619     bus_size_t offset, u_int32_t val, size_t count)
620 {
621 	volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
622 
623 	while (count--)
624 		*d = val;
625 	__asm __volatile("eieio; sync");
626 }
627 
628 #if 0
629 #define	bus_space_set_multi_stream_8	!!! unimplemented !!!
630 #endif
631 
632 /*
633  *	void bus_space_set_region_N(bus_space_tag_t tag,
634  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
635  *	    size_t count));
636  *
637  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
638  * by tag/handle starting at `offset'.
639  */
640 
641 static __inline void
642 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
643     bus_size_t offset, u_int8_t val, size_t count)
644 {
645 	volatile u_int8_t *d = __ppc_ba(tag, bsh, offset);
646 
647 	while (count--)
648 		*d++ = val;
649 	__asm __volatile("eieio; sync");
650 }
651 
652 static __inline void
653 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
654     bus_size_t offset, u_int16_t val, size_t count)
655 {
656 	volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
657 
658 	while (count--)
659 		__asm __volatile("sthbrx %0, 0, %1" ::
660 			"r"(val), "r"(d++));
661 	__asm __volatile("eieio; sync");
662 }
663 
664 static __inline void
665 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
666     bus_size_t offset, u_int32_t val, size_t count)
667 {
668 	volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
669 
670 	while (count--)
671 		__asm __volatile("stwbrx %0, 0, %1" ::
672 			"r"(val), "r"(d++));
673 	__asm __volatile("eieio; sync");
674 }
675 
676 #if 0
677 #define	bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!!
678 #endif
679 
680 static __inline void
681 bus_space_set_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
682     bus_size_t offset, u_int16_t val, size_t count)
683 {
684 	volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
685 
686 	while (count--)
687 		*d++ = val;
688 	__asm __volatile("eieio; sync");
689 }
690 
691 static __inline void
692 bus_space_set_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
693     bus_size_t offset, u_int32_t val, size_t count)
694 {
695 	volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
696 
697 	while (count--)
698 		*d++ = val;
699 	__asm __volatile("eieio; sync");
700 }
701 
702 #if 0
703 #define	bus_space_set_region_stream_8	!!! unimplemented !!!
704 #endif
705 
706 /*
707  *	void bus_space_copy_region_N(bus_space_tag_t tag,
708  *	    bus_space_handle_t bsh1, bus_size_t off1,
709  *	    bus_space_handle_t bsh2, bus_size_t off2,
710  *	    size_t count));
711  *
712  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
713  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
714  */
715 
716 	/* XXX IMPLEMENT bus_space_copy_N() XXX */
717 
718 /*
719  * Bus read/write barrier methods.
720  *
721  *	void bus_space_barrier(bus_space_tag_t tag,
722  *	    bus_space_handle_t bsh, bus_size_t offset,
723  *	    bus_size_t len, int flags));
724  *
725  * Note: the macppc does not currently require barriers, but we must
726  * provide the flags to MI code.
727  */
728 
729 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
730 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
731 
732 static __inline void
733 bus_space_barrier(bus_space_tag_t tag __unused,
734     bus_space_handle_t bsh __unused, bus_size_t offset __unused,
735     bus_size_t len __unused, int flags __unused)
736 {
737 	__asm __volatile("" : : : "memory");
738 }
739 
740 
741 #define	BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
742 
743 /*
744  * Bus DMA methods.
745  */
746 
747 /*
748  * Flags used in various bus DMA methods.
749  */
750 #define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
751 #define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
752 #define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
753 #define	BUS_DMA_COHERENT	0x04	/* hint: map memory DMA coherent */
754 #define	BUS_DMA_ZERO		0x08	/* allocate zero'ed memory */
755 #define	BUS_DMA_BUS1		0x10	/* placeholders for bus functions... */
756 #define	BUS_DMA_BUS2		0x20
757 #define	BUS_DMA_BUS3		0x40
758 #define	BUS_DMA_BUS4		0x80
759 
760 /* Forwards needed by prototypes below. */
761 struct mbuf;
762 struct uio;
763 
764 /*
765  *      Operations performed by bus_dmamap_sync().
766  */
767 typedef int bus_dmasync_op_t;
768 #define	BUS_DMASYNC_PREREAD	1
769 #define	BUS_DMASYNC_POSTREAD	2
770 #define	BUS_DMASYNC_PREWRITE	4
771 #define	BUS_DMASYNC_POSTWRITE	8
772 
773 /*
774  *      bus_dma_tag_t
775  *
776  *      A machine-dependent opaque type describing the characteristics
777  *      of how to perform DMA mappings.  This structure encapsultes
778  *      information concerning address and alignment restrictions, number
779  *      of S/G  segments, amount of data per S/G segment, etc.
780  */
781 typedef struct bus_dma_tag	*bus_dma_tag_t;
782 
783 /*
784  *      bus_dmamap_t
785  *
786  *      DMA mapping instance information.
787  */
788 typedef struct bus_dmamap	*bus_dmamap_t;
789 
790 /*
791  *	bus_dma_segment_t
792  *
793  *	Describes a single contiguous DMA transaction.  Values
794  *	are suitable for programming into DMA registers.
795  */
796 typedef struct bus_dma_segment {
797 	bus_addr_t	ds_addr;	/* DMA address */
798 	bus_size_t	ds_len;		/* length of transfer */
799 } bus_dma_segment_t;
800 
801 /*
802  * A function that returns 1 if the address cannot be accessed by
803  * a device and 0 if it can be.
804  */
805 typedef int bus_dma_filter_t(void *, bus_addr_t);
806 
807 /*
808  * A function that performs driver-specific syncronization on behalf of
809  * busdma.
810  */
811 typedef enum {
812 	BUS_DMA_LOCK    = 0x01,
813 	BUS_DMA_UNLOCK  = 0x02,
814 } bus_dma_lock_op_t;
815 
816 typedef void bus_dma_lock_t(void *, bus_dma_lock_op_t);
817 
818 /*
819  * Allocate a device specific dma_tag encapsulating the constraints of
820  * the parent tag in addition to other restrictions specified:
821  *
822  *      alignment:      alignment for segments.
823  *      boundary:       Boundary that segments cannot cross.
824  *      lowaddr:        Low restricted address that cannot appear in a mapping.
825  *      highaddr:       High restricted address that cannot appear in a mapping.
826  *      filtfunc:       An optional function to further test if an address
827  *                      within the range of lowaddr and highaddr cannot appear
828  *                      in a mapping.
829  *      filtfuncarg:    An argument that will be passed to filtfunc in addition
830  *                      to the address to test.
831  *      maxsize:        Maximum mapping size supported by this tag.
832  *      nsegments:      Number of discontinuities allowed in maps.
833  *      maxsegsz:       Maximum size of a segment in the map.
834  *      flags:          Bus DMA flags.
835  *      dmat:           A pointer to set to a valid dma tag should the return
836  *                      value of this function indicate success.
837  */
838 int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
839 		       bus_size_t boundary, bus_addr_t lowaddr,
840 		       bus_addr_t highaddr, bus_dma_filter_t *filtfunc,
841 		       void *filtfuncarg, bus_size_t maxsize, int nsegments,
842 		       bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
843 		       void *lockfuncarg, bus_dma_tag_t *dmat);
844 
845 int bus_dma_tag_destroy(bus_dma_tag_t dmat);
846 
847 /*
848  * Allocate a handle for mapping from kva/uva/physical
849  * address space into bus device space.
850  */
851 int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
852 
853 /*
854  * Destroy  a handle for mapping from kva/uva/physical
855  * address space into bus device space.
856  */
857 int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map);
858 
859 /*
860  * Allocate a piece of memory that can be efficiently mapped into
861  * bus device space based on the constraints lited in the dma tag.
862  * A dmamap to for use with dmamap_load is also allocated.
863  */
864 int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
865 		     bus_dmamap_t *mapp);
866 
867 /*
868  * Free a piece of memory and it's allociated dmamap, that was allocated
869  * via bus_dmamem_alloc.
870  */
871 void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
872 
873 /*
874  * A function that processes a successfully loaded dma map or an error
875  * from a delayed load map.
876  */
877 typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
878 
879 /*
880  * Map the buffer buf into bus space using the dmamap map.
881  */
882 int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
883 		    bus_size_t buflen, bus_dmamap_callback_t *callback,
884 		    void *callback_arg, int flags);
885 
886 /*
887  * Like bus_dmamap_callback but includes map size in bytes.  This is
888  * defined as a separate interface to maintain compatiiblity for users
889  * of bus_dmamap_callback_t--at some point these interfaces should be merged.
890  */
891 typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int);
892 /*
893  * Like bus_dmamap_load but for mbufs.  Note the use of the
894  * bus_dmamap_callback2_t interface.
895  */
896 int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map,
897 			 struct mbuf *mbuf,
898 			 bus_dmamap_callback2_t *callback, void *callback_arg,
899 			 int flags);
900 int bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map,
901 			    struct mbuf *mbuf, bus_dma_segment_t *segs,
902 			    int *nsegs, int flags);
903 /*
904  * Like bus_dmamap_load but for uios.  Note the use of the
905  * bus_dmamap_callback2_t interface.
906  */
907 int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map,
908 			struct uio *ui,
909 			bus_dmamap_callback2_t *callback, void *callback_arg,
910 			int flags);
911 
912 /*
913  * Perform a syncronization operation on the given map.
914  */
915 void bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
916 
917 /*
918  * Release the mapping held by map.
919  */
920 void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
921 
922 /*
923  * Generic helper function for manipulating mutexes.
924  */
925 void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op);
926 #endif /* _MACPPC_BUS_H_ */
927