xref: /netbsd-src/sys/arch/hp300/include/bus.h (revision e77448e07be3174235c13f58032a0d6d0ab7638d)
1 /*	$NetBSD: bus.h,v 1.15 2008/04/28 20:23:19 martin 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 
68 /*
69  * Bus address and size types
70  */
71 typedef u_long bus_addr_t;
72 typedef u_long bus_size_t;
73 
74 /*
75  * Access methods for bus resources and address space.
76  */
77 typedef struct bus_space_tag *bus_space_tag_t;
78 typedef u_long bus_space_handle_t;
79 
80 /*
81  * Implementation specific structures.
82  * XXX Don't use outside of bus_space definitions!
83  * XXX maybe this should be encapsuled in a non-global .h file?
84  */
85 
86 struct bus_space_tag {
87 	u_int		bustype;
88 
89 	uint8_t		(*bsr1)(bus_space_tag_t, bus_space_handle_t,
90 			    bus_size_t);
91 	uint16_t	(*bsr2)(bus_space_tag_t, bus_space_handle_t,
92 			    bus_size_t);
93 	uint32_t	(*bsr4)(bus_space_tag_t, bus_space_handle_t,
94 			    bus_size_t);
95 	void		(*bsrm1)(bus_space_tag_t, bus_space_handle_t,
96 			    bus_size_t, uint8_t *, bus_size_t);
97 	void		(*bsrm2)(bus_space_tag_t, bus_space_handle_t,
98 			    bus_size_t, uint16_t *, bus_size_t);
99 	void		(*bsrm4)(bus_space_tag_t, bus_space_handle_t,
100 			    bus_size_t, uint32_t *, bus_size_t);
101 	void		(*bsrr1)(bus_space_tag_t, bus_space_handle_t,
102 			    bus_size_t, uint8_t *, bus_size_t);
103 	void		(*bsrr2)(bus_space_tag_t, bus_space_handle_t,
104 			    bus_size_t, uint16_t *, bus_size_t);
105 	void		(*bsrr4)(bus_space_tag_t, bus_space_handle_t,
106 			    bus_size_t, uint32_t *, bus_size_t);
107 	void		(*bsw1)(bus_space_tag_t, bus_space_handle_t,
108 			    bus_size_t, uint8_t);
109 	void		(*bsw2)(bus_space_tag_t, bus_space_handle_t,
110 			    bus_size_t, uint16_t);
111 	void		(*bsw4)(bus_space_tag_t, bus_space_handle_t,
112 			    bus_size_t, uint32_t);
113 	void		(*bswm1)(bus_space_tag_t, bus_space_handle_t,
114 			    bus_size_t, const uint8_t *, bus_size_t);
115 	void		(*bswm2)(bus_space_tag_t, bus_space_handle_t,
116 			    bus_size_t, const uint16_t *, bus_size_t);
117 	void		(*bswm4)(bus_space_tag_t, bus_space_handle_t,
118 			    bus_size_t, const uint32_t *, bus_size_t);
119 	void		(*bswr1)(bus_space_tag_t, bus_space_handle_t ,
120 			    bus_size_t, const uint8_t *, bus_size_t);
121 	void		(*bswr2)(bus_space_tag_t, bus_space_handle_t,
122 			    bus_size_t, const uint16_t *, bus_size_t);
123 	void		(*bswr4)(bus_space_tag_t, bus_space_handle_t,
124 			    bus_size_t, const uint32_t *, bus_size_t);
125 	void		(*bssm1)(bus_space_tag_t, bus_space_handle_t,
126 			    bus_size_t, uint8_t, bus_size_t);
127 	void		(*bssm2)(bus_space_tag_t, bus_space_handle_t,
128 			    bus_size_t, uint16_t, bus_size_t);
129 	void		(*bssm4)(bus_space_tag_t, bus_space_handle_t,
130 			    bus_size_t, uint32_t, bus_size_t);
131 	void		(*bssr1)(bus_space_tag_t, bus_space_handle_t,
132 			    bus_size_t, uint8_t, bus_size_t);
133 	void		(*bssr2)(bus_space_tag_t, bus_space_handle_t,
134 			    bus_size_t, uint16_t, bus_size_t);
135 	void		(*bssr4)(bus_space_tag_t, bus_space_handle_t,
136 			    bus_size_t, uint32_t, bus_size_t);
137 };
138 
139 /*
140  *	int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
141  *	    bus_size_t size, int flags, bus_space_handle_t *bshp);
142  *
143  * Map a region of bus space.
144  */
145 
146 #define	BUS_SPACE_MAP_CACHEABLE		0x01
147 #define	BUS_SPACE_MAP_LINEAR		0x02
148 #define	BUS_SPACE_MAP_PREFETCHABLE	0x04
149 
150 int	bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t,
151 	    int, bus_space_handle_t *);
152 
153 /*
154  *	void bus_space_unmap(bus_space_tag_t t,
155  *	    bus_space_handle_t bsh, bus_size_t size);
156  *
157  * Unmap a region of bus space.
158  */
159 
160 void	bus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
161 
162 /*
163  *	int bus_space_subregion(bus_space_tag_t t,
164  *	    bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
165  *	    bus_space_handle_t *nbshp);
166  *
167  * Get a new handle for a subregion of an already-mapped area of bus space.
168  */
169 
170 int	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
171 	    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
172 
173 /*
174  *	int bus_space_alloc(bus_space_tag_t t, bus_addr_t, rstart,
175  *	    bus_addr_t rend, bus_size_t size, bus_size_t align,
176  *	    bus_size_t boundary, int flags, bus_addr_t *addrp,
177  *	    bus_space_handle_t *bshp);
178  *
179  * Allocate a region of bus space.
180  */
181 
182 int	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
183 	    bus_addr_t rend, bus_size_t size, bus_size_t align,
184 	    bus_size_t boundary, int cacheable, bus_addr_t *addrp,
185 	    bus_space_handle_t *bshp);
186 
187 /*
188  *	int bus_space_free(bus_space_tag_t t,
189  *	    bus_space_handle_t bsh, bus_size_t size);
190  *
191  * Free a region of bus space.
192  */
193 
194 void	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
195 	    bus_size_t size);
196 
197 /*
198  *	void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
199  *
200  * Get the kernel virtual address for the mapped bus space.
201  * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
202  *  (XXX not enforced)
203  */
204 #define bus_space_vaddr(t, h)	(void *)(h)
205 
206 /*
207  *	int hp300_bus_space_probe(bus_space_tag_t t,
208  *	    bus_space_handle_t bsh, bus_size_t offset, int sz);
209  *
210  * Probe the bus at t/bsh/offset, using sz as the size of the load.
211  *
212  * This is a machine-dependent extension, and is not to be used by
213  * machine-independent code.
214  */
215 
216 int	hp300_bus_space_probe(bus_space_tag_t t,
217 	    bus_space_handle_t bsh, bus_size_t offset, int sz);
218 
219 /*
220  *	u_intN_t bus_space_read_N(bus_space_tag_t tag,
221  *	    bus_space_handle_t bsh, bus_size_t offset);
222  *
223  * Read a 1, 2, 4, or 8 byte quantity from bus space
224  * described by tag/handle/offset.
225  */
226 
227 #define	bus_space_read_1(t, h, o)					\
228     (((t)->bsr1 != NULL) ? ((t)->bsr1)(t, h, o) :			\
229     (*(volatile uint8_t *)((h) + (o))))
230 
231 #define	bus_space_read_2(t, h, o)					\
232     (((t)->bsr2 != NULL) ? ((t)->bsr2)(t, h, o) :			\
233     (*(volatile uint16_t *)((h) + (o))))
234 
235 #define	bus_space_read_4(t, h, o)					\
236     (((t)->bsr4 != NULL) ? ((t)->bsr4)(t, h, o) :			\
237     (*(volatile uint32_t *)((h) + (o))))
238 
239 #if 0	/* Cause a link error for bus_space_read_8 */
240 #define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
241 #endif
242 
243 /*
244  *	void bus_space_read_multi_N(bus_space_tag_t tag,
245  *	    bus_space_handle_t bsh, bus_size_t offset,
246  *	    u_intN_t *addr, size_t count);
247  *
248  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
249  * described by tag/handle/offset and copy into buffer provided.
250  */
251 
252 #define	bus_space_read_multi_1(t, h, o, a, c)				\
253 do {									\
254 	if ((t)->bsrm1 != NULL)						\
255 		((t)->bsrm1)(t, h, o, a, c);				\
256 	else {								\
257 		__asm volatile ("					\
258 			movl	%0,%%a0				;	\
259 			movl	%1,%%a1				;	\
260 			movl	%2,%%d0				;	\
261 		1:	movb	%%a0@,%%a1@+			;	\
262 			subql	#1,%%d0				;	\
263 			jne	1b"				:	\
264 								:	\
265 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
266 			    "%a0","%a1","%d0");				\
267 	}								\
268 } while (/* CONSTCOND */ 0)
269 
270 #define	bus_space_read_multi_2(t, h, o, a, c)				\
271 do {									\
272 	if ((t)->bsrm2 != NULL)						\
273 		((t)->bsrm2)(t, h, o, a, c);				\
274 	else {								\
275 		__asm volatile ("					\
276 			movl	%0,%%a0				;	\
277 			movl	%1,%%a1				;	\
278 			movl	%2,%%d0				;	\
279 		1:	movw	%%a0@,%%a1@+			;	\
280 			subql	#1,%%d0				;	\
281 			jne	1b"				:	\
282 								:	\
283 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
284 			    "%a0","%a1","%d0");				\
285 	}								\
286 } while (/* CONSTCOND */ 0)
287 
288 #define	bus_space_read_multi_4(t, h, o, a, c) do {			\
289 	if ((t)->bsrm4 != NULL)						\
290 		((t)->bsrm4)(t, h, o, a, c);				\
291 	else {								\
292 		__asm volatile ("					\
293 			movl	%0,%%a0				;	\
294 			movl	%1,%%a1				;	\
295 			movl	%2,%%d0				;	\
296 		1:	movl	%%a0@,%%a1@+			;	\
297 			subql	#1,%%d0				;	\
298 			jne	1b"				:	\
299 								:	\
300 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
301 			    "%a0","%a1","%d0");				\
302 	}								\
303 } while (/* CONSTCOND */ 0)
304 
305 #if 0	/* Cause a link error for bus_space_read_multi_8 */
306 #define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
307 #endif
308 
309 /*
310  *	void bus_space_read_region_N(bus_space_tag_t tag,
311  *	    bus_space_handle_t bsh, bus_size_t offset,
312  *	    u_intN_t *addr, size_t count);
313  *
314  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
315  * described by tag/handle and starting at `offset' and copy into
316  * buffer provided.
317  */
318 
319 #define	bus_space_read_region_1(t, h, o, a, c)				\
320 do {									\
321 	if ((t)->bsrr1 != NULL)						\
322 		((t)->bsrr1)(t, h, o, a, c);				\
323 	else {								\
324 		__asm volatile ("					\
325 			movl	%0,%%a0				;	\
326 			movl	%1,%%a1				;	\
327 			movl	%2,%%d0				;	\
328 		1:	movb	%%a0@+,%%a1@+			;	\
329 			subql	#1,%%d0				;	\
330 			jne	1b"				:	\
331 								:	\
332 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
333 			    "%a0","%a1","%d0");				\
334 	}								\
335 } while (/* CONSTCOND */ 0)
336 
337 #define	bus_space_read_region_2(t, h, o, a, c)				\
338 do {									\
339 	if ((t)->bsrr2 != NULL)						\
340 		((t)->bsrr2)(t, h, o, a, c);				\
341 	else {								\
342 		__asm volatile ("					\
343 			movl	%0,%%a0				;	\
344 			movl	%1,%%a1				;	\
345 			movl	%2,%%d0				;	\
346 		1:	movw	%%a0@+,%%a1@+			;	\
347 			subql	#1,%%d0				;	\
348 			jne	1b"				:	\
349 								:	\
350 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
351 			    "%a0","%a1","%d0");				\
352 	}								\
353 } while (/* CONSTCOND */ 0)
354 
355 #define	bus_space_read_region_4(t, h, o, a, c)				\
356 do {									\
357 	if ((t)->bsrr4 != NULL)						\
358 		((t)->bsrr4)(t, h, o, a, c);				\
359 	else {								\
360 		__asm volatile ("					\
361 			movl	%0,%%a0				;	\
362 			movl	%1,%%a1				;	\
363 			movl	%2,%%d0				;	\
364 		1:	movl	%%a0@+,%%a1@+			;	\
365 			subql	#1,%%d0				;	\
366 			jne	1b"				:	\
367 								:	\
368 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
369 			    "%a0","%a1","%d0");				\
370 	}								\
371 } while (/* CONSTCOND */ 0)
372 
373 #if 0	/* Cause a link error for bus_space_read_region_8 */
374 #define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
375 #endif
376 
377 /*
378  *	void bus_space_write_N(bus_space_tag_t tag,
379  *	    bus_space_handle_t bsh, bus_size_t offset,
380  *	    u_intN_t value);
381  *
382  * Write the 1, 2, 4, or 8 byte value `value' to bus space
383  * described by tag/handle/offset.
384  */
385 
386 #define	bus_space_write_1(t, h, o, v)					\
387 do {									\
388 	if ((t)->bsw1 != NULL)						\
389 		((t)->bsw1)(t, h, o, v);				\
390 	else								\
391 		((void)(*(volatile uint8_t *)((h) + (o)) = (v)));	\
392 } while (/* CONSTCOND */ 0)
393 
394 #define	bus_space_write_2(t, h, o, v)					\
395 do {									\
396 	if ((t)->bsw2 != NULL)						\
397 		((t)->bsw2)(t, h, o, v);				\
398 	else								\
399 		((void)(*(volatile uint16_t *)((h) + (o)) = (v)));	\
400 } while (/* CONSTCOND */ 0)
401 
402 #define	bus_space_write_4(t, h, o, v)					\
403 do {									\
404 	if ((t)->bsw4 != NULL)						\
405 		((t)->bsw4)(t, h, o, v);				\
406 	else								\
407 		((void)(*(volatile uint32_t *)((h) + (o)) = (v)));	\
408 } while (/* CONSTCOND */ 0)
409 
410 #if 0	/* Cause a link error for bus_space_write_8 */
411 #define	bus_space_write_8	!!! bus_space_write_8 not implemented !!!
412 #endif
413 
414 /*
415  *	void bus_space_write_multi_N(bus_space_tag_t tag,
416  *	    bus_space_handle_t bsh, bus_size_t offset,
417  *	    const u_intN_t *addr, size_t count);
418  *
419  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
420  * provided to bus space described by tag/handle/offset.
421  */
422 
423 #define	bus_space_write_multi_1(t, h, o, a, c)				\
424 do {									\
425 	if ((t)->bswm1 != NULL)						\
426 		((t)->bswm1)(t, h, o, a, c);				\
427 	else {								\
428 		__asm volatile ("					\
429 			movl	%0,%%a0				;	\
430 			movl	%1,%%a1				;	\
431 			movl	%2,%%d0				;	\
432 		1:	movb	%%a1@+,%%a0@			;	\
433 			subql	#1,%%d0				;	\
434 			jne	1b"				:	\
435 								:	\
436 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
437 			    "%a0","%a1","%d0");				\
438 	}								\
439 } while (/* CONSTCOND */ 0)
440 
441 #define	bus_space_write_multi_2(t, h, o, a, c)				\
442 do {									\
443 	if ((t)->bswm2 != NULL)						\
444 		((t)->bswm2)(t, h, o, a, c);				\
445 	else {								\
446 		__asm volatile ("					\
447 			movl	%0,%%a0				;	\
448 			movl	%1,%%a1				;	\
449 			movl	%2,%%d0				;	\
450 		1:	movw	%%a1@+,%%a0@			;	\
451 			subql	#1,%%d0				;	\
452 			jne	1b"				:	\
453 								:	\
454 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
455 			    "%a0","%a1","%d0");				\
456 	}								\
457 } while (/* CONSTCOND */ 0)
458 
459 #define	bus_space_write_multi_4(t, h, o, a, c)				\
460 do {									\
461 	(void) t;							\
462 	if ((t)->bswm4 != NULL)					\
463 		((t)->bswm4)(t, h, o, a, c);				\
464 	else {								\
465 		__asm volatile ("					\
466 			movl	%0,%%a0				;	\
467 			movl	%1,%%a1				;	\
468 			movl	%2,%%d0				;	\
469 		1:	movl	%%a1@+,%%a0@			;	\
470 			subql	#1,%%d0				;	\
471 			jne	1b"				:	\
472 								:	\
473 			    "r" ((h) + (o)), "g" (a), "g" (c)	:	\
474 			    "%a0","%a1","%d0");				\
475 	}								\
476 } while (/* CONSTCOND */ 0)
477 
478 #if 0	/* Cause a link error for bus_space_write_8 */
479 #define	bus_space_write_multi_8(t, h, o, a, c)				\
480 			!!! bus_space_write_multi_8 unimplimented !!!
481 #endif
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 #if 0	/* Cause a link error for bus_space_write_region_8 */
547 #define	bus_space_write_region_8					\
548 			!!! bus_space_write_region_8 unimplemented !!!
549 #endif
550 
551 /*
552  *	void bus_space_set_multi_N(bus_space_tag_t tag,
553  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
554  *	    size_t count);
555  *
556  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
557  * by tag/handle/offset `count' times.
558  */
559 
560 #define	bus_space_set_multi_1(t, h, o, val, c)				\
561 do {									\
562 	if ((t)->bssm1 != NULL)						\
563 		((t)->bssm1)(t, h, o, val, c);				\
564 	else {								\
565 		__asm volatile ("					\
566 			movl	%0,%%a0				;	\
567 			movl	%1,%%d1				;	\
568 			movl	%2,%%d0				;	\
569 		1:	movb	%%d1,%%a0@			;	\
570 			subql	#1,%%d0				;	\
571 			jne	1b"				:	\
572 								:	\
573 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
574 			    "%a0","%d0","%d1");				\
575 	}								\
576 } while (/* CONSTCOND */ 0)
577 
578 #define	bus_space_set_multi_2(t, h, o, val, c)				\
579 do {									\
580 	if ((t)->bssm2 != NULL)						\
581 		((t)->bssm2)(t, h, o, val, c);				\
582 	else {								\
583 		__asm volatile ("					\
584 			movl	%0,%%a0				;	\
585 			movl	%1,%%d1				;	\
586 			movl	%2,%%d0				;	\
587 		1:	movw	%%d1,%%a0@			;	\
588 			subql	#1,%%d0				;	\
589 			jne	1b"				:	\
590 								:	\
591 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
592 			    "%a0","%d0","%d1");				\
593 	}								\
594 } while (/* CONSTCOND */ 0)
595 
596 #define	bus_space_set_multi_4(t, h, o, val, c)				\
597 do {									\
598 	if ((t)->bssm4 != NULL)						\
599 		((t)->bssm4)(t, h, o, val, c);				\
600 	else {								\
601 		__asm volatile ("					\
602 			movl	%0,%%a0				;	\
603 			movl	%1,%%d1				;	\
604 			movl	%2,%%d0				;	\
605 		1:	movl	%%d1,%%a0@			;	\
606 			subql	#1,%%d0				;	\
607 			jne	1b"				:	\
608 								:	\
609 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
610 			    "%a0","%d0","%d1");				\
611 	}								\
612 } while (/* CONSTCOND */ 0)
613 
614 #if 0	/* Cause a link error for bus_space_set_multi_8 */
615 #define	bus_space_set_multi_8						\
616 			!!! bus_space_set_multi_8 unimplemented !!!
617 #endif
618 
619 /*
620  *	void bus_space_set_region_N(bus_space_tag_t tag,
621  *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
622  *	    size_t count);
623  *
624  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
625  * by tag/handle starting at `offset'.
626  */
627 
628 #define	bus_space_set_region_1(t, h, o, val, c)				\
629 do {									\
630 	if ((t)->bssr1 != NULL)						\
631 		((t)->bssr1)(t, h, o, val, c);				\
632 	else {								\
633 		__asm volatile ("					\
634 			movl	%0,%%a0				;	\
635 			movl	%1,%%d1				;	\
636 			movl	%2,%%d0				;	\
637 		1:	movb	%%d1,%%a0@+			;	\
638 			subql	#1,%%d0				;	\
639 			jne	1b"				:	\
640 								:	\
641 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
642 			    "%a0","%d0","%d1");				\
643 	}								\
644 } while (/* CONSTCOND */ 0)
645 
646 #define	bus_space_set_region_2(t, h, o, val, c)				\
647 do {									\
648 	if ((t)->bssr2 != NULL)						\
649 		((t)->bssr2)(t, h, o, val, c);				\
650 	else {								\
651 		__asm volatile ("					\
652 			movl	%0,%%a0				;	\
653 			movl	%1,%%d1				;	\
654 			movl	%2,%%d0				;	\
655 		1:	movw	%%d1,%%a0@+			;	\
656 			subql	#1,%%d0				;	\
657 			jne	1b"				:	\
658 								:	\
659 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
660 			    "%a0","%d0","%d1");				\
661 	}								\
662 } while (/* CONSTCOND */ 0)
663 
664 #define	bus_space_set_region_4(t, h, o, val, c)				\
665 do {									\
666 	(void) t;							\
667 	if ((t)->bssr4 != NULL)						\
668 		((t)->bssr4)(t, h, o, val, c);				\
669 	else {								\
670 		__asm volatile ("					\
671 			movl	%0,%%a0				;	\
672 			movl	%1,%%d1				;	\
673 			movl	%2,%%d0				;	\
674 		1:	movl	%%d1,%%a0@+			;	\
675 			subql	#1,%%d0				;	\
676 			jne	1b"				:	\
677 								:	\
678 			    "r" ((h) + (o)), "g" (val), "g" (c)	:	\
679 			    "%a0","%d0","%d1");				\
680 	}								\
681 } while (/* CONSTCOND */ 0)
682 
683 #if 0	/* Cause a link error for bus_space_set_region_8 */
684 #define	bus_space_set_region_8						\
685 			!!! bus_space_set_region_8 unimplemented !!!
686 #endif
687 
688 /*
689  *	void bus_space_copy_region_N(bus_space_tag_t tag,
690  *	    bus_space_handle_t bsh1, bus_size_t off1,
691  *	    bus_space_handle_t bsh2, bus_size_t off2,
692  *	    bus_size_t count);
693  *
694  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
695  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
696  */
697 
698 #define	__HP300_copy_region_N(BYTES)					\
699 static __inline void						\
700 __CONCAT(bus_space_copy_region_,BYTES)(bus_space_tag_t t,		\
701     bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2,	\
702     bus_size_t o2, bus_size_t c)					\
703 {									\
704 	bus_size_t o;							\
705 									\
706 	if ((h1 + o1) >= (h2 + o2)) {					\
707 		/* src after dest: copy forward */			\
708 		for (o = 0; c != 0; c--, o += BYTES)			\
709 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
710 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
711 	} else {							\
712 		/* dest after src: copy backwards */			\
713 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
714 			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
715 			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
716 	}								\
717 }
718 __HP300_copy_region_N(1)
719 __HP300_copy_region_N(2)
720 __HP300_copy_region_N(4)
721 #if 0	/* Cause a link error for bus_space_copy_region_8 */
722 #define	bus_space_copy_region_8						\
723 			!!! bus_space_copy_region_8 unimplemented !!!
724 #endif
725 
726 #undef __HP300_copy_region_N
727 
728 /*
729  * Bus read/write barrier methods.
730  *
731  *	void bus_space_barrier(bus_space_tag_t tag,
732  *	    bus_space_handle_t bsh, bus_size_t offset,
733  *	    bus_size_t len, int flags);
734  *
735  * Note: the 680x0 does not currently require barriers, but we must
736  * provide the flags to MI code.
737  */
738 #define	bus_space_barrier(t, h, o, l, f)	\
739 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
740 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
741 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
742 
743 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
744 
745 #endif /* _HP300_BUS_H_ */
746