bus.h revision 1.13 1 /* $NetBSD: bus.h,v 1.13 2005/03/09 19:04:46 matt 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)(
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)(
83 bus_space_tag_t,
84 bus_space_handle_t,
85 bus_size_t);
86 int (*x68k_bus_space_subregion)(
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)(
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)(
104 bus_space_tag_t,
105 bus_space_handle_t,
106 bus_size_t);
107
108 #if 0
109 void (*x68k_bus_space_barrier)(
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(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(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 (bus_space_tag_t, bus_space_handle_t bsh, bus_size_t offset);
199 static inline u_int16_t _bus_space_read_2
200 (bus_space_tag_t, bus_space_handle_t, bus_size_t);
201 static inline u_int32_t _bus_space_read_4
202 (bus_space_tag_t, bus_space_handle_t, bus_size_t);
203
204 static inline void _bus_space_read_multi_1
205 (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 (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 (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 (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 (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 (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 (bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t);
226 static inline void _bus_space_write_2
227 (bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t);
228 static inline void _bus_space_write_4
229 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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
771 #define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0)
772
773 struct x68k_bus_dma {
774 /*
775 * The `bounce threshold' is checked while we are loading
776 * the DMA map. If the physical address of the segment
777 * exceeds the threshold, an error will be returned. The
778 * caller can then take whatever action is necessary to
779 * bounce the transfer. If this value is 0, it will be
780 * ignored.
781 */
782 bus_addr_t _bounce_thresh;
783
784 /*
785 * DMA mapping methods.
786 */
787 int (*x68k_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
788 bus_size_t, bus_size_t, int, bus_dmamap_t *);
789 void (*x68k_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
790 int (*x68k_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
791 bus_size_t, struct proc *, int);
792 int (*x68k_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
793 struct mbuf *, int);
794 int (*x68k_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
795 struct uio *, int);
796 int (*x68k_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
797 bus_dma_segment_t *, int, bus_size_t, int);
798 void (*x68k_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
799 void (*x68k_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
800 bus_addr_t, bus_size_t, int);
801
802 /*
803 * DMA memory utility functions.
804 */
805 int (*x68k_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
806 bus_size_t, bus_dma_segment_t *, int, int *, int);
807 void (*x68k_dmamem_free)(bus_dma_tag_t,
808 bus_dma_segment_t *, int);
809 int (*x68k_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
810 int, size_t, caddr_t *, int);
811 void (*x68k_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
812 paddr_t (*x68k_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
813 int, off_t, int, int);
814 };
815
816 /*
817 * bus_dmamap_t
818 *
819 * Describes a DMA mapping.
820 */
821 struct x68k_bus_dmamap {
822 /*
823 * PRIVATE MEMBERS: not for use my machine-independent code.
824 */
825 bus_size_t x68k_dm_size; /* largest DMA transfer mappable */
826 int x68k_dm_segcnt; /* number of segs this map can map */
827 bus_size_t x68k_dm_maxmaxsegsz; /* fixed largest possible segment*/
828 bus_size_t x68k_dm_boundary; /* don't cross this */
829 bus_addr_t x68k_dm_bounce_thresh; /* bounce threshold */
830 int x68k_dm_flags; /* misc. flags */
831
832 void *x68k_dm_cookie; /* cookie for bus-specific functions */
833
834 /*
835 * PUBLIC MEMBERS: these are used by machine-independent code.
836 */
837 bus_size_t dm_maxsegsz; /* largest possible segment */
838 bus_size_t dm_mapsize; /* size of the mapping */
839 int dm_nsegs; /* # valid segments in mapping */
840 bus_dma_segment_t dm_segs[1]; /* segments; variable length */
841 };
842
843 int x68k_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
844 bus_size_t, int, bus_dmamap_t *);
845 void x68k_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
846 int x68k_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
847 bus_size_t, struct proc *, int);
848 int x68k_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
849 struct mbuf *, int);
850 int x68k_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
851 struct uio *, int);
852 int x68k_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
853 bus_dma_segment_t *, int, bus_size_t, int);
854 void x68k_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
855 void x68k_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
856 bus_size_t, int);
857
858 int x68k_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
859 bus_size_t alignment, bus_size_t boundary,
860 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
861 void x68k_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
862 int nsegs);
863 int x68k_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
864 int nsegs, size_t size, caddr_t *kvap, int flags);
865 void x68k_bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
866 size_t size);
867 paddr_t x68k_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
868 int nsegs, off_t off, int prot, int flags);
869
870 int x68k_bus_dmamap_load_buffer(bus_dmamap_t, void *,
871 bus_size_t buflen, struct proc *, int, paddr_t *, int *, int);
872 int x68k_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
873 bus_size_t alignment, bus_size_t boundary,
874 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
875 paddr_t low, paddr_t high);
876
877 #define bus_dmamap_create(t,s,n,m,b,f,p) \
878 ((*((t)->x68k_dmamap_create)) ((t),(s),(n),(m),(b),(f),(p)))
879 #define bus_dmamap_destroy(t,p) \
880 ((*((t)->x68k_dmamap_destroy)) ((t),(p)))
881 #define bus_dmamap_load(t,m,b,s,p,f) \
882 ((*((t)->x68k_dmamap_load)) ((t),(m),(b),(s),(p),(f)))
883 #define bus_dmamap_load_mbuf(t,m,b,f) \
884 ((*((t)->x68k_dmamap_load_mbuf)) ((t),(m),(b),(f)))
885 #define bus_dmamap_load_uio(t,m,u,f) \
886 ((*((t)->x68k_dmamap_load_uio)) ((t),(m),(u),(f)))
887 #define bus_dmamap_load_raw(t,m,sg,n,s,f) \
888 ((*((t)->x68k_dmamap_load_raw)) ((t),(m),(sg),(n),(s),(f)))
889 #define bus_dmamap_unload(t,p) \
890 ((*((t)->x68k_dmamap_unload)) ((t),(p)))
891 #define bus_dmamap_sync(t,p,o,l,ops) \
892 ((*((t)->x68k_dmamap_sync)) ((t),(p),(o),(l),(ops)))
893
894 #define bus_dmamem_alloc(t,s,a,b,sg,n,r,f) \
895 ((*((t)->x68k_dmamem_alloc)) ((t),(s),(a),(b),(sg),(n),(r),(f)))
896 #define bus_dmamem_free(t,sg,n) \
897 ((*((t)->x68k_dmamem_free)) ((t),(sg),(n)))
898 #define bus_dmamem_map(t,sg,n,s,k,f) \
899 ((*((t)->x68k_dmamem_map)) ((t),(sg),(n),(s),(k),(f)))
900 #define bus_dmamem_unmap(t,k,s) \
901 ((*((t)->x68k_dmamem_unmap)) ((t),(k),(s)))
902 #define bus_dmamem_mmap(t,sg,n,o,p,f) \
903 ((*((t)->x68k_dmamem_mmap)) ((t),(sg),(n),(o),(p),(f)))
904
905 /*
906 * Flags used in various bus DMA methods.
907 */
908 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
909 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
910 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
911 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */
912 #define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */
913 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
914 #define BUS_DMA_BUS2 0x020
915 #define BUS_DMA_BUS3 0x040
916 #define BUS_DMA_BUS4 0x080
917 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */
918 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */
919 #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */
920
921 /*
922 * Operations performed by bus_dmamap_sync().
923 */
924 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
925 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
926 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
927 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
928
929 #endif /* _X68K_BUS_H_ */
930