1/*	$NetBSD: bus_space.h,v 1.23 2023/02/11 02:31:34 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 _NEXT68K_BUS_SPACE_H_
60#define	_NEXT68K_BUS_SPACE_H_
61/*
62 * Addresses (in bus space).
63 */
64typedef u_long bus_addr_t;
65typedef u_long bus_size_t;
66
67#define PRIxBUSADDR	"lx"
68#define PRIxBUSSIZE	"lx"
69#define PRIuBUSSIZE	"lu"
70
71/*
72 * Access methods for bus resources and address space.
73 */
74typedef volatile char *  bus_space_tag_t;
75typedef u_long	bus_space_handle_t;
76
77#define PRIxBSH		"lx"
78
79/*
80 * Value for the next68k bus space tag, not to be used directly by MI code.
81 */
82#define NEXT68K_INTIO_BUS_SPACE		((bus_space_tag_t)intiobase)
83
84/*
85 * Mapping and unmapping operations.
86 */
87
88int bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
89    bus_space_handle_t *);
90
91#define	bus_space_unmap(t, h, s)
92
93#define	bus_space_subregion(t, h, o, s, hp)				\
94     (*(hp)=(h)+(o))
95
96#define	BUS_SPACE_MAP_CACHEABLE		0x01
97#define	BUS_SPACE_MAP_LINEAR		0x02
98
99/*
100 * Allocation and deallocation operations.
101 */
102#define	bus_space_alloc(t, rs, re, s, a, b, f, ap, hp)  		\
103     (-1)
104
105#define	bus_space_free(t, h, s)
106
107/*
108 *	paddr_t bus_space_mmap(bus_space_tag_t t, bus_addr_t base,
109 *	    off_t offset, int prot, int flags);
110 *
111 * Mmap an area of bus space.
112 */
113
114paddr_t bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
115
116/*
117 *	uintN_t bus_space_read_N(bus_space_tag_t tag,
118 *	    bus_space_handle_t bsh, bus_size_t offset);
119 *
120 * Read a 1, 2, 4, or 8 byte quantity from bus space
121 * described by tag/handle/offset.
122 */
123
124#define	bus_space_read_1(t, h, o)					\
125    ((void) t, (*(volatile uint8_t *)((h) + (o))))
126
127#define	bus_space_read_2(t, h, o)					\
128    ((void) t, (*(volatile uint16_t *)((h) + (o))))
129
130#define	bus_space_read_4(t, h, o)					\
131    ((void) t, (*(volatile uint32_t *)((h) + (o))))
132
133/*
134 *	void bus_space_read_multi_N(bus_space_tag_t tag,
135 *	    bus_space_handle_t bsh, bus_size_t offset,
136 *	    uintN_t *addr, size_t count);
137 *
138 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
139 * described by tag/handle/offset and copy into buffer provided.
140 */
141
142#define	bus_space_read_multi_1(t, h, o, a, c) do {			\
143	(void) t;							\
144	__asm volatile ("						\
145		movl	%0,%%a0					;	\
146		movl	%1,%%a1					;	\
147		movl	%2,%%d0					;	\
148	1:	movb	%%a0@,%%a1@+				;	\
149		subql	#1,%%d0					;	\
150		jne	1b"					:	\
151								:	\
152		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
153		    "a0","a1","d0","memory");				\
154} while (0);
155
156#define	bus_space_read_multi_2(t, h, o, a, c) do {			\
157	(void) t;							\
158	__asm volatile ("						\
159		movl	%0,%%a0					;	\
160		movl	%1,%%a1					;	\
161		movl	%2,%%d0					;	\
162	1:	movw	%%a0@,%%a1@+				;	\
163		subql	#1,%%d0					;	\
164		jne	1b"					:	\
165								:	\
166		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
167		    "a0","a1","d0","memory");				\
168} while (0);
169
170#define	bus_space_read_multi_4(t, h, o, a, c) do {			\
171	(void) t;							\
172	__asm volatile ("						\
173		movl	%0,%%a0					;	\
174		movl	%1,%%a1					;	\
175		movl	%2,%%d0					;	\
176	1:	movl	%%a0@,%%a1@+				;	\
177		subql	#1,%%d0					;	\
178		jne	1b"					:	\
179								:	\
180		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
181		    "a0","a1","d0","memory");				\
182} while (0);
183
184/*
185 *	void bus_space_read_region_N(bus_space_tag_t tag,
186 *	    bus_space_handle_t bsh, bus_size_t offset,
187 *	    uintN_t *addr, size_t count);
188 *
189 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
190 * described by tag/handle and starting at `offset' and copy into
191 * buffer provided.
192 */
193
194#define	bus_space_read_region_1(t, h, o, a, c) do {			\
195	(void) t;							\
196	__asm volatile ("						\
197		movl	%0,%%a0					;	\
198		movl	%1,%%a1					;	\
199		movl	%2,%%d0					;	\
200	1:	movb	%%a0@+,%%a1@+				;	\
201		subql	#1,%%d0					;	\
202		jne	1b"					:	\
203								:	\
204		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
205		    "a0","a1","d0","memory");				\
206} while (0);
207
208#define	bus_space_read_region_2(t, h, o, a, c) do {			\
209	(void) t;							\
210	__asm volatile ("						\
211		movl	%0,%%a0					;	\
212		movl	%1,%%a1					;	\
213		movl	%2,%%d0					;	\
214	1:	movw	%%a0@+,%%a1@+				;	\
215		subql	#1,%%d0					;	\
216		jne	1b"					:	\
217								:	\
218		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
219		    "a0","a1","d0","memory");					\
220} while (0);
221
222#define	bus_space_read_region_4(t, h, o, a, c) do {			\
223	(void) t;							\
224	__asm volatile ("						\
225		movl	%0,%%a0					;	\
226		movl	%1,%%a1					;	\
227		movl	%2,%%d0					;	\
228	1:	movl	%%a0@+,%%a1@+				;	\
229		subql	#1,%%d0					;	\
230		jne	1b"					:	\
231								:	\
232		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
233		    "a0","a1","d0","memory");					\
234} while (0);
235
236/*
237 *	void bus_space_write_N(bus_space_tag_t tag,
238 *	    bus_space_handle_t bsh, bus_size_t offset,
239 *	    uintN_t value);
240 *
241 * Write the 1, 2, 4, or 8 byte value `value' to bus space
242 * described by tag/handle/offset.
243 */
244
245#define	bus_space_write_1(t, h, o, v)					\
246    ((void) t, ((void)(*(volatile uint8_t *)((h) + (o)) = (v))))
247
248#define	bus_space_write_2(t, h, o, v)					\
249    ((void) t, ((void)(*(volatile uint16_t *)((h) + (o)) = (v))))
250
251#define	bus_space_write_4(t, h, o, v)					\
252    ((void) t, ((void)(*(volatile uint32_t *)((h) + (o)) = (v))))
253
254/*
255 *	void bus_space_write_multi_N(bus_space_tag_t tag,
256 *	    bus_space_handle_t bsh, bus_size_t offset,
257 *	    const uintN_t *addr, size_t count);
258 *
259 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
260 * provided to bus space described by tag/handle/offset.
261 */
262
263#define	bus_space_write_multi_1(t, h, o, a, c) do {			\
264	(void) t;							\
265	__asm volatile ("						\
266		movl	%0,%%a0					;	\
267		movl	%1,%%a1					;	\
268		movl	%2,%%d0					;	\
269	1:	movb	%%a1@+,%%a0@				;	\
270		subql	#1,%%d0					;	\
271		jne	1b"					:	\
272								:	\
273		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
274		    "a0","a1","d0");					\
275} while (0);
276
277#define	bus_space_write_multi_2(t, h, o, a, c) do {			\
278	(void) t;							\
279	__asm volatile ("						\
280		movl	%0,%%a0					;	\
281		movl	%1,%%a1					;	\
282		movl	%2,%%d0					;	\
283	1:	movw	%%a1@+,%%a0@				;	\
284		subql	#1,%%d0					;	\
285		jne	1b"					:	\
286								:	\
287		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
288		    "a0","a1","d0");					\
289} while (0);
290
291#define	bus_space_write_multi_4(t, h, o, a, c) do {			\
292	(void) t;							\
293	__asm volatile ("						\
294		movl	%0,%%a0					;	\
295		movl	%1,%%a1					;	\
296		movl	%2,%%d0					;	\
297	1:	movl	%%a1@+,%%a0@				;	\
298		subql	#1,%%d0					;	\
299		jne	1b"					:	\
300								:	\
301		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
302		    "a0","a1","d0");					\
303} while (0);
304
305/*
306 *	void bus_space_write_region_N(bus_space_tag_t tag,
307 *	    bus_space_handle_t bsh, bus_size_t offset,
308 *	    const uintN_t *addr, size_t count);
309 *
310 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
311 * to bus space described by tag/handle starting at `offset'.
312 */
313
314#define	bus_space_write_region_1(t, h, o, a, c) do {			\
315	(void) t;							\
316	__asm volatile ("						\
317		movl	%0,%%a0					;	\
318		movl	%1,%%a1					;	\
319		movl	%2,%%d0					;	\
320	1:	movb	%%a1@+,%%a0@+				;	\
321		subql	#1,%%d0					;	\
322		jne	1b"					:	\
323								:	\
324		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
325		    "a0","a1","d0");					\
326} while (0);
327
328#define	bus_space_write_region_2(t, h, o, a, c) do {			\
329	(void) t;							\
330	__asm volatile ("						\
331		movl	%0,%%a0					;	\
332		movl	%1,%%a1					;	\
333		movl	%2,%%d0					;	\
334	1:	movw	%%a1@+,%%a0@+				;	\
335		subql	#1,%%d0					;	\
336		jne	1b"					:	\
337								:	\
338		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
339		    "a0","a1","d0");					\
340} while (0);
341
342#define	bus_space_write_region_4(t, h, o, a, c) do {			\
343	(void) t;							\
344	__asm volatile ("						\
345		movl	%0,%%a0					;	\
346		movl	%1,%%a1					;	\
347		movl	%2,%%d0					;	\
348	1:	movl	%%a1@+,%%a0@+				;	\
349		subql	#1,%%d0					;	\
350		jne	1b"					:	\
351								:	\
352		    "r" ((h) + (o)), "g" (a), "g" (c)		:	\
353		    "a0","a1","d0");					\
354} while (0);
355
356/*
357 *	void bus_space_set_multi_N(bus_space_tag_t tag,
358 *	    bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
359 *	    size_t count);
360 *
361 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
362 * by tag/handle/offset `count' times.
363 */
364
365#define	bus_space_set_multi_1(t, h, o, val, c) do {			\
366	(void) t;							\
367	__asm volatile ("						\
368		movl	%0,%%a0					;	\
369		movl	%1,%%d1					;	\
370		movl	%2,%%d0					;	\
371	1:	movb	%%d1,%%a0@				;	\
372		subql	#1,%%d0					;	\
373		jne	1b"					:	\
374								:	\
375		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
376		    "a0","d0","d1");					\
377} while (0);
378
379#define	bus_space_set_multi_2(t, h, o, val, c) do {			\
380	(void) t;							\
381	__asm volatile ("						\
382		movl	%0,%%a0					;	\
383		movl	%1,%%d1					;	\
384		movl	%2,%%d0					;	\
385	1:	movw	%%d1,%%a0@				;	\
386		subql	#1,%%d0					;	\
387		jne	1b"					:	\
388								:	\
389		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
390		    "a0","d0","d1");					\
391} while (0);
392
393#define	bus_space_set_multi_4(t, h, o, val, c) do {			\
394	(void) t;							\
395	__asm volatile ("						\
396		movl	%0,%%a0					;	\
397		movl	%1,%%d1					;	\
398		movl	%2,%%d0					;	\
399	1:	movl	%%d1,%%a0@				;	\
400		subql	#1,%%d0					;	\
401		jne	1b"					:	\
402								:	\
403		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
404		    "a0","d0","d1");					\
405} while (0);
406
407/*
408 *	void bus_space_set_region_N(bus_space_tag_t tag,
409 *	    bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
410 *	    size_t count);
411 *
412 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
413 * by tag/handle starting at `offset'.
414 */
415
416#define	bus_space_set_region_1(t, h, o, val, c) do {			\
417	(void) t;							\
418	__asm volatile ("						\
419		movl	%0,%%a0					;	\
420		movl	%1,%%d1					;	\
421		movl	%2,%%d0					;	\
422	1:	movb	%%d1,%%a0@+				;	\
423		subql	#1,%%d0					;	\
424		jne	1b"					:	\
425								:	\
426		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
427		    "a0","d0","d1");					\
428} while (0);
429
430#define	bus_space_set_region_2(t, h, o, val, c) do {			\
431	(void) t;							\
432	__asm volatile ("						\
433		movl	%0,%%a0					;	\
434		movl	%1,%%d1					;	\
435		movl	%2,%%d0					;	\
436	1:	movw	%%d1,%%a0@+				;	\
437		subql	#1,%%d0					;	\
438		jne	1b"					:	\
439								:	\
440		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
441		    "a0","d0","d1");					\
442} while (0);
443
444#define	bus_space_set_region_4(t, h, o, val, c) do {			\
445	(void) t;							\
446	__asm volatile ("						\
447		movl	%0,%%a0					;	\
448		movl	%1,%%d1					;	\
449		movl	%2,%%d0					;	\
450	1:	movl	%%d1,%%a0@+				;	\
451		subql	#1,%%d0					;	\
452		jne	1b"					:	\
453								:	\
454		    "r" ((h) + (o)), "g" (val), "g" (c)		:	\
455		    "a0","d0","d1");					\
456} while (0);
457
458/*
459 *	void bus_space_copy_N(bus_space_tag_t tag,
460 *	    bus_space_handle_t bsh1, bus_size_t off1,
461 *	    bus_space_handle_t bsh2, bus_size_t off2,
462 *	    size_t count);
463 *
464 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
465 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
466 */
467
468#define	__NEXT68K_copy_region_N(BYTES)					\
469static __inline void __CONCAT(bus_space_copy_region_,BYTES)		\
470	(bus_space_tag_t,						\
471	 bus_space_handle_t, bus_size_t,				\
472	 bus_space_handle_t, bus_size_t,				\
473	 bus_size_t);							\
474									\
475static __inline void							\
476__CONCAT(bus_space_copy_region_,BYTES)(					\
477	bus_space_tag_t t,						\
478	bus_space_handle_t h1,						\
479	bus_size_t o1,							\
480	bus_space_handle_t h2,						\
481	bus_size_t o2,							\
482	bus_size_t c)							\
483{									\
484	bus_size_t o;							\
485									\
486	if ((h1 + o1) >= (h2 + o2)) {					\
487		/* src after dest: copy forward */			\
488		for (o = 0; c != 0; c--, o += BYTES)			\
489			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
490			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
491	} else {							\
492		/* dest after src: copy backwards */			\
493		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
494			__CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o,	\
495			    __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \
496	}								\
497}
498__NEXT68K_copy_region_N(1)
499__NEXT68K_copy_region_N(2)
500__NEXT68K_copy_region_N(4)
501
502#undef __NEXT68K_copy_region_N
503
504/*
505 * Bus read/write barrier methods.
506 *
507 *	void bus_space_barrier(bus_space_tag_t tag,
508 *	    bus_space_handle_t bsh, bus_size_t offset,
509 *	    bus_size_t len, int flags);
510 *
511 * Note: the 680x0 does not currently require barriers, but we must
512 * provide the flags to MI code.
513 */
514#define	bus_space_barrier(t, h, o, l, f)	\
515	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
516#define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
517#define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
518
519#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
520
521#endif /* _NEXT68K_BUS_SPACE_H_ */
522