xref: /netbsd-src/sys/arch/amiga/amiga/busfuncs.c (revision d339aae03fba759372c457f57e3c514b7be60866)
1 /*	$NetBSD: busfuncs.c,v 1.13 2022/05/18 13:56:31 andvar Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Ignatios Souvatzis.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: busfuncs.c,v 1.13 2022/05/18 13:56:31 andvar Exp $");
34 
35 /*
36  * Amiga bus access methods for data widths > 1
37  * XXX currently, only 16bit methods are defined
38  */
39 
40 #include <sys/bus.h>
41 
42 bsr(amiga_contiguous_read_2, u_int16_t);
43 bsw(amiga_contiguous_write_2, u_int16_t);
44 bsrm(amiga_contiguous_read_multi_2, u_int16_t);
45 bswm(amiga_contiguous_write_multi_2, u_int16_t);
46 bsrm(amiga_contiguous_read_region_2, u_int16_t);
47 bswm(amiga_contiguous_write_region_2, u_int16_t);
48 bssr(amiga_contiguous_set_region_2, u_int16_t);
49 bscr(amiga_contiguous_copy_region_2, u_int16_t);
50 
51 bsr(amiga_interleaved_read_2, u_int16_t);
52 bsw(amiga_interleaved_write_2, u_int16_t);
53 bsrm(amiga_interleaved_read_multi_2, u_int16_t);
54 bswm(amiga_interleaved_write_multi_2, u_int16_t);
55 bsrm(amiga_interleaved_read_region_2, u_int16_t);
56 bswm(amiga_interleaved_write_region_2, u_int16_t);
57 bssr(amiga_interleaved_set_region_2, u_int16_t);
58 bscr(amiga_interleaved_copy_region_2, u_int16_t);
59 
60 bsr(amiga_interleaved_wordaccess_read_2, u_int16_t);
61 bsw(amiga_interleaved_wordaccess_write_2, u_int16_t);
62 bsrm(amiga_interleaved_wordaccess_read_multi_2, u_int16_t);
63 bswm(amiga_interleaved_wordaccess_write_multi_2, u_int16_t);
64 bsrm(amiga_interleaved_wordaccess_read_region_2, u_int16_t);
65 bswm(amiga_interleaved_wordaccess_write_region_2, u_int16_t);
66 bssr(amiga_interleaved_wordaccess_set_region_2, u_int16_t);
67 bscr(amiga_interleaved_wordaccess_copy_region_2, u_int16_t);
68 
69 const struct amiga_bus_space_methods amiga_contiguous_methods = {
70 	amiga_contiguous_read_2,
71 	amiga_contiguous_write_2,
72 	amiga_contiguous_read_multi_2,
73 	amiga_contiguous_write_multi_2,
74 	amiga_contiguous_read_region_2,
75 	amiga_contiguous_write_region_2,
76 	/* next two identical to the above here */
77 	amiga_contiguous_read_region_2,
78 	amiga_contiguous_write_region_2,
79 	amiga_contiguous_set_region_2,
80 	amiga_contiguous_copy_region_2
81 };
82 
83 const struct amiga_bus_space_methods amiga_interleaved_methods = {
84 	amiga_interleaved_read_2,
85 	amiga_interleaved_write_2,
86 	amiga_interleaved_read_multi_2,
87 	amiga_interleaved_write_multi_2,
88 	amiga_interleaved_read_region_2,
89 	amiga_interleaved_write_region_2,
90 	/* next two identical to the above here */
91 	amiga_interleaved_read_region_2,
92 	amiga_interleaved_write_region_2,
93 	amiga_interleaved_set_region_2,
94 	amiga_interleaved_copy_region_2
95 };
96 
97 const struct amiga_bus_space_methods amiga_interleaved_wordaccess_methods = {
98 	amiga_interleaved_wordaccess_read_2,
99 	amiga_interleaved_wordaccess_write_2,
100 	amiga_interleaved_wordaccess_read_multi_2,
101 	amiga_interleaved_wordaccess_write_multi_2,
102 	amiga_interleaved_wordaccess_read_region_2,
103 	amiga_interleaved_wordaccess_write_region_2,
104 	/* next two identical to the above here */
105 	amiga_interleaved_wordaccess_read_region_2,	/* region_stream */
106 	amiga_interleaved_wordaccess_write_region_2,
107 	amiga_interleaved_wordaccess_set_region_2,
108 	amiga_interleaved_wordaccess_copy_region_2
109 };
110 
111 /*
112  * Contiguous methods
113  * Be sure to only create word accesses.
114  * For busses that _need_ split byte accesses, use the interleaved functions.
115  */
116 
117 u_int16_t
amiga_contiguous_read_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)118 amiga_contiguous_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
119 {
120 	/* ARGSUSED */
121 	u_int16_t x;
122 
123 	x  = * (u_int16_t *) (h + o); /* only used if t->stride == 0 */
124 	amiga_bus_reorder_protect();
125 	return x;
126 }
127 
128 void
amiga_contiguous_write_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t v)129 amiga_contiguous_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v)
130 {
131 	/* ARGSUSED */
132 	* (u_int16_t *) (h + o) = v;
133 	amiga_bus_reorder_protect();
134 }
135 
136 void
amiga_contiguous_read_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t * p,bus_size_t s)137 amiga_contiguous_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t *p, bus_size_t s)
138 {
139 	/* ARGSUSED */
140 	volatile u_int16_t *q = (volatile u_int16_t *)(h + o);
141 
142 	while (s-- > 0) {
143 		*p++ =  *q;
144 		amiga_bus_reorder_protect();
145 	}
146 }
147 
148 void
amiga_contiguous_write_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const u_int16_t * p,bus_size_t s)149 amiga_contiguous_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const u_int16_t *p, bus_size_t s)
150 {
151 	/* ARGSUSED */
152 	volatile u_int16_t *q = (volatile u_int16_t *)(h + o);
153 
154 	while (s-- > 0) {
155 		*q = *p++;
156 		amiga_bus_reorder_protect();
157 	}
158 }
159 
160 void
amiga_contiguous_read_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t * p,bus_size_t s)161 amiga_contiguous_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t *p, bus_size_t s)
162 {
163 	/* ARGSUSED */
164 	volatile u_int16_t *q = (volatile u_int16_t *)(h + o);
165 
166 	while (s-- > 0) {
167 		*p++ =  *q++;
168 		amiga_bus_reorder_protect();
169 	}
170 }
171 
172 void
amiga_contiguous_write_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const u_int16_t * p,bus_size_t s)173 amiga_contiguous_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const u_int16_t *p, bus_size_t s)
174 {
175 	/* ARGSUSED */
176 	volatile u_int16_t *q = (volatile u_int16_t *)(h + o);
177 
178 	while (s-- > 0) {
179 		*q++ = *p++;
180 		amiga_bus_reorder_protect();
181 	}
182 }
183 
184 void
amiga_contiguous_set_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t v,bus_size_t s)185 amiga_contiguous_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v, bus_size_t s)
186 {
187 	/* ARGSUSED */
188 	volatile u_int16_t *q = (volatile u_int16_t *)(h + o);
189 
190 	while (s-- > 0) {
191 		*q++ = v;
192 		amiga_bus_reorder_protect();
193 	}
194 }
195 
196 void
amiga_contiguous_copy_region_2(bus_space_tag_t t,bus_space_handle_t srch,bus_size_t srco,bus_space_handle_t dsth,bus_size_t dsto,bus_size_t s)197 amiga_contiguous_copy_region_2(bus_space_tag_t t, bus_space_handle_t srch, bus_size_t srco, bus_space_handle_t dsth, bus_size_t dsto, bus_size_t s)
198 {
199 	/* ARGSUSED */
200 	volatile u_int16_t *p = (volatile u_int16_t *)(srch + srco);
201 	volatile u_int16_t *q = (volatile u_int16_t *)(dsth + dsto);
202 
203 	while (s-- > 0) {
204 		*q++ = *p++;
205 		amiga_bus_reorder_protect();
206 	}
207 }
208 
209 /*
210  * Interleaved methods.
211  * These use single-byte accesses. In case of stride = 0, the contiguous
212  * methods are preferred, as they only create word accesses.
213  */
214 
215 u_int16_t
amiga_interleaved_read_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)216 amiga_interleaved_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
217 {
218 	volatile u_int8_t *q;
219 	u_int16_t x;
220 	int step;
221 
222 	step = 1 << t->stride;
223 	q = (volatile u_int8_t *)(h + (o << t->stride));
224 	x = ((*q) << 8) | *(q + step);
225 	amiga_bus_reorder_protect();
226 	return x;
227 }
228 
229 void
amiga_interleaved_write_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t v)230 amiga_interleaved_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v)
231 {
232 	volatile u_int8_t *q;
233 	int step;
234 
235 	step = 1 << t->stride;
236 	q = (volatile u_int8_t *)(h + (o << t->stride));
237 
238 	*q = v >> 8;
239 	*(q+step) = v;
240 	amiga_bus_reorder_protect();
241 }
242 
243 void
amiga_interleaved_read_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t * p,bus_size_t s)244 amiga_interleaved_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t *p, bus_size_t s)
245 {
246 	volatile u_int8_t *q;
247 	int step;
248 
249 	step = 1 << t->stride;
250 	q = (volatile u_int8_t *)(h + (o << t->stride));
251 
252 	while (s-- > 0) {
253 		*p++ =  ((*q)<<8) | *(q+step);
254 		amiga_bus_reorder_protect();
255 	}
256 }
257 
258 void
amiga_interleaved_write_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const u_int16_t * p,bus_size_t s)259 amiga_interleaved_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const u_int16_t *p, bus_size_t s)
260 {
261 	volatile u_int8_t *q;
262 	int step;
263 	u_int16_t v;
264 
265 	step = 1 << t->stride;
266 	q = (volatile u_int8_t *)(h + (o << t->stride));
267 
268 	while (s-- > 0) {
269 		v = *p++;
270 		*q 		= v>>8;
271 		*(q + step)	= v;
272 		amiga_bus_reorder_protect();
273 	}
274 }
275 
276 void
amiga_interleaved_read_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t * p,bus_size_t s)277 amiga_interleaved_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t *p, bus_size_t s)
278 {
279 	volatile u_int8_t *q;
280 	int step;
281 	u_int16_t v;
282 
283 	step = 1 << t->stride;
284 	q = (volatile u_int8_t *)(h + (o << t->stride));
285 
286 	while (s-- > 0) {
287 		v = (*q) << 8;
288 		q += step;
289 		v |= *q;
290 		amiga_bus_reorder_protect();
291 		q += step;
292 		*p++ =  v;
293 	}
294 }
295 
296 void
amiga_interleaved_write_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const u_int16_t * p,bus_size_t s)297 amiga_interleaved_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const u_int16_t *p, bus_size_t s)
298 {
299 	volatile u_int8_t *q;
300 	int step;
301 	u_int16_t v;
302 
303 	step = 1 << t->stride;
304 	q = (volatile u_int8_t *)(h + (o << t->stride));
305 
306 	while (s-- > 0) {
307 		v = *p++;
308 		*q = v >> 8;
309 		q += step;
310 		*q = v;
311 		amiga_bus_reorder_protect();
312 		q += step;
313 	}
314 }
315 
316 void
amiga_interleaved_set_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t v,bus_size_t s)317 amiga_interleaved_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v, bus_size_t s)
318 {
319 	int step;
320 	volatile u_int16_t *q = (volatile u_int16_t *)(h + o);
321 
322 	step = 1 << t->stride;
323 
324 	while (s-- > 0) {
325 		*q = v;
326 		amiga_bus_reorder_protect();
327 		q += step;
328 	}
329 }
330 
331 void
amiga_interleaved_copy_region_2(bus_space_tag_t t,bus_space_handle_t srch,bus_size_t srco,bus_space_handle_t dsth,bus_size_t dsto,bus_size_t s)332 amiga_interleaved_copy_region_2(bus_space_tag_t t, bus_space_handle_t srch, bus_size_t srco, bus_space_handle_t dsth, bus_size_t dsto, bus_size_t s)
333 {
334 	int step;
335 	volatile u_int16_t *p = (volatile u_int16_t *)(srch + srco);
336 	volatile u_int16_t *q = (volatile u_int16_t *)(dsth + dsto);
337 
338 	step = 1 << t->stride;
339 
340 	while (s-- > 0) {
341 		*q = *p;
342 		amiga_bus_reorder_protect();
343 		p += step;
344 		q += step;
345 	}
346 }
347 
348 /*
349  * Interleaved_wordaccess methods. Have a stride, but translate
350  * word accesses to word accesses at the target address.
351  */
352 
353 u_int16_t
amiga_interleaved_wordaccess_read_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)354 amiga_interleaved_wordaccess_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
355 {
356 	/* ARGSUSED */
357 	u_int16_t x;
358 
359 	x = * (u_int16_t *) (h + (o << t->stride));
360 	amiga_bus_reorder_protect();
361 	return x;
362 }
363 
364 void
amiga_interleaved_wordaccess_write_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t v)365 amiga_interleaved_wordaccess_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v)
366 {
367 	/* ARGSUSED */
368 	* (u_int16_t *) (h + (o << t->stride)) = v;
369 	amiga_bus_reorder_protect();
370 }
371 
372 void
amiga_interleaved_wordaccess_read_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t * p,bus_size_t s)373 amiga_interleaved_wordaccess_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t *p, bus_size_t s)
374 {
375 	/* ARGSUSED */
376 	volatile u_int16_t *q;
377 
378 	q = (volatile u_int16_t *)(h + (o << t->stride));
379 
380 	while (s-- > 0) {
381 		*p++ =  *q;
382 		amiga_bus_reorder_protect();
383 	}
384 }
385 
386 void
amiga_interleaved_wordaccess_write_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const u_int16_t * p,bus_size_t s)387 amiga_interleaved_wordaccess_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const u_int16_t *p, bus_size_t s)
388 {
389 	/* ARGSUSED */
390 	volatile u_int16_t *q;
391 
392 	q = (volatile u_int16_t *)(h + (o << t->stride));
393 
394 	while (s-- > 0) {
395 		*q = *p++;
396 		amiga_bus_reorder_protect();
397 	}
398 }
399 
400 void
amiga_interleaved_wordaccess_read_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t * p,bus_size_t s)401 amiga_interleaved_wordaccess_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t *p, bus_size_t s)
402 {
403 	/* ARGSUSED */
404 	volatile u_int16_t *q;
405 	int step;
406 
407 	q = (volatile u_int16_t *)(h + (o << t->stride));
408 	step = (1 << t->stride) / sizeof(u_int16_t);
409 
410 	while (s-- > 0) {
411 		*p++ =  *q;
412 		amiga_bus_reorder_protect();
413 		q += step;
414 	}
415 }
416 
417 void
amiga_interleaved_wordaccess_write_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const u_int16_t * p,bus_size_t s)418 amiga_interleaved_wordaccess_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const u_int16_t *p, bus_size_t s)
419 {
420 	/* ARGSUSED */
421 	volatile u_int16_t *q;
422 	int step;
423 
424 	q = (volatile u_int16_t *)(h + (o << t->stride));
425 	step = (1 << t->stride) / sizeof(u_int16_t);
426 
427 	while (s-- > 0) {
428 		*q = *p++;
429 		amiga_bus_reorder_protect();
430 		q += step;
431 	}
432 }
433 
434 void
amiga_interleaved_wordaccess_set_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,u_int16_t v,bus_size_t s)435 amiga_interleaved_wordaccess_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v, bus_size_t s)
436 {
437 	/* ARGSUSED */
438 	volatile u_int16_t *q;
439 	int step;
440 
441 	q = (volatile u_int16_t *)(h + (o << t->stride));
442 	step = (1 << t->stride) / sizeof(u_int16_t);
443 
444 	while (s-- > 0) {
445 		*q = v;
446 		amiga_bus_reorder_protect();
447 		q += step;
448 	}
449 }
450 
451 void
amiga_interleaved_wordaccess_copy_region_2(bus_space_tag_t t,bus_space_handle_t srch,bus_size_t srco,bus_space_handle_t dsth,bus_size_t dsto,bus_size_t s)452 amiga_interleaved_wordaccess_copy_region_2(bus_space_tag_t t, bus_space_handle_t srch, bus_size_t srco, bus_space_handle_t dsth, bus_size_t dsto, bus_size_t s)
453 {
454 	int step;
455 	/* ARGSUSED */
456 	volatile u_int16_t *p;
457 	volatile u_int16_t *q;
458 
459 	p = (volatile u_int16_t *)(srch + (srco << t->stride));
460 	q = (volatile u_int16_t *)(dsth + (dsto << t->stride));
461 	step = (1 << t->stride) / sizeof(u_int16_t);
462 
463 	while (s-- > 0) {
464 		*q = *p;
465 		amiga_bus_reorder_protect();
466 		q += step;
467 		p += step;
468 	}
469 }
470