Home | History | Annotate | Line # | Download | only in amiga
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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