xref: /netbsd-src/sys/arch/sparc64/include/bus_funcs.h (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: bus_funcs.h,v 1.3 2014/07/14 12:40:38 nakayama 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 /*
69  * Debug hooks
70  */
71 
72 extern int bus_space_debug;
73 
74 bus_space_tag_t bus_space_tag_alloc(bus_space_tag_t, void *);
75 int		bus_space_translate_address_generic(struct openprom_range *,
76 						    int, bus_addr_t *);
77 
78 #if 0
79 /*
80  * The following macro could be used to generate the bus_space*() functions
81  * but it uses a gcc extension and is ANSI-only.
82 #define PROTO_bus_space_xxx		(bus_space_tag_t t, ...)
83 #define RETURNTYPE_bus_space_xxx	void *
84 #define BUSFUN(name, returntype, t, args...)			\
85 	static __inline RETURNTYPE_##name			\
86 	bus_##name PROTO_##name					\
87 	{							\
88 		while (t->sparc_##name == NULL)			\
89 			t = t->parent;				\
90 		return (*(t)->sparc_##name)(t, args);		\
91 	}
92  */
93 #endif
94 
95 /*
96  * Bus space function prototypes.
97  */
98 static void	*bus_intr_establish(
99 				bus_space_tag_t,
100 				int,			/*bus-specific intr*/
101 				int,			/*device class level,
102 							  see machine/intr.h*/
103 				int (*)(void *),	/*handler*/
104 				void *);		/*handler arg*/
105 
106 
107 /* This macro finds the first "upstream" implementation of method `f' */
108 #define _BS_CALL(t,f)			\
109 	while (t->f == NULL)		\
110 		t = t->parent;		\
111 	return (*(t)->f)
112 
113 #define _BS_VOID_CALL(t,f)			\
114 	while (t->f == NULL)		\
115 		t = t->parent;		\
116 	(*(t)->f)
117 
118 static __inline void *
119 bus_intr_establish(bus_space_tag_t t, int p, int l, int	(*h)(void *), void *a)
120 {
121 	_BS_CALL(t, sparc_intr_establish)(t, p, l, h, a, NULL);
122 }
123 
124 /* XXXX Things get complicated if we use unmapped register accesses. */
125 #define	bus_space_vaddr(t, h)	(PHYS_ASI((h)._asi) ? \
126 			NULL : (void *)(vaddr_t)((h)._ptr))
127 
128 #define bus_space_barrier(t, h, o, s, f)	\
129 	sparc_bus_space_barrier((t), (h), (o), (s), (f))
130 
131 static __inline void
132 sparc_bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h,
133     bus_size_t o, bus_size_t s, int f)
134 {
135 	/*
136 	 * We have a bit of a problem with the bus_space_barrier()
137 	 * interface.  It defines a read barrier and a write barrier
138 	 * which really don't map to the 7 different types of memory
139 	 * barriers in the SPARC v9 instruction set.
140 	 */
141 	if (f == BUS_SPACE_BARRIER_READ)
142 		/* A load followed by a load to the same location? */
143 		__asm volatile("membar #Lookaside");
144 	else if (f == BUS_SPACE_BARRIER_WRITE)
145 		/* A store followed by a store? */
146 		__asm volatile("membar #StoreStore");
147 	else
148 		/* A store followed by a load? */
149 		__asm volatile("membar #StoreLoad|#MemIssue|#Lookaside");
150 }
151 
152 /*
153  *	uintN_t bus_space_read_N(bus_space_tag_t tag,
154  *	    bus_space_handle_t bsh, bus_size_t offset);
155  *
156  * Read a 1, 2, 4, or 8 byte quantity from bus space
157  * described by tag/handle/offset.
158  */
159 #ifndef BUS_SPACE_DEBUG
160 #define	bus_space_read_1(t, h, o)					\
161 	    (0 ? (t)->type : lduba((h)._ptr + (o), (h)._asi))
162 
163 #define	bus_space_read_2(t, h, o)					\
164 	    (0 ? (t)->type : lduha((h)._ptr + (o), (h)._asi))
165 
166 #define	bus_space_read_4(t, h, o)					\
167 	    (0 ? (t)->type : lda((h)._ptr + (o), (h)._asi))
168 
169 #define	bus_space_read_8(t, h, o)					\
170 	    (0 ? (t)->type : ldxa((h)._ptr + (o), (h)._asi))
171 #else
172 #define	bus_space_read_1(t, h, o) ({					\
173 	uint8_t __bv =							\
174 	    lduba((h)._ptr + (o), (h)._asi);				\
175 	if (bus_space_debug & BSDB_ACCESS)				\
176 	printf("bsr1(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr,	\
177 		(long long)(o),						\
178 		(h)._asi, (uint32_t) __bv);				\
179 	__bv; })
180 
181 #define	bus_space_read_2(t, h, o) ({					\
182 	uint16_t __bv =							\
183 	    lduha((h)._ptr + (o), (h)._asi);				\
184 	if (bus_space_debug & BSDB_ACCESS)				\
185 	printf("bsr2(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr,	\
186 		(long long)(o),						\
187 		(h)._asi, (uint32_t)__bv);				\
188 	__bv; })
189 
190 #define	bus_space_read_4(t, h, o) ({					\
191 	uint32_t __bv =							\
192 	    lda((h)._ptr + (o), (h)._asi);				\
193 	if (bus_space_debug & BSDB_ACCESS)				\
194 	printf("bsr4(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr,	\
195 		(long long)(o),						\
196 		(h)._asi, __bv);					\
197 	__bv; })
198 
199 #define	bus_space_read_8(t, h, o) ({					\
200 	uint64_t __bv =							\
201 	    ldxa((h)._ptr + (o), (h)._asi);				\
202 	if (bus_space_debug & BSDB_ACCESS)				\
203 	printf("bsr8(%llx + %llx, %x) -> %llx\n", (long long)(h)._ptr,	\
204 		(long long)(o),						\
205 		(h)._asi, (long long)__bv);				\
206 	__bv; })
207 #endif
208 /*
209  *	void bus_space_write_N(bus_space_tag_t tag,
210  *	    bus_space_handle_t bsh, bus_size_t offset,
211  *	    uintN_t value);
212  *
213  * Write the 1, 2, 4, or 8 byte value `value' to bus space
214  * described by tag/handle/offset.
215  */
216 #ifndef BUS_SPACE_DEBUG
217 #define	bus_space_write_1(t, h, o, v)					\
218 	(0 ? (t)->type : ((void)(stba((h)._ptr + (o), (h)._asi, (v)))))
219 
220 #define	bus_space_write_2(t, h, o, v)					\
221 	(0 ? (t)->type : ((void)(stha((h)._ptr + (o), (h)._asi, (v)))))
222 
223 #define	bus_space_write_4(t, h, o, v)					\
224 	(0 ? (t)->type : ((void)(sta((h)._ptr + (o), (h)._asi, (v)))))
225 
226 #define	bus_space_write_8(t, h, o, v)					\
227 	(0 ? (t)->type : ((void)(stxa((h)._ptr + (o), (h)._asi, (v)))))
228 #else
229 #define	bus_space_write_1(t, h, o, v) ({				\
230 	if (bus_space_debug & BSDB_ACCESS)				\
231 	printf("bsw1(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr,	\
232 		(long long)(o),						\
233 		(h)._asi, (uint32_t) v);				\
234 	((void)(stba((h)._ptr + (o), (h)._asi, (v)))); })
235 
236 #define	bus_space_write_2(t, h, o, v) ({				\
237 	if (bus_space_debug & BSDB_ACCESS)				\
238 	printf("bsw2(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr,	\
239 		(long long)(o),						\
240 		(h)._asi, (uint32_t) v);				\
241 	((void)(stha((h)._ptr + (o), (h)._asi, (v)))); })
242 
243 #define	bus_space_write_4(t, h, o, v) ({				\
244 	if (bus_space_debug & BSDB_ACCESS)				\
245 	printf("bsw4(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr,	\
246 		(long long)(o),						\
247 		(h)._asi, (uint32_t) v);				\
248 	((void)(sta((h)._ptr + (o), (h)._asi, (v)))); })
249 
250 #define	bus_space_write_8(t, h, o, v) ({				\
251 	if (bus_space_debug & BSDB_ACCESS)				\
252 	printf("bsw8(%llx + %llx, %x) <- %llx\n", (long long)(h)._ptr,	\
253 		(long long)(o),						\
254 		(h)._asi, (long long) v);				\
255 	((void)(stxa((h)._ptr + (o), (h)._asi, (v)))); })
256 #endif
257 /*
258  *	uintN_t bus_space_read_stream_N(bus_space_tag_t tag,
259  *	    bus_space_handle_t bsh, bus_size_t offset);
260  *
261  * Read a 1, 2, 4, or 8 byte quantity from bus space
262  * described by tag/handle/offset.
263  */
264 #ifndef BUS_SPACE_DEBUG
265 #define	bus_space_read_stream_1(t, h, o)				\
266 	    (0 ? (t)->type : lduba((h)._ptr + (o), (h)._sasi))
267 
268 #define	bus_space_read_stream_2(t, h, o)				\
269 	    (0 ? (t)->type : lduha((h)._ptr + (o), (h)._sasi))
270 
271 #define	bus_space_read_stream_4(t, h, o)				\
272 	    (0 ? (t)->type : lda((h)._ptr + (o), (h)._sasi))
273 
274 #define	bus_space_read_stream_8(t, h, o)				\
275 	    (0 ? (t)->type : ldxa((h)._ptr + (o), (h)._sasi))
276 #else
277 #define	bus_space_read_stream_1(t, h, o) ({				\
278 	uint8_t __bv =							\
279 	    lduba((h)._ptr + (o), (h)._sasi);				\
280 	if (bus_space_debug & BSDB_ACCESS)				\
281 	printf("bsr1(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr,	\
282 		(long long)(o),						\
283 		(h)._sasi, (uint32_t) __bv);				\
284 	__bv; })
285 
286 #define	bus_space_read_stream_2(t, h, o) ({				\
287 	uint16_t __bv =							\
288 	    lduha((h)._ptr + (o), (h)._sasi);				\
289 	if (bus_space_debug & BSDB_ACCESS)				\
290 	printf("bsr2(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr,	\
291 		(long long)(o),						\
292 		(h)._sasi, (uint32_t)__bv);				\
293 	__bv; })
294 
295 #define	bus_space_read_stream_4(t, h, o) ({				\
296 	uint32_t __bv =							\
297 	    lda((h)._ptr + (o), (h)._sasi);				\
298 	if (bus_space_debug & BSDB_ACCESS)				\
299 	printf("bsr4(%llx + %llx, %x) -> %x\n", (long long)(h)._ptr,	\
300 		(long long)(o),						\
301 		(h)._sasi, __bv);					\
302 	__bv; })
303 
304 #define	bus_space_read_stream_8(t, h, o) ({				\
305 	uint64_t __bv =							\
306 	    ldxa((h)._ptr + (o), (h)._sasi);				\
307 	if (bus_space_debug & BSDB_ACCESS)				\
308 	printf("bsr8(%llx + %llx, %x) -> %llx\n", (long long)(h)._ptr,	\
309 		(long long)(o),						\
310 		(h)._sasi, (long long)__bv);				\
311 	__bv; })
312 #endif
313 /*
314  *	void bus_space_write_stream_N(bus_space_tag_t tag,
315  *	    bus_space_handle_t bsh, bus_size_t offset,
316  *	    uintN_t value);
317  *
318  * Write the 1, 2, 4, or 8 byte value `value' to bus space
319  * described by tag/handle/offset.
320  */
321 #ifndef BUS_SPACE_DEBUG
322 #define	bus_space_write_stream_1(t, h, o, v)				\
323 	(0 ? (t)->type : ((void)(stba((h)._ptr + (o), (h)._sasi, (v)))))
324 
325 #define	bus_space_write_stream_2(t, h, o, v)				\
326 	(0 ? (t)->type : ((void)(stha((h)._ptr + (o), (h)._sasi, (v)))))
327 
328 #define	bus_space_write_stream_4(t, h, o, v)				\
329 	(0 ? (t)->type : ((void)(sta((h)._ptr + (o), (h)._sasi, (v)))))
330 
331 #define	bus_space_write_stream_8(t, h, o, v)				\
332 	(0 ? (t)->type : ((void)(stxa((h)._ptr + (o), (h)._sasi, (v)))))
333 #else
334 #define	bus_space_write_stream_1(t, h, o, v) ({				\
335 	if (bus_space_debug & BSDB_ACCESS)				\
336 	printf("bsw1(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr,	\
337 		(long long)(o),						\
338 		(h)._sasi, (uint32_t) v);				\
339 	((void)(stba((h)._ptr + (o), (h)._sasi, (v)))); })
340 
341 #define	bus_space_write_stream_2(t, h, o, v) ({				\
342 	if (bus_space_debug & BSDB_ACCESS)				\
343 	printf("bsw2(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr,	\
344 		(long long)(o),						\
345 		(h)._sasi, (uint32_t) v);				\
346 	((void)(stha((h)._ptr + (o), (h)._sasi, (v)))); })
347 
348 #define	bus_space_write_stream_4(t, h, o, v) ({				\
349 	if (bus_space_debug & BSDB_ACCESS)				\
350 	printf("bsw4(%llx + %llx, %x) <- %x\n", (long long)(h)._ptr,	\
351 		(long long)(o),						\
352 		(h)._sasi, (uint32_t) v);				\
353 	((void)(sta((h)._ptr + (o), (h)._sasi, (v)))); })
354 
355 #define	bus_space_write_stream_8(t, h, o, v) ({				\
356 	if (bus_space_debug & BSDB_ACCESS)				\
357 	printf("bsw8(%llx + %llx, %x) <- %llx\n", (long long)(h)._ptr,	\
358 		(long long)(o),						\
359 		(h)._sasi, (long long) v);				\
360 	((void)(stxa((h)._ptr + (o), (h)._sasi, (v)))); })
361 #endif
362 /* Forwards needed by prototypes below. */
363 struct mbuf;
364 struct uio;
365 
366 #define	bus_dmamap_create(t, s, n, m, b, f, p)			\
367 	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
368 #define	bus_dmamap_destroy(t, p)				\
369 	(*(t)->_dmamap_destroy)((t), (p))
370 #define	bus_dmamap_load(t, m, b, s, p, f)			\
371 	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
372 #define	bus_dmamap_load_mbuf(t, m, b, f)			\
373 	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
374 #define	bus_dmamap_load_uio(t, m, u, f)				\
375 	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
376 #define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
377 	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
378 #define	bus_dmamap_unload(t, p)					\
379 	(*(t)->_dmamap_unload)((t), (p))
380 #define	bus_dmamap_sync(t, p, o, l, ops)			\
381 	(void)((t)->_dmamap_sync ?				\
382 	    (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
383 
384 #define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
385 	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
386 #define	bus_dmamem_free(t, sg, n)				\
387 	(*(t)->_dmamem_free)((t), (sg), (n))
388 #define	bus_dmamem_map(t, sg, n, s, k, f)			\
389 	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
390 #define	bus_dmamem_unmap(t, k, s)				\
391 	(*(t)->_dmamem_unmap)((t), (k), (s))
392 #define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
393 	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
394 
395 #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP
396 #define bus_dmatag_destroy(t)
397 
398 #ifdef _SPARC_BUS_DMA_PRIVATE
399 int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
400 	    bus_size_t, int, bus_dmamap_t *);
401 void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
402 int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
403 	    bus_size_t, struct proc *, int);
404 int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
405 	    struct mbuf *, int);
406 int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
407 	    struct uio *, int);
408 int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
409 	    bus_dma_segment_t *, int, bus_size_t, int);
410 void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
411 void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
412 	    bus_size_t, int);
413 
414 int	_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
415 	    bus_size_t alignment, bus_size_t boundary,
416 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
417 void	_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
418 	    int nsegs);
419 int	_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
420 	    int nsegs, size_t size, void **kvap, int flags);
421 void	_bus_dmamem_unmap(bus_dma_tag_t tag, void *kva,
422 	    size_t size);
423 paddr_t	_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
424 	    int nsegs, off_t off, int prot, int flags);
425 
426 int	_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
427 	    bus_size_t alignment, bus_size_t boundary,
428 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
429 	    vaddr_t low, vaddr_t high);
430 #endif /* _SPARC_BUS_DMA_PRIVATE */
431 
432 #endif /* _SPARC64_BUS_FUNCS_H_ */
433