1 /* $OpenBSD: tc_bus_mem.c,v 1.18 2023/03/08 04:43:07 guenther Exp $ */ 2 /* $NetBSD: tc_bus_mem.c,v 1.25 2001/09/04 05:31:28 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1996 Carnegie-Mellon University. 6 * All rights reserved. 7 * 8 * Author: Chris G. Demetriou 9 * 10 * Permission to use, copy, modify and distribute this software and 11 * its documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 */ 30 31 /* 32 * Common TurboChannel Chipset "bus memory" functions. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/malloc.h> 38 #include <sys/syslog.h> 39 #include <sys/device.h> 40 41 #include <uvm/uvm_extern.h> 42 43 #include <machine/bus.h> 44 #include <dev/tc/tcvar.h> 45 46 #define __C(A,B) __CONCAT(A,B) 47 48 /* mapping/unmapping */ 49 int tc_mem_map(void *, bus_addr_t, bus_size_t, int, 50 bus_space_handle_t *); 51 void tc_mem_unmap(void *, bus_space_handle_t, bus_size_t); 52 int tc_mem_subregion(void *, bus_space_handle_t, bus_size_t, 53 bus_size_t, bus_space_handle_t *); 54 55 /* allocation/deallocation */ 56 int tc_mem_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, 57 bus_size_t, bus_addr_t, int, bus_addr_t *, 58 bus_space_handle_t *); 59 void tc_mem_free(void *, bus_space_handle_t, bus_size_t); 60 61 /* get kernel virtual address */ 62 void * tc_mem_vaddr(void *, bus_space_handle_t); 63 64 /* barrier */ 65 inline void tc_mem_barrier(void *, bus_space_handle_t, 66 bus_size_t, bus_size_t, int); 67 68 /* read (single) */ 69 inline u_int8_t tc_mem_read_1(void *, bus_space_handle_t, bus_size_t); 70 inline u_int16_t tc_mem_read_2(void *, bus_space_handle_t, bus_size_t); 71 inline u_int32_t tc_mem_read_4(void *, bus_space_handle_t, bus_size_t); 72 inline u_int64_t tc_mem_read_8(void *, bus_space_handle_t, bus_size_t); 73 74 /* read multiple */ 75 void tc_mem_read_multi_1(void *, bus_space_handle_t, 76 bus_size_t, u_int8_t *, bus_size_t); 77 void tc_mem_read_multi_2(void *, bus_space_handle_t, 78 bus_size_t, u_int16_t *, bus_size_t); 79 void tc_mem_read_multi_4(void *, bus_space_handle_t, 80 bus_size_t, u_int32_t *, bus_size_t); 81 void tc_mem_read_multi_8(void *, bus_space_handle_t, 82 bus_size_t, u_int64_t *, bus_size_t); 83 84 /* read region */ 85 void tc_mem_read_region_1(void *, bus_space_handle_t, 86 bus_size_t, u_int8_t *, bus_size_t); 87 void tc_mem_read_region_2(void *, bus_space_handle_t, 88 bus_size_t, u_int16_t *, bus_size_t); 89 void tc_mem_read_region_4(void *, bus_space_handle_t, 90 bus_size_t, u_int32_t *, bus_size_t); 91 void tc_mem_read_region_8(void *, bus_space_handle_t, 92 bus_size_t, u_int64_t *, bus_size_t); 93 94 /* write (single) */ 95 inline void tc_mem_write_1(void *, bus_space_handle_t, bus_size_t, 96 u_int8_t); 97 inline void tc_mem_write_2(void *, bus_space_handle_t, bus_size_t, 98 u_int16_t); 99 inline void tc_mem_write_4(void *, bus_space_handle_t, bus_size_t, 100 u_int32_t); 101 inline void tc_mem_write_8(void *, bus_space_handle_t, bus_size_t, 102 u_int64_t); 103 104 /* write multiple */ 105 void tc_mem_write_multi_1(void *, bus_space_handle_t, 106 bus_size_t, const u_int8_t *, bus_size_t); 107 void tc_mem_write_multi_2(void *, bus_space_handle_t, 108 bus_size_t, const u_int16_t *, bus_size_t); 109 void tc_mem_write_multi_4(void *, bus_space_handle_t, 110 bus_size_t, const u_int32_t *, bus_size_t); 111 void tc_mem_write_multi_8(void *, bus_space_handle_t, 112 bus_size_t, const u_int64_t *, bus_size_t); 113 114 /* write region */ 115 void tc_mem_write_region_1(void *, bus_space_handle_t, 116 bus_size_t, const u_int8_t *, bus_size_t); 117 void tc_mem_write_region_2(void *, bus_space_handle_t, 118 bus_size_t, const u_int16_t *, bus_size_t); 119 void tc_mem_write_region_4(void *, bus_space_handle_t, 120 bus_size_t, const u_int32_t *, bus_size_t); 121 void tc_mem_write_region_8(void *, bus_space_handle_t, 122 bus_size_t, const u_int64_t *, bus_size_t); 123 124 /* set multiple */ 125 void tc_mem_set_multi_1(void *, bus_space_handle_t, 126 bus_size_t, u_int8_t, bus_size_t); 127 void tc_mem_set_multi_2(void *, bus_space_handle_t, 128 bus_size_t, u_int16_t, bus_size_t); 129 void tc_mem_set_multi_4(void *, bus_space_handle_t, 130 bus_size_t, u_int32_t, bus_size_t); 131 void tc_mem_set_multi_8(void *, bus_space_handle_t, 132 bus_size_t, u_int64_t, bus_size_t); 133 134 /* set region */ 135 void tc_mem_set_region_1(void *, bus_space_handle_t, 136 bus_size_t, u_int8_t, bus_size_t); 137 void tc_mem_set_region_2(void *, bus_space_handle_t, 138 bus_size_t, u_int16_t, bus_size_t); 139 void tc_mem_set_region_4(void *, bus_space_handle_t, 140 bus_size_t, u_int32_t, bus_size_t); 141 void tc_mem_set_region_8(void *, bus_space_handle_t, 142 bus_size_t, u_int64_t, bus_size_t); 143 144 /* copy */ 145 void tc_mem_copy_1(void *, bus_space_handle_t, 146 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 147 void tc_mem_copy_2(void *, bus_space_handle_t, 148 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 149 void tc_mem_copy_4(void *, bus_space_handle_t, 150 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 151 void tc_mem_copy_8(void *, bus_space_handle_t, 152 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 153 154 struct alpha_bus_space tc_mem_space = { 155 /* cookie */ 156 NULL, 157 158 /* mapping/unmapping */ 159 tc_mem_map, 160 tc_mem_unmap, 161 tc_mem_subregion, 162 163 /* allocation/deallocation */ 164 tc_mem_alloc, 165 tc_mem_free, 166 167 /* get kernel virtual address */ 168 tc_mem_vaddr, 169 170 /* barrier */ 171 tc_mem_barrier, 172 173 /* read (single) */ 174 tc_mem_read_1, 175 tc_mem_read_2, 176 tc_mem_read_4, 177 tc_mem_read_8, 178 179 /* read multiple */ 180 tc_mem_read_multi_1, 181 tc_mem_read_multi_2, 182 tc_mem_read_multi_4, 183 tc_mem_read_multi_8, 184 185 /* read region */ 186 tc_mem_read_region_1, 187 tc_mem_read_region_2, 188 tc_mem_read_region_4, 189 tc_mem_read_region_8, 190 191 /* write (single) */ 192 tc_mem_write_1, 193 tc_mem_write_2, 194 tc_mem_write_4, 195 tc_mem_write_8, 196 197 /* write multiple */ 198 tc_mem_write_multi_1, 199 tc_mem_write_multi_2, 200 tc_mem_write_multi_4, 201 tc_mem_write_multi_8, 202 203 /* write region */ 204 tc_mem_write_region_1, 205 tc_mem_write_region_2, 206 tc_mem_write_region_4, 207 tc_mem_write_region_8, 208 209 /* set multiple */ 210 tc_mem_set_multi_1, 211 tc_mem_set_multi_2, 212 tc_mem_set_multi_4, 213 tc_mem_set_multi_8, 214 215 /* set region */ 216 tc_mem_set_region_1, 217 tc_mem_set_region_2, 218 tc_mem_set_region_4, 219 tc_mem_set_region_8, 220 221 /* copy */ 222 tc_mem_copy_1, 223 tc_mem_copy_2, 224 tc_mem_copy_4, 225 tc_mem_copy_8, 226 }; 227 228 bus_space_tag_t 229 tc_bus_mem_init(memv) 230 void *memv; 231 { 232 bus_space_tag_t h = &tc_mem_space; 233 234 h->abs_cookie = memv; 235 return (h); 236 } 237 238 int 239 tc_mem_map(v, memaddr, memsize, flags, memhp) 240 void *v; 241 bus_addr_t memaddr; 242 bus_size_t memsize; 243 int flags; 244 bus_space_handle_t *memhp; 245 { 246 int cacheable = flags & BUS_SPACE_MAP_CACHEABLE; 247 int linear = flags & BUS_SPACE_MAP_LINEAR; 248 249 /* Requests for linear uncacheable space can't be satisfied. */ 250 if (linear && !cacheable) 251 return (EOPNOTSUPP); 252 253 if (memaddr & 0x7) 254 panic("tc_mem_map needs 8 byte alignment"); 255 if (cacheable) 256 *memhp = ALPHA_PHYS_TO_K0SEG(memaddr); 257 else 258 *memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr)); 259 return (0); 260 } 261 262 void 263 tc_mem_unmap(v, memh, memsize) 264 void *v; 265 bus_space_handle_t memh; 266 bus_size_t memsize; 267 { 268 269 /* XXX XX XXX nothing to do. */ 270 } 271 272 int 273 tc_mem_subregion(v, memh, offset, size, nmemh) 274 void *v; 275 bus_space_handle_t memh, *nmemh; 276 bus_size_t offset, size; 277 { 278 279 /* Disallow subregioning that would make the handle unaligned. */ 280 if ((offset & 0x7) != 0) 281 return (1); 282 283 if ((memh & TC_SPACE_SPARSE) != 0) 284 *nmemh = memh + (offset << 1); 285 else 286 *nmemh = memh + offset; 287 288 return (0); 289 } 290 291 int 292 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp) 293 void *v; 294 bus_addr_t rstart, rend, *addrp; 295 bus_size_t size, align, boundary; 296 int flags; 297 bus_space_handle_t *bshp; 298 { 299 300 /* XXX XXX XXX XXX XXX XXX */ 301 panic("tc_mem_alloc unimplemented"); 302 } 303 304 void 305 tc_mem_free(v, bsh, size) 306 void *v; 307 bus_space_handle_t bsh; 308 bus_size_t size; 309 { 310 311 /* XXX XXX XXX XXX XXX XXX */ 312 panic("tc_mem_free unimplemented"); 313 } 314 315 void * 316 tc_mem_vaddr(void *v, bus_space_handle_t bsh) 317 { 318 #ifdef DIAGNOSTIC 319 if ((bsh & TC_SPACE_SPARSE) != 0) { 320 /* 321 * tc_mem_map() catches linear && !cacheable, 322 * so we shouldn't come here 323 */ 324 panic("tc_mem_vaddr"); 325 } 326 #endif 327 return ((void *)bsh); 328 } 329 330 inline void 331 tc_mem_barrier(v, h, o, l, f) 332 void *v; 333 bus_space_handle_t h; 334 bus_size_t o, l; 335 int f; 336 { 337 338 if ((f & BUS_SPACE_BARRIER_READ) != 0) 339 alpha_mb(); 340 else if ((f & BUS_SPACE_BARRIER_WRITE) != 0) 341 alpha_wmb(); 342 } 343 344 inline u_int8_t 345 tc_mem_read_1(v, memh, off) 346 void *v; 347 bus_space_handle_t memh; 348 bus_size_t off; 349 { 350 volatile u_int8_t *p; 351 352 alpha_mb(); /* XXX XXX XXX */ 353 354 if ((memh & TC_SPACE_SPARSE) != 0) 355 panic("tc_mem_read_1 not implemented for sparse space"); 356 357 p = (u_int8_t *)(memh + off); 358 return (*p); 359 } 360 361 inline u_int16_t 362 tc_mem_read_2(v, memh, off) 363 void *v; 364 bus_space_handle_t memh; 365 bus_size_t off; 366 { 367 volatile u_int16_t *p; 368 369 alpha_mb(); /* XXX XXX XXX */ 370 371 if ((memh & TC_SPACE_SPARSE) != 0) 372 panic("tc_mem_read_2 not implemented for sparse space"); 373 374 p = (u_int16_t *)(memh + off); 375 return (*p); 376 } 377 378 inline u_int32_t 379 tc_mem_read_4(v, memh, off) 380 void *v; 381 bus_space_handle_t memh; 382 bus_size_t off; 383 { 384 volatile u_int32_t *p; 385 386 alpha_mb(); /* XXX XXX XXX */ 387 388 if ((memh & TC_SPACE_SPARSE) != 0) 389 /* Nothing special to do for 4-byte sparse space accesses */ 390 p = (u_int32_t *)(memh + (off << 1)); 391 else 392 p = (u_int32_t *)(memh + off); 393 return (*p); 394 } 395 396 inline u_int64_t 397 tc_mem_read_8(v, memh, off) 398 void *v; 399 bus_space_handle_t memh; 400 bus_size_t off; 401 { 402 volatile u_int64_t *p; 403 404 alpha_mb(); /* XXX XXX XXX */ 405 406 if ((memh & TC_SPACE_SPARSE) != 0) 407 panic("tc_mem_read_8 not implemented for sparse space"); 408 409 p = (u_int64_t *)(memh + off); 410 return (*p); 411 } 412 413 #define tc_mem_read_multi_N(BYTES,TYPE) \ 414 void \ 415 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c) \ 416 void *v; \ 417 bus_space_handle_t h; \ 418 bus_size_t o, c; \ 419 TYPE *a; \ 420 { \ 421 \ 422 while (c-- > 0) { \ 423 tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \ 424 *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 425 } \ 426 } 427 tc_mem_read_multi_N(1,u_int8_t) 428 tc_mem_read_multi_N(2,u_int16_t) 429 tc_mem_read_multi_N(4,u_int32_t) 430 tc_mem_read_multi_N(8,u_int64_t) 431 432 #define tc_mem_read_region_N(BYTES,TYPE) \ 433 void \ 434 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c) \ 435 void *v; \ 436 bus_space_handle_t h; \ 437 bus_size_t o, c; \ 438 TYPE *a; \ 439 { \ 440 \ 441 while (c-- > 0) { \ 442 *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 443 o += sizeof *a; \ 444 } \ 445 } 446 tc_mem_read_region_N(1,u_int8_t) 447 tc_mem_read_region_N(2,u_int16_t) 448 tc_mem_read_region_N(4,u_int32_t) 449 tc_mem_read_region_N(8,u_int64_t) 450 451 inline void 452 tc_mem_write_1(v, memh, off, val) 453 void *v; 454 bus_space_handle_t memh; 455 bus_size_t off; 456 u_int8_t val; 457 { 458 459 if ((memh & TC_SPACE_SPARSE) != 0) { 460 volatile u_int64_t *p, v; 461 u_int64_t shift, msk; 462 463 shift = off & 0x3; 464 off &= 0x3; 465 466 p = (u_int64_t *)(memh + (off << 1)); 467 468 msk = ~(0x1 << shift) & 0xf; 469 v = (msk << 32) | (((u_int64_t)val) << (shift * 8)); 470 471 *p = val; 472 } else { 473 volatile u_int8_t *p; 474 475 p = (u_int8_t *)(memh + off); 476 *p = val; 477 } 478 alpha_mb(); /* XXX XXX XXX */ 479 } 480 481 inline void 482 tc_mem_write_2(v, memh, off, val) 483 void *v; 484 bus_space_handle_t memh; 485 bus_size_t off; 486 u_int16_t val; 487 { 488 489 if ((memh & TC_SPACE_SPARSE) != 0) { 490 volatile u_int64_t *p, v; 491 u_int64_t shift, msk; 492 493 shift = off & 0x2; 494 off &= 0x3; 495 496 p = (u_int64_t *)(memh + (off << 1)); 497 498 msk = ~(0x3 << shift) & 0xf; 499 v = (msk << 32) | (((u_int64_t)val) << (shift * 8)); 500 501 *p = val; 502 } else { 503 volatile u_int16_t *p; 504 505 p = (u_int16_t *)(memh + off); 506 *p = val; 507 } 508 alpha_mb(); /* XXX XXX XXX */ 509 } 510 511 inline void 512 tc_mem_write_4(v, memh, off, val) 513 void *v; 514 bus_space_handle_t memh; 515 bus_size_t off; 516 u_int32_t val; 517 { 518 volatile u_int32_t *p; 519 520 if ((memh & TC_SPACE_SPARSE) != 0) 521 /* Nothing special to do for 4-byte sparse space accesses */ 522 p = (u_int32_t *)(memh + (off << 1)); 523 else 524 p = (u_int32_t *)(memh + off); 525 *p = val; 526 alpha_mb(); /* XXX XXX XXX */ 527 } 528 529 inline void 530 tc_mem_write_8(v, memh, off, val) 531 void *v; 532 bus_space_handle_t memh; 533 bus_size_t off; 534 u_int64_t val; 535 { 536 volatile u_int64_t *p; 537 538 if ((memh & TC_SPACE_SPARSE) != 0) 539 panic("tc_mem_read_8 not implemented for sparse space"); 540 541 p = (u_int64_t *)(memh + off); 542 *p = val; 543 alpha_mb(); /* XXX XXX XXX */ 544 } 545 546 #define tc_mem_write_multi_N(BYTES,TYPE) \ 547 void \ 548 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c) \ 549 void *v; \ 550 bus_space_handle_t h; \ 551 bus_size_t o, c; \ 552 const TYPE *a; \ 553 { \ 554 \ 555 while (c-- > 0) { \ 556 __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 557 tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \ 558 } \ 559 } 560 tc_mem_write_multi_N(1,u_int8_t) 561 tc_mem_write_multi_N(2,u_int16_t) 562 tc_mem_write_multi_N(4,u_int32_t) 563 tc_mem_write_multi_N(8,u_int64_t) 564 565 #define tc_mem_write_region_N(BYTES,TYPE) \ 566 void \ 567 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c) \ 568 void *v; \ 569 bus_space_handle_t h; \ 570 bus_size_t o, c; \ 571 const TYPE *a; \ 572 { \ 573 \ 574 while (c-- > 0) { \ 575 __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 576 o += sizeof *a; \ 577 } \ 578 } 579 tc_mem_write_region_N(1,u_int8_t) 580 tc_mem_write_region_N(2,u_int16_t) 581 tc_mem_write_region_N(4,u_int32_t) 582 tc_mem_write_region_N(8,u_int64_t) 583 584 #define tc_mem_set_multi_N(BYTES,TYPE) \ 585 void \ 586 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c) \ 587 void *v; \ 588 bus_space_handle_t h; \ 589 bus_size_t o, c; \ 590 TYPE val; \ 591 { \ 592 \ 593 while (c-- > 0) { \ 594 __C(tc_mem_write_,BYTES)(v, h, o, val); \ 595 tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \ 596 } \ 597 } 598 tc_mem_set_multi_N(1,u_int8_t) 599 tc_mem_set_multi_N(2,u_int16_t) 600 tc_mem_set_multi_N(4,u_int32_t) 601 tc_mem_set_multi_N(8,u_int64_t) 602 603 #define tc_mem_set_region_N(BYTES,TYPE) \ 604 void \ 605 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c) \ 606 void *v; \ 607 bus_space_handle_t h; \ 608 bus_size_t o, c; \ 609 TYPE val; \ 610 { \ 611 \ 612 while (c-- > 0) { \ 613 __C(tc_mem_write_,BYTES)(v, h, o, val); \ 614 o += sizeof val; \ 615 } \ 616 } 617 tc_mem_set_region_N(1,u_int8_t) 618 tc_mem_set_region_N(2,u_int16_t) 619 tc_mem_set_region_N(4,u_int32_t) 620 tc_mem_set_region_N(8,u_int64_t) 621 622 #define tc_mem_copy_N(BYTES) \ 623 void \ 624 __C(tc_mem_copy_,BYTES)(v, h1, o1, h2, o2, c) \ 625 void *v; \ 626 bus_space_handle_t h1, h2; \ 627 bus_size_t o1, o2, c; \ 628 { \ 629 bus_size_t o; \ 630 \ 631 if ((h1 & TC_SPACE_SPARSE) != 0 && \ 632 (h2 & TC_SPACE_SPARSE) != 0) { \ 633 bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \ 634 return; \ 635 } \ 636 \ 637 if (h1 + o1 >= h2 + o2) \ 638 /* src after dest: copy forward */ \ 639 for (o = 0; c > 0; c--, o += BYTES) \ 640 __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 641 __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 642 else \ 643 /* dest after src: copy backwards */ \ 644 for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES) \ 645 __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 646 __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 647 } 648 tc_mem_copy_N(1) 649 tc_mem_copy_N(2) 650 tc_mem_copy_N(4) 651 tc_mem_copy_N(8) 652