Home | History | Annotate | Line # | Download | only in include
bus.h revision 1.8
      1 /*	$NetBSD: bus.h,v 1.8 2001/07/19 15:32:20 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 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  * bus_space(9) and bus_dma(9) interface for NetBSD/x68k.
     42  */
     43 
     44 #ifndef _X68K_BUS_H_
     45 #define _X68K_BUS_H_
     46 
     47 #ifndef X68K_BUS_PERFORMANCE_HACK
     48 #if defined(__GNUC__) && defined(__STDC__)
     49 #define X68K_BUS_PERFORMANCE_HACK	1
     50 #else
     51 #define X68K_BUS_PERFORMANCE_HACK	0
     52 #endif
     53 #endif
     54 
     55 /*
     56  * Bus address and size types
     57  */
     58 typedef u_long	bus_addr_t;
     59 typedef u_long	bus_size_t;
     60 typedef	u_long	bus_space_handle_t;
     61 
     62 /*
     63  * Bus space descripter
     64  */
     65 typedef struct x68k_bus_space *bus_space_tag_t;
     66 
     67 struct x68k_bus_space {
     68 #if 0
     69 	enum {
     70 		X68K_INTIO_BUS,
     71 		X68K_PCI_BUS,
     72 		X68K_NEPTUNE_BUS
     73 	}	x68k_bus_type;
     74 #endif
     75 
     76 	int	(*x68k_bus_space_map) __P((
     77 				bus_space_tag_t,
     78 				bus_addr_t,
     79 				bus_size_t,
     80 				int,			/* flags */
     81 				bus_space_handle_t *));
     82 	void	(*x68k_bus_space_unmap) __P((
     83 				bus_space_tag_t,
     84 				bus_space_handle_t,
     85 				bus_size_t));
     86 	int	(*x68k_bus_space_subregion) __P((
     87 				bus_space_tag_t,
     88 				bus_space_handle_t,
     89 				bus_size_t,		/* offset */
     90 				bus_size_t,		/* size */
     91 				bus_space_handle_t *));
     92 
     93 	int	(*x68k_bus_space_alloc) __P((
     94 				bus_space_tag_t,
     95 				bus_addr_t,		/* reg_start */
     96 				bus_addr_t,		/* reg_end */
     97 				bus_size_t,
     98 				bus_size_t,		/* alignment */
     99 				bus_size_t,		/* boundary */
    100 				int,			/* flags */
    101 				bus_addr_t *,
    102 				bus_space_handle_t *));
    103 	void	(*x68k_bus_space_free) __P((
    104 				bus_space_tag_t,
    105 				bus_space_handle_t,
    106 				bus_size_t));
    107 
    108 #if 0
    109 	void	(*x68k_bus_space_barrier) __P((
    110 				bus_space_tag_t,
    111 				bus_space_handle_t,
    112 				bus_size_t,		/* offset */
    113 				bus_size_t,		/* length */
    114 				int));			/* flags */
    115 #endif
    116 
    117 	struct device *x68k_bus_device;
    118 };
    119 
    120 int x68k_bus_space_alloc __P((bus_space_tag_t, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *));
    121 void x68k_bus_space_free __P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
    122 
    123 /*
    124  * bus_space(9) interface
    125  */
    126 
    127 #define bus_space_map(t,a,s,f,h) \
    128 		((*((t)->x68k_bus_space_map)) ((t),(a),(s),(f),(h)))
    129 #define bus_space_unmap(t,h,s) \
    130 		((*((t)->x68k_bus_space_unmap)) ((t),(h),(s)))
    131 #define bus_space_subregion(t,h,o,s,p) \
    132 		((*((t)->x68k_bus_space_subregion)) ((t),(h),(o),(s),(p)))
    133 #define BUS_SPACE_MAP_CACHEABLE		0x0001
    134 #define BUS_SPACE_MAP_LINEAR		0x0002
    135 #define BUS_SPACE_MAP_PREFETCHABLE	0x0004
    136 /*
    137  * For simpler hadware, many x68k devices are mapped with shifted address
    138  * i.e. only on even or odd addresses.
    139  */
    140 #define BUS_SPACE_MAP_SHIFTED	0x1001
    141 
    142 #define bus_space_alloc(t,rs,re,s,a,b,f,r,h) \
    143 		((*((t)->x68k_bus_space_alloc)) ((t),(rs),(re),(s),(a),(b),(f),(r),(h)))
    144 #define bus_space_free(t,h,s) \
    145 		((*((t)->x68k_bus_space_free)) ((t),(h),(s)))
    146 
    147 /*
    148  * Note: the 680x0 does not currently require barriers, but we must
    149  * provide the flags to MI code.
    150  */
    151 #define	bus_space_barrier(t, h, o, l, f)	\
    152 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
    153 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
    154 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
    155 
    156 #define bus_space_read_1(t,h,o) _bus_space_read_1(t,h,o)
    157 #define bus_space_read_2(t,h,o) _bus_space_read_2(t,h,o)
    158 #define bus_space_read_4(t,h,o) _bus_space_read_4(t,h,o)
    159 
    160 #define bus_space_read_multi_1(t,h,o,p,c) _bus_space_read_multi_1(t,h,o,p,c)
    161 #define bus_space_read_multi_2(t,h,o,p,c) _bus_space_read_multi_2(t,h,o,p,c)
    162 #define bus_space_read_multi_4(t,h,o,p,c) _bus_space_read_multi_4(t,h,o,p,c)
    163 
    164 #define bus_space_read_region_1(t,h,o,p,c) _bus_space_read_region_1(t,h,o,p,c)
    165 #define bus_space_read_region_2(t,h,o,p,c) _bus_space_read_region_2(t,h,o,p,c)
    166 #define bus_space_read_region_4(t,h,o,p,c) _bus_space_read_region_4(t,h,o,p,c)
    167 
    168 #define bus_space_write_1(t,h,o,v) _bus_space_write_1(t,h,o,v)
    169 #define bus_space_write_2(t,h,o,v) _bus_space_write_2(t,h,o,v)
    170 #define bus_space_write_4(t,h,o,v) _bus_space_write_4(t,h,o,v)
    171 
    172 #define bus_space_write_multi_1(t,h,o,p,c) _bus_space_write_multi_1(t,h,o,p,c)
    173 #define bus_space_write_multi_2(t,h,o,p,c) _bus_space_write_multi_2(t,h,o,p,c)
    174 #define bus_space_write_multi_4(t,h,o,p,c) _bus_space_write_multi_4(t,h,o,p,c)
    175 
    176 #define bus_space_write_region_1(t,h,o,p,c) \
    177 		_bus_space_write_region_1(t,h,o,p,c)
    178 #define bus_space_write_region_2(t,h,o,p,c) \
    179 		_bus_space_write_region_2(t,h,o,p,c)
    180 #define bus_space_write_region_4(t,h,o,p,c) \
    181 		_bus_space_write_region_4(t,h,o,p,c)
    182 
    183 #define bus_space_set_region_1(t,h,o,v,c) _bus_space_set_region_1(t,h,o,v,c)
    184 #define bus_space_set_region_2(t,h,o,v,c) _bus_space_set_region_2(t,h,o,v,c)
    185 #define bus_space_set_region_4(t,h,o,v,c) _bus_space_set_region_4(t,h,o,v,c)
    186 
    187 #define bus_space_copy_region_1(t,sh,so,dh,do,c) \
    188 		_bus_space_copy_region_1(t,sh,so,dh,do,c)
    189 #define bus_space_copy_region_2(t,sh,so,dh,do,c) \
    190 		_bus_space_copy_region_2(t,sh,so,dh,do,c)
    191 #define bus_space_copy_region_4(t,sh,so,dh,do,c) \
    192 		_bus_space_copy_region_4(t,sh,so,dh,do,c)
    193 
    194 static inline u_int8_t _bus_space_read_1
    195 	__P((bus_space_tag_t, bus_space_handle_t bsh, bus_size_t offset));
    196 static inline u_int16_t _bus_space_read_2
    197 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
    198 static inline u_int32_t _bus_space_read_4
    199 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
    200 
    201 static inline void _bus_space_read_multi_1
    202 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    203 	     u_int8_t *, bus_size_t));
    204 static inline void _bus_space_read_multi_2
    205 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    206 	     u_int16_t *, bus_size_t));
    207 static inline void _bus_space_read_multi_4
    208 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    209 	     u_int32_t *, bus_size_t));
    210 
    211 static inline void _bus_space_read_region_1
    212 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    213 	     u_int8_t *, bus_size_t));
    214 static inline void _bus_space_read_region_2
    215 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    216 	     u_int16_t *, bus_size_t));
    217 static inline void _bus_space_read_region_4
    218 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    219 	     u_int32_t *, bus_size_t));
    220 
    221 static inline void _bus_space_write_1
    222 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t));
    223 static inline void _bus_space_write_2
    224 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t));
    225 static inline void _bus_space_write_4
    226 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t));
    227 
    228 static inline void _bus_space_write_multi_1
    229 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    230 	     u_int8_t *, bus_size_t));
    231 static inline void _bus_space_write_multi_2
    232 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    233 	     u_int16_t *, bus_size_t));
    234 static inline void _bus_space_write_multi_4
    235 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    236 	     u_int32_t *, bus_size_t));
    237 
    238 static inline void _bus_space_write_region_1
    239 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    240 	     u_int8_t *, bus_size_t));
    241 static inline void _bus_space_write_region_2
    242 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    243 	     u_int16_t *, bus_size_t));
    244 static inline void _bus_space_write_region_4
    245 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    246 	     u_int32_t *, bus_size_t));
    247 
    248 static inline void _bus_space_set_region_1
    249 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    250 	     u_int8_t, bus_size_t));
    251 static inline void _bus_space_set_region_2
    252 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    253 	     u_int16_t, bus_size_t));
    254 static inline void _bus_space_set_region_4
    255 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    256 	     u_int32_t, bus_size_t));
    257 
    258 static inline void _bus_space_copy_region_1
    259 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    260 	     bus_space_handle_t, bus_size_t, bus_size_t));
    261 static inline void _bus_space_copy_region_2
    262 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    263 	     bus_space_handle_t, bus_size_t, bus_size_t));
    264 static inline void _bus_space_copy_region_4
    265 	__P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
    266 	     bus_space_handle_t, bus_size_t, bus_size_t));
    267 
    268 
    269 #define __X68K_BUS_ADDR(tag, handle, offset)	\
    270 	(((long)(handle) < 0 ? (offset) * 2 : (offset))	\
    271 		+ ((handle) & 0x7fffffff))
    272 
    273 static inline u_int8_t
    274 _bus_space_read_1(t, bsh, offset)
    275 	bus_space_tag_t t;
    276 	bus_space_handle_t bsh;
    277 	bus_size_t offset;
    278 {
    279 	return (*((volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset)));
    280 }
    281 
    282 static inline u_int16_t
    283 _bus_space_read_2(t, bsh, offset)
    284 	bus_space_tag_t t;
    285 	bus_space_handle_t bsh;
    286 	bus_size_t offset;
    287 {
    288 	return (*((volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset)));
    289 }
    290 
    291 static inline u_int32_t
    292 _bus_space_read_4(t, bsh, offset)
    293 	bus_space_tag_t t;
    294 	bus_space_handle_t bsh;
    295 	bus_size_t offset;
    296 {
    297 	return (*((volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset)));
    298 }
    299 
    300 static inline void
    301 _bus_space_read_multi_1(t, bsh, offset, datap, count)
    302 	bus_space_tag_t t;
    303 	bus_space_handle_t bsh;
    304 	bus_size_t offset;
    305 	u_int8_t *datap;
    306 	bus_size_t count;
    307 {
    308 #if X68K_BUS_PERFORMANCE_HACK
    309 	u_int8_t *regadr = (u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset);
    310 	for (; count; count--) {
    311 		__asm("| avoid optim. _bus_space_read_multi_1" : : : "memory");
    312 		*datap++ = *regadr;
    313 	}
    314 #else
    315 	while (count-- > 0) {
    316 		*datap++ = *(volatile u_int8_t *)
    317 				__X68K_BUS_ADDR(t, bsh, offset);
    318 	}
    319 #endif
    320 }
    321 
    322 static inline void
    323 _bus_space_read_multi_2(t, bsh, offset, datap, count)
    324 	bus_space_tag_t t;
    325 	bus_space_handle_t bsh;
    326 	bus_size_t offset;
    327 	u_int16_t *datap;
    328 	bus_size_t count;
    329 {
    330 #if X68K_BUS_PERFORMANCE_HACK
    331 	u_int16_t *regadr = (u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset);
    332 	for (; count; count--) {
    333 		__asm("| avoid optim. _bus_space_read_multi_2" : : : "memory");
    334 		*datap++ = *regadr;
    335 	}
    336 #else
    337 	while (count-- > 0) {
    338 		*datap++ = *(volatile u_int16_t *)
    339 				__X68K_BUS_ADDR(t, bsh, offset);
    340 	}
    341 #endif
    342 }
    343 
    344 static inline void
    345 _bus_space_read_multi_4(t, bsh, offset, datap, count)
    346 	bus_space_tag_t t;
    347 	bus_space_handle_t bsh;
    348 	bus_size_t offset;
    349 	u_int32_t *datap;
    350 	bus_size_t count;
    351 {
    352 #if X68K_BUS_PERFORMANCE_HACK
    353 	u_int32_t *regadr = (u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset);
    354 	for (; count; count--) {
    355 		__asm("| avoid optim. _bus_space_read_multi_4" : : : "memory");
    356 		*datap++ = *regadr;
    357 	}
    358 #else
    359 	while (count-- > 0) {
    360 		*datap++ = *(volatile u_int32_t *)
    361 				__X68K_BUS_ADDR(t, bsh, offset);
    362 	}
    363 #endif
    364 }
    365 
    366 static inline void
    367 _bus_space_read_region_1(t, bsh, offset, datap, count)
    368 	bus_space_tag_t t;
    369 	bus_space_handle_t bsh;
    370 	bus_size_t offset;
    371 	u_int8_t *datap;
    372 	bus_size_t count;
    373 {
    374 #if X68K_BUS_PERFORMANCE_HACK
    375 	u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    376 
    377 	for (; count; count--) {
    378 		__asm("| avoid optim. _bus_space_read_region_1" : : : "memory");
    379 		*datap++ = *addr++;
    380 	}
    381 #else
    382 	volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    383 
    384 	while (count-- > 0) {
    385 		*datap++ = *addr++;
    386 	}
    387 #endif
    388 }
    389 
    390 static inline void
    391 _bus_space_read_region_2(t, bsh, offset, datap, count)
    392 	bus_space_tag_t t;
    393 	bus_space_handle_t bsh;
    394 	bus_size_t offset;
    395 	u_int16_t *datap;
    396 	bus_size_t count;
    397 {
    398 #if X68K_BUS_PERFORMANCE_HACK
    399 	u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    400 
    401 	for (; count; count--) {
    402 		__asm("| avoid optim. _bus_space_read_region_2" : : : "memory");
    403 		*datap++ = *addr++;
    404 	}
    405 #else
    406 	volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    407 
    408 	while (count-- > 0) {
    409 		*datap++ = *addr++;
    410 	}
    411 #endif
    412 }
    413 
    414 static inline void
    415 _bus_space_read_region_4(t, bsh, offset, datap, count)
    416 	bus_space_tag_t t;
    417 	bus_space_handle_t bsh;
    418 	bus_size_t offset;
    419 	u_int32_t *datap;
    420 	bus_size_t count;
    421 {
    422 #if X68K_BUS_PERFORMANCE_HACK
    423 	u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    424 
    425 	for (; count; count--) {
    426 		__asm("| avoid optim. _bus_space_read_region_4" : : : "memory");
    427 		*datap++ = *addr++;
    428 	}
    429 #else
    430 	volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    431 
    432 	while (count-- > 0) {
    433 		*datap++ = *addr++;
    434 	}
    435 #endif
    436 }
    437 
    438 static inline void
    439 _bus_space_write_1(t, bsh, offset, value)
    440 	bus_space_tag_t t;
    441 	bus_space_handle_t bsh;
    442 	bus_size_t offset;
    443 	u_int8_t value;
    444 {
    445 	*(volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
    446 }
    447 
    448 static inline void
    449 _bus_space_write_2(t, bsh, offset, value)
    450 	bus_space_tag_t t;
    451 	bus_space_handle_t bsh;
    452 	bus_size_t offset;
    453 	u_int16_t value;
    454 {
    455 	*(volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
    456 }
    457 
    458 static inline void
    459 _bus_space_write_4(t, bsh, offset, value)
    460 	bus_space_tag_t t;
    461 	bus_space_handle_t bsh;
    462 	bus_size_t offset;
    463 	u_int32_t value;
    464 {
    465 	*(volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset) = value;
    466 }
    467 
    468 static inline void
    469 _bus_space_write_multi_1(t, bsh, offset, datap, count)
    470 	bus_space_tag_t t;
    471 	bus_space_handle_t bsh;
    472 	bus_size_t offset;
    473 	u_int8_t *datap;
    474 	bus_size_t count;
    475 {
    476 #if X68K_BUS_PERFORMANCE_HACK
    477 	u_int8_t *regadr = (u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset);
    478 	for (; count; count--) {
    479 		__asm("| avoid optim. _bus_space_write_multi_1" : : : "memory");
    480 		*regadr = *datap++;
    481 	}
    482 #else
    483 	while (count-- > 0) {
    484 		*(volatile u_int8_t *) __X68K_BUS_ADDR(t, bsh, offset)
    485 		    = *datap++;
    486 	}
    487 #endif
    488 }
    489 
    490 static inline void
    491 _bus_space_write_multi_2(t, bsh, offset, datap, count)
    492 	bus_space_tag_t t;
    493 	bus_space_handle_t bsh;
    494 	bus_size_t offset;
    495 	u_int16_t *datap;
    496 	bus_size_t count;
    497 {
    498 #if X68K_BUS_PERFORMANCE_HACK
    499 	u_int16_t *regadr = (u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset);
    500 	for (; count; count--) {
    501 		__asm("| avoid optim. _bus_space_write_multi_2" : : : "memory");
    502 		*regadr = *datap++;
    503 	}
    504 #else
    505 	while (count-- > 0) {
    506 		*(volatile u_int16_t *) __X68K_BUS_ADDR(t, bsh, offset)
    507 		    = *datap++;
    508 	}
    509 #endif
    510 }
    511 
    512 static inline void
    513 _bus_space_write_multi_4(t, bsh, offset, datap, count)
    514 	bus_space_tag_t t;
    515 	bus_space_handle_t bsh;
    516 	bus_size_t offset;
    517 	u_int32_t *datap;
    518 	bus_size_t count;
    519 {
    520 #if X68K_BUS_PERFORMANCE_HACK
    521 	u_int32_t *regadr = (u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset);
    522 	for (; count; count--) {
    523 		__asm("| avoid optim. _bus_space_write_multi_4" : : : "memory");
    524 		*regadr = *datap++;
    525 	}
    526 #else
    527 	while (count-- > 0) {
    528 		*(volatile u_int32_t *) __X68K_BUS_ADDR(t, bsh, offset)
    529 		    = *datap++;
    530 	}
    531 #endif
    532 }
    533 
    534 static inline void
    535 _bus_space_write_region_1(t, bsh, offset, datap, count)
    536 	bus_space_tag_t t;
    537 	bus_space_handle_t bsh;
    538 	bus_size_t offset;
    539 	u_int8_t *datap;
    540 	bus_size_t count;
    541 {
    542 #if X68K_BUS_PERFORMANCE_HACK
    543 	u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    544 
    545 	for (; count; count--) {
    546 		__asm("| avoid optim. _bus_space_write_region_1": : : "memory");
    547 		*addr++ = *datap++;
    548 	}
    549 #else
    550 	volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    551 
    552 	while (count-- > 0) {
    553 		*addr++ = *datap++;
    554 	}
    555 #endif
    556 }
    557 
    558 static inline void
    559 _bus_space_write_region_2(t, bsh, offset, datap, count)
    560 	bus_space_tag_t t;
    561 	bus_space_handle_t bsh;
    562 	bus_size_t offset;
    563 	u_int16_t *datap;
    564 	bus_size_t count;
    565 {
    566 #if X68K_BUS_PERFORMANCE_HACK
    567 	u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    568 
    569 	for (; count; count--) {
    570 		__asm("| avoid optim. _bus_space_write_region_2": : : "memory");
    571 		*addr++ = *datap++;
    572 	}
    573 #else
    574 	volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    575 
    576 	while (count-- > 0) {
    577 		*addr++ = *datap++;
    578 	}
    579 #endif
    580 }
    581 
    582 static inline void
    583 _bus_space_write_region_4(t, bsh, offset, datap, count)
    584 	bus_space_tag_t t;
    585 	bus_space_handle_t bsh;
    586 	bus_size_t offset;
    587 	u_int32_t *datap;
    588 	bus_size_t count;
    589 {
    590 #if X68K_BUS_PERFORMANCE_HACK
    591 	u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    592 
    593 	for (; count; count--) {
    594 		__asm("| avoid optim. _bus_space_write_region_4": : : "memory");
    595 		*addr++ = *datap++;
    596 	}
    597 #else
    598 	volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    599 
    600 	while (count-- > 0) {
    601 		*addr++ = *datap++;
    602 	}
    603 #endif
    604 }
    605 
    606 static inline void
    607 _bus_space_set_region_1(t, bsh, offset, value, count)
    608 	bus_space_tag_t t;
    609 	bus_space_handle_t bsh;
    610 	bus_size_t offset;
    611 	u_int8_t value;
    612 	bus_size_t count;
    613 {
    614 #if X68K_BUS_PERFORMANCE_HACK
    615 	u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    616 
    617 	for (; count; count--) {
    618 		__asm("| avoid optim. _bus_space_set_region_1" : : : "memory");
    619 		*addr++ = value;
    620 	}
    621 #else
    622 	volatile u_int8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    623 
    624 	while (count-- > 0) {
    625 		*addr++ = value;
    626 	}
    627 #endif
    628 }
    629 
    630 static inline void
    631 _bus_space_set_region_2(t, bsh, offset, value, count)
    632 	bus_space_tag_t t;
    633 	bus_space_handle_t bsh;
    634 	bus_size_t offset;
    635 	u_int16_t value;
    636 	bus_size_t count;
    637 {
    638 #if X68K_BUS_PERFORMANCE_HACK
    639 	u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    640 
    641 	for (; count; count--) {
    642 		__asm("| avoid optim. _bus_space_set_region_2" : : : "memory");
    643 		*addr++ = value;
    644 	}
    645 #else
    646 	volatile u_int16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    647 
    648 	while (count-- > 0) {
    649 		*addr++ = value;
    650 	}
    651 #endif
    652 }
    653 
    654 static inline void
    655 _bus_space_set_region_4(t, bsh, offset, value, count)
    656 	bus_space_tag_t t;
    657 	bus_space_handle_t bsh;
    658 	bus_size_t offset;
    659 	u_int32_t value;
    660 	bus_size_t count;
    661 {
    662 #if X68K_BUS_PERFORMANCE_HACK
    663 	u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    664 
    665 	for (; count; count--) {
    666 		__asm("| avoid optim. _bus_space_set_region_4" : : : "memory");
    667 		*addr++ = value;
    668 	}
    669 #else
    670 	volatile u_int32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset);
    671 
    672 	while (count-- > 0) {
    673 		*addr++ = value;
    674 	}
    675 #endif
    676 }
    677 
    678 static inline void
    679 _bus_space_copy_region_1(t, sbsh, soffset, dbsh, doffset, count)
    680 	bus_space_tag_t t;
    681 	bus_space_handle_t sbsh;
    682 	bus_size_t soffset;
    683 	bus_space_handle_t dbsh;
    684 	bus_size_t doffset;
    685 	bus_size_t count;
    686 {
    687 	volatile u_int8_t *saddr = (void *) (sbsh + soffset);
    688 	volatile u_int8_t *daddr = (void *) (dbsh + doffset);
    689 
    690 	if ((u_int32_t) saddr >= (u_int32_t) daddr)
    691 		while (count-- > 0)
    692 			*daddr++ = *saddr++;
    693 	else {
    694 		saddr += count;
    695 		daddr += count;
    696 		while (count-- > 0)
    697 			*--daddr = *--saddr;
    698 	}
    699 }
    700 
    701 static inline void
    702 _bus_space_copy_region_2(t, sbsh, soffset, dbsh, doffset, count)
    703 	bus_space_tag_t t;
    704 	bus_space_handle_t sbsh;
    705 	bus_size_t soffset;
    706 	bus_space_handle_t dbsh;
    707 	bus_size_t doffset;
    708 	bus_size_t count;
    709 {
    710 	volatile u_int16_t *saddr = (void *) (sbsh + soffset);
    711 	volatile u_int16_t *daddr = (void *) (dbsh + doffset);
    712 
    713 	if ((u_int32_t) saddr >= (u_int32_t) daddr)
    714 		while (count-- > 0)
    715 			*daddr++ = *saddr++;
    716 	else {
    717 		saddr += count;
    718 		daddr += count;
    719 		while (count-- > 0)
    720 			*--daddr = *--saddr;
    721 	}
    722 }
    723 
    724 static inline void
    725 _bus_space_copy_region_4(t, sbsh, soffset, dbsh, doffset, count)
    726 	bus_space_tag_t t;
    727 	bus_space_handle_t sbsh;
    728 	bus_size_t soffset;
    729 	bus_space_handle_t dbsh;
    730 	bus_size_t doffset;
    731 	bus_size_t count;
    732 {
    733 	volatile u_int32_t *saddr = (void *) (sbsh + soffset);
    734 	volatile u_int32_t *daddr = (void *) (dbsh + doffset);
    735 
    736 	if ((u_int32_t) saddr >= (u_int32_t) daddr)
    737 		while (count-- > 0)
    738 			*daddr++ = *saddr++;
    739 	else {
    740 		saddr += count;
    741 		daddr += count;
    742 		while (count-- > 0)
    743 			*--daddr = *--saddr;
    744 	}
    745 }
    746 
    747 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
    748 
    749 /*
    750  * DMA segment
    751  */
    752 struct x68k_bus_dma_segment {
    753 	bus_addr_t	ds_addr;
    754 	bus_size_t	ds_len;
    755 };
    756 typedef struct x68k_bus_dma_segment	bus_dma_segment_t;
    757 
    758 /*
    759  * DMA descriptor
    760  */
    761 /* Forwards needed by prototypes below. */
    762 struct mbuf;
    763 struct uio;
    764 
    765 typedef struct x68k_bus_dma		*bus_dma_tag_t;
    766 typedef struct x68k_bus_dmamap		*bus_dmamap_t;
    767 struct x68k_bus_dma {
    768 	/*
    769 	 * The `bounce threshold' is checked while we are loading
    770 	 * the DMA map.  If the physical address of the segment
    771 	 * exceeds the threshold, an error will be returned.  The
    772 	 * caller can then take whatever action is necessary to
    773 	 * bounce the transfer.  If this value is 0, it will be
    774 	 * ignored.
    775 	 */
    776 	bus_addr_t _bounce_thresh;
    777 
    778 	/*
    779 	 * DMA mapping methods.
    780 	 */
    781 	int	(*x68k_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int,
    782 		    bus_size_t, bus_size_t, int, bus_dmamap_t *));
    783 	void	(*x68k_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t));
    784 	int	(*x68k_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *,
    785 		    bus_size_t, struct proc *, int));
    786 	int	(*x68k_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t,
    787 		    struct mbuf *, int));
    788 	int	(*x68k_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t,
    789 		    struct uio *, int));
    790 	int	(*x68k_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t,
    791 		    bus_dma_segment_t *, int, bus_size_t, int));
    792 	void	(*x68k_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t));
    793 	void	(*x68k_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t,
    794 		    bus_addr_t, bus_size_t, int));
    795 
    796 	/*
    797 	 * DMA memory utility functions.
    798 	 */
    799 	int	(*x68k_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t,
    800 		    bus_size_t, bus_dma_segment_t *, int, int *, int));
    801 	void	(*x68k_dmamem_free) __P((bus_dma_tag_t,
    802 		    bus_dma_segment_t *, int));
    803 	int	(*x68k_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *,
    804 		    int, size_t, caddr_t *, int));
    805 	void	(*x68k_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t));
    806 	paddr_t	(*x68k_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *,
    807 		    int, off_t, int, int));
    808 };
    809 
    810 /*
    811  *	bus_dmamap_t
    812  *
    813  *	Describes a DMA mapping.
    814  */
    815 struct x68k_bus_dmamap {
    816 	/*
    817 	 * PRIVATE MEMBERS: not for use my machine-independent code.
    818 	 */
    819 	bus_size_t	x68k_dm_size;	/* largest DMA transfer mappable */
    820 	int		x68k_dm_segcnt;	/* number of segs this map can map */
    821 	bus_size_t	x68k_dm_maxsegsz; /* largest possible segment */
    822 	bus_size_t	x68k_dm_boundary; /* don't cross this */
    823 	bus_addr_t	x68k_dm_bounce_thresh; /* bounce threshold */
    824 	int		x68k_dm_flags;	/* misc. flags */
    825 
    826 	void		*x68k_dm_cookie; /* cookie for bus-specific functions */
    827 
    828 	/*
    829 	 * PUBLIC MEMBERS: these are used by machine-independent code.
    830 	 */
    831 	bus_size_t	dm_mapsize;	/* size of the mapping */
    832 	int		dm_nsegs;	/* # valid segments in mapping */
    833 	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
    834 };
    835 
    836 int	x68k_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t,
    837 	    bus_size_t, int, bus_dmamap_t *));
    838 void	x68k_bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
    839 int	x68k_bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
    840 	    bus_size_t, struct proc *, int));
    841 int	x68k_bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
    842 	    struct mbuf *, int));
    843 int	x68k_bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t,
    844 	    struct uio *, int));
    845 int	x68k_bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
    846 	    bus_dma_segment_t *, int, bus_size_t, int));
    847 void	x68k_bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
    848 void	x68k_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
    849 	    bus_size_t, int));
    850 
    851 int	x68k_bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size,
    852 	    bus_size_t alignment, bus_size_t boundary,
    853 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags));
    854 void	x68k_bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
    855 	    int nsegs));
    856 int	x68k_bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
    857 	    int nsegs, size_t size, caddr_t *kvap, int flags));
    858 void	x68k_bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva,
    859 	    size_t size));
    860 paddr_t	x68k_bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
    861 	    int nsegs, off_t off, int prot, int flags));
    862 
    863 int	x68k_bus_dmamap_load_buffer __P((bus_dmamap_t, void *,
    864 	    bus_size_t buflen, struct proc *, int, paddr_t *, int *, int));
    865 int	x68k_bus_dmamem_alloc_range __P((bus_dma_tag_t tag, bus_size_t size,
    866 	    bus_size_t alignment, bus_size_t boundary,
    867 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
    868 	    paddr_t low, paddr_t high));
    869 
    870 #define	bus_dmamap_create(t,s,n,m,b,f,p) \
    871 	((*((t)->x68k_dmamap_create)) ((t),(s),(n),(m),(b),(f),(p)))
    872 #define	bus_dmamap_destroy(t,p) \
    873 	((*((t)->x68k_dmamap_destroy)) ((t),(p)))
    874 #define	bus_dmamap_load(t,m,b,s,p,f) \
    875 	((*((t)->x68k_dmamap_load)) ((t),(m),(b),(s),(p),(f)))
    876 #define	bus_dmamap_load_mbuf(t,m,b,f) \
    877 	((*((t)->x68k_dmamap_load_mbuf)) ((t),(m),(b),(f)))
    878 #define	bus_dmamap_load_uio(t,m,u,f) \
    879 	((*((t)->x68k_dmamap_load_uio)) ((t),(m),(u),(f)))
    880 #define	bus_dmamap_load_raw(t,m,sg,n,s,f) \
    881 	((*((t)->x68k_dmamap_load_raw)) ((t),(m),(sg),(n),(s),(f)))
    882 #define	bus_dmamap_unload(t,p) \
    883 	((*((t)->x68k_dmamap_unload)) ((t),(p)))
    884 #define	bus_dmamap_sync(t,p,o,l,ops) \
    885 	((*((t)->x68k_dmamap_sync)) ((t),(p),(o),(l),(ops)))
    886 
    887 #define	bus_dmamem_alloc(t,s,a,b,sg,n,r,f) \
    888 	((*((t)->x68k_dmamem_alloc)) ((t),(s),(a),(b),(sg),(n),(r),(f)))
    889 #define	bus_dmamem_free(t,sg,n) \
    890 	((*((t)->x68k_dmamem_free)) ((t),(sg),(n)))
    891 #define	bus_dmamem_map(t,sg,n,s,k,f) \
    892 	((*((t)->x68k_dmamem_map)) ((t),(sg),(n),(s),(k),(f)))
    893 #define	bus_dmamem_unmap(t,k,s) \
    894 	((*((t)->x68k_dmamem_unmap)) ((t),(k),(s)))
    895 #define	bus_dmamem_mmap(t,sg,n,o,p,f) \
    896 	((*((t)->x68k_dmamem_mmap)) ((t),(sg),(n),(o),(p),(f)))
    897 
    898 /*
    899  * Flags used in various bus DMA methods.
    900  */
    901 #define	BUS_DMA_WAITOK		0x000	/* safe to sleep (pseudo-flag) */
    902 #define	BUS_DMA_NOWAIT		0x001	/* not safe to sleep */
    903 #define	BUS_DMA_ALLOCNOW	0x002	/* perform resource allocation now */
    904 #define	BUS_DMA_COHERENT	0x004	/* hint: map memory DMA coherent */
    905 #define	BUS_DMA_STREAMING	0x008	/* hint: sequential, unidirectional */
    906 #define	BUS_DMA_BUS1		0x010	/* placeholders for bus functions... */
    907 #define	BUS_DMA_BUS2		0x020
    908 #define	BUS_DMA_BUS3		0x040
    909 #define	BUS_DMA_BUS4		0x080
    910 #define	BUS_DMA_READ		0x100	/* mapping is device -> memory only */
    911 #define	BUS_DMA_WRITE		0x200	/* mapping is memory -> device only */
    912 
    913 /*
    914  * Operations performed by bus_dmamap_sync().
    915  */
    916 #define	BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
    917 #define	BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
    918 #define	BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
    919 #define	BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
    920 
    921 #endif /* _X68K_BUS_H_ */
    922