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