Home | History | Annotate | Line # | Download | only in include
      1 /*	$NetBSD: bus.h,v 1.24 2023/01/27 19:48:00 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 #define PRIxBUSADDR	"lx"
     76 #define PRIxBUSSIZE	"lx"
     77 #define PRIuBUSSIZE	"lu"
     78 
     79 /*
     80  * Access methods for bus resources and address space.
     81  */
     82 typedef struct bus_space_tag *bus_space_tag_t;
     83 typedef u_long bus_space_handle_t;
     84 
     85 #define PRIxBSH		"lx"
     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 	uint8_t		(*bsr1)(bus_space_tag_t, bus_space_handle_t,
     97 			    bus_size_t);
     98 	uint16_t	(*bsr2)(bus_space_tag_t, bus_space_handle_t,
     99 			    bus_size_t);
    100 	uint32_t	(*bsr4)(bus_space_tag_t, bus_space_handle_t,
    101 			    bus_size_t);
    102 	void		(*bsrm1)(bus_space_tag_t, bus_space_handle_t,
    103 			    bus_size_t, uint8_t *, bus_size_t);
    104 	void		(*bsrm2)(bus_space_tag_t, bus_space_handle_t,
    105 			    bus_size_t, uint16_t *, bus_size_t);
    106 	void		(*bsrm4)(bus_space_tag_t, bus_space_handle_t,
    107 			    bus_size_t, uint32_t *, bus_size_t);
    108 	void		(*bsrr1)(bus_space_tag_t, bus_space_handle_t,
    109 			    bus_size_t, uint8_t *, bus_size_t);
    110 	void		(*bsrr2)(bus_space_tag_t, bus_space_handle_t,
    111 			    bus_size_t, uint16_t *, bus_size_t);
    112 	void		(*bsrr4)(bus_space_tag_t, bus_space_handle_t,
    113 			    bus_size_t, uint32_t *, bus_size_t);
    114 	void		(*bsw1)(bus_space_tag_t, bus_space_handle_t,
    115 			    bus_size_t, uint8_t);
    116 	void		(*bsw2)(bus_space_tag_t, bus_space_handle_t,
    117 			    bus_size_t, uint16_t);
    118 	void		(*bsw4)(bus_space_tag_t, bus_space_handle_t,
    119 			    bus_size_t, uint32_t);
    120 	void		(*bswm1)(bus_space_tag_t, bus_space_handle_t,
    121 			    bus_size_t, const uint8_t *, bus_size_t);
    122 	void		(*bswm2)(bus_space_tag_t, bus_space_handle_t,
    123 			    bus_size_t, const uint16_t *, bus_size_t);
    124 	void		(*bswm4)(bus_space_tag_t, bus_space_handle_t,
    125 			    bus_size_t, const uint32_t *, bus_size_t);
    126 	void		(*bswr1)(bus_space_tag_t, bus_space_handle_t ,
    127 			    bus_size_t, const uint8_t *, bus_size_t);
    128 	void		(*bswr2)(bus_space_tag_t, bus_space_handle_t,
    129 			    bus_size_t, const uint16_t *, bus_size_t);
    130 	void		(*bswr4)(bus_space_tag_t, bus_space_handle_t,
    131 			    bus_size_t, const uint32_t *, bus_size_t);
    132 	void		(*bssm1)(bus_space_tag_t, bus_space_handle_t,
    133 			    bus_size_t, uint8_t, bus_size_t);
    134 	void		(*bssm2)(bus_space_tag_t, bus_space_handle_t,
    135 			    bus_size_t, uint16_t, bus_size_t);
    136 	void		(*bssm4)(bus_space_tag_t, bus_space_handle_t,
    137 			    bus_size_t, uint32_t, bus_size_t);
    138 	void		(*bssr1)(bus_space_tag_t, bus_space_handle_t,
    139 			    bus_size_t, uint8_t, bus_size_t);
    140 	void		(*bssr2)(bus_space_tag_t, bus_space_handle_t,
    141 			    bus_size_t, uint16_t, bus_size_t);
    142 	void		(*bssr4)(bus_space_tag_t, bus_space_handle_t,
    143 			    bus_size_t, uint32_t, bus_size_t);
    144 };
    145 
    146 /*
    147  *	int bus_space_map(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(bus_space_tag_t, bus_addr_t, bus_size_t,
    158 	    int, bus_space_handle_t *);
    159 
    160 /*
    161  *	void bus_space_unmap(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(bus_space_tag_t, bus_space_handle_t, bus_size_t);
    168 
    169 /*
    170  *	paddr_t bus_space_mmap(bus_space_tag_t t,
    171  *	    bus_addr_t addr, off_t off, int prot, int flags);
    172  *
    173  * Provide a cookie for pmap_phys_address/pmap_mmap_flags for bus_space address at
    174  * addr + offset and flags.
    175  */
    176 static __inline paddr_t
    177 bus_space_mmap(bus_space_tag_t t, bus_addr_t addr, off_t off, int prot, int flags)
    178 {
    179 	/* Always fail for now */
    180 	return -1;
    181 }
    182 
    183 /*
    184  *	int bus_space_subregion(bus_space_tag_t t,
    185  *	    bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
    186  *	    bus_space_handle_t *nbshp);
    187  *
    188  * Get a new handle for a subregion of an already-mapped area of bus space.
    189  */
    190 
    191 int	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
    192 	    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
    193 
    194 /*
    195  *	int bus_space_alloc(bus_space_tag_t t, bus_addr_t, rstart,
    196  *	    bus_addr_t rend, bus_size_t size, bus_size_t align,
    197  *	    bus_size_t boundary, int flags, bus_addr_t *addrp,
    198  *	    bus_space_handle_t *bshp);
    199  *
    200  * Allocate a region of bus space.
    201  */
    202 
    203 int	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
    204 	    bus_addr_t rend, bus_size_t size, bus_size_t align,
    205 	    bus_size_t boundary, int cacheable, bus_addr_t *addrp,
    206 	    bus_space_handle_t *bshp);
    207 
    208 /*
    209  *	int bus_space_free(bus_space_tag_t t,
    210  *	    bus_space_handle_t bsh, bus_size_t size);
    211  *
    212  * Free a region of bus space.
    213  */
    214 
    215 void	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
    216 	    bus_size_t size);
    217 
    218 /*
    219  *	void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
    220  *
    221  * Get the kernel virtual address for the mapped bus space.
    222  * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
    223  *  (XXX not enforced)
    224  */
    225 #define bus_space_vaddr(t, h)	(void *)(h)
    226 
    227 /*
    228  *	int hp300_bus_space_probe(bus_space_tag_t t,
    229  *	    bus_space_handle_t bsh, bus_size_t offset, int sz);
    230  *
    231  * Probe the bus at t/bsh/offset, using sz as the size of the load.
    232  *
    233  * This is a machine-dependent extension, and is not to be used by
    234  * machine-independent code.
    235  */
    236 
    237 int	hp300_bus_space_probe(bus_space_tag_t t,
    238 	    bus_space_handle_t bsh, bus_size_t offset, int sz);
    239 
    240 /*
    241  *	u_intN_t bus_space_read_N(bus_space_tag_t tag,
    242  *	    bus_space_handle_t bsh, bus_size_t offset);
    243  *
    244  * Read a 1, 2, 4, or 8 byte quantity from bus space
    245  * described by tag/handle/offset.
    246  */
    247 
    248 #define	bus_space_read_1(t, h, o)					\
    249     (((t)->bsr1 != NULL) ? ((t)->bsr1)(t, h, o) :			\
    250     (*(volatile uint8_t *)((h) + (o))))
    251 
    252 #define	bus_space_read_2(t, h, o)					\
    253     (((t)->bsr2 != NULL) ? ((t)->bsr2)(t, h, o) :			\
    254     (*(volatile uint16_t *)((h) + (o))))
    255 
    256 #define	bus_space_read_4(t, h, o)					\
    257     (((t)->bsr4 != NULL) ? ((t)->bsr4)(t, h, o) :			\
    258     (*(volatile uint32_t *)((h) + (o))))
    259 
    260 /*
    261  *	void bus_space_read_multi_N(bus_space_tag_t tag,
    262  *	    bus_space_handle_t bsh, bus_size_t offset,
    263  *	    u_intN_t *addr, size_t count);
    264  *
    265  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
    266  * described by tag/handle/offset and copy into buffer provided.
    267  */
    268 
    269 #define	bus_space_read_multi_1(t, h, o, a, c)				\
    270 do {									\
    271 	if ((t)->bsrm1 != NULL)						\
    272 		((t)->bsrm1)(t, h, o, a, c);				\
    273 	else {								\
    274 		__asm volatile ("					\
    275 			movl	%0,%%a0				;	\
    276 			movl	%1,%%a1				;	\
    277 			movl	%2,%%d0				;	\
    278 		1:	movb	%%a0@,%%a1@+			;	\
    279 			subql	#1,%%d0				;	\
    280 			jne	1b"				:	\
    281 								:	\
    282 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    283 			    "a0","a1","d0","memory");			\
    284 	}								\
    285 } while (/* CONSTCOND */ 0)
    286 
    287 #define	bus_space_read_multi_2(t, h, o, a, c)				\
    288 do {									\
    289 	if ((t)->bsrm2 != NULL)						\
    290 		((t)->bsrm2)(t, h, o, a, c);				\
    291 	else {								\
    292 		__asm volatile ("					\
    293 			movl	%0,%%a0				;	\
    294 			movl	%1,%%a1				;	\
    295 			movl	%2,%%d0				;	\
    296 		1:	movw	%%a0@,%%a1@+			;	\
    297 			subql	#1,%%d0				;	\
    298 			jne	1b"				:	\
    299 								:	\
    300 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    301 			    "a0","a1","d0","memory");			\
    302 	}								\
    303 } while (/* CONSTCOND */ 0)
    304 
    305 #define	bus_space_read_multi_4(t, h, o, a, c) do {			\
    306 	if ((t)->bsrm4 != NULL)						\
    307 		((t)->bsrm4)(t, h, o, a, c);				\
    308 	else {								\
    309 		__asm volatile ("					\
    310 			movl	%0,%%a0				;	\
    311 			movl	%1,%%a1				;	\
    312 			movl	%2,%%d0				;	\
    313 		1:	movl	%%a0@,%%a1@+			;	\
    314 			subql	#1,%%d0				;	\
    315 			jne	1b"				:	\
    316 								:	\
    317 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    318 			    "a0","a1","d0","memory");			\
    319 	}								\
    320 } while (/* CONSTCOND */ 0)
    321 
    322 /*
    323  *	void bus_space_read_region_N(bus_space_tag_t tag,
    324  *	    bus_space_handle_t bsh, bus_size_t offset,
    325  *	    u_intN_t *addr, size_t count);
    326  *
    327  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
    328  * described by tag/handle and starting at `offset' and copy into
    329  * buffer provided.
    330  */
    331 
    332 #define	bus_space_read_region_1(t, h, o, a, c)				\
    333 do {									\
    334 	if ((t)->bsrr1 != NULL)						\
    335 		((t)->bsrr1)(t, h, o, a, c);				\
    336 	else {								\
    337 		__asm volatile ("					\
    338 			movl	%0,%%a0				;	\
    339 			movl	%1,%%a1				;	\
    340 			movl	%2,%%d0				;	\
    341 		1:	movb	%%a0@+,%%a1@+			;	\
    342 			subql	#1,%%d0				;	\
    343 			jne	1b"				:	\
    344 								:	\
    345 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    346 			    "a0","a1","d0","memory");			\
    347 	}								\
    348 } while (/* CONSTCOND */ 0)
    349 
    350 #define	bus_space_read_region_2(t, h, o, a, c)				\
    351 do {									\
    352 	if ((t)->bsrr2 != NULL)						\
    353 		((t)->bsrr2)(t, h, o, a, c);				\
    354 	else {								\
    355 		__asm volatile ("					\
    356 			movl	%0,%%a0				;	\
    357 			movl	%1,%%a1				;	\
    358 			movl	%2,%%d0				;	\
    359 		1:	movw	%%a0@+,%%a1@+			;	\
    360 			subql	#1,%%d0				;	\
    361 			jne	1b"				:	\
    362 								:	\
    363 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    364 			    "a0","a1","d0","memory");			\
    365 	}								\
    366 } while (/* CONSTCOND */ 0)
    367 
    368 #define	bus_space_read_region_4(t, h, o, a, c)				\
    369 do {									\
    370 	if ((t)->bsrr4 != NULL)						\
    371 		((t)->bsrr4)(t, h, o, a, c);				\
    372 	else {								\
    373 		__asm volatile ("					\
    374 			movl	%0,%%a0				;	\
    375 			movl	%1,%%a1				;	\
    376 			movl	%2,%%d0				;	\
    377 		1:	movl	%%a0@+,%%a1@+			;	\
    378 			subql	#1,%%d0				;	\
    379 			jne	1b"				:	\
    380 								:	\
    381 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    382 			    "a0","a1","d0","memory");			\
    383 	}								\
    384 } while (/* CONSTCOND */ 0)
    385 
    386 /*
    387  *	void bus_space_write_N(bus_space_tag_t tag,
    388  *	    bus_space_handle_t bsh, bus_size_t offset,
    389  *	    u_intN_t value);
    390  *
    391  * Write the 1, 2, 4, or 8 byte value `value' to bus space
    392  * described by tag/handle/offset.
    393  */
    394 
    395 #define	bus_space_write_1(t, h, o, v)					\
    396 do {									\
    397 	if ((t)->bsw1 != NULL)						\
    398 		((t)->bsw1)(t, h, o, v);				\
    399 	else								\
    400 		((void)(*(volatile uint8_t *)((h) + (o)) = (v)));	\
    401 } while (/* CONSTCOND */ 0)
    402 
    403 #define	bus_space_write_2(t, h, o, v)					\
    404 do {									\
    405 	if ((t)->bsw2 != NULL)						\
    406 		((t)->bsw2)(t, h, o, v);				\
    407 	else								\
    408 		((void)(*(volatile uint16_t *)((h) + (o)) = (v)));	\
    409 } while (/* CONSTCOND */ 0)
    410 
    411 #define	bus_space_write_4(t, h, o, v)					\
    412 do {									\
    413 	if ((t)->bsw4 != NULL)						\
    414 		((t)->bsw4)(t, h, o, v);				\
    415 	else								\
    416 		((void)(*(volatile uint32_t *)((h) + (o)) = (v)));	\
    417 } while (/* CONSTCOND */ 0)
    418 
    419 /*
    420  *	void bus_space_write_multi_N(bus_space_tag_t tag,
    421  *	    bus_space_handle_t bsh, bus_size_t offset,
    422  *	    const u_intN_t *addr, size_t count);
    423  *
    424  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
    425  * provided to bus space described by tag/handle/offset.
    426  */
    427 
    428 #define	bus_space_write_multi_1(t, h, o, a, c)				\
    429 do {									\
    430 	if ((t)->bswm1 != NULL)						\
    431 		((t)->bswm1)(t, h, o, a, c);				\
    432 	else {								\
    433 		__asm volatile ("					\
    434 			movl	%0,%%a0				;	\
    435 			movl	%1,%%a1				;	\
    436 			movl	%2,%%d0				;	\
    437 		1:	movb	%%a1@+,%%a0@			;	\
    438 			subql	#1,%%d0				;	\
    439 			jne	1b"				:	\
    440 								:	\
    441 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    442 			    "a0","a1","d0");				\
    443 	}								\
    444 } while (/* CONSTCOND */ 0)
    445 
    446 #define	bus_space_write_multi_2(t, h, o, a, c)				\
    447 do {									\
    448 	if ((t)->bswm2 != NULL)						\
    449 		((t)->bswm2)(t, h, o, a, c);				\
    450 	else {								\
    451 		__asm volatile ("					\
    452 			movl	%0,%%a0				;	\
    453 			movl	%1,%%a1				;	\
    454 			movl	%2,%%d0				;	\
    455 		1:	movw	%%a1@+,%%a0@			;	\
    456 			subql	#1,%%d0				;	\
    457 			jne	1b"				:	\
    458 								:	\
    459 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    460 			    "a0","a1","d0");				\
    461 	}								\
    462 } while (/* CONSTCOND */ 0)
    463 
    464 #define	bus_space_write_multi_4(t, h, o, a, c)				\
    465 do {									\
    466 	(void) t;							\
    467 	if ((t)->bswm4 != NULL)					\
    468 		((t)->bswm4)(t, h, o, a, c);				\
    469 	else {								\
    470 		__asm volatile ("					\
    471 			movl	%0,%%a0				;	\
    472 			movl	%1,%%a1				;	\
    473 			movl	%2,%%d0				;	\
    474 		1:	movl	%%a1@+,%%a0@			;	\
    475 			subql	#1,%%d0				;	\
    476 			jne	1b"				:	\
    477 								:	\
    478 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    479 			    "a0","a1","d0");				\
    480 	}								\
    481 } while (/* CONSTCOND */ 0)
    482 
    483 /*
    484  *	void bus_space_write_region_N(bus_space_tag_t tag,
    485  *	    bus_space_handle_t bsh, bus_size_t offset,
    486  *	    const u_intN_t *addr, size_t count);
    487  *
    488  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
    489  * to bus space described by tag/handle starting at `offset'.
    490  */
    491 
    492 #define	bus_space_write_region_1(t, h, o, a, c)				\
    493 do {									\
    494 	if ((t)->bswr1 != NULL)					\
    495 		((t)->bswr1)(t, h, o, a, c);				\
    496 	else {								\
    497 		__asm volatile ("					\
    498 			movl	%0,%%a0				;	\
    499 			movl	%1,%%a1				;	\
    500 			movl	%2,%%d0				;	\
    501 		1:	movb	%%a1@+,%%a0@+			;	\
    502 			subql	#1,%%d0				;	\
    503 			jne	1b"				:	\
    504 								:	\
    505 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    506 			    "a0","a1","d0");				\
    507 	}								\
    508 } while (/* CONSTCOND */ 0)
    509 
    510 #define	bus_space_write_region_2(t, h, o, a, c)				\
    511 do {									\
    512 	if ((t)->bswr2) != NULL)					\
    513 		((t)->bswr2)(t, h, o, a, c);				\
    514 	else {								\
    515 		__asm volatile ("					\
    516 			movl	%0,%%a0				;	\
    517 			movl	%1,%%a1				;	\
    518 			movl	%2,%%d0				;	\
    519 		1:	movw	%%a1@+,%%a0@+			;	\
    520 			subql	#1,%%d0				;	\
    521 			jne	1b"				:	\
    522 								:	\
    523 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    524 			    "a0","a1","d0");				\
    525 	}								\
    526 } while (/* CONSTCOND */ 0)
    527 
    528 #define	bus_space_write_region_4(t, h, o, a, c)				\
    529 do {									\
    530 	if ((t)->bswr4) != NULL)					\
    531 		((t)->bswr4)(t, h, o, a, c);				\
    532 	else {								\
    533 		__asm volatile ("					\
    534 			movl	%0,%%a0				;	\
    535 			movl	%1,%%a1				;	\
    536 			movl	%2,%%d0				;	\
    537 		1:	movl	%%a1@+,%%a0@+			;	\
    538 			subql	#1,%%d0				;	\
    539 			jne	1b"				:	\
    540 								:	\
    541 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
    542 			    "a0","a1","d0");				\
    543 	}								\
    544 } while (/* CONSTCOND */ 0)
    545 
    546 /*
    547  *	void bus_space_set_multi_N(bus_space_tag_t tag,
    548  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
    549  *	    size_t count);
    550  *
    551  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
    552  * by tag/handle/offset `count' times.
    553  */
    554 
    555 #define	bus_space_set_multi_1(t, h, o, val, c)				\
    556 do {									\
    557 	if ((t)->bssm1 != NULL)						\
    558 		((t)->bssm1)(t, h, o, val, c);				\
    559 	else {								\
    560 		__asm volatile ("					\
    561 			movl	%0,%%a0				;	\
    562 			movl	%1,%%d1				;	\
    563 			movl	%2,%%d0				;	\
    564 		1:	movb	%%d1,%%a0@			;	\
    565 			subql	#1,%%d0				;	\
    566 			jne	1b"				:	\
    567 								:	\
    568 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    569 			    "a0","d0","d1");				\
    570 	}								\
    571 } while (/* CONSTCOND */ 0)
    572 
    573 #define	bus_space_set_multi_2(t, h, o, val, c)				\
    574 do {									\
    575 	if ((t)->bssm2 != NULL)						\
    576 		((t)->bssm2)(t, h, o, val, c);				\
    577 	else {								\
    578 		__asm volatile ("					\
    579 			movl	%0,%%a0				;	\
    580 			movl	%1,%%d1				;	\
    581 			movl	%2,%%d0				;	\
    582 		1:	movw	%%d1,%%a0@			;	\
    583 			subql	#1,%%d0				;	\
    584 			jne	1b"				:	\
    585 								:	\
    586 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    587 			    "a0","d0","d1");				\
    588 	}								\
    589 } while (/* CONSTCOND */ 0)
    590 
    591 #define	bus_space_set_multi_4(t, h, o, val, c)				\
    592 do {									\
    593 	if ((t)->bssm4 != NULL)						\
    594 		((t)->bssm4)(t, h, o, val, c);				\
    595 	else {								\
    596 		__asm volatile ("					\
    597 			movl	%0,%%a0				;	\
    598 			movl	%1,%%d1				;	\
    599 			movl	%2,%%d0				;	\
    600 		1:	movl	%%d1,%%a0@			;	\
    601 			subql	#1,%%d0				;	\
    602 			jne	1b"				:	\
    603 								:	\
    604 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    605 			    "a0","d0","d1");				\
    606 	}								\
    607 } while (/* CONSTCOND */ 0)
    608 
    609 /*
    610  *	void bus_space_set_region_N(bus_space_tag_t tag,
    611  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
    612  *	    size_t count);
    613  *
    614  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
    615  * by tag/handle starting at `offset'.
    616  */
    617 
    618 #define	bus_space_set_region_1(t, h, o, val, c)				\
    619 do {									\
    620 	if ((t)->bssr1 != NULL)						\
    621 		((t)->bssr1)(t, h, o, val, c);				\
    622 	else {								\
    623 		__asm volatile ("					\
    624 			movl	%0,%%a0				;	\
    625 			movl	%1,%%d1				;	\
    626 			movl	%2,%%d0				;	\
    627 		1:	movb	%%d1,%%a0@+			;	\
    628 			subql	#1,%%d0				;	\
    629 			jne	1b"				:	\
    630 								:	\
    631 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    632 			    "a0","d0","d1");				\
    633 	}								\
    634 } while (/* CONSTCOND */ 0)
    635 
    636 #define	bus_space_set_region_2(t, h, o, val, c)				\
    637 do {									\
    638 	if ((t)->bssr2 != NULL)						\
    639 		((t)->bssr2)(t, h, o, val, c);				\
    640 	else {								\
    641 		__asm volatile ("					\
    642 			movl	%0,%%a0				;	\
    643 			movl	%1,%%d1				;	\
    644 			movl	%2,%%d0				;	\
    645 		1:	movw	%%d1,%%a0@+			;	\
    646 			subql	#1,%%d0				;	\
    647 			jne	1b"				:	\
    648 								:	\
    649 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    650 			    "a0","d0","d1");				\
    651 	}								\
    652 } while (/* CONSTCOND */ 0)
    653 
    654 #define	bus_space_set_region_4(t, h, o, val, c)				\
    655 do {									\
    656 	(void) t;							\
    657 	if ((t)->bssr4 != NULL)						\
    658 		((t)->bssr4)(t, h, o, val, c);				\
    659 	else {								\
    660 		__asm volatile ("					\
    661 			movl	%0,%%a0				;	\
    662 			movl	%1,%%d1				;	\
    663 			movl	%2,%%d0				;	\
    664 		1:	movl	%%d1,%%a0@+			;	\
    665 			subql	#1,%%d0				;	\
    666 			jne	1b"				:	\
    667 								:	\
    668 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
    669 			    "a0","d0","d1");				\
    670 	}								\
    671 } while (/* CONSTCOND */ 0)
    672 
    673 /*
    674  *	void bus_space_copy_region_N(bus_space_tag_t tag,
    675  *	    bus_space_handle_t bsh1, bus_size_t off1,
    676  *	    bus_space_handle_t bsh2, bus_size_t off2,
    677  *	    bus_size_t count);
    678  *
    679  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
    680  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
    681  */
    682 
    683 #define	__HP300_copy_region_N(BYTES)					\
    684 static __inline void						\
    685 __CONCAT(bus_space_copy_region_,BYTES)(bus_space_tag_t t,		\
    686     bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2,	\
    687     bus_size_t o2, bus_size_t c)					\
    688 {									\
    689 	bus_size_t o;							\
    690 									\
    691 	if ((h1 + o1) >= (h2 + o2)) {					\
    692 		/* src after dest: copy forward */			\
    693 		for (o = 0; c != 0; c--, o += BYTES)			\
    694 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
    695 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
    696 	} else {							\
    697 		/* dest after src: copy backwards */			\
    698 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
    699 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
    700 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
    701 	}								\
    702 }
    703 __HP300_copy_region_N(1)
    704 __HP300_copy_region_N(2)
    705 __HP300_copy_region_N(4)
    706 
    707 #undef __HP300_copy_region_N
    708 
    709 /*
    710  * Bus stream operations--defined in terms of non-stream counterparts
    711  */
    712 #define	__BUS_SPACE_HAS_STREAM_METHODS 1
    713 #define	bus_space_read_stream_1 bus_space_read_1
    714 #define	bus_space_read_stream_2 bus_space_read_2
    715 #define	bus_space_read_stream_4 bus_space_read_4
    716 #define	bus_space_read_stream_8 bus_space_read_8
    717 #define	bus_space_read_multi_stream_1 bus_space_read_multi_1
    718 #define	bus_space_read_multi_stream_2 bus_space_read_multi_2
    719 #define	bus_space_read_multi_stream_4 bus_space_read_multi_4
    720 #define	bus_space_read_multi_stream_8 bus_space_read_multi_8
    721 #define	bus_space_read_region_stream_1 bus_space_read_region_1
    722 #define	bus_space_read_region_stream_2 bus_space_read_region_2
    723 #define	bus_space_read_region_stream_4 bus_space_read_region_4
    724 #define	bus_space_read_region_stream_8 bus_space_read_region_8
    725 #define	bus_space_write_stream_1 bus_space_write_1
    726 #define	bus_space_write_stream_2 bus_space_write_2
    727 #define	bus_space_write_stream_4 bus_space_write_4
    728 #define	bus_space_write_stream_8 bus_space_write_8
    729 #define	bus_space_write_multi_stream_1 bus_space_write_multi_1
    730 #define	bus_space_write_multi_stream_2 bus_space_write_multi_2
    731 #define	bus_space_write_multi_stream_4 bus_space_write_multi_4
    732 #define	bus_space_write_multi_stream_8 bus_space_write_multi_8
    733 #define	bus_space_write_region_stream_1 bus_space_write_region_1
    734 #define	bus_space_write_region_stream_2 bus_space_write_region_2
    735 #define	bus_space_write_region_stream_4 bus_space_write_region_4
    736 #define	bus_space_write_region_stream_8	bus_space_write_region_8
    737 
    738 /*
    739  * Bus read/write barrier methods.
    740  *
    741  *	void bus_space_barrier(bus_space_tag_t tag,
    742  *	    bus_space_handle_t bsh, bus_size_t offset,
    743  *	    bus_size_t len, int flags);
    744  *
    745  * Note: the 680x0 does not currently require barriers, but we must
    746  * provide the flags to MI code.
    747  */
    748 #define	bus_space_barrier(t, h, o, l, f)	\
    749 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
    750 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
    751 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
    752 
    753 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
    754 
    755 /*
    756  * There is no bus_dma(9)'fied bus drivers on this port.
    757  */
    758 #define __HAVE_NO_BUS_DMA
    759 
    760 #endif /* _HP300_BUS_H_ */
    761