xref: /netbsd-src/sys/arch/ia64/include/bus.h (revision 55030085d73aaf24b1cbe869cf332de89aa2f069)
1 /*	$NetBSD: bus.h,v 1.5 2021/11/15 07:26:23 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 _IA64_BUS_H_
65 #define _IA64_BUS_H_
66 
67 #include <sys/systm.h>
68 
69 #include <machine/cpufunc.h>
70 #include <machine/vmparam.h>
71 
72 #ifdef BUS_SPACE_DEBUG
73 /*
74  * Macros for sanity-checking the aligned-ness of pointers passed to
75  * bus space ops.  These are not strictly necessary on the x86, but
76  * could lead to performance improvements, and help catch problems
77  * with drivers that would creep up on other architectures.
78  */
79 #define	__BUS_SPACE_ALIGNED_ADDRESS(p, t)				\
80 	((((u_long)(p)) & (sizeof(t)-1)) == 0)
81 
82 #define	__BUS_SPACE_ADDRESS_SANITY(p, t, d)				\
83 ({									\
84 	if (__BUS_SPACE_ALIGNED_ADDRESS((p), t) == 0) {			\
85 		printf("%s 0x%lx not aligned to %d bytes %s:%d\n",	\
86 		    d, (u_long)(p), sizeof(t), __FILE__, __LINE__);	\
87 	}								\
88 	(void) 0;							\
89 })
90 
91 #define BUS_SPACE_ALIGNED_POINTER(p, t) __BUS_SPACE_ALIGNED_ADDRESS(p, t)
92 #else
93 #define	__BUS_SPACE_ADDRESS_SANITY(p,t,d)	(void) 0
94 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
95 #endif /* BUS_SPACE_DEBUG */
96 
97 /*
98  * bus_space_map flags
99  */
100 
101 #define	BUS_SPACE_MAP_CACHEABLE		0x01
102 #define	BUS_SPACE_MAP_LINEAR		0x02
103 #define	BUS_SPACE_MAP_PREFETCHABLE	0x04
104 
105 /*
106  * Derived from x86 implementation, ia64 has both i/o and mem spaces
107  * These values are for bus space tag.
108  */
109 #define IA64_BUS_SPACE_IO	 0	 /* space is i/o space */
110 #define IA64_BUS_SPACE_MEM	 1	 /* space is mem space */
111 
112 #define __BUS_SPACE_HAS_STREAM_METHODS 1
113 
114 /*
115  * Bus address and size types
116  */
117 typedef u_long bus_addr_t;
118 typedef u_long bus_size_t;
119 
120 #define PRIxBUSADDR	"lx"
121 #define PRIxBUSSIZE	"lx"
122 #define PRIuBUSSIZE	"lu"
123 
124 /*
125  * Access methods for bus resources and address space.
126  */
127 typedef	int bus_space_tag_t;
128 typedef	u_long bus_space_handle_t;
129 
130 #define PRIxBSH		"lx"
131 
132 /* map/unmap */
133 
134 int	ia64_bus_space_map(bus_space_tag_t, bus_addr_t,
135 	    bus_size_t, int, bus_space_handle_t *);
136 void	ia64_bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
137 	    bus_size_t);
138 int	ia64_bus_space_subregion(bus_space_tag_t, bus_space_handle_t,
139 	    bus_size_t, bus_size_t, bus_space_handle_t *);
140 #define	bus_space_map(t, a, s, f, hp)					\
141 	ia64_bus_space_map((t), (a), (s), (f), (hp))
142 #define bus_space_unmap(t, h, s)					\
143 	ia64_bus_space_unmap((t), (h), (s))
144 #define bus_space_subregion(t, h, o, s, nhp)				\
145 	ia64_bus_space_subregion((t), (h), (o), (s), (nhp))
146 
147 /* vaddr */
148 
149 #define bus_space_vaddr(t, h) \
150 	((t) == IA64_BUS_SPACE_MEM ? (void *)(h) : (void *)0)
151 
152 /* map to user space */
153 
154 paddr_t	ia64_bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
155 
156 #define	bus_space_mmap(t, b, o, p, f)					\
157 	ia64_bus_space_mmap((t), (b), (o), (p), (f))
158 
159 /* alloc/free */
160 
161 int	ia64_bus_space_alloc(bus_space_tag_t, bus_addr_t, bus_addr_t,
162 	    bus_size_t, bus_size_t, bus_size_t, int, bus_addr_t *,
163 	    bus_space_handle_t *);
164 void	ia64_bus_space_free(bus_space_tag_t, bus_space_handle_t, bus_size_t);
165 
166 #define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp)			\
167 	ia64_bus_space__alloc((t), (rs), (re), (s), (a), (b), (f), (ap), (hp))
168 #define bus_space_free(t, h, s)						\
169 	ia64_bus_space_free((t), (h), (s))
170 
171 /*
172  *	uintN_t bus_space_read_N(bus_space_tag_t tag,
173  *	    bus_space_handle_t bsh, bus_size_t offset);
174  *
175  * Read a 1, 2, 4, or 8 byte quantity from bus space
176  * described by tag/handle/offset.
177  */
178 
179 #define	bus_space_read_1(t, h, o)					\
180 	((t) == IA64_BUS_SPACE_IO ? (inb((h) + (o))) :\
181 	    (*(volatile uint8_t *)((h) + (o))))
182 
183 #define	bus_space_read_2(t, h, o)					\
184 	 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"),	\
185 	  ((t) == IA64_BUS_SPACE_IO ? (inw((h) + (o))) :		\
186 	    (*(volatile uint16_t *)((h) + (o)))))
187 
188 #define	bus_space_read_4(t, h, o)					\
189 	 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"),	\
190 	  ((t) == IA64_BUS_SPACE_IO ? (inl((h) + (o))) :		\
191 	    (*(volatile uint32_t *)((h) + (o)))))
192 
193 #define	bus_space_read_8(t, h, o)					\
194 	 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"),	\
195 	  ((t) == IA64_BUS_SPACE_IO ?					\
196 	    ({ printf("%s: can't read 8bytes from I/O space\n", __FUNCTION__); 0;}) : \
197 	    (*(volatile uint64_t *)((h) + (o)))))
198 
199 #define bus_space_read_stream_1 bus_space_read_1
200 #define bus_space_read_stream_2 bus_space_read_2
201 #define bus_space_read_stream_4 bus_space_read_4
202 #define bus_space_read_stream_8 bus_space_read_8
203 
204 /*
205  *	void bus_space_read_multi_N(bus_space_tag_t tag,
206  *	    bus_space_handle_t bsh, bus_size_t offset,
207  *	    uintN_t *addr, size_t count);
208  *
209  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
210  * described by tag/handle/offset and copy into buffer provided.
211  */
212 
213 #define	bus_space_read_multi_1(t, h, o, ptr, cnt)			\
214 do {									\
215 	if ((t) == IA64_BUS_SPACE_IO) {					\
216 		insb((h) + (o), (ptr), (cnt));				\
217 	} else {							\
218 		int __i;						\
219 		volatile uint8_t *__p = (uint8_t *)((h) + (o));		\
220 		uint8_t *__dst = (ptr);					\
221 		for (__i = 0; __i < (cnt); __i++)			\
222 			*__dst++ = *__p;				\
223 	}								\
224 } while (/* CONSTCOND */ 0)
225 
226 #define	bus_space_read_multi_2(t, h, o, ptr, cnt)			\
227 do {									\
228 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer");		\
229 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr");	\
230 	if ((t) == IA64_BUS_SPACE_IO) {					\
231 		insw((h) + (o), (ptr), (cnt));				\
232 	} else {							\
233 		int __i;						\
234 		volatile uint16_t *__p = (uint16_t *)((h) + (o));	\
235 		uint16_t *__dst = (ptr);				\
236 		for (__i = 0; __i < (cnt); __i++)			\
237 			*__dst++ = *__p;				\
238 	}								\
239 } while (/* CONSTCOND */ 0)
240 
241 #define	bus_space_read_multi_4(t, h, o, ptr, cnt)			\
242 do {									\
243 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer");		\
244 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr");	\
245 	if ((t) == IA64_BUS_SPACE_IO) {					\
246 		insl((h) + (o), (ptr), (cnt));				\
247 	} else {							\
248 		int __i;						\
249 		volatile uint32_t *__p = (uint32_t *)((h) + (o));	\
250 		uint32_t *__dst = (ptr);				\
251 		for (__i = 0; __i < (cnt); __i++)			\
252 			*__dst++ = *__p;				\
253 	}								\
254 } while (/* CONSTCOND */ 0)
255 
256 #define	bus_space_read_multi_8(t, h, o, ptr, cnt)			\
257 do {									\
258 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer");		\
259 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr");	\
260 	if ((t) == IA64_BUS_SPACE_IO) {					\
261 		printf("%s: can't read 8bytes from I/O space\n",	\
262 		    __FUNCTION__);					\
263 	} else {							\
264 		int __i;						\
265 		volatile uint64_t *__p = (uint64_t *)((h) + (o));	\
266 		uint64_t *__dst = (ptr);				\
267 		for (__i = 0; __i < (cnt); __i++)			\
268 			*__dst++ = *__p;				\
269 	}								\
270 } while (/* CONSTCOND */ 0)
271 
272 #define bus_space_read_multi_stream_1 bus_space_read_multi_1
273 #define bus_space_read_multi_stream_2 bus_space_read_multi_2
274 #define bus_space_read_multi_stream_4 bus_space_read_multi_4
275 #define bus_space_read_multi_stream_8 bus_space_read_multi_8
276 
277 
278 /*
279  *	void bus_space_read_region_N(bus_space_tag_t tag,
280  *	    bus_space_handle_t bsh, bus_size_t offset,
281  *	    uintN_t *addr, size_t count);
282  *
283  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
284  * described by tag/handle and starting at `offset' and copy into
285  * buffer provided.
286  */
287 
288 #define	bus_space_read_region_1(t, h, o, ptr, cnt)			\
289 do {									\
290 	if ((t) == IA64_BUS_SPACE_IO) {					\
291 		int __i;						\
292 		volatile bus_addr_t __port = (h) + (o);			\
293 		uint8_t *__dst = (ptr);					\
294 		for (__i = 0; __i < (cnt); __i++) {			\
295 			*__dst++ = inb(__port);				\
296 			__port++;					\
297 		}							\
298 	} else {							\
299 		int __i;						\
300 		volatile uint8_t *__p = (uint8_t *)((h) + (o));		\
301 		uint8_t *__dst = (ptr);					\
302 		for (__i = 0; __i < (cnt); __i++)			\
303 			*__dst++ = *__p++;				\
304 	}								\
305 } while (/* CONSTCOND */ 0)
306 
307 #define	bus_space_read_region_2(t, h, o, ptr, cnt)			\
308 do {									\
309 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer");		\
310 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr");	\
311 	if ((t) == IA64_BUS_SPACE_IO) {					\
312 		int __i;						\
313 		volatile bus_addr_t __port = (h) + (o);			\
314 		uint8_t *__dst = (ptr);					\
315 		for (__i = 0; __i < (cnt); __i++) {			\
316 			*__dst++ = inb(__port);				\
317 			__port += 2;					\
318 		}							\
319 	} else {							\
320 		int __i;						\
321 		volatile uint16_t *__p = (uint16_t *)((h) + (o));	\
322 		uint16_t *__dst = (ptr);				\
323 		for (__i = 0; __i < (cnt); __i++)			\
324 			*__dst++ = *__p++;				\
325 	}								\
326 } while (/* CONSTCOND */ 0)
327 
328 #define	bus_space_read_region_4(t, h, o, ptr, cnt)			\
329 do {									\
330 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer");		\
331 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr");	\
332 	if ((t) == IA64_BUS_SPACE_IO) {					\
333 		int __i;						\
334 		volatile bus_addr_t __port = (h) + (o);			\
335 		uint8_t *__dst = (ptr);					\
336 		for (__i = 0; __i < (cnt); __i++) {			\
337 			*__dst++ = inb(__port);				\
338 			__port += 4;					\
339 		}							\
340 	} else {							\
341 		volatile uint32_t *__p = (uint32_t *)((h) + (o));	\
342 		uint32_t *__dst = (ptr);				\
343 		for (__i = 0; __i < (cnt); __i++)			\
344 			*__dst++ = *__p++;				\
345 	}								\
346 } while (/* CONSTCOND */ 0)
347 
348 #define	bus_space_read_region_8(t, h, o, ptr, cnt)			\
349 do {									\
350 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer");		\
351 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr");	\
352 	if ((t) == IA64_BUS_SPACE_IO) {					\
353 		printf("%s: can't read 8bytes from I/O space\n",	\
354 		    __FUNCTION__);					\
355 	} else {							\
356 		volatile uint64_t *__p = (uint64_t *)((h) + (o));	\
357 		uint64_t *__dst = (ptr);				\
358 		for (__i = 0; __i < (cnt); __i++)			\
359 			*__dst++ = *__p++;				\
360 	}								\
361 } while (/* CONSTCOND */ 0)
362 
363 #define bus_space_read_region_stream_1 bus_space_read_region_1
364 #define bus_space_read_region_stream_2 bus_space_read_region_2
365 #define bus_space_read_region_stream_4 bus_space_read_region_4
366 #define bus_space_read_region_stream_8 bus_space_read_region_8
367 
368 
369 /*
370  *	void bus_space_write_N(bus_space_tag_t tag,
371  *	    bus_space_handle_t bsh, bus_size_t offset,
372  *	    uintN_t value);
373  *
374  * Write the 1, 2, 4, or 8 byte value `value' to bus space
375  * described by tag/handle/offset.
376  */
377 
378 #define	bus_space_write_1(t, h, o, v)					\
379 do {									\
380 	if ((t) == IA64_BUS_SPACE_IO)					\
381 		outb((h) + (o), (v));					\
382 	else								\
383 		((void)(*(volatile uint8_t *)((h) + (o)) = (v)));	\
384 } while (/* CONSTCOND */ 0)
385 
386 #define	bus_space_write_2(t, h, o, v)					\
387 do {									\
388 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr");	\
389 	if ((t) == IA64_BUS_SPACE_IO)					\
390 		outw((h) + (o), (v));					\
391 	else								\
392 		((void)(*(volatile uint16_t *)((h) + (o)) = (v)));	\
393 } while (/* CONSTCOND */ 0)
394 
395 #define	bus_space_write_4(t, h, o, v)					\
396 do {									\
397 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr");	\
398 	if ((t) == IA64_BUS_SPACE_IO)					\
399 		outl((h) + (o), (v));					\
400 	else								\
401 		((void)(*(volatile uint32_t *)((h) + (o)) = (v)));	\
402 } while (/* CONSTCOND */ 0)
403 
404 #define	bus_space_write_8(t, h, o, v)					\
405 	 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr");	\
406 	 if ((t) == IA64_BUS_SPACE_IO ?					\
407 	     printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__); : \
408 	     (*(volatile uint64_t *)((h) + (o)) = (v)))
409 
410 #define bus_space_write_stream_1 bus_space_write_1
411 #define bus_space_write_stream_2 bus_space_write_2
412 #define bus_space_write_stream_4 bus_space_write_4
413 #define bus_space_write_stream_8 bus_space_write_8
414 
415 /*
416  *	void bus_space_write_multi_N(bus_space_tag_t tag,
417  *	    bus_space_handle_t bsh, bus_size_t offset,
418  *	    const uintN_t *addr, size_t count);
419  *
420  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
421  * provided to bus space described by tag/handle/offset.
422  */
423 
424 #define	bus_space_write_multi_1(t, h, o, ptr, cnt)			\
425 do {									\
426 	if ((t) == IA64_BUS_SPACE_IO) {					\
427 		outsb((h) + (o), (ptr), (cnt));				\
428 	} else {							\
429 		int __i;						\
430 		volatile uint8_t *__p = (uint8_t *)((h) + (o));		\
431 		const uint8_t *__src = (ptr);				\
432 		for (__i = 0; __i < (cnt); __i++)			\
433 			*__p = *__src++;				\
434 	}								\
435 } while (/* CONSTCOND */ 0)
436 
437 #define bus_space_write_multi_2(t, h, o, ptr, cnt)			\
438 do {									\
439 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer");		\
440 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr");	\
441 	if ((t) == IA64_BUS_SPACE_IO) {					\
442 		outsw((h) + (o), (ptr), (cnt));				\
443 	} else {							\
444 		int __i;						\
445 		volatile uint16_t *__p = (uint16_t *)((h) + (o));	\
446 		const uint16_t *__src = (ptr);				\
447 		for (__i = 0; __i < (cnt); __i++)			\
448 			*__p = *__src++;				\
449 	}								\
450 } while (/* CONSTCOND */ 0)
451 
452 #define bus_space_write_multi_4(t, h, o, ptr, cnt)			\
453 do {									\
454 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer");		\
455 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr");	\
456 	if ((t) == IA64_BUS_SPACE_IO) {					\
457 		outsl((h) + (o), (ptr), (cnt));				\
458 	} else {							\
459 		int __i;						\
460 		volatile uint32_t *__p = (uint32_t *)((h) + (o));	\
461 		const uint32_t *__src = (ptr);				\
462 		for (__i = 0; __i < (cnt); __i++)			\
463 			*__p = *__src++;				\
464 	}								\
465 } while (/* CONSTCOND */ 0)
466 
467 #define bus_space_write_multi_8(t, h, o, ptr, cnt)			\
468 do {									\
469 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer");		\
470 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr");	\
471 	if ((t) == IA64_BUS_SPACE_IO) {					\
472 		printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);\
473 	} else {							\
474 		int __i;						\
475 		volatile uint64_t *__p = (uint64_t *)((h) + (o));	\
476 		const uint64_t *__src = (ptr);				\
477 		for (__i = 0; __i < (cnt); __i++)			\
478 			*__p = *__src++;				\
479 	}								\
480 } while (/* CONSTCOND */ 0)
481 
482 #define bus_space_write_multi_stream_1 bus_space_write_multi_1
483 #define bus_space_write_multi_stream_2 bus_space_write_multi_2
484 #define bus_space_write_multi_stream_4 bus_space_write_multi_4
485 #define bus_space_write_multi_stream_8 bus_space_write_multi_8
486 
487 
488 /*
489  *	void bus_space_write_region_N(bus_space_tag_t tag,
490  *	    bus_space_handle_t bsh, bus_size_t offset,
491  *	    const uintN_t *addr, size_t count);
492  *
493  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
494  * to bus space described by tag/handle starting at `offset'.
495  */
496 
497 #define	bus_space_write_region_1(t, h, o, ptr, cnt)			\
498 do {									\
499 	if ((t) == IA64_BUS_SPACE_IO) {					\
500 		int __i;						\
501 		volatile bus_addr_t __port = (h) + (o);			\
502 		const uint8_t *__src = (ptr);				\
503 		for (__i = 0; __i < (cnt); __i++) {			\
504 			outb(__port, *__src);				\
505 			__port++;					\
506 			__src++;					\
507 		}							\
508 	} else {							\
509 		int __i;						\
510 		volatile uint8_t *__p = (uint8_t *)((h) + (o));		\
511 		const uint8_t *__src = (ptr);				\
512 		for (__i = 0; __i < (cnt); __i++)			\
513 			*__p++ = *__src++;				\
514 	}								\
515 } while (/* CONSTCOND */ 0)
516 
517 #define	bus_space_write_region_2(t, h, o, ptr, cnt)			\
518 do {									\
519 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer");		\
520 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr");	\
521 	if ((t) == IA64_BUS_SPACE_IO) {					\
522 		int __i;						\
523 		volatile bus_addr_t __port = (h) + (o);			\
524 		const uint16_t *__src = (ptr);				\
525 		for (__i = 0; __i < (cnt); __i++) {			\
526 			outw(__port, *__src);				\
527 			__port += 2;					\
528 			__src++;					\
529 		}							\
530 	} else {							\
531 		int __i;						\
532 		volatile uint16_t *__p = (uint16_t *)((h) + (o));	\
533 		const uint16_t *__src = (ptr);				\
534 		for (__i = 0; __i < (cnt); __i++)			\
535 			*__p++ = *__src++;				\
536 	}								\
537 } while (/* CONSTCOND */ 0)
538 
539 #define	bus_space_write_region_4(t, h, o, ptr, cnt)			\
540 do {									\
541 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer");		\
542 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr");	\
543 	if ((t) == IA64_BUS_SPACE_IO) {					\
544 		int __i;						\
545 		volatile bus_addr_t __port = (h) + (o);			\
546 		const uint32_t *__src = (ptr);				\
547 		for (__i = 0; __i < (cnt); __i++) {			\
548 			outl(__port, *__src);				\
549 			__port += 4;					\
550 			__src++;					\
551 		}							\
552 	} else {							\
553 		int __i;						\
554 		volatile uint32_t *__p = (uint32_t *)(h) + (o);		\
555 		const uint32_t *__src = (ptr);				\
556 		for (__i = 0; __i < (cnt); __i++)			\
557 			*__p++ = *__src++;				\
558 	}								\
559 } while (/* CONSTCOND */ 0)
560 
561 #define	bus_space_write_region_8(t, h, o, ptr, cnt)			\
562 do {									\
563 	__BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer");		\
564 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr");	\
565 	if ((t) == IA64_BUS_SPACE_IO) {					\
566 		printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);\
567 	} else {							\
568 		int __i;						\
569 		volatile uint64_t *__p = (uint64_t *)((h) + (o));	\
570 		const uint64_t *__src = (ptr);				\
571 		for (__i = 0; __i < (cnt); __i++)			\
572 			*__p++ = *__src++;				\
573 	}								\
574 } while (/* CONSTCOND */ 0)
575 
576 #define bus_space_write_region_stream_1 bus_space_write_region_1
577 #define bus_space_write_region_stream_2 bus_space_write_region_2
578 #define bus_space_write_region_stream_4 bus_space_write_region_4
579 #define bus_space_write_region_stream_8 bus_space_write_region_8
580 
581 
582 /*
583  *	void bus_space_set_multi_N(bus_space_tag_t tag,
584  *	    bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
585  *	    size_t count);
586  *
587  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
588  * by tag/handle/offset `count' times.
589  */
590 
591 static __inline void ia64_bus_space_set_multi_1(bus_space_tag_t,
592 	bus_space_handle_t, bus_size_t, uint8_t, size_t);
593 static __inline void ia64_bus_space_set_multi_2(bus_space_tag_t,
594 	bus_space_handle_t, bus_size_t, uint16_t, size_t);
595 static __inline void ia64_bus_space_set_multi_4(bus_space_tag_t,
596 	bus_space_handle_t, bus_size_t, uint32_t, size_t);
597 static __inline void ia64_bus_space_set_multi_8(bus_space_tag_t,
598 	bus_space_handle_t, bus_size_t, uint64_t, size_t);
599 
600 #define	bus_space_set_multi_1(t, h, o, v, c)				\
601 	ia64_bus_space_set_multi_1((t), (h), (o), (v), (c))
602 
603 #define	bus_space_set_multi_2(t, h, o, v, c)				\
604 do {									\
605 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr");	\
606 	ia64_bus_space_set_multi_2((t), (h), (o), (v), (c));		\
607 } while (/* CONSTCOND */ 0)
608 
609 #define	bus_space_set_multi_4(t, h, o, v, c)				\
610 do {									\
611 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr");	\
612 	ia64_bus_space_set_multi_4((t), (h), (o), (v), (c));		\
613 } while (/* CONSTCOND */ 0)
614 
615 #define	bus_space_set_multi_8(t, h, o, v, c)				\
616 do {									\
617 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr");	\
618 	ia64_bus_space_set_multi_8((t), (h), (o), (v), (c));		\
619 } while (/* CONSTCOND */ 0)
620 
621 static __inline void
ia64_bus_space_set_multi_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t v,size_t c)622 ia64_bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h,
623     bus_size_t o, uint8_t v, size_t c)
624 {
625 	bus_addr_t addr = h + o;
626 
627 	if (t == IA64_BUS_SPACE_IO)
628 		while (c--)
629 			outb(addr, v);
630 	else
631 		while (c--)
632 			*(volatile uint8_t *)(addr) = v;
633 }
634 
635 static __inline void
ia64_bus_space_set_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t v,size_t c)636 ia64_bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h,
637     bus_size_t o, uint16_t v, size_t c)
638 {
639 	bus_addr_t addr = h + o;
640 
641 	if (t == IA64_BUS_SPACE_IO)
642 		while (c--)
643 			outw(addr, v);
644 	else
645 		while (c--)
646 			*(volatile uint16_t *)(addr) = v;
647 }
648 
649 static __inline void
ia64_bus_space_set_multi_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t v,size_t c)650 ia64_bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h,
651     bus_size_t o, uint32_t v, size_t c)
652 {
653 	bus_addr_t addr = h + o;
654 
655 	if (t == IA64_BUS_SPACE_IO)
656 		while (c--)
657 			outl(addr, v);
658 	else
659 		while (c--)
660 			*(volatile uint32_t *)(addr) = v;
661 }
662 
663 static __inline void
ia64_bus_space_set_multi_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t v,size_t c)664 ia64_bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h,
665     bus_size_t o, uint64_t v, size_t c)
666 {
667 	bus_addr_t addr = h + o;
668 
669 	if (t == IA64_BUS_SPACE_IO)
670 		printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);
671 	else
672 		while (c--)
673 			*(volatile uint64_t *)(addr) = v;
674 }
675 
676 
677 /*
678  *	void bus_space_set_region_N(bus_space_tag_t tag,
679  *	    bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
680  *	    size_t count);
681  *
682  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
683  * by tag/handle starting at `offset'.
684  */
685 
686 static __inline void ia64_bus_space_set_region_1(bus_space_tag_t,
687 	bus_space_handle_t, bus_size_t, uint8_t, size_t);
688 static __inline void ia64_bus_space_set_region_2(bus_space_tag_t,
689 	bus_space_handle_t, bus_size_t, uint16_t, size_t);
690 static __inline void ia64_bus_space_set_region_4(bus_space_tag_t,
691 	bus_space_handle_t, bus_size_t, uint32_t, size_t);
692 
693 #define	bus_space_set_region_1(t, h, o, v, c)				\
694 	ia64_bus_space_set_region_1((t), (h), (o), (v), (c))
695 
696 #define	bus_space_set_region_2(t, h, o, v, c)				\
697 do {									\
698 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr");	\
699 	ia64_bus_space_set_region_2((t), (h), (o), (v), (c));		\
700 } while (/* CONSTCOND */ 0)
701 
702 #define	bus_space_set_region_4(t, h, o, v, c)				\
703 do {									\
704 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr");	\
705 	ia64_bus_space_set_region_4((t), (h), (o), (v), (c));		\
706 } while (/* CONSTCOND */ 0)
707 
708 #define	bus_space_set_region_8(t, h, o, v, c)				\
709 do {									\
710 	__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr");	\
711 	ia64_bus_space_set_region_8((t), (h), (o), (v), (c));		\
712 } while (/* CONSTCOND */ 0)
713 
714 static __inline void
ia64_bus_space_set_region_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t v,size_t c)715 ia64_bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h,
716     bus_size_t o, uint8_t v, size_t c)
717 {
718 	bus_addr_t addr = h + o;
719 
720 	if (t == IA64_BUS_SPACE_IO)
721 		for (; c != 0; c--, addr++)
722 			outb(addr, v);
723 	else
724 		for (; c != 0; c--, addr++)
725 			*(volatile uint8_t *)(addr) = v;
726 }
727 
728 static __inline void
ia64_bus_space_set_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t v,size_t c)729 ia64_bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h,
730     bus_size_t o, uint16_t v, size_t c)
731 {
732 	bus_addr_t addr = h + o;
733 
734 	if (t == IA64_BUS_SPACE_IO)
735 		for (; c != 0; c--, addr += 2)
736 			outw(addr, v);
737 	else
738 		for (; c != 0; c--, addr += 2)
739 			*(volatile uint16_t *)(addr) = v;
740 }
741 
742 static __inline void
ia64_bus_space_set_region_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t v,size_t c)743 ia64_bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h,
744     bus_size_t o, uint32_t v, size_t c)
745 {
746 	bus_addr_t addr = h + o;
747 
748 	if (t == IA64_BUS_SPACE_IO)
749 		for (; c != 0; c--, addr += 4)
750 			outl(addr, v);
751 	else
752 		for (; c != 0; c--, addr += 4)
753 			*(volatile uint32_t *)(addr) = v;
754 }
755 
756 static __inline void
ia64_bus_space_set_region_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t v,size_t c)757 ia64_bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h,
758     bus_size_t o, uint64_t v, size_t c)
759 {
760 	bus_addr_t addr = h + o;
761 
762 	if (t == IA64_BUS_SPACE_IO)
763 		printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);
764 	else
765 		for (; c != 0; c--, addr += 8)
766 			*(volatile uint32_t *)(addr) = v;
767 }
768 
769 
770 /*
771  *	void bus_space_copy_region_N(bus_space_tag_t tag,
772  *	    bus_space_handle_t bsh1, bus_size_t off1,
773  *	    bus_space_handle_t bsh2, bus_size_t off2,
774  *	    size_t count);
775  *
776  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
777  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
778  */
779 
780 static __inline void ia64_bus_space_copy_region_1(bus_space_tag_t,
781 	bus_space_handle_t, bus_size_t, bus_space_handle_t,
782 	bus_size_t, size_t);
783 static __inline void ia64_bus_space_copy_region_2(bus_space_tag_t,
784 	bus_space_handle_t, bus_size_t, bus_space_handle_t,
785 	bus_size_t, size_t);
786 static __inline void ia64_bus_space_copy_region_4(bus_space_tag_t,
787 	bus_space_handle_t, bus_size_t, bus_space_handle_t,
788 	bus_size_t, size_t);
789 
790 #define	bus_space_copy_region_1(t, h1, o1, h2, o2, c)			\
791 	ia64_bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
792 
793 #define	bus_space_copy_region_2(t, h1, o1, h2, o2, c)			\
794 do {									\
795 	__BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint16_t, "bus addr 1"); \
796 	__BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint16_t, "bus addr 2"); \
797 	ia64_bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c));	\
798 } while (/* CONSTCOND */ 0)
799 
800 #define	bus_space_copy_region_4(t, h1, o1, h2, o2, c)			\
801 do {									\
802 	__BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint32_t, "bus addr 1"); \
803 	__BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint32_t, "bus addr 2"); \
804 	ia64_bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c));	\
805 } while (/* CONSTCOND */ 0)
806 
807 #define	bus_space_copy_region_8(t, h1, o1, h2, o2, c)			\
808 do {									\
809 	__BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint64_t, "bus addr 1"); \
810 	__BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint64_t, "bus addr 2"); \
811 	ia64_bus_space_copy_region_8((t), (h1), (o1), (h2), (o2), (c));	\
812 } while (/* CONSTCOND */ 0)
813 
814 static __inline void
ia64_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,size_t c)815 ia64_bus_space_copy_region_1(bus_space_tag_t t,
816     bus_space_handle_t h1, bus_size_t o1,
817     bus_space_handle_t h2, bus_size_t o2, size_t c)
818 {
819 	bus_addr_t addr1 = h1 + o1;
820 	bus_addr_t addr2 = h2 + o2;
821 
822 	if (t == IA64_BUS_SPACE_IO) {
823 		if (addr1 >= addr2) {
824 			/* src after dest: copy forward */
825 			for (; c != 0; c--, addr1++, addr2++)
826 				outb(addr2, inb(addr1));
827 		} else {
828 			/* dest after src: copy backwards */
829 			for (addr1 += (c - 1), addr2 += (c - 1);
830 			    c != 0; c--, addr1--, addr2--)
831 				outb(addr2, inb(addr1));
832 		}
833 	} else {
834 		if (addr1 >= addr2) {
835 			/* src after dest: copy forward */
836 			for (; c != 0; c--, addr1++, addr2++)
837 				*(volatile uint8_t *)(addr2) =
838 				    *(volatile uint8_t *)(addr1);
839 		} else {
840 			/* dest after src: copy backwards */
841 			for (addr1 += (c - 1), addr2 += (c - 1);
842 			    c != 0; c--, addr1--, addr2--)
843 				*(volatile uint8_t *)(addr2) =
844 				    *(volatile uint8_t *)(addr1);
845 		}
846 	}
847 }
848 
849 static __inline void
ia64_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,size_t c)850 ia64_bus_space_copy_region_2(bus_space_tag_t t,
851     bus_space_handle_t h1, bus_size_t o1,
852     bus_space_handle_t h2, bus_size_t o2, size_t c)
853 {
854 	bus_addr_t addr1 = h1 + o1;
855 	bus_addr_t addr2 = h2 + o2;
856 
857 	if (t == IA64_BUS_SPACE_IO) {
858 		if (addr1 >= addr2) {
859 			/* src after dest: copy forward */
860 			for (; c != 0; c--, addr1 += 2, addr2 += 2)
861 				outw(addr2, inw(addr1));
862 		} else {
863 			/* dest after src: copy backwards */
864 			for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1);
865 			    c != 0; c--, addr1 -= 2, addr2 -= 2)
866 				outw(addr2, inw(addr1));
867 		}
868 	} else {
869 		if (addr1 >= addr2) {
870 			/* src after dest: copy forward */
871 			for (; c != 0; c--, addr1 += 2, addr2 += 2)
872 				*(volatile uint16_t *)(addr2) =
873 				    *(volatile uint16_t *)(addr1);
874 		} else {
875 			/* dest after src: copy backwards */
876 			for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1);
877 			    c != 0; c--, addr1 -= 2, addr2 -= 2)
878 				*(volatile uint16_t *)(addr2) =
879 				    *(volatile uint16_t *)(addr1);
880 		}
881 	}
882 }
883 
884 static __inline void
ia64_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,size_t c)885 ia64_bus_space_copy_region_4(bus_space_tag_t t,
886     bus_space_handle_t h1, bus_size_t o1,
887     bus_space_handle_t h2, bus_size_t o2, size_t c)
888 {
889 	bus_addr_t addr1 = h1 + o1;
890 	bus_addr_t addr2 = h2 + o2;
891 
892 	if (t == IA64_BUS_SPACE_IO) {
893 		if (addr1 >= addr2) {
894 			/* src after dest: copy forward */
895 			for (; c != 0; c--, addr1 += 4, addr2 += 4)
896 				outl(addr2, inl(addr1));
897 		} else {
898 			/* dest after src: copy backwards */
899 			for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1);
900 			    c != 0; c--, addr1 -= 4, addr2 -= 4)
901 				outl(addr2, inl(addr1));
902 		}
903 	} else {
904 		if (addr1 >= addr2) {
905 			/* src after dest: copy forward */
906 			for (; c != 0; c--, addr1 += 4, addr2 += 4)
907 				*(volatile uint32_t *)(addr2) =
908 				    *(volatile uint32_t *)(addr1);
909 		} else {
910 			/* dest after src: copy backwards */
911 			for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1);
912 			    c != 0; c--, addr1 -= 4, addr2 -= 4)
913 				*(volatile uint32_t *)(addr2) =
914 				    *(volatile uint32_t *)(addr1);
915 		}
916 	}
917 }
918 
919 static __inline void
ia64_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,size_t c)920 ia64_bus_space_copy_region_8(bus_space_tag_t t,
921     bus_space_handle_t h1, bus_size_t o1,
922     bus_space_handle_t h2, bus_size_t o2, size_t c)
923 {
924 	bus_addr_t addr1 = h1 + o1;
925 	bus_addr_t addr2 = h2 + o2;
926 
927 	if (t == IA64_BUS_SPACE_IO) {
928 		printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);
929 	} else {
930 		if (addr1 >= addr2) {
931 			/* src after dest: copy forward */
932 			for (; c != 0; c--, addr1 += 8, addr2 += 8)
933 				*(volatile uint64_t *)(addr2) =
934 				    *(volatile uint64_t *)(addr1);
935 		} else {
936 			/* dest after src: copy backwards */
937 			for (addr1 += 8 * (c - 1), addr2 += 8 * (c - 1);
938 			    c != 0; c--, addr1 -= 8, addr2 -= 8)
939 				*(volatile uint64_t *)(addr2) =
940 				    *(volatile uint64_t *)(addr1);
941 		}
942 	}
943 }
944 
945 
946 /*
947  * Bus read/write barrier methods.
948  *
949  *	void bus_space_barrier(bus_space_tag_t tag,
950  *	    bus_space_handle_t bsh, bus_size_t offset,
951  *	    bus_size_t len, int flags);
952  *
953  * Note: the x86 does not currently require barriers, but we must
954  * provide the flags to MI code.
955  */
956 #define	bus_space_barrier(t, h, o, l, f)	\
957 	ia64_bus_space_barrier((t), (h), (o), (l), (f))
958 
959 #define	BUS_SPACE_BARRIER_READ	0x01
960 #define	BUS_SPACE_BARRIER_WRITE	0x02
961 
962 static __inline void
ia64_bus_space_barrier(bus_space_tag_t t,bus_space_handle_t handle,bus_size_t offset,bus_size_t length,int flags)963 ia64_bus_space_barrier(bus_space_tag_t t, bus_space_handle_t handle,
964     bus_size_t offset, bus_size_t length, int flags)
965 {
966 	if (t == IA64_BUS_SPACE_IO)
967 		return;
968 
969 	switch (flags) {
970 	case BUS_SPACE_BARRIER_READ:
971 		__asm volatile("mf" ::: "memory");
972 		break;
973 	case BUS_SPACE_BARRIER_WRITE:
974 		__asm volatile("mf" ::: "memory");
975 		break;
976 	case BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE:
977 		__asm volatile("mf" ::: "memory");
978 		break;
979 	default:
980 		printf("%s: Unknown barrier %d\n", __FUNCTION__, flags);
981 		break;
982 	}
983 }
984 
985 
986 /*
987  * Flags used in various bus DMA methods.
988  */
989 #define	BUS_DMA_WAITOK		0x000	/* safe to sleep (pseudo-flag) */
990 #define	BUS_DMA_NOWAIT		0x001	/* not safe to sleep */
991 #define	BUS_DMA_ALLOCNOW	0x002	/* perform resource allocation now */
992 #define	BUS_DMA_COHERENT	0x004	/* hint: map memory DMA coherent */
993 #define	BUS_DMA_STREAMING	0x008	/* hint: sequential, unidirectional */
994 #define	BUS_DMA_BUS1		0x010	/* placeholders for bus functions... */
995 #define	BUS_DMA_BUS2		0x020
996 #define	BUS_DMA_BUS3		0x040
997 #define	BUS_DMA_BUS4		0x080
998 #define	BUS_DMA_READ		0x100	/* mapping is device -> memory only */
999 #define	BUS_DMA_WRITE		0x200	/* mapping is memory -> device only */
1000 #define	BUS_DMA_NOCACHE		0x400	/* hint: map non-cached memory */
1001 
1002 /* Forwards needed by prototypes below. */
1003 struct mbuf;
1004 struct uio;
1005 
1006 /*
1007  * Operations performed by bus_dmamap_sync().
1008  */
1009 #define	BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
1010 #define	BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
1011 #define	BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
1012 #define	BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
1013 
1014 typedef struct ia64_bus_dma_tag		*bus_dma_tag_t;
1015 typedef struct ia64_bus_dmamap		*bus_dmamap_t;
1016 
1017 #define BUS_DMA_TAG_VALID(t)    ((t) != (bus_dma_tag_t)0)
1018 
1019 /*
1020  *	bus_dma_segment_t
1021  *
1022  *	Describes a single contiguous DMA transaction.  Values
1023  *	are suitable for programming into DMA registers.
1024  */
1025 struct ia64_bus_dma_segment {
1026 	bus_addr_t	ds_addr;	/* DMA address */
1027 	bus_size_t	ds_len;		/* length of transfer */
1028 };
1029 typedef struct ia64_bus_dma_segment	bus_dma_segment_t;
1030 
1031 /*
1032  *	bus_dma_tag_t
1033  *
1034  *	A machine-dependent opaque type describing the implementation of
1035  *	DMA for a given bus.
1036  */
1037 
1038 struct ia64_bus_dma_tag {
1039 	/*
1040 	 * The `bounce threshold' is checked while we are loading
1041 	 * the DMA map.  If the physical address of the segment
1042 	 * exceeds the threshold, an error will be returned.  The
1043 	 * caller can then take whatever action is necessary to
1044 	 * bounce the transfer.  If this value is 0, it will be
1045 	 * ignored.
1046 	 */
1047 	bus_addr_t _bounce_thresh;
1048 	bus_addr_t _bounce_alloc_lo;
1049 	bus_addr_t _bounce_alloc_hi;
1050 	int	(*_may_bounce)(bus_dma_tag_t, bus_dmamap_t, int, int *);
1051 
1052 	/*
1053 	 * DMA mapping methods.
1054 	 */
1055 	int	(*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
1056 		    bus_size_t, bus_size_t, int, bus_dmamap_t *);
1057 	void	(*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
1058 	int	(*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
1059 		    bus_size_t, struct proc *, int);
1060 	int	(*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
1061 		    struct mbuf *, int);
1062 	int	(*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
1063 		    struct uio *, int);
1064 	int	(*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
1065 		    bus_dma_segment_t *, int, bus_size_t, int);
1066 	void	(*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
1067 	void	(*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
1068 		    bus_addr_t, bus_size_t, int);
1069 
1070 	/*
1071 	 * DMA memory utility functions.
1072 	 */
1073 	int	(*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
1074 		    bus_size_t, bus_dma_segment_t *, int, int *, int);
1075 	void	(*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int);
1076 	int	(*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
1077 		    int, size_t, void **, int);
1078 	void	(*_dmamem_unmap)(bus_dma_tag_t, void *, size_t);
1079 	paddr_t	(*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
1080 		    int, off_t, int, int);
1081 };
1082 
1083 static __inline void bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t,
1084     bus_addr_t, bus_size_t, int) __attribute__((__unused__));
1085 
1086 #define	bus_dmamap_create(t, s, n, m, b, f, p)			\
1087 	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
1088 #define	bus_dmamap_destroy(t, p)				\
1089 	(*(t)->_dmamap_destroy)((t), (p))
1090 #define	bus_dmamap_load(t, m, b, s, p, f)			\
1091 	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
1092 #define	bus_dmamap_load_mbuf(t, m, b, f)			\
1093 	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
1094 #define	bus_dmamap_load_uio(t, m, u, f)				\
1095 	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
1096 #define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
1097 	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
1098 #define	bus_dmamap_unload(t, p)					\
1099 	(*(t)->_dmamap_unload)((t), (p))
1100 static __inline void
bus_dmamap_sync(bus_dma_tag_t t,bus_dmamap_t p,bus_addr_t o,bus_size_t l,int ops)1101 bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t p, bus_addr_t o, bus_size_t l,
1102     int ops)
1103 {
1104 	/* if (ops & BUS_DMASYNC_POSTREAD)
1105 	   x86_lfence(); */
1106 	if (t->_dmamap_sync)
1107 		(*t->_dmamap_sync)(t, p, o, l, ops);
1108 }
1109 
1110 #define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
1111 	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
1112 #define	bus_dmamem_free(t, sg, n)				\
1113 	(*(t)->_dmamem_free)((t), (sg), (n))
1114 #define	bus_dmamem_map(t, sg, n, s, k, f)			\
1115 	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
1116 #define	bus_dmamem_unmap(t, k, s)				\
1117 	(*(t)->_dmamem_unmap)((t), (k), (s))
1118 #define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
1119 	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
1120 
1121 /*
1122  *	bus_dmamap_t
1123  *
1124  *	Describes a DMA mapping.
1125  */
1126 struct ia64_bus_dmamap {
1127 	/*
1128 	 * PRIVATE MEMBERS: not for use by machine-independent code.
1129 	 */
1130 	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
1131 	int		_dm_segcnt;	/* number of segs this map can map */
1132 	bus_size_t	_dm_maxmaxsegsz; /* fixed largest possible segment */
1133 	bus_size_t	_dm_boundary;	/* don't cross this */
1134 	bus_addr_t	_dm_bounce_thresh; /* bounce threshold; see tag */
1135 	int		_dm_flags;	/* misc. flags */
1136 
1137 	void		*_dm_cookie;	/* cookie for bus-specific functions */
1138 
1139 	/*
1140 	 * PUBLIC MEMBERS: these are used by machine-independent code.
1141 	 */
1142 	bus_size_t	dm_maxsegsz;	/* largest possible segment */
1143 	bus_size_t	dm_mapsize;	/* size of the mapping */
1144 	int		dm_nsegs;	/* # valid segments in mapping */
1145 	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
1146 };
1147 
1148 #endif /* _IA64_BUS_H_ */
1149