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