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