Home | History | Annotate | Line # | Download | only in include
bus.h revision 1.1
      1 /*	$NetBSD: bus.h,v 1.1 2001/03/29 04:16:21 fredette 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) 1996 Charles M. Hannum.  All rights reserved.
     42  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
     43  *
     44  * Redistribution and use in source and binary forms, with or without
     45  * modification, are permitted provided that the following conditions
     46  * are met:
     47  * 1. Redistributions of source code must retain the above copyright
     48  *    notice, this list of conditions and the following disclaimer.
     49  * 2. Redistributions in binary form must reproduce the above copyright
     50  *    notice, this list of conditions and the following disclaimer in the
     51  *    documentation and/or other materials provided with the distribution.
     52  * 3. All advertising materials mentioning features or use of this software
     53  *    must display the following acknowledgement:
     54  *      This product includes software developed by Christopher G. Demetriou
     55  *	for the NetBSD Project.
     56  * 4. The name of the author may not be used to endorse or promote products
     57  *    derived from this software without specific prior written permission
     58  *
     59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     69  */
     70 
     71 #ifndef _SUN2_BUS_H_
     72 #define _SUN2_BUS_H_
     73 
     74 #define	SUN2_BUS_SPACE	0
     75 
     76 /*
     77  * Bus address and size types
     78  */
     79 typedef	u_long	bus_space_handle_t;
     80 typedef u_long	bus_type_t;
     81 typedef u_long	bus_addr_t;
     82 typedef u_long	bus_size_t;
     83 
     84 /*
     85  * Access methods for bus resources and address space.
     86  */
     87 typedef struct sun2_bus_space_tag	*bus_space_tag_t;
     88 
     89 struct sun2_bus_space_tag {
     90 	void		*cookie;
     91 	bus_space_tag_t	parent;
     92 
     93 	int	(*sun2_bus_map) __P((
     94 				bus_space_tag_t,
     95 				bus_type_t,
     96 				bus_addr_t,
     97 				bus_size_t,
     98 				int,			/*flags*/
     99 				vaddr_t,		/*preferred vaddr*/
    100 				bus_space_handle_t *));
    101 	int	(*sun2_bus_unmap) __P((
    102 				bus_space_tag_t,
    103 				bus_space_handle_t,
    104 				bus_size_t));
    105 	int	(*sun2_bus_subregion) __P((
    106 				bus_space_tag_t,
    107 				bus_space_handle_t,
    108 				bus_size_t,		/*offset*/
    109 				bus_size_t,		/*size*/
    110 				bus_space_handle_t *));
    111 
    112 	void	(*sun2_bus_barrier) __P((
    113 				bus_space_tag_t,
    114 				bus_space_handle_t,
    115 				bus_size_t,		/*offset*/
    116 				bus_size_t,		/*size*/
    117 				int));			/*flags*/
    118 
    119 	int	(*sun2_bus_mmap) __P((
    120 				bus_space_tag_t,
    121 				bus_type_t,		/**/
    122 				bus_addr_t,		/**/
    123 				int,			/*flags*/
    124 				bus_space_handle_t *));
    125 
    126 	void	*(*sun2_intr_establish) __P((
    127 				bus_space_tag_t,
    128 				int,			/*bus-specific intr*/
    129 				int,			/*device class level,
    130 							  see machine/intr.h*/
    131 				int,			/*flags*/
    132 				int (*) __P((void *)),	/*handler*/
    133 				void *));		/*handler arg*/
    134 
    135 };
    136 
    137 #if 0
    138 /*
    139  * The following macro could be used to generate the bus_space*() functions
    140  * but it uses a gcc extension and is ANSI-only.
    141 #define PROTO_bus_space_xxx		__P((bus_space_tag_t t, ...))
    142 #define RETURNTYPE_bus_space_xxx	void *
    143 #define BUSFUN(name, returntype, t, args...)			\
    144 	__inline__ RETURNTYPE_##name				\
    145 	bus_##name PROTO_##name					\
    146 	{							\
    147 		while (t->sun2_##name == NULL)			\
    148 			t = t->parent;				\
    149 		return (*(t)->sun2_##name)(t, args);		\
    150 	}
    151  */
    152 #endif
    153 
    154 /*
    155  * Bus space function prototypes.
    156  * In bus_space_map2(), supply a special virtual address only if you
    157  * get it from ../sun2/vaddrs.h.
    158  */
    159 static int	bus_space_map __P((
    160 				bus_space_tag_t,
    161 				bus_addr_t,
    162 				bus_size_t,
    163 				int,			/*flags*/
    164 				bus_space_handle_t *));
    165 static int	bus_space_map2 __P((
    166 				bus_space_tag_t,
    167 				bus_type_t,
    168 				bus_addr_t,
    169 				bus_size_t,
    170 				int,			/*flags*/
    171 				vaddr_t,		/*preferred vaddr*/
    172 				bus_space_handle_t *));
    173 static int	bus_space_unmap __P((
    174 				bus_space_tag_t,
    175 				bus_space_handle_t,
    176 				bus_size_t));
    177 static int	bus_space_subregion __P((
    178 				bus_space_tag_t,
    179 				bus_space_handle_t,
    180 				bus_size_t,
    181 				bus_size_t,
    182 				bus_space_handle_t *));
    183 static void	bus_space_barrier __P((
    184 				bus_space_tag_t,
    185 				bus_space_handle_t,
    186 				bus_size_t,
    187 				bus_size_t,
    188 				int));
    189 static int	bus_space_mmap __P((
    190 				bus_space_tag_t,
    191 				bus_type_t,		/**/
    192 				bus_addr_t,		/**/
    193 				int,			/*flags*/
    194 				bus_space_handle_t *));
    195 static void	*bus_intr_establish __P((
    196 				bus_space_tag_t,
    197 				int,			/*bus-specific intr*/
    198 				int,			/*device class level,
    199 							  see machine/intr.h*/
    200 				int,			/*flags*/
    201 				int (*) __P((void *)),	/*handler*/
    202 				void *));		/*handler arg*/
    203 
    204 
    205 /* This macro finds the first "upstream" implementation of method `f' */
    206 #define _BS_CALL(t,f)			\
    207 	while (t->f == NULL)		\
    208 		t = t->parent;		\
    209 	return (*(t)->f)
    210 
    211 __inline__ int
    212 bus_space_map(t, a, s, f, hp)
    213 	bus_space_tag_t	t;
    214 	bus_addr_t	a;
    215 	bus_size_t	s;
    216 	int		f;
    217 	bus_space_handle_t *hp;
    218 {
    219 	_BS_CALL(t, sun2_bus_map)((t), 0, (a), (s), (f), 0, (hp));
    220 }
    221 
    222 __inline__ int
    223 bus_space_map2(t, bt, a, s, f, v, hp)
    224 	bus_space_tag_t	t;
    225 	bus_type_t	bt;
    226 	bus_addr_t	a;
    227 	bus_size_t	s;
    228 	int		f;
    229 	vaddr_t		v;
    230 	bus_space_handle_t *hp;
    231 {
    232 	_BS_CALL(t, sun2_bus_map)(t, bt, a, s, f, v, hp);
    233 }
    234 
    235 __inline__ int
    236 bus_space_unmap(t, h, s)
    237 	bus_space_tag_t t;
    238 	bus_space_handle_t h;
    239 	bus_size_t	s;
    240 {
    241 	_BS_CALL(t, sun2_bus_unmap)(t, h, s);
    242 }
    243 
    244 __inline__ int
    245 bus_space_subregion(t, h, o, s, hp)
    246 	bus_space_tag_t	t;
    247 	bus_space_handle_t h;
    248 	bus_size_t	o;
    249 	bus_size_t	s;
    250 	bus_space_handle_t *hp;
    251 {
    252 	_BS_CALL(t, sun2_bus_subregion)(t, h, o, s, hp);
    253 }
    254 
    255 __inline__ int
    256 bus_space_mmap(t, bt, a, f, hp)
    257 	bus_space_tag_t	t;
    258 	bus_type_t	bt;
    259 	bus_addr_t	a;
    260 	int		f;
    261 	bus_space_handle_t *hp;
    262 {
    263 	_BS_CALL(t, sun2_bus_mmap)(t, bt, a, f, hp);
    264 }
    265 
    266 __inline__ void *
    267 bus_intr_establish(t, p, l, f, h, a)
    268 	bus_space_tag_t t;
    269 	int	p;
    270 	int	l;
    271 	int	f;
    272 	int	(*h)__P((void *));
    273 	void	*a;
    274 {
    275 	_BS_CALL(t, sun2_intr_establish)(t, p, l, f, h, a);
    276 }
    277 
    278 __inline__ void
    279 bus_space_barrier(t, h, o, s, f)
    280 	bus_space_tag_t t;
    281 	bus_space_handle_t h;
    282 	bus_size_t o;
    283 	bus_size_t s;
    284 	int f;
    285 {
    286 	_BS_CALL(t, sun2_bus_barrier)(t, h, o, s, f);
    287 }
    288 
    289 
    290 #if 0
    291 int	bus_space_alloc __P((bus_space_tag_t t, bus_addr_t rstart,
    292 	    bus_addr_t rend, bus_size_t size, bus_size_t align,
    293 	    bus_size_t boundary, int flags, bus_addr_t *addrp,
    294 	    bus_space_handle_t *bshp));
    295 void	bus_space_free __P((bus_space_tag_t t, bus_space_handle_t bsh,
    296 	    bus_size_t size));
    297 #endif
    298 
    299 /* flags for bus space map functions */
    300 #define BUS_SPACE_MAP_CACHEABLE	0x0001
    301 #define BUS_SPACE_MAP_LINEAR	0x0002
    302 #define BUS_SPACE_MAP_PREFETCHABLE	0x0004
    303 #define BUS_SPACE_MAP_BUS1	0x0100	/* placeholders for bus functions... */
    304 #define BUS_SPACE_MAP_BUS2	0x0200
    305 #define BUS_SPACE_MAP_BUS3	0x0400
    306 #define BUS_SPACE_MAP_BUS4	0x0800
    307 
    308 
    309 /* flags for intr_establish() */
    310 #define BUS_INTR_ESTABLISH_FASTTRAP	1
    311 #define BUS_INTR_ESTABLISH_SOFTINTR	2
    312 
    313 /* flags for bus_space_barrier() */
    314 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
    315 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
    316 
    317 /*
    318  * Device space probe assistant.
    319  * The optional callback function's arguments are:
    320  *	the temporary virtual address
    321  *	the passed `arg' argument
    322  */
    323 int bus_space_probe __P((
    324 		bus_space_tag_t,
    325 		bus_type_t,
    326 		bus_addr_t,
    327 		bus_size_t,			/* probe size */
    328 		size_t,				/* offset */
    329 		int,				/* flags */
    330 		int (*) __P((void *, void *)),	/* callback function */
    331 		void *));			/* callback arg */
    332 
    333 
    334 /*
    335  *	u_intN_t bus_space_read_N __P((bus_space_tag_t tag,
    336  *	    bus_space_handle_t bsh, bus_size_t offset));
    337  *
    338  * Read a 1, 2, 4, or 8 byte quantity from bus space
    339  * described by tag/handle/offset.
    340  */
    341 
    342 #define	bus_space_read_1(t, h, o)					\
    343 	    ((void)t, *(volatile u_int8_t *)((h) + (o)))
    344 
    345 #define	bus_space_read_2(t, h, o)					\
    346 	    ((void)t, *(volatile u_int16_t *)((h) + (o)))
    347 
    348 #define	bus_space_read_4(t, h, o)					\
    349 	    ((void)t, *(volatile u_int32_t *)((h) + (o)))
    350 
    351 #define	bus_space_read_8(t, h, o)					\
    352 	    ((void)t, *(volatile u_int64_t *)((h) + (o)))
    353 
    354 
    355 /*
    356  *	void bus_space_write_N __P((bus_space_tag_t tag,
    357  *	    bus_space_handle_t bsh, bus_size_t offset,
    358  *	    u_intN_t value));
    359  *
    360  * Write the 1, 2, 4, or 8 byte value `value' to bus space
    361  * described by tag/handle/offset.
    362  */
    363 
    364 #define	bus_space_write_1(t, h, o, v)	do {				\
    365 	((void)t, (void)(*(volatile u_int8_t *)((h) + (o)) = (v)));	\
    366 } while (0)
    367 
    368 #define	bus_space_write_2(t, h, o, v)	do {				\
    369 	((void)t, (void)(*(volatile u_int16_t *)((h) + (o)) = (v)));	\
    370 } while (0)
    371 
    372 #define	bus_space_write_4(t, h, o, v)	do {				\
    373 	((void)t, (void)(*(volatile u_int32_t *)((h) + (o)) = (v)));	\
    374 } while (0)
    375 
    376 #define	bus_space_write_8(t, h, o, v)	do {				\
    377 	((void)t, (void)(*(volatile u_int64_t *)((h) + (o)) = (v)));	\
    378 } while (0)
    379 
    380 
    381 /*
    382  *	void bus_space_read_multi_N __P((bus_space_tag_t tag,
    383  *	    bus_space_handle_t bsh, bus_size_t offset,
    384  *	    u_intN_t *addr, bus_size_t count));
    385  *
    386  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
    387  * described by tag/handle/offset and copy into buffer provided.
    388  */
    389 
    390 void bus_space_read_multi_1 __P((bus_space_tag_t,
    391 				 bus_space_handle_t,
    392 				 bus_size_t,
    393 				 u_int8_t *,
    394 				 bus_size_t));
    395 
    396 void bus_space_read_multi_2 __P((bus_space_tag_t,
    397 				 bus_space_handle_t,
    398 				 bus_size_t,
    399 				 u_int16_t *,
    400 				 bus_size_t));
    401 
    402 void bus_space_read_multi_4 __P((bus_space_tag_t,
    403 				 bus_space_handle_t,
    404 				 bus_size_t,
    405 				 u_int32_t *,
    406 				 bus_size_t));
    407 
    408 void bus_space_read_multi_8 __P((bus_space_tag_t,
    409 				 bus_space_handle_t,
    410 				 bus_size_t,
    411 				 u_int64_t *,
    412 				 bus_size_t));
    413 
    414 extern __inline__ void
    415 bus_space_read_multi_1(t, h, o, a, c)
    416 	bus_space_tag_t		t;
    417 	bus_space_handle_t	h;
    418 	bus_size_t		o, c;
    419 	u_int8_t		*a;
    420 {
    421 	while (c-- > 0)
    422 		*a++ = bus_space_read_1(t, h, o);
    423 }
    424 
    425 extern __inline__ void
    426 bus_space_read_multi_2(t, h, o, a, c)
    427 	bus_space_tag_t		t;
    428 	bus_space_handle_t	h;
    429 	bus_size_t		o, c;
    430 	u_int16_t		*a;
    431 {
    432 	while (c-- > 0)
    433 		*a++ = bus_space_read_2(t, h, o);
    434 }
    435 
    436 extern __inline__ void
    437 bus_space_read_multi_4(t, h, o, a, c)
    438 	bus_space_tag_t		t;
    439 	bus_space_handle_t	h;
    440 	bus_size_t		o, c;
    441 	u_int32_t		*a;
    442 {
    443 	while (c-- > 0)
    444 		*a++ = bus_space_read_4(t, h, o);
    445 }
    446 
    447 extern __inline__ void
    448 bus_space_read_multi_8(t, h, o, a, c)
    449 	bus_space_tag_t		t;
    450 	bus_space_handle_t	h;
    451 	bus_size_t		o, c;
    452 	u_int64_t		*a;
    453 {
    454 	while (c-- > 0)
    455 		*a++ = bus_space_read_8(t, h, o);
    456 }
    457 
    458 
    459 /*
    460  *	void bus_space_write_multi_N __P((bus_space_tag_t tag,
    461  *	    bus_space_handle_t bsh, bus_size_t offset,
    462  *	    const u_intN_t *addr, bus_size_t count));
    463  *
    464  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
    465  * provided to bus space described by tag/handle/offset.
    466  */
    467 void bus_space_write_multi_1 __P((bus_space_tag_t,
    468 				  bus_space_handle_t,
    469 				  bus_size_t,
    470 				  const u_int8_t *,
    471 				  bus_size_t));
    472 void bus_space_write_multi_2 __P((bus_space_tag_t,
    473 				  bus_space_handle_t,
    474 				  bus_size_t,
    475 				  const u_int16_t *,
    476 				  bus_size_t));
    477 void bus_space_write_multi_4 __P((bus_space_tag_t,
    478 				  bus_space_handle_t,
    479 				  bus_size_t,
    480 				  const u_int32_t *,
    481 				  bus_size_t));
    482 void bus_space_write_multi_8 __P((bus_space_tag_t,
    483 				  bus_space_handle_t,
    484 				  bus_size_t,
    485 				  const u_int64_t *,
    486 				  bus_size_t));
    487 extern __inline__ void
    488 bus_space_write_multi_1(t, h, o, a, c)
    489 	bus_space_tag_t		t;
    490 	bus_space_handle_t	h;
    491 	bus_size_t		o, c;
    492 	const u_int8_t		*a;
    493 {
    494 	while (c-- > 0)
    495 		bus_space_write_1(t, h, o, *a++);
    496 }
    497 
    498 extern __inline__ void
    499 bus_space_write_multi_2(t, h, o, a, c)
    500 	bus_space_tag_t		t;
    501 	bus_space_handle_t	h;
    502 	bus_size_t		o, c;
    503 	const u_int16_t		*a;
    504 {
    505 	while (c-- > 0)
    506 		bus_space_write_2(t, h, o, *a++);
    507 }
    508 
    509 extern __inline__ void
    510 bus_space_write_multi_4(t, h, o, a, c)
    511 	bus_space_tag_t		t;
    512 	bus_space_handle_t	h;
    513 	bus_size_t		o, c;
    514 	const u_int32_t		*a;
    515 {
    516 	while (c-- > 0)
    517 		bus_space_write_4(t, h, o, *a++);
    518 }
    519 
    520 extern __inline__ void
    521 bus_space_write_multi_8(t, h, o, a, c)
    522 	bus_space_tag_t		t;
    523 	bus_space_handle_t	h;
    524 	bus_size_t		o, c;
    525 	const u_int64_t		*a;
    526 {
    527 	while (c-- > 0)
    528 		bus_space_write_8(t, h, o, *a++);
    529 }
    530 
    531 /*
    532  *	void bus_space_set_multi_N __P((bus_space_tag_t tag,
    533  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
    534  *	    bus_size_t count));
    535  *
    536  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
    537  * by tag/handle/offset `count' times.
    538  */
    539 void bus_space_set_multi_1 __P((bus_space_tag_t,
    540 				bus_space_handle_t,
    541 				bus_size_t,
    542 				const u_int8_t,
    543 				bus_size_t));
    544 void bus_space_set_multi_2 __P((bus_space_tag_t,
    545 				bus_space_handle_t,
    546 				bus_size_t,
    547 				const u_int16_t,
    548 				bus_size_t));
    549 void bus_space_set_multi_4 __P((bus_space_tag_t,
    550 				bus_space_handle_t,
    551 				bus_size_t,
    552 				const u_int32_t,
    553 				bus_size_t));
    554 void bus_space_set_multi_8 __P((bus_space_tag_t,
    555 				bus_space_handle_t,
    556 				bus_size_t,
    557 				const u_int64_t,
    558 				bus_size_t));
    559 
    560 extern __inline__ void
    561 bus_space_set_multi_1(t, h, o, v, c)
    562 	bus_space_tag_t		t;
    563 	bus_space_handle_t	h;
    564 	bus_size_t		o, c;
    565 	const u_int8_t		v;
    566 {
    567 	while (c-- > 0)
    568 		bus_space_write_1(t, h, o, v);
    569 }
    570 
    571 extern __inline__ void
    572 bus_space_set_multi_2(t, h, o, v, c)
    573 	bus_space_tag_t		t;
    574 	bus_space_handle_t	h;
    575 	bus_size_t		o, c;
    576 	const u_int16_t		v;
    577 {
    578 	while (c-- > 0)
    579 		bus_space_write_2(t, h, o, v);
    580 }
    581 
    582 extern __inline__ void
    583 bus_space_set_multi_4(t, h, o, v, c)
    584 	bus_space_tag_t		t;
    585 	bus_space_handle_t	h;
    586 	bus_size_t		o, c;
    587 	const u_int32_t		v;
    588 {
    589 	while (c-- > 0)
    590 		bus_space_write_4(t, h, o, v);
    591 }
    592 
    593 extern __inline__ void
    594 bus_space_set_multi_8(t, h, o, v, c)
    595 	bus_space_tag_t		t;
    596 	bus_space_handle_t	h;
    597 	bus_size_t		o, c;
    598 	const u_int64_t		v;
    599 {
    600 	while (c-- > 0)
    601 		bus_space_write_8(t, h, o, v);
    602 }
    603 
    604 
    605 /*
    606  *	void bus_space_read_region_N __P((bus_space_tag_t tag,
    607  *	    bus_space_handle_t bsh, bus_size_t off,
    608  *	    u_intN_t *addr, bus_size_t count));
    609  *
    610  */
    611 void bus_space_read_region_1 __P((bus_space_tag_t,
    612 				  bus_space_handle_t,
    613 				  bus_size_t,
    614 				  u_int8_t *,
    615 				  bus_size_t));
    616 void bus_space_read_region_2 __P((bus_space_tag_t,
    617 				  bus_space_handle_t,
    618 				  bus_size_t,
    619 				  u_int16_t *,
    620 				  bus_size_t));
    621 void bus_space_read_region_4 __P((bus_space_tag_t,
    622 				  bus_space_handle_t,
    623 				  bus_size_t,
    624 				  u_int32_t *,
    625 				  bus_size_t));
    626 void bus_space_read_region_8 __P((bus_space_tag_t,
    627 				  bus_space_handle_t,
    628 				  bus_size_t,
    629 				  u_int64_t *,
    630 				  bus_size_t));
    631 
    632 extern __inline__ void
    633 bus_space_read_region_1(t, h, o, a, c)
    634 	bus_space_tag_t		t;
    635 	bus_space_handle_t	h;
    636 	bus_size_t		o, c;
    637 	u_int8_t		*a;
    638 {
    639 	for (; c; a++, c--, o++)
    640 		*a = bus_space_read_1(t, h, o);
    641 }
    642 extern __inline__ void
    643 bus_space_read_region_2(t, h, o, a, c)
    644 	bus_space_tag_t		t;
    645 	bus_space_handle_t	h;
    646 	bus_size_t		o, c;
    647 	u_int16_t		*a;
    648 {
    649 	for (; c; a++, c--, o+=2)
    650 		*a = bus_space_read_2(t, h, o);
    651 }
    652 extern __inline__ void
    653 bus_space_read_region_4(t, h, o, a, c)
    654 	bus_space_tag_t		t;
    655 	bus_space_handle_t	h;
    656 	bus_size_t		o, c;
    657 	u_int32_t		*a;
    658 {
    659 	for (; c; a++, c--, o+=4)
    660 		*a = bus_space_read_4(t, h, o);
    661 }
    662 extern __inline__ void
    663 bus_space_read_region_8(t, h, o, a, c)
    664 	bus_space_tag_t		t;
    665 	bus_space_handle_t	h;
    666 	bus_size_t		o, c;
    667 	u_int64_t		*a;
    668 {
    669 	for (; c; a++, c--, o+=8)
    670 		*a = bus_space_read_8(t, h, o);
    671 }
    672 
    673 /*
    674  *	void bus_space_write_region_N __P((bus_space_tag_t tag,
    675  *	    bus_space_handle_t bsh, bus_size_t off,
    676  *	    u_intN_t *addr, bus_size_t count));
    677  *
    678  */
    679 void bus_space_write_region_1 __P((bus_space_tag_t,
    680 				   bus_space_handle_t,
    681 				   bus_size_t,
    682 				   const u_int8_t *,
    683 				   bus_size_t));
    684 void bus_space_write_region_2 __P((bus_space_tag_t,
    685 				   bus_space_handle_t,
    686 				   bus_size_t,
    687 				   const u_int16_t *,
    688 				   bus_size_t));
    689 void bus_space_write_region_4 __P((bus_space_tag_t,
    690 				   bus_space_handle_t,
    691 				   bus_size_t,
    692 				   const u_int32_t *,
    693 				   bus_size_t));
    694 void bus_space_write_region_8 __P((bus_space_tag_t,
    695 				   bus_space_handle_t,
    696 				   bus_size_t,
    697 				   const u_int64_t *,
    698 				   bus_size_t));
    699 extern __inline__ void
    700 bus_space_write_region_1(t, h, o, a, c)
    701 	bus_space_tag_t		t;
    702 	bus_space_handle_t	h;
    703 	bus_size_t		o, c;
    704 	const u_int8_t		*a;
    705 {
    706 	for (; c; a++, c--, o++)
    707 		bus_space_write_1(t, h, o, *a);
    708 }
    709 
    710 extern __inline__ void
    711 bus_space_write_region_2(t, h, o, a, c)
    712 	bus_space_tag_t		t;
    713 	bus_space_handle_t	h;
    714 	bus_size_t		o, c;
    715 	const u_int16_t		*a;
    716 {
    717 	for (; c; a++, c--, o+=2)
    718 		bus_space_write_2(t, h, o, *a);
    719 }
    720 
    721 extern __inline__ void
    722 bus_space_write_region_4(t, h, o, a, c)
    723 	bus_space_tag_t		t;
    724 	bus_space_handle_t	h;
    725 	bus_size_t		o, c;
    726 	const u_int32_t		*a;
    727 {
    728 	for (; c; a++, c--, o+=4)
    729 		bus_space_write_4(t, h, o, *a);
    730 }
    731 
    732 extern __inline__ void
    733 bus_space_write_region_8(t, h, o, a, c)
    734 	bus_space_tag_t		t;
    735 	bus_space_handle_t	h;
    736 	bus_size_t		o, c;
    737 	const u_int64_t		*a;
    738 {
    739 	for (; c; a++, c--, o+=8)
    740 		bus_space_write_8(t, h, o, *a);
    741 }
    742 
    743 
    744 /*
    745  *	void bus_space_set_region_N __P((bus_space_tag_t tag,
    746  *	    bus_space_handle_t bsh, bus_size_t off,
    747  *	    u_intN_t *addr, bus_size_t count));
    748  *
    749  */
    750 void bus_space_set_region_1 __P((bus_space_tag_t,
    751 				 bus_space_handle_t,
    752 				 bus_size_t,
    753 				 const u_int8_t,
    754 				 bus_size_t));
    755 void bus_space_set_region_2 __P((bus_space_tag_t,
    756 				 bus_space_handle_t,
    757 				 bus_size_t,
    758 				 const u_int16_t,
    759 				 bus_size_t));
    760 void bus_space_set_region_4 __P((bus_space_tag_t,
    761 				 bus_space_handle_t,
    762 				 bus_size_t,
    763 				 const u_int32_t,
    764 				 bus_size_t));
    765 void bus_space_set_region_8 __P((bus_space_tag_t,
    766 				 bus_space_handle_t,
    767 				 bus_size_t,
    768 				 const u_int64_t,
    769 				 bus_size_t));
    770 
    771 extern __inline__ void
    772 bus_space_set_region_1(t, h, o, v, c)
    773 	bus_space_tag_t		t;
    774 	bus_space_handle_t	h;
    775 	bus_size_t		o, c;
    776 	const u_int8_t		v;
    777 {
    778 	for (; c; c--, o++)
    779 		bus_space_write_1(t, h, o, v);
    780 }
    781 
    782 extern __inline__ void
    783 bus_space_set_region_2(t, h, o, v, c)
    784 	bus_space_tag_t		t;
    785 	bus_space_handle_t	h;
    786 	bus_size_t		o, c;
    787 	const u_int16_t		v;
    788 {
    789 	for (; c; c--, o+=2)
    790 		bus_space_write_2(t, h, o, v);
    791 }
    792 
    793 extern __inline__ void
    794 bus_space_set_region_4(t, h, o, v, c)
    795 	bus_space_tag_t		t;
    796 	bus_space_handle_t	h;
    797 	bus_size_t		o, c;
    798 	const u_int32_t		v;
    799 {
    800 	for (; c; c--, o+=4)
    801 		bus_space_write_4(t, h, o, v);
    802 }
    803 
    804 extern __inline__ void
    805 bus_space_set_region_8(t, h, o, v, c)
    806 	bus_space_tag_t		t;
    807 	bus_space_handle_t	h;
    808 	bus_size_t		o, c;
    809 	const u_int64_t		v;
    810 {
    811 	for (; c; c--, o+=8)
    812 		bus_space_write_8(t, h, o, v);
    813 }
    814 
    815 
    816 /*
    817  *	void bus_space_copy_region_N __P((bus_space_tag_t tag,
    818  *	    bus_space_handle_t bsh1, bus_size_t off1,
    819  *	    bus_space_handle_t bsh2, bus_size_t off2,
    820  *	    bus_size_t count));
    821  *
    822  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
    823  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
    824  */
    825 void bus_space_copy_region_1 __P((bus_space_tag_t,
    826 				  bus_space_handle_t,
    827 				  bus_size_t,
    828 				  bus_space_handle_t,
    829 				  bus_size_t,
    830 				  bus_size_t));
    831 void bus_space_copy_region_2 __P((bus_space_tag_t,
    832 				  bus_space_handle_t,
    833 				  bus_size_t,
    834 				  bus_space_handle_t,
    835 				  bus_size_t,
    836 				  bus_size_t));
    837 void bus_space_copy_region_4 __P((bus_space_tag_t,
    838 				  bus_space_handle_t,
    839 				  bus_size_t,
    840 				  bus_space_handle_t,
    841 				  bus_size_t,
    842 				  bus_size_t));
    843 void bus_space_copy_region_8 __P((bus_space_tag_t,
    844 				  bus_space_handle_t,
    845 				  bus_size_t,
    846 				  bus_space_handle_t,
    847 				  bus_size_t,
    848 				  bus_size_t));
    849 
    850 
    851 extern __inline__ void
    852 bus_space_copy_region_1(t, h1, o1, h2, o2, c)
    853 	bus_space_tag_t		t;
    854 	bus_space_handle_t	h1, h2;
    855 	bus_size_t		o1, o2;
    856 	bus_size_t		c;
    857 {
    858 	for (; c; c--, o1++, o2++)
    859 	    bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2));
    860 }
    861 
    862 extern __inline__ void
    863 bus_space_copy_region_2(t, h1, o1, h2, o2, c)
    864 	bus_space_tag_t		t;
    865 	bus_space_handle_t	h1, h2;
    866 	bus_size_t		o1, o2;
    867 	bus_size_t		c;
    868 {
    869 	for (; c; c--, o1+=2, o2+=2)
    870 	    bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2));
    871 }
    872 
    873 extern __inline__ void
    874 bus_space_copy_region_4(t, h1, o1, h2, o2, c)
    875 	bus_space_tag_t		t;
    876 	bus_space_handle_t	h1, h2;
    877 	bus_size_t		o1, o2;
    878 	bus_size_t		c;
    879 {
    880 	for (; c; c--, o1+=4, o2+=4)
    881 	    bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2));
    882 }
    883 
    884 extern __inline__ void
    885 bus_space_copy_region_8(t, h1, o1, h2, o2, c)
    886 	bus_space_tag_t		t;
    887 	bus_space_handle_t	h1, h2;
    888 	bus_size_t		o1, o2;
    889 	bus_size_t		c;
    890 {
    891 	for (; c; c--, o1+=8, o2+=8)
    892 	    bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2));
    893 }
    894 
    895 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
    896 
    897 /*--------------------------------*/
    898 
    899 /*
    900  * Flags used in various bus DMA methods.
    901  */
    902 #define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
    903 #define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
    904 #define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
    905 #define	BUS_DMA_COHERENT	0x04	/* hint: map memory DMA coherent */
    906 #define	BUS_DMA_BUS1		0x10	/* placeholders for bus functions... */
    907 #define	BUS_DMA_BUS2		0x20
    908 #define	BUS_DMA_BUS3		0x40
    909 #define	BUS_DMA_BUS4		0x80
    910 
    911 /* For devices that have a 24-bit address space */
    912 #define BUS_DMA_24BIT		BUS_DMA_BUS1
    913 
    914 /* Internal flag: current DVMA address is equal to the KVA buffer address */
    915 #define _BUS_DMA_DIRECTMAP	BUS_DMA_BUS2
    916 
    917 /* Forwards needed by prototypes below. */
    918 struct mbuf;
    919 struct uio;
    920 
    921 /*
    922  * Operations performed by bus_dmamap_sync().
    923  */
    924 #define	BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
    925 #define	BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
    926 #define	BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
    927 #define	BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
    928 
    929 typedef struct sun2_bus_dma_tag	*bus_dma_tag_t;
    930 typedef struct sun2_bus_dmamap		*bus_dmamap_t;
    931 
    932 /*
    933  *	bus_dma_segment_t
    934  *
    935  *	Describes a single contiguous DMA transaction.  Values
    936  *	are suitable for programming into DMA registers.
    937  */
    938 struct sun2_bus_dma_segment {
    939 	bus_addr_t	ds_addr;	/* DVMA address */
    940 	bus_size_t	ds_len;		/* length of transfer */
    941 	bus_size_t	_ds_sgsize;	/* size of allocated DVMA segment */
    942 	void		*_ds_mlist;	/* page list when dmamem_alloc'ed */
    943 	vaddr_t		_ds_va;		/* VA when dmamem_map'ed */
    944 };
    945 typedef struct sun2_bus_dma_segment	bus_dma_segment_t;
    946 
    947 
    948 /*
    949  *	bus_dma_tag_t
    950  *
    951  *	A machine-dependent opaque type describing the implementation of
    952  *	DMA for a given bus.
    953  */
    954 struct sun2_bus_dma_tag {
    955 	void	*_cookie;		/* cookie used in the guts */
    956 
    957 	/*
    958 	 * DMA mapping methods.
    959 	 */
    960 	int	(*_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int,
    961 		    bus_size_t, bus_size_t, int, bus_dmamap_t *));
    962 	void	(*_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t));
    963 	int	(*_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *,
    964 		    bus_size_t, struct proc *, int));
    965 	int	(*_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t,
    966 		    struct mbuf *, int));
    967 	int	(*_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t,
    968 		    struct uio *, int));
    969 	int	(*_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t,
    970 		    bus_dma_segment_t *, int, bus_size_t, int));
    971 	void	(*_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t));
    972 	void	(*_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t,
    973 		    bus_addr_t, bus_size_t, int));
    974 
    975 	/*
    976 	 * DMA memory utility functions.
    977 	 */
    978 	int	(*_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t,
    979 		    bus_size_t, bus_dma_segment_t *, int, int *, int));
    980 	void	(*_dmamem_free) __P((bus_dma_tag_t,
    981 		    bus_dma_segment_t *, int));
    982 	int	(*_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *,
    983 		    int, size_t, caddr_t *, int));
    984 	void	(*_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t));
    985 	paddr_t	(*_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *,
    986 		    int, off_t, int, int));
    987 };
    988 
    989 #define	bus_dmamap_create(t, s, n, m, b, f, p)			\
    990 	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
    991 #define	bus_dmamap_destroy(t, p)				\
    992 	(*(t)->_dmamap_destroy)((t), (p))
    993 #define	bus_dmamap_load(t, m, b, s, p, f)			\
    994 	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
    995 #define	bus_dmamap_load_mbuf(t, m, b, f)			\
    996 	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
    997 #define	bus_dmamap_load_uio(t, m, u, f)				\
    998 	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
    999 #define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
   1000 	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
   1001 #define	bus_dmamap_unload(t, p)					\
   1002 	(*(t)->_dmamap_unload)((t), (p))
   1003 #define	bus_dmamap_sync(t, p, o, l, ops)			\
   1004 	(void)((t)->_dmamap_sync ?				\
   1005 	    (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
   1006 
   1007 #define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
   1008 	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
   1009 #define	bus_dmamem_free(t, sg, n)				\
   1010 	(*(t)->_dmamem_free)((t), (sg), (n))
   1011 #define	bus_dmamem_map(t, sg, n, s, k, f)			\
   1012 	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
   1013 #define	bus_dmamem_unmap(t, k, s)				\
   1014 	(*(t)->_dmamem_unmap)((t), (k), (s))
   1015 #define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
   1016 	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
   1017 
   1018 /*
   1019  *	bus_dmamap_t
   1020  *
   1021  *	Describes a DMA mapping.
   1022  */
   1023 struct sun2_bus_dmamap {
   1024 	/*
   1025 	 * PRIVATE MEMBERS: not for use by machine-independent code.
   1026 	 */
   1027 	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
   1028 	int		_dm_segcnt;	/* number of segs this map can map */
   1029 	bus_size_t	_dm_maxsegsz;	/* largest possible segment */
   1030 	bus_size_t	_dm_boundary;	/* don't cross this */
   1031 	int		_dm_flags;	/* misc. flags */
   1032 
   1033 	void		*_dm_cookie;	/* cookie for bus-specific functions */
   1034 
   1035 	u_long		_dm_align;	/* DVMA alignment; must be a
   1036 					   multiple of the page size */
   1037 	u_long		_dm_ex_start;	/* constraints on DVMA map */
   1038 	u_long		_dm_ex_end;	/* allocations; used by the VME bus
   1039 					   driver and by the IOMMU driver
   1040 					   when mapping 24-bit devices */
   1041 
   1042 	/*
   1043 	 * PUBLIC MEMBERS: these are used by machine-independent code.
   1044 	 */
   1045 	bus_size_t	dm_mapsize;	/* size of the mapping */
   1046 	int		dm_nsegs;	/* # valid segments in mapping */
   1047 	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
   1048 };
   1049 
   1050 #ifdef _SUN2_BUS_DMA_PRIVATE
   1051 int	_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t,
   1052 	    bus_size_t, int, bus_dmamap_t *));
   1053 void	_bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
   1054 int	_bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
   1055 	    struct mbuf *, int));
   1056 int	_bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t,
   1057 	    struct uio *, int));
   1058 int	_bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
   1059 	    bus_dma_segment_t *, int, bus_size_t, int));
   1060 void	_bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
   1061 void	_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
   1062 	    bus_size_t, int));
   1063 
   1064 int	_bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size,
   1065 	    bus_size_t alignment, bus_size_t boundary,
   1066 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags));
   1067 void	_bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
   1068 	    int nsegs));
   1069 void	_bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva,
   1070 	    size_t size));
   1071 paddr_t	_bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
   1072 	    int nsegs, off_t off, int prot, int flags));
   1073 
   1074 int	_bus_dmamem_alloc_range __P((bus_dma_tag_t tag, bus_size_t size,
   1075 	    bus_size_t alignment, bus_size_t boundary,
   1076 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
   1077 	    vaddr_t low, vaddr_t high));
   1078 
   1079 vaddr_t	_bus_dma_valloc_skewed(size_t, u_long, u_long, u_long);
   1080 #endif /* _SUN2_BUS_DMA_PRIVATE */
   1081 
   1082 #endif /* _SUN2_BUS_H_ */
   1083