Home | History | Annotate | Line # | Download | only in include
bus.h revision 1.7
      1 /*	$NetBSD: bus.h,v 1.7 2003/08/01 00:23:18 tsutsui Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the NetBSD
     22  *	Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 /*
     41  * Copyright (C) 1997 Scott Reynolds.  All rights reserved.
     42  *
     43  * Redistribution and use in source and binary forms, with or without
     44  * modification, are permitted provided that the following conditions
     45  * are met:
     46  * 1. Redistributions of source code must retain the above copyright
     47  *    notice, this list of conditions and the following disclaimer.
     48  * 2. Redistributions in binary form must reproduce the above copyright
     49  *    notice, this list of conditions and the following disclaimer in the
     50  *    documentation and/or other materials provided with the distribution.
     51  * 3. The name of the author may not be used to endorse or promote products
     52  *    derived from this software without specific prior written permission
     53  *
     54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     64  */
     65 
     66 #ifndef _HP300_BUS_H_
     67 #define _HP300_BUS_H_
     68 
     69 /*
     70  * Values for the hp300 bus space tag, not to be used directly by MI code.
     71  */
     72 #define	HP300_BUS_SPACE_INTIO	0	/* space is intio space */
     73 #define	HP300_BUS_SPACE_DIO	1	/* space is dio space */
     74 
     75 /*
     76  * Bus address and size types
     77  */
     78 typedef u_long bus_addr_t;
     79 typedef u_long bus_size_t;
     80 
     81 /*
     82  * Access methods for bus resources and address space.
     83  */
     84 typedef struct bus_space_tag *bus_space_tag_t;
     85 typedef u_long bus_space_handle_t;
     86 
     87 /*
     88  * Implementation specific structures.
     89  * XXX Don't use outside of bus_space definitions!
     90  * XXX maybe this should be encapsuled in a non-global .h file?
     91  */
     92 
     93 struct bus_space_tag {
     94 	u_int		bustype;
     95 
     96 	u_int8_t	(*bsr1) __P((bus_space_tag_t, bus_space_handle_t,
     97 			    bus_size_t));
     98 	u_int16_t	(*bsr2) __P((bus_space_tag_t, bus_space_handle_t,
     99 			    bus_size_t));
    100 	u_int32_t	(*bsr4) __P((bus_space_tag_t, bus_space_handle_t,
    101 			    bus_size_t));
    102 	void		(*bsrm1) __P((bus_space_tag_t, bus_space_handle_t,
    103 			    bus_size_t, u_int8_t *, bus_size_t));
    104 	void		(*bsrm2) __P((bus_space_tag_t, bus_space_handle_t,
    105 			    bus_size_t, u_int16_t *, bus_size_t));
    106 	void		(*bsrm4) __P((bus_space_tag_t, bus_space_handle_t,
    107 			    bus_size_t, u_int32_t *, bus_size_t));
    108 	void		(*bsrr1) __P((bus_space_tag_t, bus_space_handle_t,
    109 			    bus_size_t, u_int8_t *, bus_size_t));
    110 	void		(*bsrr2) __P((bus_space_tag_t, bus_space_handle_t,
    111 			    bus_size_t, u_int16_t *, bus_size_t));
    112 	void		(*bsrr4) __P((bus_space_tag_t, bus_space_handle_t,
    113 			    bus_size_t, u_int32_t *, bus_size_t));
    114 	void		(*bsw1) __P((bus_space_tag_t, bus_space_handle_t,
    115 			    bus_size_t, u_int8_t));
    116 	void		(*bsw2) __P((bus_space_tag_t, bus_space_handle_t,
    117 			    bus_size_t, u_int16_t));
    118 	void		(*bsw4) __P((bus_space_tag_t, bus_space_handle_t,
    119 			    bus_size_t, u_int32_t));
    120 	void		(*bswm1) __P((bus_space_tag_t, bus_space_handle_t,
    121 			    bus_size_t, const u_int8_t *, bus_size_t));
    122 	void		(*bswm2) __P((bus_space_tag_t, bus_space_handle_t,
    123 			    bus_size_t, const u_int16_t *, bus_size_t));
    124 	void		(*bswm4) __P((bus_space_tag_t, bus_space_handle_t,
    125 			    bus_size_t, const u_int32_t *, bus_size_t));
    126 	void		(*bswr1) __P((bus_space_tag_t, bus_space_handle_t ,
    127 			    bus_size_t, const u_int8_t *, bus_size_t));
    128 	void		(*bswr2) __P((bus_space_tag_t, bus_space_handle_t,
    129 			    bus_size_t, const u_int16_t *, bus_size_t));
    130 	void		(*bswr4) __P((bus_space_tag_t, bus_space_handle_t,
    131 			    bus_size_t, const u_int32_t *, bus_size_t));
    132 	void		(*bssm1) __P((bus_space_tag_t, bus_space_handle_t,
    133 			    bus_size_t, u_int8_t, bus_size_t));
    134 	void		(*bssm2) __P((bus_space_tag_t, bus_space_handle_t,
    135 			    bus_size_t, u_int16_t, bus_size_t));
    136 	void		(*bssm4) __P((bus_space_tag_t, bus_space_handle_t,
    137 			    bus_size_t, u_int32_t, bus_size_t));
    138 	void		(*bssr1) __P((bus_space_tag_t, bus_space_handle_t,
    139 			    bus_size_t, u_int8_t, bus_size_t));
    140 	void		(*bssr2) __P((bus_space_tag_t, bus_space_handle_t,
    141 			    bus_size_t, u_int16_t, bus_size_t));
    142 	void		(*bssr4) __P((bus_space_tag_t, bus_space_handle_t,
    143 			    bus_size_t, u_int32_t, bus_size_t));
    144 };
    145 
    146 /*
    147  *	int bus_space_map __P((bus_space_tag_t t, bus_addr_t addr,
    148  *	    bus_size_t size, int flags, bus_space_handle_t *bshp));
    149  *
    150  * Map a region of bus space.
    151  */
    152 
    153 #define	BUS_SPACE_MAP_CACHEABLE		0x01
    154 #define	BUS_SPACE_MAP_LINEAR		0x02
    155 #define	BUS_SPACE_MAP_PREFETCHABLE	0x04
    156 
    157 int	bus_space_map __P((bus_space_tag_t, bus_addr_t, bus_size_t,
    158 	    int, bus_space_handle_t *));
    159 
    160 /*
    161  *	void bus_space_unmap __P((bus_space_tag_t t,
    162  *	    bus_space_handle_t bsh, bus_size_t size));
    163  *
    164  * Unmap a region of bus space.
    165  */
    166 
    167 void	bus_space_unmap __P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
    168 
    169 /*
    170  *	int bus_space_subregion __P((bus_space_tag_t t,
    171  *	    bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
    172  *	    bus_space_handle_t *nbshp));
    173  *
    174  * Get a new handle for a subregion of an already-mapped area of bus space.
    175  */
    176 
    177 int	bus_space_subregion __P((bus_space_tag_t t, bus_space_handle_t bsh,
    178 	    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp));
    179 
    180 /*
    181  *	int bus_space_alloc __P((bus_space_tag_t t, bus_addr_t, rstart,
    182  *	    bus_addr_t rend, bus_size_t size, bus_size_t align,
    183  *	    bus_size_t boundary, int flags, bus_addr_t *addrp,
    184  *	    bus_space_handle_t *bshp));
    185  *
    186  * Allocate a region of bus space.
    187  */
    188 
    189 int	bus_space_alloc __P((bus_space_tag_t t, bus_addr_t rstart,
    190 	    bus_addr_t rend, bus_size_t size, bus_size_t align,
    191 	    bus_size_t boundary, int cacheable, bus_addr_t *addrp,
    192 	    bus_space_handle_t *bshp));
    193 
    194 /*
    195  *	int bus_space_free __P((bus_space_tag_t t,
    196  *	    bus_space_handle_t bsh, bus_size_t size));
    197  *
    198  * Free a region of bus space.
    199  */
    200 
    201 void	bus_space_free __P((bus_space_tag_t t, bus_space_handle_t bsh,
    202 	    bus_size_t size));
    203 
    204 /*
    205  *	void *bus_space_vaddr __P((bus_space_tag_t, bus_space_handle_t));
    206  *
    207  * Get the kernel virtual address for the mapped bus space.
    208  * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
    209  *  (XXX not enforced)
    210  */
    211 #define bus_space_vaddr(t, h)	(void *)(h)
    212 
    213 /*
    214  *	int hp300_bus_space_probe __P((bus_space_tag_t t,
    215  *	    bus_space_handle_t bsh, bus_size_t offset, int sz));
    216  *
    217  * Probe the bus at t/bsh/offset, using sz as the size of the load.
    218  *
    219  * This is a machine-dependent extension, and is not to be used by
    220  * machine-independent code.
    221  */
    222 
    223 int	hp300_bus_space_probe __P((bus_space_tag_t t,
    224 	    bus_space_handle_t bsh, bus_size_t offset, int sz));
    225 
    226 /*
    227  *	u_intN_t bus_space_read_N __P((bus_space_tag_t tag,
    228  *	    bus_space_handle_t bsh, bus_size_t offset));
    229  *
    230  * Read a 1, 2, 4, or 8 byte quantity from bus space
    231  * described by tag/handle/offset.
    232  */
    233 
    234 #define	bus_space_read_1(t, h, o)					\
    235     (((t)->bsr1 != NULL) ? ((t)->bsr1)(t, h, o) :			\
    236     (*(volatile u_int8_t *)((h) + (o))))
    237 
    238 #define	bus_space_read_2(t, h, o)					\
    239     (((t)->bsr2 != NULL) ? ((t)->bsr2)(t, h, o) :			\
    240     (*(volatile u_int16_t *)((h) + (o))))
    241 
    242 #define	bus_space_read_4(t, h, o)					\
    243     (((t)->bsr4 != NULL) ? ((t)->bsr4)(t, h, o) :			\
    244     (*(volatile u_int32_t *)((h) + (o))))
    245 
    246 #if 0	/* Cause a link error for bus_space_read_8 */
    247 #define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
    248 #endif
    249 
    250 /*
    251  *	void bus_space_read_multi_N __P((bus_space_tag_t tag,
    252  *	    bus_space_handle_t bsh, bus_size_t offset,
    253  *	    u_intN_t *addr, size_t count));
    254  *
    255  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
    256  * described by tag/handle/offset and copy into buffer provided.
    257  */
    258 
    259 #define	bus_space_read_multi_1(t, h, o, a, c)				\
    260 do {									\
    261 	if ((t)->bsrm1 != NULL)						\
    262 		((t)->bsrm1)(t, h, o, a, c);				\
    263 	else {								\
    264 		__asm __volatile ("					\
    265 			movl	%0,%%a0				;	\
    266 			movl	%1,%%a1				;	\
    267 			movl	%2,%%d0				;	\
    268 		1:	movb	%%a0@,%%a1@+			;	\
    269 			subql	#1,%%d0				;	\
    270 			jne	1b"				:	\
    271 								:	\
    272 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    273 			    "%a0","%a1","%d0");				\
    274 	}								\
    275 } while (/* CONSTCOND */ 0)
    276 
    277 #define	bus_space_read_multi_2(t, h, o, a, c)				\
    278 do {									\
    279 	if ((t)->bsrm2 != NULL)						\
    280 		((t)->bsrm2)(t, h, o, a, c);				\
    281 	else {								\
    282 		__asm __volatile ("					\
    283 			movl	%0,%%a0				;	\
    284 			movl	%1,%%a1				;	\
    285 			movl	%2,%%d0				;	\
    286 		1:	movw	%%a0@,%%a1@+			;	\
    287 			subql	#1,%%d0				;	\
    288 			jne	1b"				:	\
    289 								:	\
    290 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    291 			    "%a0","%a1","%d0");				\
    292 	}								\
    293 } while (/* CONSTCOND */ 0)
    294 
    295 #define	bus_space_read_multi_4(t, h, o, a, c) do {			\
    296 	if ((t)->bsrm4 != NULL)						\
    297 		((t)->bsrm4)(t, h, o, a, c);				\
    298 	else {								\
    299 		__asm __volatile ("					\
    300 			movl	%0,%%a0				;	\
    301 			movl	%1,%%a1				;	\
    302 			movl	%2,%%d0				;	\
    303 		1:	movl	%%a0@,%%a1@+			;	\
    304 			subql	#1,%%d0				;	\
    305 			jne	1b"				:	\
    306 								:	\
    307 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    308 			    "%a0","%a1","%d0");				\
    309 	}								\
    310 } while (/* CONSTCOND */ 0)
    311 
    312 #if 0	/* Cause a link error for bus_space_read_multi_8 */
    313 #define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
    314 #endif
    315 
    316 /*
    317  *	void bus_space_read_region_N __P((bus_space_tag_t tag,
    318  *	    bus_space_handle_t bsh, bus_size_t offset,
    319  *	    u_intN_t *addr, size_t count));
    320  *
    321  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
    322  * described by tag/handle and starting at `offset' and copy into
    323  * buffer provided.
    324  */
    325 
    326 #define	bus_space_read_region_1(t, h, o, a, c)				\
    327 do {									\
    328 	if ((t)->bsrr1 != NULL)						\
    329 		((t)->bsrr1)(t, h, o, a, c);				\
    330 	else {								\
    331 		__asm __volatile ("					\
    332 			movl	%0,%%a0				;	\
    333 			movl	%1,%%a1				;	\
    334 			movl	%2,%%d0				;	\
    335 		1:	movb	%%a0@+,%%a1@+			;	\
    336 			subql	#1,%%d0				;	\
    337 			jne	1b"				:	\
    338 								:	\
    339 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    340 			    "%a0","%a1","%d0");				\
    341 	}								\
    342 } while (/* CONSTCOND */ 0)
    343 
    344 #define	bus_space_read_region_2(t, h, o, a, c)				\
    345 do {									\
    346 	if ((t)->bsrr2 != NULL)						\
    347 		((t)->bsrr2)(t, h, o, a, c);				\
    348 	else {								\
    349 		__asm __volatile ("					\
    350 			movl	%0,%%a0				;	\
    351 			movl	%1,%%a1				;	\
    352 			movl	%2,%%d0				;	\
    353 		1:	movw	%%a0@+,%%a1@+			;	\
    354 			subql	#1,%%d0				;	\
    355 			jne	1b"				:	\
    356 								:	\
    357 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    358 			    "%a0","%a1","%d0");				\
    359 	}								\
    360 } while (/* CONSTCOND */ 0)
    361 
    362 #define	bus_space_read_region_4(t, h, o, a, c)				\
    363 do {									\
    364 	if ((t)->bsrr4 != NULL)						\
    365 		((t)->bsrr4)(t, h, o, a, c);				\
    366 	else {								\
    367 		__asm __volatile ("					\
    368 			movl	%0,%%a0				;	\
    369 			movl	%1,%%a1				;	\
    370 			movl	%2,%%d0				;	\
    371 		1:	movl	%%a0@+,%%a1@+			;	\
    372 			subql	#1,%%d0				;	\
    373 			jne	1b"				:	\
    374 								:	\
    375 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    376 			    "%a0","%a1","%d0");				\
    377 	}								\
    378 } while (/* CONSTCOND */ 0)
    379 
    380 #if 0	/* Cause a link error for bus_space_read_region_8 */
    381 #define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
    382 #endif
    383 
    384 /*
    385  *	void bus_space_write_N __P((bus_space_tag_t tag,
    386  *	    bus_space_handle_t bsh, bus_size_t offset,
    387  *	    u_intN_t value));
    388  *
    389  * Write the 1, 2, 4, or 8 byte value `value' to bus space
    390  * described by tag/handle/offset.
    391  */
    392 
    393 #define	bus_space_write_1(t, h, o, v)					\
    394 do {									\
    395 	if ((t)->bsw1 != NULL)						\
    396 		((t)->bsw1)(t, h, o, v);				\
    397 	else								\
    398 		((void)(*(volatile u_int8_t *)((h) + (o)) = (v)));	\
    399 } while (/* CONSTCOND */ 0)
    400 
    401 #define	bus_space_write_2(t, h, o, v)					\
    402 do {									\
    403 	if ((t)->bsw2 != NULL)						\
    404 		((t)->bsw2)(t, h, o, v);				\
    405 	else								\
    406 		((void)(*(volatile u_int16_t *)((h) + (o)) = (v)));	\
    407 } while (/* CONSTCOND */ 0)
    408 
    409 #define	bus_space_write_4(t, h, o, v)					\
    410 do {									\
    411 	if ((t)->bsw4 != NULL)						\
    412 		((t)->bsw4)(t, h, o, v);				\
    413 	else								\
    414 		((void)(*(volatile u_int32_t *)((h) + (o)) = (v)));	\
    415 } while (/* CONSTCOND */ 0)
    416 
    417 #if 0	/* Cause a link error for bus_space_write_8 */
    418 #define	bus_space_write_8	!!! bus_space_write_8 not implemented !!!
    419 #endif
    420 
    421 /*
    422  *	void bus_space_write_multi_N __P((bus_space_tag_t tag,
    423  *	    bus_space_handle_t bsh, bus_size_t offset,
    424  *	    const u_intN_t *addr, size_t count));
    425  *
    426  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
    427  * provided to bus space described by tag/handle/offset.
    428  */
    429 
    430 #define	bus_space_write_multi_1(t, h, o, a, c)				\
    431 do {									\
    432 	if ((t)->bswm1 != NULL)						\
    433 		((t)->bswm1)(t, h, o, a, c);				\
    434 	else {								\
    435 		__asm __volatile ("					\
    436 			movl	%0,%%a0				;	\
    437 			movl	%1,%%a1				;	\
    438 			movl	%2,%%d0				;	\
    439 		1:	movb	%%a1@+,%%a0@			;	\
    440 			subql	#1,%%d0				;	\
    441 			jne	1b"				:	\
    442 								:	\
    443 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    444 			    "%a0","%a1","%d0");				\
    445 	}								\
    446 } while (/* CONSTCOND */ 0)
    447 
    448 #define	bus_space_write_multi_2(t, h, o, a, c)				\
    449 do {									\
    450 	if ((t)->bswm2 != NULL)						\
    451 		((t)->bswm2)(t, h, o, a, c);				\
    452 	else {								\
    453 		__asm __volatile ("					\
    454 			movl	%0,%%a0				;	\
    455 			movl	%1,%%a1				;	\
    456 			movl	%2,%%d0				;	\
    457 		1:	movw	%%a1@+,%%a0@			;	\
    458 			subql	#1,%%d0				;	\
    459 			jne	1b"				:	\
    460 								:	\
    461 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    462 			    "%a0","%a1","%d0");				\
    463 	}								\
    464 } while (/* CONSTCOND */ 0)
    465 
    466 #define	bus_space_write_multi_4(t, h, o, a, c)				\
    467 do {									\
    468 	(void) t;							\
    469 	if ((t)->bswm4 != NULL)					\
    470 		((t)->bswm4)(t, h, o, a, c);				\
    471 	else {								\
    472 		__asm __volatile ("					\
    473 			movl	%0,%%a0				;	\
    474 			movl	%1,%%a1				;	\
    475 			movl	%2,%%d0				;	\
    476 		1:	movl	%%a1@+,%%a0@			;	\
    477 			subql	#1,%%d0				;	\
    478 			jne	1b"				:	\
    479 								:	\
    480 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    481 			    "%a0","%a1","%d0");				\
    482 	}								\
    483 } while (/* CONSTCOND */ 0)
    484 
    485 #if 0	/* Cause a link error for bus_space_write_8 */
    486 #define	bus_space_write_multi_8(t, h, o, a, c)				\
    487 			!!! bus_space_write_multi_8 unimplimented !!!
    488 #endif
    489 
    490 /*
    491  *	void bus_space_write_region_N __P((bus_space_tag_t tag,
    492  *	    bus_space_handle_t bsh, bus_size_t offset,
    493  *	    const u_intN_t *addr, size_t count));
    494  *
    495  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
    496  * to bus space described by tag/handle starting at `offset'.
    497  */
    498 
    499 #define	bus_space_write_region_1(t, h, o, a, c)				\
    500 do {									\
    501 	if ((t)->bswr1 != NULL)					\
    502 		((t)->bswr1)(t, h, o, a, c);				\
    503 	else {								\
    504 		__asm __volatile ("					\
    505 			movl	%0,%%a0				;	\
    506 			movl	%1,%%a1				;	\
    507 			movl	%2,%%d0				;	\
    508 		1:	movb	%%a1@+,%%a0@+			;	\
    509 			subql	#1,%%d0				;	\
    510 			jne	1b"				:	\
    511 								:	\
    512 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    513 			    "%a0","%a1","%d0");				\
    514 	}								\
    515 } while (/* CONSTCOND */ 0)
    516 
    517 #define	bus_space_write_region_2(t, h, o, a, c)				\
    518 do {									\
    519 	if ((t)->bswr2) != NULL)					\
    520 		((t)->bswr2)(t, h, o, a, c);				\
    521 	else {								\
    522 		__asm __volatile ("					\
    523 			movl	%0,%%a0				;	\
    524 			movl	%1,%%a1				;	\
    525 			movl	%2,%%d0				;	\
    526 		1:	movw	%%a1@+,%%a0@+			;	\
    527 			subql	#1,%%d0				;	\
    528 			jne	1b"				:	\
    529 								:	\
    530 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    531 			    "%a0","%a1","%d0");				\
    532 	}								\
    533 } while (/* CONSTCOND */ 0)
    534 
    535 #define	bus_space_write_region_4(t, h, o, a, c)				\
    536 do {									\
    537 	if ((t)->bswr4) != NULL)					\
    538 		((t)->bswr4)(t, h, o, a, c);				\
    539 	else {								\
    540 		__asm __volatile ("					\
    541 			movl	%0,%%a0				;	\
    542 			movl	%1,%%a1				;	\
    543 			movl	%2,%%d0				;	\
    544 		1:	movl	%%a1@+,%%a0@+			;	\
    545 			subql	#1,%%d0				;	\
    546 			jne	1b"				:	\
    547 								:	\
    548 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    549 			    "%a0","%a1","%d0");				\
    550 	}								\
    551 } while (/* CONSTCOND */ 0)
    552 
    553 #if 0	/* Cause a link error for bus_space_write_region_8 */
    554 #define	bus_space_write_region_8					\
    555 			!!! bus_space_write_region_8 unimplemented !!!
    556 #endif
    557 
    558 /*
    559  *	void bus_space_set_multi_N __P((bus_space_tag_t tag,
    560  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
    561  *	    size_t count));
    562  *
    563  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
    564  * by tag/handle/offset `count' times.
    565  */
    566 
    567 #define	bus_space_set_multi_1(t, h, o, val, c)				\
    568 do {									\
    569 	if ((t)->bssm1 != NULL)						\
    570 		((t)->bssm1)(t, h, o, val, c);				\
    571 	else {								\
    572 		__asm __volatile ("					\
    573 			movl	%0,%%a0				;	\
    574 			movl	%1,%%d1				;	\
    575 			movl	%2,%%d0				;	\
    576 		1:	movb	%%d1,%%a0@			;	\
    577 			subql	#1,%%d0				;	\
    578 			jne	1b"				:	\
    579 								:	\
    580 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    581 			    "%a0","%d0","%d1");				\
    582 	}								\
    583 } while (/* CONSTCOND */ 0)
    584 
    585 #define	bus_space_set_multi_2(t, h, o, val, c)				\
    586 do {									\
    587 	if ((t)->bssm2 != NULL)						\
    588 		((t)->bssm2)(t, h, o, val, c);				\
    589 	else {								\
    590 		__asm __volatile ("					\
    591 			movl	%0,%%a0				;	\
    592 			movl	%1,%%d1				;	\
    593 			movl	%2,%%d0				;	\
    594 		1:	movw	%%d1,%%a0@			;	\
    595 			subql	#1,%%d0				;	\
    596 			jne	1b"				:	\
    597 								:	\
    598 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    599 			    "%a0","%d0","%d1");				\
    600 	}								\
    601 } while (/* CONSTCOND */ 0)
    602 
    603 #define	bus_space_set_multi_4(t, h, o, val, c)				\
    604 do {									\
    605 	if ((t)->bssm4 != NULL)						\
    606 		((t)->bssm4)(t, h, o, val, c);				\
    607 	else {								\
    608 		__asm __volatile ("					\
    609 			movl	%0,%%a0				;	\
    610 			movl	%1,%%d1				;	\
    611 			movl	%2,%%d0				;	\
    612 		1:	movl	%%d1,%%a0@			;	\
    613 			subql	#1,%%d0				;	\
    614 			jne	1b"				:	\
    615 								:	\
    616 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    617 			    "%a0","%d0","%d1");				\
    618 	}								\
    619 } while (/* CONSTCOND */ 0)
    620 
    621 #if 0	/* Cause a link error for bus_space_set_multi_8 */
    622 #define	bus_space_set_multi_8						\
    623 			!!! bus_space_set_multi_8 unimplemented !!!
    624 #endif
    625 
    626 /*
    627  *	void bus_space_set_region_N __P((bus_space_tag_t tag,
    628  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
    629  *	    size_t count));
    630  *
    631  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
    632  * by tag/handle starting at `offset'.
    633  */
    634 
    635 #define	bus_space_set_region_1(t, h, o, val, c)				\
    636 do {									\
    637 	if ((t)->bssr1 != NULL)						\
    638 		((t)->bssr1)(t, h, o, val, c);				\
    639 	else {								\
    640 		__asm __volatile ("					\
    641 			movl	%0,%%a0				;	\
    642 			movl	%1,%%d1				;	\
    643 			movl	%2,%%d0				;	\
    644 		1:	movb	%%d1,%%a0@+			;	\
    645 			subql	#1,%%d0				;	\
    646 			jne	1b"				:	\
    647 								:	\
    648 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    649 			    "%a0","%d0","%d1");				\
    650 	}								\
    651 } while (/* CONSTCOND */ 0)
    652 
    653 #define	bus_space_set_region_2(t, h, o, val, c)				\
    654 do {									\
    655 	if ((t)->bssr2 != NULL)						\
    656 		((t)->bssr2)(t, h, o, val, c);				\
    657 	else {								\
    658 		__asm __volatile ("					\
    659 			movl	%0,%%a0				;	\
    660 			movl	%1,%%d1				;	\
    661 			movl	%2,%%d0				;	\
    662 		1:	movw	%%d1,%%a0@+			;	\
    663 			subql	#1,%%d0				;	\
    664 			jne	1b"				:	\
    665 								:	\
    666 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    667 			    "%a0","%d0","%d1");				\
    668 	}								\
    669 } while (/* CONSTCOND */ 0)
    670 
    671 #define	bus_space_set_region_4(t, h, o, val, c)				\
    672 do {									\
    673 	(void) t;							\
    674 	if ((t)->bssr4 != NULL)						\
    675 		((t)->bssr4)(t, h, o, val, c);				\
    676 	else {								\
    677 		__asm __volatile ("					\
    678 			movl	%0,%%a0				;	\
    679 			movl	%1,%%d1				;	\
    680 			movl	%2,%%d0				;	\
    681 		1:	movl	%%d1,%%a0@+			;	\
    682 			subql	#1,%%d0				;	\
    683 			jne	1b"				:	\
    684 								:	\
    685 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    686 			    "%a0","%d0","%d1");				\
    687 	}								\
    688 } while (/* CONSTCOND */ 0)
    689 
    690 #if 0	/* Cause a link error for bus_space_set_region_8 */
    691 #define	bus_space_set_region_8						\
    692 			!!! bus_space_set_region_8 unimplemented !!!
    693 #endif
    694 
    695 /*
    696  *	void bus_space_copy_region_N __P((bus_space_tag_t tag,
    697  *	    bus_space_handle_t bsh1, bus_size_t off1,
    698  *	    bus_space_handle_t bsh2, bus_size_t off2,
    699  *	    bus_size_t count));
    700  *
    701  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
    702  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
    703  */
    704 
    705 #define	__HP300_copy_region_N(BYTES)					\
    706 static __inline void __CONCAT(bus_space_copy_region_,BYTES)		\
    707 	__P((bus_space_tag_t,						\
    708 	    bus_space_handle_t, bus_size_t,				\
    709 	    bus_space_handle_t, bus_size_t,				\
    710 	    bus_size_t));						\
    711 									\
    712 static __inline void							\
    713 __CONCAT(bus_space_copy_region_,BYTES)(t, h1, o1, h2, o2, c)		\
    714 	bus_space_tag_t t;						\
    715 	bus_space_handle_t h1, h2;					\
    716 	bus_size_t o1, o2, c;						\
    717 {									\
    718 	bus_size_t o;							\
    719 									\
    720 	if ((h1 + o1) >= (h2 + o2)) {					\
    721 		/* src after dest: copy forward */			\
    722 		for (o = 0; c != 0; c--, o += BYTES)			\
    723 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
    724 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
    725 	} else {							\
    726 		/* dest after src: copy backwards */			\
    727 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
    728 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
    729 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
    730 	}								\
    731 }
    732 __HP300_copy_region_N(1)
    733 __HP300_copy_region_N(2)
    734 __HP300_copy_region_N(4)
    735 #if 0	/* Cause a link error for bus_space_copy_region_8 */
    736 #define	bus_space_copy_region_8						\
    737 			!!! bus_space_copy_region_8 unimplemented !!!
    738 #endif
    739 
    740 #undef __HP300_copy_region_N
    741 
    742 /*
    743  * Bus read/write barrier methods.
    744  *
    745  *	void bus_space_barrier __P((bus_space_tag_t tag,
    746  *	    bus_space_handle_t bsh, bus_size_t offset,
    747  *	    bus_size_t len, int flags));
    748  *
    749  * Note: the 680x0 does not currently require barriers, but we must
    750  * provide the flags to MI code.
    751  */
    752 #define	bus_space_barrier(t, h, o, l, f)	\
    753 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
    754 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
    755 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
    756 
    757 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
    758 
    759 #endif /* _HP300_BUS_H_ */
    760