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