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