1/*	$NetBSD$	*/
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 */
124typedef u_long bus_addr_t;
125typedef u_long bus_size_t;
126
127/*
128 * Access methods for bus resources and address space.
129 */
130typedef	int bus_space_tag_t;
131typedef	u_long bus_space_handle_t;
132
133/* map/unmap */
134
135int	ia64_bus_space_map(bus_space_tag_t, bus_addr_t,
136	    bus_size_t, int, bus_space_handle_t *);
137void	ia64_bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
138	    bus_size_t);
139int	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
155paddr_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
162int	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 *);
165void	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)			\
215do {									\
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)			\
228do {									\
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)			\
243do {									\
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)			\
258do {									\
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)			\
290do {									\
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)			\
309do {									\
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)			\
330do {									\
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)			\
350do {									\
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)					\
380do {									\
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)					\
388do {									\
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)					\
397do {									\
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)			\
426do {									\
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)			\
439do {									\
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)			\
454do {									\
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)			\
469do {									\
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)			\
499do {									\
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)			\
519do {									\
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)			\
541do {									\
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)			\
563do {									\
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
592static __inline void ia64_bus_space_set_multi_1(bus_space_tag_t,
593	bus_space_handle_t, bus_size_t, uint8_t, size_t);
594static __inline void ia64_bus_space_set_multi_2(bus_space_tag_t,
595	bus_space_handle_t, bus_size_t, uint16_t, size_t);
596static __inline void ia64_bus_space_set_multi_4(bus_space_tag_t,
597	bus_space_handle_t, bus_size_t, uint32_t, size_t);
598static __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)				\
605do {									\
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)				\
611do {									\
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)				\
617do {									\
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
622static __inline void
623ia64_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
636static __inline void
637ia64_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
650static __inline void
651ia64_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
664static __inline void
665ia64_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
687static __inline void ia64_bus_space_set_region_1(bus_space_tag_t,
688	bus_space_handle_t, bus_size_t, uint8_t, size_t);
689static __inline void ia64_bus_space_set_region_2(bus_space_tag_t,
690	bus_space_handle_t, bus_size_t, uint16_t, size_t);
691static __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)				\
698do {									\
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)				\
704do {									\
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)				\
710do {									\
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
715static __inline void
716ia64_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
729static __inline void
730ia64_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
743static __inline void
744ia64_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
757static __inline void
758ia64_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
781static __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);
784static __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);
787static __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)			\
795do {									\
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)			\
802do {									\
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)			\
809do {									\
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
815static __inline void
816ia64_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
850static __inline void
851ia64_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
885static __inline void
886ia64_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
920static __inline void
921ia64_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
971static __inline void
972ia64_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. */
1012struct mbuf;
1013struct 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
1023typedef struct ia64_bus_dma_tag		*bus_dma_tag_t;
1024typedef 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 */
1034struct ia64_bus_dma_segment {
1035	bus_addr_t	ds_addr;	/* DMA address */
1036	bus_size_t	ds_len;		/* length of transfer */
1037};
1038typedef 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
1047struct 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
1092static __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))
1109static __inline void
1110bus_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 */
1135struct 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