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