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