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