1 /* $NetBSD: bus_funcs.h,v 1.5 2018/08/27 16:16:16 riastradh 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) 1997-1999, 2001 Eduardo E. Horvath. All rights reserved.
35 * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
36 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by Christopher G. Demetriou
49 * for the NetBSD Project.
50 * 4. The name of the author may not be used to endorse or promote products
51 * derived from this software without specific prior written permission
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
54 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
57 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
62 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 */
64
65 #ifndef _SPARC64_BUS_FUNCS_H_
66 #define _SPARC64_BUS_FUNCS_H_
67
68 #include <sys/cdefs.h>
69 #include <sys/types.h>
70 #include <sys/null.h>
71
72 #include <machine/bus_defs.h>
73
74 struct mbuf;
75 struct openprom_range;
76 struct proc;
77 struct uio;
78
79 /*
80 * Debug hooks
81 */
82
83 extern int bus_space_debug;
84
85 bus_space_tag_t bus_space_tag_alloc(bus_space_tag_t, void *);
86 int bus_space_translate_address_generic(struct openprom_range *,
87 int, bus_addr_t *);
88
89 #if 0
90 /*
91 * The following macro could be used to generate the bus_space*() functions
92 * but it uses a gcc extension and is ANSI-only.
93 #define PROTO_bus_space_xxx (bus_space_tag_t t, ...)
94 #define RETURNTYPE_bus_space_xxx void *
95 #define BUSFUN(name, returntype, t, args...) \
96 static __inline RETURNTYPE_##name \
97 bus_##name PROTO_##name \
98 { \
99 while (t->sparc_##name == NULL) \
100 t = t->parent; \
101 return (*(t)->sparc_##name)(t, args); \
102 }
103 */
104 #endif
105
106 /*
107 * Bus space function prototypes.
108 */
109 static void *bus_intr_establish(
110 bus_space_tag_t,
111 int, /*bus-specific intr*/
112 int, /*device class level,
113 see machine/intr.h*/
114 int (*)(void *), /*handler*/
115 void *); /*handler arg*/
116
117
118 /* This macro finds the first "upstream" implementation of method `f' */
119 #define _BS_CALL(t,f) \
120 while (t->f == NULL) \
121 t = t->parent; \
122 return (*(t)->f)
123
124 #define _BS_VOID_CALL(t,f) \
125 while (t->f == NULL) \
126 t = t->parent; \
127 (*(t)->f)
128
129 static __inline void *
bus_intr_establish(bus_space_tag_t t,int p,int l,int (* h)(void *),void * a)130 bus_intr_establish(bus_space_tag_t t, int p, int l, int (*h)(void *), void *a)
131 {
132 _BS_CALL(t, sparc_intr_establish)(t, p, l, h, a, NULL);
133 }
134
135 /* XXXX Things get complicated if we use unmapped register accesses. */
136 #define bus_space_vaddr(t, h) (PHYS_ASI((h)._asi) ? \
137 NULL : (void *)(vaddr_t)((h)._ptr))
138
139 #define bus_space_barrier(t, h, o, s, f) \
140 sparc_bus_space_barrier((t), (h), (o), (s), (f))
141
142 static __inline void
sparc_bus_space_barrier(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,bus_size_t s,int f)143 sparc_bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h,
144 bus_size_t o, bus_size_t s, int f)
145 {
146 /*
147 * We have a bit of a problem with the bus_space_barrier()
148 * interface. It defines a read barrier and a write barrier
149 * which really don't map to the 7 different types of memory
150 * barriers in the SPARC v9 instruction set.
151 */
152 if (f == BUS_SPACE_BARRIER_READ)
153 /* A load followed by a load to the same location? */
154 __asm volatile("membar #Lookaside");
155 else if (f == BUS_SPACE_BARRIER_WRITE)
156 /* A store followed by a store? */
157 __asm volatile("membar #StoreStore");
158 else
159 /* A store followed by a load? */
160 __asm volatile("membar #StoreLoad|#MemIssue|#Lookaside");
161 }
162
163 /*
164 * uintN_t bus_space_read_N(bus_space_tag_t tag,
165 * bus_space_handle_t bsh, bus_size_t offset);
166 *
167 * Read a 1, 2, 4, or 8 byte quantity from bus space
168 * described by tag/handle/offset.
169 */
170 #ifndef BUS_SPACE_DEBUG
171 #define bus_space_read_1(t, h, o) \
172 (0 ? (t)->type : lduba((h)._ptr + (o), (h)._asi))
173
174 #define bus_space_read_2(t, h, o) \
175 (0 ? (t)->type : lduha((h)._ptr + (o), (h)._asi))
176
177 #define bus_space_read_4(t, h, o) \
178 (0 ? (t)->type : lda((h)._ptr + (o), (h)._asi))
179
180 #define bus_space_read_8(t, h, o) \
181 (0 ? (t)->type : ldxa((h)._ptr + (o), (h)._asi))
182 #else
183 #define bus_space_read_1(t, h, o) ({ \
184 uint8_t __bv = \
185 lduba((h)._ptr + (o), (h)._asi); \
186 if (bus_space_debug & BSDB_ACCESS) \
187 printf("bsr1(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr, \
188 (long long)(o), \
189 (h)._asi, (uint32_t) __bv); \
190 __bv; })
191
192 #define bus_space_read_2(t, h, o) ({ \
193 uint16_t __bv = \
194 lduha((h)._ptr + (o), (h)._asi); \
195 if (bus_space_debug & BSDB_ACCESS) \
196 printf("bsr2(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr, \
197 (long long)(o), \
198 (h)._asi, (uint32_t)__bv); \
199 __bv; })
200
201 #define bus_space_read_4(t, h, o) ({ \
202 uint32_t __bv = \
203 lda((h)._ptr + (o), (h)._asi); \
204 if (bus_space_debug & BSDB_ACCESS) \
205 printf("bsr4(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr, \
206 (long long)(o), \
207 (h)._asi, __bv); \
208 __bv; })
209
210 #define bus_space_read_8(t, h, o) ({ \
211 uint64_t __bv = \
212 ldxa((h)._ptr + (o), (h)._asi); \
213 if (bus_space_debug & BSDB_ACCESS) \
214 printf("bsr8(%llx + %llx, %x) -> %llx\n", (long long)(h)._ptr, \
215 (long long)(o), \
216 (h)._asi, (long long)__bv); \
217 __bv; })
218 #endif
219 /*
220 * void bus_space_write_N(bus_space_tag_t tag,
221 * bus_space_handle_t bsh, bus_size_t offset,
222 * uintN_t value);
223 *
224 * Write the 1, 2, 4, or 8 byte value `value' to bus space
225 * described by tag/handle/offset.
226 */
227 #ifndef BUS_SPACE_DEBUG
228 #define bus_space_write_1(t, h, o, v) \
229 (0 ? (t)->type : ((void)(stba((h)._ptr + (o), (h)._asi, (v)))))
230
231 #define bus_space_write_2(t, h, o, v) \
232 (0 ? (t)->type : ((void)(stha((h)._ptr + (o), (h)._asi, (v)))))
233
234 #define bus_space_write_4(t, h, o, v) \
235 (0 ? (t)->type : ((void)(sta((h)._ptr + (o), (h)._asi, (v)))))
236
237 #define bus_space_write_8(t, h, o, v) \
238 (0 ? (t)->type : ((void)(stxa((h)._ptr + (o), (h)._asi, (v)))))
239 #else
240 #define bus_space_write_1(t, h, o, v) ({ \
241 if (bus_space_debug & BSDB_ACCESS) \
242 printf("bsw1(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr, \
243 (long long)(o), \
244 (h)._asi, (uint32_t) v); \
245 ((void)(stba((h)._ptr + (o), (h)._asi, (v)))); })
246
247 #define bus_space_write_2(t, h, o, v) ({ \
248 if (bus_space_debug & BSDB_ACCESS) \
249 printf("bsw2(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr, \
250 (long long)(o), \
251 (h)._asi, (uint32_t) v); \
252 ((void)(stha((h)._ptr + (o), (h)._asi, (v)))); })
253
254 #define bus_space_write_4(t, h, o, v) ({ \
255 if (bus_space_debug & BSDB_ACCESS) \
256 printf("bsw4(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr, \
257 (long long)(o), \
258 (h)._asi, (uint32_t) v); \
259 ((void)(sta((h)._ptr + (o), (h)._asi, (v)))); })
260
261 #define bus_space_write_8(t, h, o, v) ({ \
262 if (bus_space_debug & BSDB_ACCESS) \
263 printf("bsw8(%llx + %llx, %x) <- %llx\n", (long long)(h)._ptr, \
264 (long long)(o), \
265 (h)._asi, (long long) v); \
266 ((void)(stxa((h)._ptr + (o), (h)._asi, (v)))); })
267 #endif
268 /*
269 * uintN_t bus_space_read_stream_N(bus_space_tag_t tag,
270 * bus_space_handle_t bsh, bus_size_t offset);
271 *
272 * Read a 1, 2, 4, or 8 byte quantity from bus space
273 * described by tag/handle/offset.
274 */
275 #ifndef BUS_SPACE_DEBUG
276 #define bus_space_read_stream_1(t, h, o) \
277 (0 ? (t)->type : lduba((h)._ptr + (o), (h)._sasi))
278
279 #define bus_space_read_stream_2(t, h, o) \
280 (0 ? (t)->type : lduha((h)._ptr + (o), (h)._sasi))
281
282 #define bus_space_read_stream_4(t, h, o) \
283 (0 ? (t)->type : lda((h)._ptr + (o), (h)._sasi))
284
285 #define bus_space_read_stream_8(t, h, o) \
286 (0 ? (t)->type : ldxa((h)._ptr + (o), (h)._sasi))
287 #else
288 #define bus_space_read_stream_1(t, h, o) ({ \
289 uint8_t __bv = \
290 lduba((h)._ptr + (o), (h)._sasi); \
291 if (bus_space_debug & BSDB_ACCESS) \
292 printf("bsr1(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr, \
293 (long long)(o), \
294 (h)._sasi, (uint32_t) __bv); \
295 __bv; })
296
297 #define bus_space_read_stream_2(t, h, o) ({ \
298 uint16_t __bv = \
299 lduha((h)._ptr + (o), (h)._sasi); \
300 if (bus_space_debug & BSDB_ACCESS) \
301 printf("bsr2(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr, \
302 (long long)(o), \
303 (h)._sasi, (uint32_t)__bv); \
304 __bv; })
305
306 #define bus_space_read_stream_4(t, h, o) ({ \
307 uint32_t __bv = \
308 lda((h)._ptr + (o), (h)._sasi); \
309 if (bus_space_debug & BSDB_ACCESS) \
310 printf("bsr4(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr, \
311 (long long)(o), \
312 (h)._sasi, __bv); \
313 __bv; })
314
315 #define bus_space_read_stream_8(t, h, o) ({ \
316 uint64_t __bv = \
317 ldxa((h)._ptr + (o), (h)._sasi); \
318 if (bus_space_debug & BSDB_ACCESS) \
319 printf("bsr8(%llx + %llx, %x) -> %llx\n", (long long)(h)._ptr, \
320 (long long)(o), \
321 (h)._sasi, (long long)__bv); \
322 __bv; })
323 #endif
324 /*
325 * void bus_space_write_stream_N(bus_space_tag_t tag,
326 * bus_space_handle_t bsh, bus_size_t offset,
327 * uintN_t value);
328 *
329 * Write the 1, 2, 4, or 8 byte value `value' to bus space
330 * described by tag/handle/offset.
331 */
332 #ifndef BUS_SPACE_DEBUG
333 #define bus_space_write_stream_1(t, h, o, v) \
334 (0 ? (t)->type : ((void)(stba((h)._ptr + (o), (h)._sasi, (v)))))
335
336 #define bus_space_write_stream_2(t, h, o, v) \
337 (0 ? (t)->type : ((void)(stha((h)._ptr + (o), (h)._sasi, (v)))))
338
339 #define bus_space_write_stream_4(t, h, o, v) \
340 (0 ? (t)->type : ((void)(sta((h)._ptr + (o), (h)._sasi, (v)))))
341
342 #define bus_space_write_stream_8(t, h, o, v) \
343 (0 ? (t)->type : ((void)(stxa((h)._ptr + (o), (h)._sasi, (v)))))
344 #else
345 #define bus_space_write_stream_1(t, h, o, v) ({ \
346 if (bus_space_debug & BSDB_ACCESS) \
347 printf("bsw1(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr, \
348 (long long)(o), \
349 (h)._sasi, (uint32_t) v); \
350 ((void)(stba((h)._ptr + (o), (h)._sasi, (v)))); })
351
352 #define bus_space_write_stream_2(t, h, o, v) ({ \
353 if (bus_space_debug & BSDB_ACCESS) \
354 printf("bsw2(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr, \
355 (long long)(o), \
356 (h)._sasi, (uint32_t) v); \
357 ((void)(stha((h)._ptr + (o), (h)._sasi, (v)))); })
358
359 #define bus_space_write_stream_4(t, h, o, v) ({ \
360 if (bus_space_debug & BSDB_ACCESS) \
361 printf("bsw4(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr, \
362 (long long)(o), \
363 (h)._sasi, (uint32_t) v); \
364 ((void)(sta((h)._ptr + (o), (h)._sasi, (v)))); })
365
366 #define bus_space_write_stream_8(t, h, o, v) ({ \
367 if (bus_space_debug & BSDB_ACCESS) \
368 printf("bsw8(%llx + %llx, %x) <- %llx\n", (long long)(h)._ptr, \
369 (long long)(o), \
370 (h)._sasi, (long long) v); \
371 ((void)(stxa((h)._ptr + (o), (h)._sasi, (v)))); })
372 #endif
373 /* Forwards needed by prototypes below. */
374 struct mbuf;
375 struct uio;
376
377 #define bus_dmamap_create(t, s, n, m, b, f, p) \
378 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
379 #define bus_dmamap_destroy(t, p) \
380 (*(t)->_dmamap_destroy)((t), (p))
381 #define bus_dmamap_load(t, m, b, s, p, f) \
382 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
383 #define bus_dmamap_load_mbuf(t, m, b, f) \
384 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
385 #define bus_dmamap_load_uio(t, m, u, f) \
386 (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
387 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \
388 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
389 #define bus_dmamap_unload(t, p) \
390 (*(t)->_dmamap_unload)((t), (p))
391 #define bus_dmamap_sync(t, p, o, l, ops) \
392 (void)((t)->_dmamap_sync ? \
393 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
394
395 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
396 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
397 #define bus_dmamem_free(t, sg, n) \
398 (*(t)->_dmamem_free)((t), (sg), (n))
399 #define bus_dmamem_map(t, sg, n, s, k, f) \
400 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
401 #define bus_dmamem_unmap(t, k, s) \
402 (*(t)->_dmamem_unmap)((t), (k), (s))
403 #define bus_dmamem_mmap(t, sg, n, o, p, f) \
404 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
405
406 #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP
407 #define bus_dmatag_destroy(t) __nothing
408
409 #ifdef _SPARC_BUS_DMA_PRIVATE
410 int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
411 bus_size_t, int, bus_dmamap_t *);
412 void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
413 int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
414 bus_size_t, struct proc *, int);
415 int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
416 struct mbuf *, int);
417 int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
418 struct uio *, int);
419 int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
420 bus_dma_segment_t *, int, bus_size_t, int);
421 void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
422 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
423 bus_size_t, int);
424
425 int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
426 bus_size_t alignment, bus_size_t boundary,
427 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
428 void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
429 int nsegs);
430 int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
431 int nsegs, size_t size, void **kvap, int flags);
432 void _bus_dmamem_unmap(bus_dma_tag_t tag, void *kva,
433 size_t size);
434 paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
435 int nsegs, off_t off, int prot, int flags);
436
437 int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
438 bus_size_t alignment, bus_size_t boundary,
439 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
440 vaddr_t low, vaddr_t high);
441 #endif /* _SPARC_BUS_DMA_PRIVATE */
442
443 #endif /* _SPARC64_BUS_FUNCS_H_ */
444