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