xref: /netbsd/sys/arch/hp300/include/bus.h (revision 2187b58f)
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
bus_space_mmap(bus_space_tag_t t,bus_addr_t addr,off_t off,int prot,int flags)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