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