1 /* $NetBSD: bus.h,v 1.19 2019/09/23 16:17:58 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1997, 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 * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
35 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by Christopher G. Demetriou
48 * for the NetBSD Project.
49 * 4. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 */
63
64 #ifndef _SUN68K_BUS_H_
65 #define _SUN68K_BUS_H_
66
67 #define SUN68K_BUS_SPACE 0
68
69 /*
70 * Bus address and size types
71 */
72 typedef u_long bus_space_handle_t;
73 typedef u_long bus_type_t;
74 typedef u_long bus_addr_t;
75 typedef u_long bus_size_t;
76
77 #define PRIxBSH "lx"
78 #define PRIxBUSADDR "lx"
79 #define PRIxBUSSIZE "lx"
80 #define PRIuBUSSIZE "lu"
81
82 #define BUS_ADDR_PADDR(x) ((x) & 0xffffffff)
83
84 /*
85 * Access methods for bus resources and address space.
86 */
87 typedef struct sun68k_bus_space_tag *bus_space_tag_t;
88
89 struct sun68k_bus_space_tag {
90 void *cookie;
91 bus_space_tag_t parent;
92
93 int (*sun68k_bus_map)(
94 bus_space_tag_t,
95 bus_type_t,
96 bus_addr_t,
97 bus_size_t,
98 int, /*flags*/
99 vaddr_t, /*preferred vaddr*/
100 bus_space_handle_t *);
101
102 int (*sun68k_bus_unmap)(
103 bus_space_tag_t,
104 bus_space_handle_t,
105 bus_size_t);
106
107 int (*sun68k_bus_subregion)(
108 bus_space_tag_t,
109 bus_space_handle_t,
110 bus_size_t, /*offset*/
111 bus_size_t, /*size*/
112 bus_space_handle_t *);
113
114 void (*sun68k_bus_barrier)(
115 bus_space_tag_t,
116 bus_space_handle_t,
117 bus_size_t, /*offset*/
118 bus_size_t, /*size*/
119 int); /*flags*/
120
121 paddr_t (*sun68k_bus_mmap)(
122 bus_space_tag_t,
123 bus_type_t, /**/
124 bus_addr_t, /**/
125 off_t, /*offset*/
126 int, /*prot*/
127 int); /*flags*/
128
129 void *(*sun68k_intr_establish)(
130 bus_space_tag_t,
131 int, /*bus-specific intr*/
132 int, /*device class level,
133 see machine/intr.h*/
134 int, /*flags*/
135 int (*)(void *), /*handler*/
136 void *); /*handler arg*/
137
138 int (*sun68k_bus_peek)(
139 bus_space_tag_t,
140 bus_space_handle_t,
141 bus_size_t, /*offset*/
142 size_t, /*probe size*/
143 void *); /*result ptr*/
144
145 int (*sun68k_bus_poke)(
146 bus_space_tag_t,
147 bus_space_handle_t,
148 bus_size_t, /*offset*/
149 size_t, /*probe size*/
150 uint32_t); /*value*/
151 };
152
153 #if 0
154 /*
155 * The following macro could be used to generate the bus_space*() functions
156 * but it uses a gcc extension and is ANSI-only.
157 #define PROTO_bus_space_xxx (bus_space_tag_t t, ...)
158 #define RETURNTYPE_bus_space_xxx void *
159 #define BUSFUN(name, returntype, t, args...) \
160 __inline RETURNTYPE_##name \
161 bus_##name PROTO_##name \
162 { \
163 while (t->sun68k_##name == NULL) \
164 t = t->parent; \
165 return (*(t)->sun68k_##name)(t, args); \
166 }
167 */
168 #endif
169
170 /*
171 * Bus space function prototypes.
172 */
173 static int bus_space_map(
174 bus_space_tag_t,
175 bus_addr_t,
176 bus_size_t,
177 int, /*flags*/
178 bus_space_handle_t *);
179 static int bus_space_map2(
180 bus_space_tag_t,
181 bus_type_t,
182 bus_addr_t,
183 bus_size_t,
184 int, /*flags*/
185 vaddr_t, /*preferred vaddr*/
186 bus_space_handle_t *);
187 static int bus_space_unmap(
188 bus_space_tag_t,
189 bus_space_handle_t,
190 bus_size_t);
191 static int bus_space_subregion(
192 bus_space_tag_t,
193 bus_space_handle_t,
194 bus_size_t,
195 bus_size_t,
196 bus_space_handle_t *);
197 static void bus_space_barrier(
198 bus_space_tag_t,
199 bus_space_handle_t,
200 bus_size_t,
201 bus_size_t,
202 int);
203 static paddr_t bus_space_mmap(
204 bus_space_tag_t,
205 bus_addr_t, /**/
206 off_t, /*offset*/
207 int, /*prot*/
208 int); /*flags*/
209 static paddr_t bus_space_mmap2(
210 bus_space_tag_t,
211 bus_type_t,
212 bus_addr_t, /**/
213 off_t, /*offset*/
214 int, /*prot*/
215 int); /*flags*/
216 static void *bus_intr_establish(
217 bus_space_tag_t,
218 int, /*bus-specific intr*/
219 int, /*device class level,
220 see machine/intr.h*/
221 int, /*flags*/
222 int (*)(void *), /*handler*/
223 void *); /*handler arg*/
224 static int _bus_space_peek(
225 bus_space_tag_t,
226 bus_space_handle_t,
227 bus_size_t, /*offset*/
228 size_t, /*probe size*/
229 void *); /*result ptr*/
230 static int _bus_space_poke(
231 bus_space_tag_t,
232 bus_space_handle_t,
233 bus_size_t, /*offset*/
234 size_t, /*probe size*/
235 uint32_t); /*value*/
236
237 /* This macro finds the first "upstream" implementation of method `f' */
238 #define _BS_CALL(t,f) \
239 while (t->f == NULL) \
240 t = t->parent; \
241 return (*(t)->f)
242
243 static __inline int
bus_space_map(bus_space_tag_t t,bus_addr_t a,bus_size_t s,int f,bus_space_handle_t * hp)244 bus_space_map(bus_space_tag_t t, bus_addr_t a, bus_size_t s, int f,
245 bus_space_handle_t *hp)
246 {
247 _BS_CALL(t, sun68k_bus_map)((t), 0, (a), (s), (f), 0, (hp));
248 }
249
250 static __inline int
bus_space_map2(bus_space_tag_t t,bus_type_t bt,bus_addr_t a,bus_size_t s,int f,vaddr_t v,bus_space_handle_t * hp)251 bus_space_map2(bus_space_tag_t t, bus_type_t bt, bus_addr_t a, bus_size_t s,
252 int f, vaddr_t v, bus_space_handle_t *hp)
253 {
254 _BS_CALL(t, sun68k_bus_map)(t, bt, a, s, f, v, hp);
255 }
256
257 static __inline int
bus_space_unmap(bus_space_tag_t t,bus_space_handle_t h,bus_size_t s)258 bus_space_unmap(bus_space_tag_t t, bus_space_handle_t h, bus_size_t s)
259 {
260 _BS_CALL(t, sun68k_bus_unmap)(t, h, s);
261 }
262
263 static __inline int
bus_space_subregion(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,bus_size_t s,bus_space_handle_t * hp)264 bus_space_subregion(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
265 bus_size_t s, bus_space_handle_t *hp)
266 {
267 _BS_CALL(t, sun68k_bus_subregion)(t, h, o, s, hp);
268 }
269
270 static __inline paddr_t
bus_space_mmap(bus_space_tag_t t,bus_addr_t a,off_t o,int p,int f)271 bus_space_mmap(bus_space_tag_t t, bus_addr_t a, off_t o, int p, int f)
272 {
273 _BS_CALL(t, sun68k_bus_mmap)(t, 0, a, o, p, f);
274 }
275
276 static __inline paddr_t
bus_space_mmap2(bus_space_tag_t t,bus_type_t bt,bus_addr_t a,off_t o,int p,int f)277 bus_space_mmap2(bus_space_tag_t t, bus_type_t bt, bus_addr_t a, off_t o, int p,
278 int f)
279 {
280 _BS_CALL(t, sun68k_bus_mmap)(t, bt, a, o, p, f);
281 }
282
283 static __inline void *
bus_intr_establish(bus_space_tag_t t,int p,int l,int f,int (* h)(void *),void * a)284 bus_intr_establish(bus_space_tag_t t, int p, int l, int f, int (*h)(void *),
285 void *a)
286 {
287 _BS_CALL(t, sun68k_intr_establish)(t, p, l, f, h, a);
288 }
289
290 static __inline void
bus_space_barrier(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,bus_size_t s,int f)291 bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
292 bus_size_t s, int f)
293 {
294 _BS_CALL(t, sun68k_bus_barrier)(t, h, o, s, f);
295 }
296
297 static __inline int
_bus_space_peek(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,size_t s,void * vp)298 _bus_space_peek(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, size_t s,
299 void *vp)
300 {
301 _BS_CALL(t, sun68k_bus_peek)(t, h, o, s, vp);
302 }
303
304 static __inline int
_bus_space_poke(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,size_t s,uint32_t v)305 _bus_space_poke(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, size_t s,
306 uint32_t v)
307 {
308 _BS_CALL(t, sun68k_bus_poke)(t, h, o, s, v);
309 }
310
311 #if 0
312 int bus_space_alloc(bus_space_tag_t, bus_addr_t, bus_addr_t, bus_size_t,
313 bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
314 void bus_space_free(bus_space_tag_t, bus_space_handle_t, bus_size_t);
315 #endif
316
317 /*
318 * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
319 *
320 * Get the kernel virtual address for the mapped bus space.
321 * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
322 * (XXX not enforced)
323 */
324 #define bus_space_vaddr(t, h) ((void)(t), (void *)(h))
325
326 /* flags for bus space map functions */
327 #define BUS_SPACE_MAP_CACHEABLE 0x0001
328 #define BUS_SPACE_MAP_LINEAR 0x0002
329 #define BUS_SPACE_MAP_PREFETCHABLE 0x0004
330 #define BUS_SPACE_MAP_BUS1 0x0100 /* placeholders for bus functions... */
331 #define BUS_SPACE_MAP_BUS2 0x0200
332 #define BUS_SPACE_MAP_BUS3 0x0400
333 #define BUS_SPACE_MAP_BUS4 0x0800
334
335 /* Internal flag: try to find and use a PROM maping for the device. */
336 #define _SUN68K_BUS_MAP_USE_PROM BUS_SPACE_MAP_BUS1
337
338 /* flags for intr_establish() */
339 #define BUS_INTR_ESTABLISH_FASTTRAP 1
340 #define BUS_INTR_ESTABLISH_SOFTINTR 2
341
342 /* flags for bus_space_barrier() */
343 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
344 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
345
346 /*
347 * int bus_space_peek_N(bus_space_tag_t tag,
348 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t *valuep);
349 *
350 * Cautiously read 1, 2, 4 or 8 byte quantity from bus space described
351 * by tag/handle/offset.
352 * If no hardware responds to the read access, the function returns a
353 * non-zero value. Otherwise the value read is placed in `valuep'.
354 */
355
356 #define bus_space_peek_1(t, h, o, vp) \
357 _bus_space_peek(t, h, o, sizeof(uint8_t), (void *)vp)
358
359 #define bus_space_peek_2(t, h, o, vp) \
360 _bus_space_peek(t, h, o, sizeof(uint16_t), (void *)vp)
361
362 #define bus_space_peek_4(t, h, o, vp) \
363 _bus_space_peek(t, h, o, sizeof(uint32_t), (void *)vp)
364
365 /*
366 * int bus_space_poke_N(bus_space_tag_t tag,
367 * bus_space_handle_t bsh, bus_size_t offset, uintN_t value);
368 *
369 * Cautiously write 1, 2, 4 or 8 byte quantity to bus space described
370 * by tag/handle/offset.
371 * If no hardware responds to the write access, the function returns a
372 * non-zero value.
373 */
374
375 #define bus_space_poke_1(t, h, o, v) \
376 _bus_space_poke(t, h, o, sizeof(uint8_t), v)
377
378 #define bus_space_poke_2(t, h, o, v) \
379 _bus_space_poke(t, h, o, sizeof(uint16_t), v)
380
381 #define bus_space_poke_4(t, h, o, v) \
382 _bus_space_poke(t, h, o, sizeof(uint32_t), v)
383
384 /*
385 * uintN_t bus_space_read_N(bus_space_tag_t tag,
386 * bus_space_handle_t bsh, bus_size_t offset);
387 *
388 * Read a 1, 2, 4, or 8 byte quantity from bus space
389 * described by tag/handle/offset.
390 */
391
392 #define bus_space_read_1(t, h, o) \
393 ((void)t, *(volatile uint8_t *)((h) + (o)))
394
395 #define bus_space_read_2(t, h, o) \
396 ((void)t, *(volatile uint16_t *)((h) + (o)))
397
398 #define bus_space_read_4(t, h, o) \
399 ((void)t, *(volatile uint32_t *)((h) + (o)))
400
401 #define bus_space_read_8(t, h, o) \
402 ((void)t, *(volatile uint64_t *)((h) + (o)))
403
404
405 /*
406 * void bus_space_write_N(bus_space_tag_t tag,
407 * bus_space_handle_t bsh, bus_size_t offset,
408 * uintN_t value);
409 *
410 * Write the 1, 2, 4, or 8 byte value `value' to bus space
411 * described by tag/handle/offset.
412 */
413
414 #define bus_space_write_1(t, h, o, v) do { \
415 ((void)t, (void)(*(volatile uint8_t *)((h) + (o)) = (v))); \
416 } while (0)
417
418 #define bus_space_write_2(t, h, o, v) do { \
419 ((void)t, (void)(*(volatile uint16_t *)((h) + (o)) = (v))); \
420 } while (0)
421
422 #define bus_space_write_4(t, h, o, v) do { \
423 ((void)t, (void)(*(volatile uint32_t *)((h) + (o)) = (v))); \
424 } while (0)
425
426 #define bus_space_write_8(t, h, o, v) do { \
427 ((void)t, (void)(*(volatile uint64_t *)((h) + (o)) = (v))); \
428 } while (0)
429
430
431 /*
432 * void bus_space_read_multi_N(bus_space_tag_t tag,
433 * bus_space_handle_t bsh, bus_size_t offset,
434 * uintN_t *addr, bus_size_t count);
435 *
436 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
437 * described by tag/handle/offset and copy into buffer provided.
438 */
439
440 static __inline void
bus_space_read_multi_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t * a,bus_size_t c)441 bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
442 uint8_t *a, bus_size_t c)
443 {
444 volatile uint8_t *p;
445
446 p = (volatile uint8_t *)(h + o);
447 while (c-- > 0)
448 *a++ = *p;
449 }
450
451 static __inline void
bus_space_read_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)452 bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
453 uint16_t *a, bus_size_t c)
454 {
455 volatile uint16_t *p;
456
457 p = (volatile uint16_t *)(h + o);
458 while (c-- > 0)
459 *a++ = *p;
460 }
461
462 static __inline void
bus_space_read_multi_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)463 bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
464 uint32_t *a, bus_size_t c)
465 {
466 volatile uint32_t *p;
467
468 p = (volatile uint32_t *)(h + o);
469 while (c-- > 0)
470 *a++ = *p;
471 }
472
473 static __inline void
bus_space_read_multi_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t * a,bus_size_t c)474 bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
475 uint64_t *a, bus_size_t c)
476 {
477 volatile uint64_t *p;
478
479 p = (volatile uint64_t *)(h + o);
480 while (c-- > 0)
481 *a++ = *p;
482 }
483
484
485 /*
486 * void bus_space_write_multi_N(bus_space_tag_t tag,
487 * bus_space_handle_t bsh, bus_size_t offset,
488 * const u_intN_t *addr, bus_size_t count);
489 *
490 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
491 * provided to bus space described by tag/handle/offset.
492 */
493
494 static __inline void
bus_space_write_multi_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint8_t * a,bus_size_t c)495 bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
496 const uint8_t *a, bus_size_t c)
497 {
498 volatile uint8_t *p;
499
500 p = (volatile uint8_t *)(h + o);
501 while (c-- > 0)
502 *p = *a++;
503 }
504
505 static __inline void
bus_space_write_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)506 bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
507 const uint16_t *a, bus_size_t c)
508 {
509 volatile uint16_t *p;
510
511 p = (volatile uint16_t *)(h + o);
512 while (c-- > 0)
513 *p = *a++;
514 }
515
516 static __inline void
bus_space_write_multi_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)517 bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
518 const uint32_t *a, bus_size_t c)
519 {
520 volatile uint32_t *p;
521
522 p = (volatile uint32_t *)(h + o);
523 while (c-- > 0)
524 *p = *a++;
525 }
526
527 static __inline void
bus_space_write_multi_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t * a,bus_size_t c)528 bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
529 const uint64_t *a, bus_size_t c)
530 {
531 volatile uint64_t *p;
532
533 p = (volatile uint64_t *)(h + o);
534 while (c-- > 0)
535 *p = *a++;
536 }
537
538 /*
539 * void bus_space_set_multi_N(bus_space_tag_t tag,
540 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
541 * bus_size_t count);
542 *
543 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
544 * by tag/handle/offset `count' times.
545 */
546
547 static __inline void
bus_space_set_multi_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint8_t v,bus_size_t c)548 bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
549 const uint8_t v, bus_size_t c)
550 {
551 volatile uint8_t *p;
552
553 p = (volatile uint8_t *)(h + o);
554 while (c-- > 0)
555 *p = v;
556 }
557
558 static __inline void
bus_space_set_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t v,bus_size_t c)559 bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
560 const uint16_t v, bus_size_t c)
561 {
562 volatile uint16_t *p;
563
564 p = (volatile uint16_t *)(h + o);
565 while (c-- > 0)
566 *p = v;
567 }
568
569 static __inline void
bus_space_set_multi_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t v,bus_size_t c)570 bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
571 const uint32_t v, bus_size_t c)
572 {
573 volatile uint32_t *p;
574
575 p = (volatile uint32_t *)(h + o);
576 while (c-- > 0)
577 *p = v;
578 }
579
580 static __inline void
bus_space_set_multi_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t v,bus_size_t c)581 bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
582 const uint64_t v, bus_size_t c)
583 {
584 volatile uint64_t *p;
585
586 p = (volatile uint64_t *)(h + o);
587 while (c-- > 0)
588 *p = v;
589 }
590
591
592 /*
593 * void bus_space_read_region_N(bus_space_tag_t tag,
594 * bus_space_handle_t bsh, bus_size_t off,
595 * uintN_t *addr, bus_size_t count);
596 *
597 */
598
599 static __inline void
bus_space_read_region_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t * a,bus_size_t c)600 bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
601 uint8_t *a, bus_size_t c)
602 {
603 volatile uint8_t *p;
604
605 p = (volatile uint8_t *)(h + o);
606 while (c-- > 0)
607 *a++ = *p++;
608 }
609 static __inline void
bus_space_read_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)610 bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
611 uint16_t *a, bus_size_t c)
612 {
613 volatile uint16_t *p;
614
615 p = (volatile uint16_t *)(h + o);
616 while (c-- > 0)
617 *a++ = *p++;
618 }
619 static __inline void
bus_space_read_region_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)620 bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
621 uint32_t *a, bus_size_t c)
622 {
623 volatile uint32_t *p;
624
625 p = (volatile uint32_t *)(h + o);
626 while (c-- > 0)
627 *a++ = *p++;
628 }
629 static __inline void
bus_space_read_region_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t * a,bus_size_t c)630 bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
631 uint64_t *a, bus_size_t c)
632 {
633 volatile uint64_t *p;
634
635 p = (volatile uint64_t *)(h + o);
636 while (c-- > 0)
637 *a++ = *p++;
638 }
639
640 /*
641 * void bus_space_write_region_N(bus_space_tag_t tag,
642 * bus_space_handle_t bsh, bus_size_t off,
643 * uintN_t *addr, bus_size_t count);
644 *
645 */
646
647 static __inline void
bus_space_write_region_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint8_t * a,bus_size_t c)648 bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
649 const uint8_t *a, bus_size_t c)
650 {
651 volatile uint8_t *p;
652
653 p = (volatile uint8_t *)(h + o);
654 while (c-- > 0)
655 *p++ = *a++;
656 }
657
658 static __inline void
bus_space_write_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)659 bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
660 const uint16_t *a, bus_size_t c)
661 {
662 volatile uint16_t *p;
663
664 p = (volatile uint16_t *)(h + o);
665 while (c-- > 0)
666 *p++ = *a++;
667 }
668
669 static __inline void
bus_space_write_region_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)670 bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
671 const uint32_t *a, bus_size_t c)
672 {
673 volatile uint32_t *p;
674
675 p = (volatile uint32_t *)(h + o);
676 while (c-- > 0)
677 *p++ = *a++;
678 }
679
680 static __inline void
bus_space_write_region_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t * a,bus_size_t c)681 bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
682 const uint64_t *a, bus_size_t c)
683 {
684 volatile uint64_t *p;
685
686 p = (volatile uint64_t *)(h + o);
687 while (c-- > 0)
688 *p++ = *a++;
689 }
690
691
692 /*
693 * void bus_space_set_region_N(bus_space_tag_t tag,
694 * bus_space_handle_t bsh, bus_size_t off,
695 * uintN_t *addr, bus_size_t count);
696 *
697 */
698
699 static __inline void
bus_space_set_region_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint8_t v,bus_size_t c)700 bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
701 const uint8_t v, bus_size_t c)
702 {
703 volatile uint8_t *p;
704
705 p = (volatile uint8_t *)(h + o);
706 while (c-- > 0)
707 *p++ = v;
708 }
709
710 static __inline void
bus_space_set_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t v,bus_size_t c)711 bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
712 const uint16_t v, bus_size_t c)
713 {
714 volatile uint16_t *p;
715
716 p = (volatile uint16_t *)(h + o);
717 while (c-- > 0)
718 *p++ = v;
719 }
720
721 static __inline void
bus_space_set_region_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t v,bus_size_t c)722 bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
723 const uint32_t v, bus_size_t c)
724 {
725 volatile uint32_t *p;
726
727 p = (volatile uint32_t *)(h + o);
728 while (c-- > 0)
729 *p++ = v;
730 }
731
732 static __inline void
bus_space_set_region_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t v,bus_size_t c)733 bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
734 const uint64_t v, bus_size_t c)
735 {
736 volatile uint64_t *p;
737
738 p = (volatile uint64_t *)(h + o);
739 while (c-- > 0)
740 *p++ = v;
741 }
742
743
744 /*
745 * void bus_space_copy_region_N(bus_space_tag_t tag,
746 * bus_space_handle_t bsh1, bus_size_t off1,
747 * bus_space_handle_t bsh2, bus_size_t off2,
748 * bus_size_t count);
749 *
750 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
751 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
752 */
753
754 static __inline void
bus_space_copy_region_1(bus_space_tag_t t,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)755 bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
756 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
757 {
758 volatile uint8_t *srcp, *dstp;
759 bus_size_t offset;
760
761 srcp = (volatile uint8_t *)(h1 + o1);
762 dstp = (volatile uint8_t *)(h2 + o2);
763 if (srcp >= dstp) {
764 /* src after dest; copy forward */
765 for (offset = 0; c > 0; c--, offset++)
766 dstp[offset] = srcp[offset];
767 } else {
768 /* dst after src; copy backward */
769 for (offset = c; c > 0; c--, offset--)
770 dstp[offset] = srcp[offset];
771 }
772 }
773
774 static __inline void
bus_space_copy_region_2(bus_space_tag_t t,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)775 bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
776 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
777 {
778 volatile uint16_t *srcp, *dstp;
779 bus_size_t offset;
780
781 srcp = (volatile uint16_t *)(h1 + o1);
782 dstp = (volatile uint16_t *)(h2 + o2);
783 if (srcp >= dstp) {
784 /* src after dest; copy forward */
785 for (offset = 0; c > 0; c--, offset++)
786 dstp[offset] = srcp[offset];
787 } else {
788 /* dst after src; copy backward */
789 for (offset = c; c > 0; c--, offset--)
790 dstp[offset] = srcp[offset];
791 }
792 }
793
794 static __inline void
bus_space_copy_region_4(bus_space_tag_t t,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)795 bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
796 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
797 {
798 volatile uint32_t *srcp, *dstp;
799 bus_size_t offset;
800
801 srcp = (volatile uint32_t *)(h1 + o1);
802 dstp = (volatile uint32_t *)(h2 + o2);
803 if (srcp >= dstp) {
804 /* src after dest; copy forward */
805 for (offset = 0; c > 0; c--, offset++)
806 dstp[offset] = srcp[offset];
807 } else {
808 /* dst after src; copy backward */
809 for (offset = c; c > 0; c--, offset--)
810 dstp[offset] = srcp[offset];
811 }
812 }
813
814 static __inline void
bus_space_copy_region_8(bus_space_tag_t t,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)815 bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
816 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
817 {
818 volatile uint64_t *srcp, *dstp;
819 bus_size_t offset;
820
821 srcp = (volatile uint64_t *)(h1 + o1);
822 dstp = (volatile uint64_t *)(h2 + o2);
823 if (srcp >= dstp) {
824 /* src after dest; copy forward */
825 for (offset = 0; c > 0; c--, offset++)
826 dstp[offset] = srcp[offset];
827 } else {
828 /* dst after src; copy backward */
829 for (offset = c; c > 0; c--, offset--)
830 dstp[offset] = srcp[offset];
831 }
832 }
833
834 /*
835 * void bus_space_copyin(bus_space_tag_t tag,
836 * bus_space_handle_t bsh, bus_size_t off,
837 * void *addr, bus_size_t count);
838 *
839 * Copy `count' bytes from bus space starting at tag/bsh/off
840 * to kernel memory at addr using the most optimized transfer
841 * possible for the bus.
842 */
843
844 #define bus_space_copyin(t, h, o, a, c) \
845 ((void)t, w16copy((uint8_t *)((h) + (o)), (a), (c)))
846
847 /*
848 * void bus_space_copyout(bus_space_tag_t tag,
849 * bus_space_handle_t bsh, bus_size_t off,
850 * const void *addr, bus_size_t count);
851 *
852 * Copy `count' bytes to bus space starting at tag/bsh/off
853 * from kernel memory at addr using the most optimized transfer
854 * possible for the bus.
855 */
856
857 #define bus_space_copyout(t, h, o, a, c) \
858 ((void)t, w16copy((a), (uint8_t *)((h) + (o)), (c)))
859
860 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
861
862 int find_prom_map(paddr_t, bus_type_t, int, vaddr_t *);
863
864 /*--------------------------------*/
865
866 /*
867 * Flags used in various bus DMA methods.
868 */
869 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
870 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
871 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
872 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */
873 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
874 #define BUS_DMA_BUS2 0x020
875 #define BUS_DMA_BUS3 0x040
876 #define BUS_DMA_BUS4 0x080
877 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */
878 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */
879 #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */
880
881 /* For devices that have a 24-bit address space */
882 #define BUS_DMA_24BIT BUS_DMA_BUS1
883
884 /* Internal flag: current DVMA address is equal to the KVA buffer address */
885 #define _BUS_DMA_DIRECTMAP BUS_DMA_BUS2
886
887 /*
888 * Internal flag: current DVMA address has been double-mapped by hand
889 * to the KVA buffer address (without the pmap's help).
890 */
891 #define _BUS_DMA_NOPMAP BUS_DMA_BUS3
892
893 /* Forwards needed by prototypes below. */
894 struct mbuf;
895 struct uio;
896
897 /*
898 * Operations performed by bus_dmamap_sync().
899 */
900 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
901 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
902 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
903 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
904
905 typedef struct sun68k_bus_dma_tag *bus_dma_tag_t;
906 typedef struct sun68k_bus_dmamap *bus_dmamap_t;
907
908 #define BUS_DMA_TAG_VALID(t) ((t) != NULL)
909
910 /*
911 * bus_dma_segment_t
912 *
913 * Describes a single contiguous DMA transaction. Values
914 * are suitable for programming into DMA registers.
915 */
916 struct sun68k_bus_dma_segment {
917 bus_addr_t ds_addr; /* DVMA address */
918 bus_size_t ds_len; /* length of transfer */
919 bus_size_t _ds_sgsize; /* size of allocated DVMA segment */
920 void *_ds_mlist; /* page list when dmamem_alloc'ed */
921 vaddr_t _ds_va; /* VA when dmamem_map'ed */
922 };
923 typedef struct sun68k_bus_dma_segment bus_dma_segment_t;
924
925
926 /*
927 * bus_dma_tag_t
928 *
929 * A machine-dependent opaque type describing the implementation of
930 * DMA for a given bus.
931 */
932 struct sun68k_bus_dma_tag {
933 void *_cookie; /* cookie used in the guts */
934
935 /*
936 * DMA mapping methods.
937 */
938 int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, bus_size_t,
939 bus_size_t, int, bus_dmamap_t *);
940 void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
941 int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
942 struct proc *, int);
943 int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, struct mbuf *,
944 int);
945 int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *,
946 int);
947 int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
948 bus_dma_segment_t *, int, bus_size_t, int);
949 void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
950 void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
951 bus_size_t, int);
952
953 /*
954 * DMA memory utility functions.
955 */
956 int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
957 bus_size_t, bus_dma_segment_t *, int, int *, int);
958 void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int);
959 int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, int, size_t,
960 void **, int);
961 void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t);
962 paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, int, off_t,
963 int, int);
964 };
965
966 #define bus_dmamap_create(t, s, n, m, b, f, p) \
967 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
968 #define bus_dmamap_destroy(t, p) \
969 (*(t)->_dmamap_destroy)((t), (p))
970 #define bus_dmamap_load(t, m, b, s, p, f) \
971 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
972 #define bus_dmamap_load_mbuf(t, m, b, f) \
973 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
974 #define bus_dmamap_load_uio(t, m, u, f) \
975 (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
976 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \
977 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
978 #define bus_dmamap_unload(t, p) \
979 (*(t)->_dmamap_unload)((t), (p))
980 #define bus_dmamap_sync(t, p, o, l, ops) \
981 (void)((t)->_dmamap_sync ? \
982 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
983
984 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
985 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
986 #define bus_dmamem_free(t, sg, n) \
987 (*(t)->_dmamem_free)((t), (sg), (n))
988 #define bus_dmamem_map(t, sg, n, s, k, f) \
989 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
990 #define bus_dmamem_unmap(t, k, s) \
991 (*(t)->_dmamem_unmap)((t), (k), (s))
992 #define bus_dmamem_mmap(t, sg, n, o, p, f) \
993 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
994
995 #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP
996 #define bus_dmatag_destroy(t)
997
998 /*
999 * bus_dmamap_t
1000 *
1001 * Describes a DMA mapping.
1002 */
1003 struct sun68k_bus_dmamap {
1004 /*
1005 * PRIVATE MEMBERS: not for use by machine-independent code.
1006 */
1007 bus_size_t _dm_size; /* largest DMA transfer mappable */
1008 int _dm_segcnt; /* number of segs this map can map */
1009 bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */
1010 bus_size_t _dm_boundary; /* don't cross this */
1011 int _dm_flags; /* misc. flags */
1012
1013 void *_dm_cookie; /* cookie for bus-specific functions */
1014
1015 u_long _dm_align; /* DVMA alignment; must be a
1016 multiple of the page size */
1017 u_long _dm_ex_start; /* constraints on DVMA map */
1018 u_long _dm_ex_end; /* allocations; used by the VME bus
1019 driver and by the IOMMU driver
1020 when mapping 24-bit devices */
1021
1022 /*
1023 * PUBLIC MEMBERS: these are used by machine-independent code.
1024 */
1025 bus_size_t dm_maxsegsz; /* largest possible segment */
1026 bus_size_t dm_mapsize; /* size of the mapping */
1027 int dm_nsegs; /* # valid segments in mapping */
1028 bus_dma_segment_t dm_segs[1]; /* segments; variable length */
1029 };
1030
1031 #ifdef _SUN68K_BUS_DMA_PRIVATE
1032 int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
1033 bus_size_t, int, bus_dmamap_t *);
1034 void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
1035 int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int);
1036 int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
1037 int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *,
1038 int, bus_size_t, int);
1039 int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
1040 struct proc *, int);
1041 void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
1042 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t,
1043 int);
1044
1045 int _bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t,
1046 bus_dma_segment_t *, int, int *, int);
1047 void _bus_dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int);
1048 int _bus_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, int, size_t,
1049 void **, int);
1050 void _bus_dmamem_unmap(bus_dma_tag_t, void *, size_t);
1051 paddr_t _bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int,
1052 int);
1053
1054 int _bus_dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t,
1055 bus_size_t, bus_dma_segment_t *, int, int *, int, vaddr_t, vaddr_t);
1056
1057 vaddr_t _bus_dma_valloc_skewed(size_t, u_long, u_long, u_long);
1058 #endif /* _SUN68K_BUS_DMA_PRIVATE */
1059
1060 #endif /* _SUN68K_BUS_H_ */
1061