]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/include/bus.h
This commit was generated by cvs2svn to compensate for changes in r141858,
[FreeBSD/FreeBSD.git] / sys / powerpc / include / bus.h
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_ */