bus.h revision 1.8 1 /* $NetBSD: bus.h,v 1.8 2001/07/19 15:32:20 thorpej 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 0x1001
141
142 #define bus_space_alloc(t,rs,re,s,a,b,f,r,h) \
143 ((*((t)->x68k_bus_space_alloc)) ((t),(rs),(re),(s),(a),(b),(f),(r),(h)))
144 #define bus_space_free(t,h,s) \
145 ((*((t)->x68k_bus_space_free)) ((t),(h),(s)))
146
147 /*
148 * Note: the 680x0 does not currently require barriers, but we must
149 * provide the flags to MI code.
150 */
151 #define bus_space_barrier(t, h, o, l, f) \
152 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
153 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
154 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
155
156 #define bus_space_read_1(t,h,o) _bus_space_read_1(t,h,o)
157 #define bus_space_read_2(t,h,o) _bus_space_read_2(t,h,o)
158 #define bus_space_read_4(t,h,o) _bus_space_read_4(t,h,o)
159
160 #define bus_space_read_multi_1(t,h,o,p,c) _bus_space_read_multi_1(t,h,o,p,c)
161 #define bus_space_read_multi_2(t,h,o,p,c) _bus_space_read_multi_2(t,h,o,p,c)
162 #define bus_space_read_multi_4(t,h,o,p,c) _bus_space_read_multi_4(t,h,o,p,c)
163
164 #define bus_space_read_region_1(t,h,o,p,c) _bus_space_read_region_1(t,h,o,p,c)
165 #define bus_space_read_region_2(t,h,o,p,c) _bus_space_read_region_2(t,h,o,p,c)
166 #define bus_space_read_region_4(t,h,o,p,c) _bus_space_read_region_4(t,h,o,p,c)
167
168 #define bus_space_write_1(t,h,o,v) _bus_space_write_1(t,h,o,v)
169 #define bus_space_write_2(t,h,o,v) _bus_space_write_2(t,h,o,v)
170 #define bus_space_write_4(t,h,o,v) _bus_space_write_4(t,h,o,v)
171
172 #define bus_space_write_multi_1(t,h,o,p,c) _bus_space_write_multi_1(t,h,o,p,c)
173 #define bus_space_write_multi_2(t,h,o,p,c) _bus_space_write_multi_2(t,h,o,p,c)
174 #define bus_space_write_multi_4(t,h,o,p,c) _bus_space_write_multi_4(t,h,o,p,c)
175
176 #define bus_space_write_region_1(t,h,o,p,c) \
177 _bus_space_write_region_1(t,h,o,p,c)
178 #define bus_space_write_region_2(t,h,o,p,c) \
179 _bus_space_write_region_2(t,h,o,p,c)
180 #define bus_space_write_region_4(t,h,o,p,c) \
181 _bus_space_write_region_4(t,h,o,p,c)
182
183 #define bus_space_set_region_1(t,h,o,v,c) _bus_space_set_region_1(t,h,o,v,c)
184 #define bus_space_set_region_2(t,h,o,v,c) _bus_space_set_region_2(t,h,o,v,c)
185 #define bus_space_set_region_4(t,h,o,v,c) _bus_space_set_region_4(t,h,o,v,c)
186
187 #define bus_space_copy_region_1(t,sh,so,dh,do,c) \
188 _bus_space_copy_region_1(t,sh,so,dh,do,c)
189 #define bus_space_copy_region_2(t,sh,so,dh,do,c) \
190 _bus_space_copy_region_2(t,sh,so,dh,do,c)
191 #define bus_space_copy_region_4(t,sh,so,dh,do,c) \
192 _bus_space_copy_region_4(t,sh,so,dh,do,c)
193
194 static inline u_int8_t _bus_space_read_1
195 __P((bus_space_tag_t, bus_space_handle_t bsh, bus_size_t offset));
196 static inline u_int16_t _bus_space_read_2
197 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
198 static inline u_int32_t _bus_space_read_4
199 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
200
201 static inline void _bus_space_read_multi_1
202 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
203 u_int8_t *, bus_size_t));
204 static inline void _bus_space_read_multi_2
205 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
206 u_int16_t *, bus_size_t));
207 static inline void _bus_space_read_multi_4
208 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
209 u_int32_t *, bus_size_t));
210
211 static inline void _bus_space_read_region_1
212 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
213 u_int8_t *, bus_size_t));
214 static inline void _bus_space_read_region_2
215 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
216 u_int16_t *, bus_size_t));
217 static inline void _bus_space_read_region_4
218 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
219 u_int32_t *, bus_size_t));
220
221 static inline void _bus_space_write_1
222 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t));
223 static inline void _bus_space_write_2
224 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t));
225 static inline void _bus_space_write_4
226 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t));
227
228 static inline void _bus_space_write_multi_1
229 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
230 u_int8_t *, bus_size_t));
231 static inline void _bus_space_write_multi_2
232 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
233 u_int16_t *, bus_size_t));
234 static inline void _bus_space_write_multi_4
235 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
236 u_int32_t *, bus_size_t));
237
238 static inline void _bus_space_write_region_1
239 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
240 u_int8_t *, bus_size_t));
241 static inline void _bus_space_write_region_2
242 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
243 u_int16_t *, bus_size_t));
244 static inline void _bus_space_write_region_4
245 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
246 u_int32_t *, bus_size_t));
247
248 static inline void _bus_space_set_region_1
249 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
250 u_int8_t, bus_size_t));
251 static inline void _bus_space_set_region_2
252 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
253 u_int16_t, bus_size_t));
254 static inline void _bus_space_set_region_4
255 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
256 u_int32_t, bus_size_t));
257
258 static inline void _bus_space_copy_region_1
259 __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
260 bus_space_handle_t, bus_size_t, bus_size_t));
261 static inline void _bus_space_copy_region_2
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_4
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
268
269 #define __X68K_BUS_ADDR(tag, handle, offset) \
270 (((long)(handle) < 0 ? (offset) * 2 : (offset)) \
271 + ((handle) & 0x7fffffff))
272
273 static inline u_int8_t
274 _bus_space_read_1(t, bsh, offset)
275 bus_space_tag_t t;
276 bus_space_handle_t bsh;
277 bus_size_t offset;
278 {
279 return (*((volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset)));
280 }
281
282 static inline u_int16_t
283 _bus_space_read_2(t, bsh, offset)
284 bus_space_tag_t t;
285 bus_space_handle_t bsh;
286 bus_size_t offset;
287 {
288 return (*((volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset)));
289 }
290
291 static inline u_int32_t
292 _bus_space_read_4(t, bsh, offset)
293 bus_space_tag_t t;
294 bus_space_handle_t bsh;
295 bus_size_t offset;
296 {
297 return (*((volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset)));
298 }
299
300 static inline void
301 _bus_space_read_multi_1(t, bsh, offset, datap, count)
302 bus_space_tag_t t;
303 bus_space_handle_t bsh;
304 bus_size_t offset;
305 u_int8_t *datap;
306 bus_size_t count;
307 {
308 #if X68K_BUS_PERFORMANCE_HACK
309 u_int8_t *regadr = (u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset);
310 for (; count; count--) {
311 __asm("| avoid optim. _bus_space_read_multi_1" : : : "memory");
312 *datap++ = *regadr;
313 }
314 #else
315 while (count-- > 0) {
316 *datap++ = *(volatile u_int8_t *)
317 __X68K_BUS_ADDR(t, bsh, offset);
318 }
319 #endif
320 }
321
322 static inline void
323 _bus_space_read_multi_2(t, bsh, offset, datap, count)
324 bus_space_tag_t t;
325 bus_space_handle_t bsh;
326 bus_size_t offset;
327 u_int16_t *datap;
328 bus_size_t count;
329 {
330 #if X68K_BUS_PERFORMANCE_HACK
331 u_int16_t *regadr = (u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset);
332 for (; count; count--) {
333 __asm("| avoid optim. _bus_space_read_multi_2" : : : "memory");
334 *datap++ = *regadr;
335 }
336 #else
337 while (count-- > 0) {
338 *datap++ = *(volatile u_int16_t *)
339 __X68K_BUS_ADDR(t, bsh, offset);
340 }
341 #endif
342 }
343
344 static inline void
345 _bus_space_read_multi_4(t, bsh, offset, datap, count)
346 bus_space_tag_t t;
347 bus_space_handle_t bsh;
348 bus_size_t offset;
349 u_int32_t *datap;
350 bus_size_t count;
351 {
352 #if X68K_BUS_PERFORMANCE_HACK
353 u_int32_t *regadr = (u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset);
354 for (; count; count--) {
355 __asm("| avoid optim. _bus_space_read_multi_4" : : : "memory");
356 *datap++ = *regadr;
357 }
358 #else
359 while (count-- > 0) {
360 *datap++ = *(volatile u_int32_t *)
361 __X68K_BUS_ADDR(t, bsh, offset);
362 }
363 #endif
364 }
365
366 static inline void
367 _bus_space_read_region_1(t, bsh, offset, datap, count)
368 bus_space_tag_t t;
369 bus_space_handle_t bsh;
370 bus_size_t offset;
371 u_int8_t *datap;
372 bus_size_t count;
373 {
374 #if X68K_BUS_PERFORMANCE_HACK
375 u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
376
377 for (; count; count--) {
378 __asm("| avoid optim. _bus_space_read_region_1" : : : "memory");
379 *datap++ = *addr++;
380 }
381 #else
382 volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
383
384 while (count-- > 0) {
385 *datap++ = *addr++;
386 }
387 #endif
388 }
389
390 static inline void
391 _bus_space_read_region_2(t, bsh, offset, datap, count)
392 bus_space_tag_t t;
393 bus_space_handle_t bsh;
394 bus_size_t offset;
395 u_int16_t *datap;
396 bus_size_t count;
397 {
398 #if X68K_BUS_PERFORMANCE_HACK
399 u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
400
401 for (; count; count--) {
402 __asm("| avoid optim. _bus_space_read_region_2" : : : "memory");
403 *datap++ = *addr++;
404 }
405 #else
406 volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
407
408 while (count-- > 0) {
409 *datap++ = *addr++;
410 }
411 #endif
412 }
413
414 static inline void
415 _bus_space_read_region_4(t, bsh, offset, datap, count)
416 bus_space_tag_t t;
417 bus_space_handle_t bsh;
418 bus_size_t offset;
419 u_int32_t *datap;
420 bus_size_t count;
421 {
422 #if X68K_BUS_PERFORMANCE_HACK
423 u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
424
425 for (; count; count--) {
426 __asm("| avoid optim. _bus_space_read_region_4" : : : "memory");
427 *datap++ = *addr++;
428 }
429 #else
430 volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
431
432 while (count-- > 0) {
433 *datap++ = *addr++;
434 }
435 #endif
436 }
437
438 static inline void
439 _bus_space_write_1(t, bsh, offset, value)
440 bus_space_tag_t t;
441 bus_space_handle_t bsh;
442 bus_size_t offset;
443 u_int8_t value;
444 {
445 *(volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
446 }
447
448 static inline void
449 _bus_space_write_2(t, bsh, offset, value)
450 bus_space_tag_t t;
451 bus_space_handle_t bsh;
452 bus_size_t offset;
453 u_int16_t value;
454 {
455 *(volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
456 }
457
458 static inline void
459 _bus_space_write_4(t, bsh, offset, value)
460 bus_space_tag_t t;
461 bus_space_handle_t bsh;
462 bus_size_t offset;
463 u_int32_t value;
464 {
465 *(volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
466 }
467
468 static inline void
469 _bus_space_write_multi_1(t, bsh, offset, datap, count)
470 bus_space_tag_t t;
471 bus_space_handle_t bsh;
472 bus_size_t offset;
473 u_int8_t *datap;
474 bus_size_t count;
475 {
476 #if X68K_BUS_PERFORMANCE_HACK
477 u_int8_t *regadr = (u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset);
478 for (; count; count--) {
479 __asm("| avoid optim. _bus_space_write_multi_1" : : : "memory");
480 *regadr = *datap++;
481 }
482 #else
483 while (count-- > 0) {
484 *(volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset)
485 = *datap++;
486 }
487 #endif
488 }
489
490 static inline void
491 _bus_space_write_multi_2(t, bsh, offset, datap, count)
492 bus_space_tag_t t;
493 bus_space_handle_t bsh;
494 bus_size_t offset;
495 u_int16_t *datap;
496 bus_size_t count;
497 {
498 #if X68K_BUS_PERFORMANCE_HACK
499 u_int16_t *regadr = (u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset);
500 for (; count; count--) {
501 __asm("| avoid optim. _bus_space_write_multi_2" : : : "memory");
502 *regadr = *datap++;
503 }
504 #else
505 while (count-- > 0) {
506 *(volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset)
507 = *datap++;
508 }
509 #endif
510 }
511
512 static inline void
513 _bus_space_write_multi_4(t, bsh, offset, datap, count)
514 bus_space_tag_t t;
515 bus_space_handle_t bsh;
516 bus_size_t offset;
517 u_int32_t *datap;
518 bus_size_t count;
519 {
520 #if X68K_BUS_PERFORMANCE_HACK
521 u_int32_t *regadr = (u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset);
522 for (; count; count--) {
523 __asm("| avoid optim. _bus_space_write_multi_4" : : : "memory");
524 *regadr = *datap++;
525 }
526 #else
527 while (count-- > 0) {
528 *(volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset)
529 = *datap++;
530 }
531 #endif
532 }
533
534 static inline void
535 _bus_space_write_region_1(t, bsh, offset, datap, count)
536 bus_space_tag_t t;
537 bus_space_handle_t bsh;
538 bus_size_t offset;
539 u_int8_t *datap;
540 bus_size_t count;
541 {
542 #if X68K_BUS_PERFORMANCE_HACK
543 u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
544
545 for (; count; count--) {
546 __asm("| avoid optim. _bus_space_write_region_1": : : "memory");
547 *addr++ = *datap++;
548 }
549 #else
550 volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
551
552 while (count-- > 0) {
553 *addr++ = *datap++;
554 }
555 #endif
556 }
557
558 static inline void
559 _bus_space_write_region_2(t, bsh, offset, datap, count)
560 bus_space_tag_t t;
561 bus_space_handle_t bsh;
562 bus_size_t offset;
563 u_int16_t *datap;
564 bus_size_t count;
565 {
566 #if X68K_BUS_PERFORMANCE_HACK
567 u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
568
569 for (; count; count--) {
570 __asm("| avoid optim. _bus_space_write_region_2": : : "memory");
571 *addr++ = *datap++;
572 }
573 #else
574 volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
575
576 while (count-- > 0) {
577 *addr++ = *datap++;
578 }
579 #endif
580 }
581
582 static inline void
583 _bus_space_write_region_4(t, bsh, offset, datap, count)
584 bus_space_tag_t t;
585 bus_space_handle_t bsh;
586 bus_size_t offset;
587 u_int32_t *datap;
588 bus_size_t count;
589 {
590 #if X68K_BUS_PERFORMANCE_HACK
591 u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
592
593 for (; count; count--) {
594 __asm("| avoid optim. _bus_space_write_region_4": : : "memory");
595 *addr++ = *datap++;
596 }
597 #else
598 volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
599
600 while (count-- > 0) {
601 *addr++ = *datap++;
602 }
603 #endif
604 }
605
606 static inline void
607 _bus_space_set_region_1(t, bsh, offset, value, count)
608 bus_space_tag_t t;
609 bus_space_handle_t bsh;
610 bus_size_t offset;
611 u_int8_t value;
612 bus_size_t count;
613 {
614 #if X68K_BUS_PERFORMANCE_HACK
615 u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
616
617 for (; count; count--) {
618 __asm("| avoid optim. _bus_space_set_region_1" : : : "memory");
619 *addr++ = value;
620 }
621 #else
622 volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
623
624 while (count-- > 0) {
625 *addr++ = value;
626 }
627 #endif
628 }
629
630 static inline void
631 _bus_space_set_region_2(t, bsh, offset, value, count)
632 bus_space_tag_t t;
633 bus_space_handle_t bsh;
634 bus_size_t offset;
635 u_int16_t value;
636 bus_size_t count;
637 {
638 #if X68K_BUS_PERFORMANCE_HACK
639 u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
640
641 for (; count; count--) {
642 __asm("| avoid optim. _bus_space_set_region_2" : : : "memory");
643 *addr++ = value;
644 }
645 #else
646 volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
647
648 while (count-- > 0) {
649 *addr++ = value;
650 }
651 #endif
652 }
653
654 static inline void
655 _bus_space_set_region_4(t, bsh, offset, value, count)
656 bus_space_tag_t t;
657 bus_space_handle_t bsh;
658 bus_size_t offset;
659 u_int32_t value;
660 bus_size_t count;
661 {
662 #if X68K_BUS_PERFORMANCE_HACK
663 u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
664
665 for (; count; count--) {
666 __asm("| avoid optim. _bus_space_set_region_4" : : : "memory");
667 *addr++ = value;
668 }
669 #else
670 volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
671
672 while (count-- > 0) {
673 *addr++ = value;
674 }
675 #endif
676 }
677
678 static inline void
679 _bus_space_copy_region_1(t, sbsh, soffset, dbsh, doffset, count)
680 bus_space_tag_t t;
681 bus_space_handle_t sbsh;
682 bus_size_t soffset;
683 bus_space_handle_t dbsh;
684 bus_size_t doffset;
685 bus_size_t count;
686 {
687 volatile u_int8_t *saddr = (void *) (sbsh + soffset);
688 volatile u_int8_t *daddr = (void *) (dbsh + doffset);
689
690 if ((u_int32_t) saddr >= (u_int32_t) daddr)
691 while (count-- > 0)
692 *daddr++ = *saddr++;
693 else {
694 saddr += count;
695 daddr += count;
696 while (count-- > 0)
697 *--daddr = *--saddr;
698 }
699 }
700
701 static inline void
702 _bus_space_copy_region_2(t, sbsh, soffset, dbsh, doffset, count)
703 bus_space_tag_t t;
704 bus_space_handle_t sbsh;
705 bus_size_t soffset;
706 bus_space_handle_t dbsh;
707 bus_size_t doffset;
708 bus_size_t count;
709 {
710 volatile u_int16_t *saddr = (void *) (sbsh + soffset);
711 volatile u_int16_t *daddr = (void *) (dbsh + doffset);
712
713 if ((u_int32_t) saddr >= (u_int32_t) daddr)
714 while (count-- > 0)
715 *daddr++ = *saddr++;
716 else {
717 saddr += count;
718 daddr += count;
719 while (count-- > 0)
720 *--daddr = *--saddr;
721 }
722 }
723
724 static inline void
725 _bus_space_copy_region_4(t, sbsh, soffset, dbsh, doffset, count)
726 bus_space_tag_t t;
727 bus_space_handle_t sbsh;
728 bus_size_t soffset;
729 bus_space_handle_t dbsh;
730 bus_size_t doffset;
731 bus_size_t count;
732 {
733 volatile u_int32_t *saddr = (void *) (sbsh + soffset);
734 volatile u_int32_t *daddr = (void *) (dbsh + doffset);
735
736 if ((u_int32_t) saddr >= (u_int32_t) daddr)
737 while (count-- > 0)
738 *daddr++ = *saddr++;
739 else {
740 saddr += count;
741 daddr += count;
742 while (count-- > 0)
743 *--daddr = *--saddr;
744 }
745 }
746
747 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
748
749 /*
750 * DMA segment
751 */
752 struct x68k_bus_dma_segment {
753 bus_addr_t ds_addr;
754 bus_size_t ds_len;
755 };
756 typedef struct x68k_bus_dma_segment bus_dma_segment_t;
757
758 /*
759 * DMA descriptor
760 */
761 /* Forwards needed by prototypes below. */
762 struct mbuf;
763 struct uio;
764
765 typedef struct x68k_bus_dma *bus_dma_tag_t;
766 typedef struct x68k_bus_dmamap *bus_dmamap_t;
767 struct x68k_bus_dma {
768 /*
769 * The `bounce threshold' is checked while we are loading
770 * the DMA map. If the physical address of the segment
771 * exceeds the threshold, an error will be returned. The
772 * caller can then take whatever action is necessary to
773 * bounce the transfer. If this value is 0, it will be
774 * ignored.
775 */
776 bus_addr_t _bounce_thresh;
777
778 /*
779 * DMA mapping methods.
780 */
781 int (*x68k_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int,
782 bus_size_t, bus_size_t, int, bus_dmamap_t *));
783 void (*x68k_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t));
784 int (*x68k_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *,
785 bus_size_t, struct proc *, int));
786 int (*x68k_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t,
787 struct mbuf *, int));
788 int (*x68k_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t,
789 struct uio *, int));
790 int (*x68k_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t,
791 bus_dma_segment_t *, int, bus_size_t, int));
792 void (*x68k_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t));
793 void (*x68k_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t,
794 bus_addr_t, bus_size_t, int));
795
796 /*
797 * DMA memory utility functions.
798 */
799 int (*x68k_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t,
800 bus_size_t, bus_dma_segment_t *, int, int *, int));
801 void (*x68k_dmamem_free) __P((bus_dma_tag_t,
802 bus_dma_segment_t *, int));
803 int (*x68k_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *,
804 int, size_t, caddr_t *, int));
805 void (*x68k_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t));
806 paddr_t (*x68k_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *,
807 int, off_t, int, int));
808 };
809
810 /*
811 * bus_dmamap_t
812 *
813 * Describes a DMA mapping.
814 */
815 struct x68k_bus_dmamap {
816 /*
817 * PRIVATE MEMBERS: not for use my machine-independent code.
818 */
819 bus_size_t x68k_dm_size; /* largest DMA transfer mappable */
820 int x68k_dm_segcnt; /* number of segs this map can map */
821 bus_size_t x68k_dm_maxsegsz; /* largest possible segment */
822 bus_size_t x68k_dm_boundary; /* don't cross this */
823 bus_addr_t x68k_dm_bounce_thresh; /* bounce threshold */
824 int x68k_dm_flags; /* misc. flags */
825
826 void *x68k_dm_cookie; /* cookie for bus-specific functions */
827
828 /*
829 * PUBLIC MEMBERS: these are used by machine-independent code.
830 */
831 bus_size_t dm_mapsize; /* size of the mapping */
832 int dm_nsegs; /* # valid segments in mapping */
833 bus_dma_segment_t dm_segs[1]; /* segments; variable length */
834 };
835
836 int x68k_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t,
837 bus_size_t, int, bus_dmamap_t *));
838 void x68k_bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
839 int x68k_bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
840 bus_size_t, struct proc *, int));
841 int x68k_bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
842 struct mbuf *, int));
843 int x68k_bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t,
844 struct uio *, int));
845 int x68k_bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
846 bus_dma_segment_t *, int, bus_size_t, int));
847 void x68k_bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
848 void x68k_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
849 bus_size_t, int));
850
851 int x68k_bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size,
852 bus_size_t alignment, bus_size_t boundary,
853 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags));
854 void x68k_bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
855 int nsegs));
856 int x68k_bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
857 int nsegs, size_t size, caddr_t *kvap, int flags));
858 void x68k_bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva,
859 size_t size));
860 paddr_t x68k_bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
861 int nsegs, off_t off, int prot, int flags));
862
863 int x68k_bus_dmamap_load_buffer __P((bus_dmamap_t, void *,
864 bus_size_t buflen, struct proc *, int, paddr_t *, int *, int));
865 int x68k_bus_dmamem_alloc_range __P((bus_dma_tag_t tag, bus_size_t size,
866 bus_size_t alignment, bus_size_t boundary,
867 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
868 paddr_t low, paddr_t high));
869
870 #define bus_dmamap_create(t,s,n,m,b,f,p) \
871 ((*((t)->x68k_dmamap_create)) ((t),(s),(n),(m),(b),(f),(p)))
872 #define bus_dmamap_destroy(t,p) \
873 ((*((t)->x68k_dmamap_destroy)) ((t),(p)))
874 #define bus_dmamap_load(t,m,b,s,p,f) \
875 ((*((t)->x68k_dmamap_load)) ((t),(m),(b),(s),(p),(f)))
876 #define bus_dmamap_load_mbuf(t,m,b,f) \
877 ((*((t)->x68k_dmamap_load_mbuf)) ((t),(m),(b),(f)))
878 #define bus_dmamap_load_uio(t,m,u,f) \
879 ((*((t)->x68k_dmamap_load_uio)) ((t),(m),(u),(f)))
880 #define bus_dmamap_load_raw(t,m,sg,n,s,f) \
881 ((*((t)->x68k_dmamap_load_raw)) ((t),(m),(sg),(n),(s),(f)))
882 #define bus_dmamap_unload(t,p) \
883 ((*((t)->x68k_dmamap_unload)) ((t),(p)))
884 #define bus_dmamap_sync(t,p,o,l,ops) \
885 ((*((t)->x68k_dmamap_sync)) ((t),(p),(o),(l),(ops)))
886
887 #define bus_dmamem_alloc(t,s,a,b,sg,n,r,f) \
888 ((*((t)->x68k_dmamem_alloc)) ((t),(s),(a),(b),(sg),(n),(r),(f)))
889 #define bus_dmamem_free(t,sg,n) \
890 ((*((t)->x68k_dmamem_free)) ((t),(sg),(n)))
891 #define bus_dmamem_map(t,sg,n,s,k,f) \
892 ((*((t)->x68k_dmamem_map)) ((t),(sg),(n),(s),(k),(f)))
893 #define bus_dmamem_unmap(t,k,s) \
894 ((*((t)->x68k_dmamem_unmap)) ((t),(k),(s)))
895 #define bus_dmamem_mmap(t,sg,n,o,p,f) \
896 ((*((t)->x68k_dmamem_mmap)) ((t),(sg),(n),(o),(p),(f)))
897
898 /*
899 * Flags used in various bus DMA methods.
900 */
901 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
902 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
903 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
904 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */
905 #define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */
906 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
907 #define BUS_DMA_BUS2 0x020
908 #define BUS_DMA_BUS3 0x040
909 #define BUS_DMA_BUS4 0x080
910 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */
911 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */
912
913 /*
914 * Operations performed by bus_dmamap_sync().
915 */
916 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
917 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
918 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
919 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
920
921 #endif /* _X68K_BUS_H_ */
922