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