xref: /freebsd/sys/powerpc/include/bus.h (revision 2357939bc239bd5334a169b62313806178dd8f30)
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(t, h, o, l, f)	\
730 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
731 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
732 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
733 
734 #define	BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
735 
736 /*
737  * Bus DMA methods.
738  */
739 
740 /*
741  * Flags used in various bus DMA methods.
742  */
743 #define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
744 #define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
745 #define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
746 #define	BUS_DMA_COHERENT	0x04	/* hint: map memory DMA coherent */
747 #define	BUS_DMA_ZERO		0x08	/* allocate zero'ed memory */
748 #define	BUS_DMA_BUS1		0x10	/* placeholders for bus functions... */
749 #define	BUS_DMA_BUS2		0x20
750 #define	BUS_DMA_BUS3		0x40
751 #define	BUS_DMA_BUS4		0x80
752 
753 /* Forwards needed by prototypes below. */
754 struct mbuf;
755 struct uio;
756 
757 /*
758  *      Operations performed by bus_dmamap_sync().
759  */
760 typedef int bus_dmasync_op_t;
761 #define	BUS_DMASYNC_PREREAD	1
762 #define	BUS_DMASYNC_POSTREAD	2
763 #define	BUS_DMASYNC_PREWRITE	4
764 #define	BUS_DMASYNC_POSTWRITE	8
765 
766 /*
767  *      bus_dma_tag_t
768  *
769  *      A machine-dependent opaque type describing the characteristics
770  *      of how to perform DMA mappings.  This structure encapsultes
771  *      information concerning address and alignment restrictions, number
772  *      of S/G  segments, amount of data per S/G segment, etc.
773  */
774 typedef struct bus_dma_tag	*bus_dma_tag_t;
775 
776 /*
777  *      bus_dmamap_t
778  *
779  *      DMA mapping instance information.
780  */
781 typedef struct bus_dmamap	*bus_dmamap_t;
782 
783 /*
784  *	bus_dma_segment_t
785  *
786  *	Describes a single contiguous DMA transaction.  Values
787  *	are suitable for programming into DMA registers.
788  */
789 typedef struct bus_dma_segment {
790 	bus_addr_t	ds_addr;	/* DMA address */
791 	bus_size_t	ds_len;		/* length of transfer */
792 } bus_dma_segment_t;
793 
794 /*
795  * A function that returns 1 if the address cannot be accessed by
796  * a device and 0 if it can be.
797  */
798 typedef int bus_dma_filter_t(void *, bus_addr_t);
799 
800 /*
801  * A function that performs driver-specific syncronization on behalf of
802  * busdma.
803  */
804 typedef enum {
805 	BUS_DMA_LOCK    = 0x01,
806 	BUS_DMA_UNLOCK  = 0x02,
807 } bus_dma_lock_op_t;
808 
809 typedef void bus_dma_lock_t(void *, bus_dma_lock_op_t);
810 
811 /*
812  * Allocate a device specific dma_tag encapsulating the constraints of
813  * the parent tag in addition to other restrictions specified:
814  *
815  *      alignment:      alignment for segments.
816  *      boundary:       Boundary that segments cannot cross.
817  *      lowaddr:        Low restricted address that cannot appear in a mapping.
818  *      highaddr:       High restricted address that cannot appear in a mapping.
819  *      filtfunc:       An optional function to further test if an address
820  *                      within the range of lowaddr and highaddr cannot appear
821  *                      in a mapping.
822  *      filtfuncarg:    An argument that will be passed to filtfunc in addition
823  *                      to the address to test.
824  *      maxsize:        Maximum mapping size supported by this tag.
825  *      nsegments:      Number of discontinuities allowed in maps.
826  *      maxsegsz:       Maximum size of a segment in the map.
827  *      flags:          Bus DMA flags.
828  *      dmat:           A pointer to set to a valid dma tag should the return
829  *                      value of this function indicate success.
830  */
831 int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
832 		       bus_size_t boundary, bus_addr_t lowaddr,
833 		       bus_addr_t highaddr, bus_dma_filter_t *filtfunc,
834 		       void *filtfuncarg, bus_size_t maxsize, int nsegments,
835 		       bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
836 		       void *lockfuncarg, bus_dma_tag_t *dmat);
837 
838 int bus_dma_tag_destroy(bus_dma_tag_t dmat);
839 
840 /*
841  * Allocate a handle for mapping from kva/uva/physical
842  * address space into bus device space.
843  */
844 int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
845 
846 /*
847  * Destroy  a handle for mapping from kva/uva/physical
848  * address space into bus device space.
849  */
850 int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map);
851 
852 /*
853  * Allocate a piece of memory that can be efficiently mapped into
854  * bus device space based on the constraints lited in the dma tag.
855  * A dmamap to for use with dmamap_load is also allocated.
856  */
857 int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
858 		     bus_dmamap_t *mapp);
859 
860 /*
861  * Free a piece of memory and it's allociated dmamap, that was allocated
862  * via bus_dmamem_alloc.
863  */
864 void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
865 
866 /*
867  * A function that processes a successfully loaded dma map or an error
868  * from a delayed load map.
869  */
870 typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
871 
872 /*
873  * Map the buffer buf into bus space using the dmamap map.
874  */
875 int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
876 		    bus_size_t buflen, bus_dmamap_callback_t *callback,
877 		    void *callback_arg, int flags);
878 
879 /*
880  * Like bus_dmamap_callback but includes map size in bytes.  This is
881  * defined as a separate interface to maintain compatiiblity for users
882  * of bus_dmamap_callback_t--at some point these interfaces should be merged.
883  */
884 typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int);
885 /*
886  * Like bus_dmamap_load but for mbufs.  Note the use of the
887  * bus_dmamap_callback2_t interface.
888  */
889 int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map,
890 			 struct mbuf *mbuf,
891 			 bus_dmamap_callback2_t *callback, void *callback_arg,
892 			 int flags);
893 /*
894  * Like bus_dmamap_load but for uios.  Note the use of the
895  * bus_dmamap_callback2_t interface.
896  */
897 int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map,
898 			struct uio *ui,
899 			bus_dmamap_callback2_t *callback, void *callback_arg,
900 			int flags);
901 
902 /*
903  * Perform a syncronization operation on the given map.
904  */
905 void bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
906 
907 /*
908  * Release the mapping held by map.
909  */
910 void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
911 
912 /*
913  * Generic helper function for manipulating mutexes.
914  */
915 void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op);
916 #endif /* _MACPPC_BUS_H_ */
917