1 /* $OpenBSD: tc_bus_mem.c,v 1.17 2010/04/04 12:49:27 miod 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 /* ARGSUSED */ 239 int 240 tc_mem_map(v, memaddr, memsize, flags, memhp) 241 void *v; 242 bus_addr_t memaddr; 243 bus_size_t memsize; 244 int flags; 245 bus_space_handle_t *memhp; 246 { 247 int cacheable = flags & BUS_SPACE_MAP_CACHEABLE; 248 int linear = flags & BUS_SPACE_MAP_LINEAR; 249 250 /* Requests for linear uncacheable space can't be satisfied. */ 251 if (linear && !cacheable) 252 return (EOPNOTSUPP); 253 254 if (memaddr & 0x7) 255 panic("tc_mem_map needs 8 byte alignment"); 256 if (cacheable) 257 *memhp = ALPHA_PHYS_TO_K0SEG(memaddr); 258 else 259 *memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr)); 260 return (0); 261 } 262 263 /* ARGSUSED */ 264 void 265 tc_mem_unmap(v, memh, memsize) 266 void *v; 267 bus_space_handle_t memh; 268 bus_size_t memsize; 269 { 270 271 /* XXX XX XXX nothing to do. */ 272 } 273 274 int 275 tc_mem_subregion(v, memh, offset, size, nmemh) 276 void *v; 277 bus_space_handle_t memh, *nmemh; 278 bus_size_t offset, size; 279 { 280 281 /* Disallow subregioning that would make the handle unaligned. */ 282 if ((offset & 0x7) != 0) 283 return (1); 284 285 if ((memh & TC_SPACE_SPARSE) != 0) 286 *nmemh = memh + (offset << 1); 287 else 288 *nmemh = memh + offset; 289 290 return (0); 291 } 292 293 int 294 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp) 295 void *v; 296 bus_addr_t rstart, rend, *addrp; 297 bus_size_t size, align, boundary; 298 int flags; 299 bus_space_handle_t *bshp; 300 { 301 302 /* XXX XXX XXX XXX XXX XXX */ 303 panic("tc_mem_alloc unimplemented"); 304 } 305 306 void 307 tc_mem_free(v, bsh, size) 308 void *v; 309 bus_space_handle_t bsh; 310 bus_size_t size; 311 { 312 313 /* XXX XXX XXX XXX XXX XXX */ 314 panic("tc_mem_free unimplemented"); 315 } 316 317 void * 318 tc_mem_vaddr(void *v, bus_space_handle_t bsh) 319 { 320 #ifdef DIAGNOSTIC 321 if ((bsh & TC_SPACE_SPARSE) != 0) { 322 /* 323 * tc_mem_map() catches linear && !cacheable, 324 * so we shouldn't come here 325 */ 326 panic("tc_mem_vaddr"); 327 } 328 #endif 329 return ((void *)bsh); 330 } 331 332 inline void 333 tc_mem_barrier(v, h, o, l, f) 334 void *v; 335 bus_space_handle_t h; 336 bus_size_t o, l; 337 int f; 338 { 339 340 if ((f & BUS_SPACE_BARRIER_READ) != 0) 341 alpha_mb(); 342 else if ((f & BUS_SPACE_BARRIER_WRITE) != 0) 343 alpha_wmb(); 344 } 345 346 inline u_int8_t 347 tc_mem_read_1(v, memh, off) 348 void *v; 349 bus_space_handle_t memh; 350 bus_size_t off; 351 { 352 volatile u_int8_t *p; 353 354 alpha_mb(); /* XXX XXX XXX */ 355 356 if ((memh & TC_SPACE_SPARSE) != 0) 357 panic("tc_mem_read_1 not implemented for sparse space"); 358 359 p = (u_int8_t *)(memh + off); 360 return (*p); 361 } 362 363 inline u_int16_t 364 tc_mem_read_2(v, memh, off) 365 void *v; 366 bus_space_handle_t memh; 367 bus_size_t off; 368 { 369 volatile u_int16_t *p; 370 371 alpha_mb(); /* XXX XXX XXX */ 372 373 if ((memh & TC_SPACE_SPARSE) != 0) 374 panic("tc_mem_read_2 not implemented for sparse space"); 375 376 p = (u_int16_t *)(memh + off); 377 return (*p); 378 } 379 380 inline u_int32_t 381 tc_mem_read_4(v, memh, off) 382 void *v; 383 bus_space_handle_t memh; 384 bus_size_t off; 385 { 386 volatile u_int32_t *p; 387 388 alpha_mb(); /* XXX XXX XXX */ 389 390 if ((memh & TC_SPACE_SPARSE) != 0) 391 /* Nothing special to do for 4-byte sparse space accesses */ 392 p = (u_int32_t *)(memh + (off << 1)); 393 else 394 p = (u_int32_t *)(memh + off); 395 return (*p); 396 } 397 398 inline u_int64_t 399 tc_mem_read_8(v, memh, off) 400 void *v; 401 bus_space_handle_t memh; 402 bus_size_t off; 403 { 404 volatile u_int64_t *p; 405 406 alpha_mb(); /* XXX XXX XXX */ 407 408 if ((memh & TC_SPACE_SPARSE) != 0) 409 panic("tc_mem_read_8 not implemented for sparse space"); 410 411 p = (u_int64_t *)(memh + off); 412 return (*p); 413 } 414 415 #define tc_mem_read_multi_N(BYTES,TYPE) \ 416 void \ 417 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c) \ 418 void *v; \ 419 bus_space_handle_t h; \ 420 bus_size_t o, c; \ 421 TYPE *a; \ 422 { \ 423 \ 424 while (c-- > 0) { \ 425 tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \ 426 *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 427 } \ 428 } 429 tc_mem_read_multi_N(1,u_int8_t) 430 tc_mem_read_multi_N(2,u_int16_t) 431 tc_mem_read_multi_N(4,u_int32_t) 432 tc_mem_read_multi_N(8,u_int64_t) 433 434 #define tc_mem_read_region_N(BYTES,TYPE) \ 435 void \ 436 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c) \ 437 void *v; \ 438 bus_space_handle_t h; \ 439 bus_size_t o, c; \ 440 TYPE *a; \ 441 { \ 442 \ 443 while (c-- > 0) { \ 444 *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 445 o += sizeof *a; \ 446 } \ 447 } 448 tc_mem_read_region_N(1,u_int8_t) 449 tc_mem_read_region_N(2,u_int16_t) 450 tc_mem_read_region_N(4,u_int32_t) 451 tc_mem_read_region_N(8,u_int64_t) 452 453 inline void 454 tc_mem_write_1(v, memh, off, val) 455 void *v; 456 bus_space_handle_t memh; 457 bus_size_t off; 458 u_int8_t val; 459 { 460 461 if ((memh & TC_SPACE_SPARSE) != 0) { 462 volatile u_int64_t *p, v; 463 u_int64_t shift, msk; 464 465 shift = off & 0x3; 466 off &= 0x3; 467 468 p = (u_int64_t *)(memh + (off << 1)); 469 470 msk = ~(0x1 << shift) & 0xf; 471 v = (msk << 32) | (((u_int64_t)val) << (shift * 8)); 472 473 *p = val; 474 } else { 475 volatile u_int8_t *p; 476 477 p = (u_int8_t *)(memh + off); 478 *p = val; 479 } 480 alpha_mb(); /* XXX XXX XXX */ 481 } 482 483 inline void 484 tc_mem_write_2(v, memh, off, val) 485 void *v; 486 bus_space_handle_t memh; 487 bus_size_t off; 488 u_int16_t val; 489 { 490 491 if ((memh & TC_SPACE_SPARSE) != 0) { 492 volatile u_int64_t *p, v; 493 u_int64_t shift, msk; 494 495 shift = off & 0x2; 496 off &= 0x3; 497 498 p = (u_int64_t *)(memh + (off << 1)); 499 500 msk = ~(0x3 << shift) & 0xf; 501 v = (msk << 32) | (((u_int64_t)val) << (shift * 8)); 502 503 *p = val; 504 } else { 505 volatile u_int16_t *p; 506 507 p = (u_int16_t *)(memh + off); 508 *p = val; 509 } 510 alpha_mb(); /* XXX XXX XXX */ 511 } 512 513 inline void 514 tc_mem_write_4(v, memh, off, val) 515 void *v; 516 bus_space_handle_t memh; 517 bus_size_t off; 518 u_int32_t val; 519 { 520 volatile u_int32_t *p; 521 522 if ((memh & TC_SPACE_SPARSE) != 0) 523 /* Nothing special to do for 4-byte sparse space accesses */ 524 p = (u_int32_t *)(memh + (off << 1)); 525 else 526 p = (u_int32_t *)(memh + off); 527 *p = val; 528 alpha_mb(); /* XXX XXX XXX */ 529 } 530 531 inline void 532 tc_mem_write_8(v, memh, off, val) 533 void *v; 534 bus_space_handle_t memh; 535 bus_size_t off; 536 u_int64_t val; 537 { 538 volatile u_int64_t *p; 539 540 if ((memh & TC_SPACE_SPARSE) != 0) 541 panic("tc_mem_read_8 not implemented for sparse space"); 542 543 p = (u_int64_t *)(memh + off); 544 *p = val; 545 alpha_mb(); /* XXX XXX XXX */ 546 } 547 548 #define tc_mem_write_multi_N(BYTES,TYPE) \ 549 void \ 550 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c) \ 551 void *v; \ 552 bus_space_handle_t h; \ 553 bus_size_t o, c; \ 554 const TYPE *a; \ 555 { \ 556 \ 557 while (c-- > 0) { \ 558 __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 559 tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \ 560 } \ 561 } 562 tc_mem_write_multi_N(1,u_int8_t) 563 tc_mem_write_multi_N(2,u_int16_t) 564 tc_mem_write_multi_N(4,u_int32_t) 565 tc_mem_write_multi_N(8,u_int64_t) 566 567 #define tc_mem_write_region_N(BYTES,TYPE) \ 568 void \ 569 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c) \ 570 void *v; \ 571 bus_space_handle_t h; \ 572 bus_size_t o, c; \ 573 const TYPE *a; \ 574 { \ 575 \ 576 while (c-- > 0) { \ 577 __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 578 o += sizeof *a; \ 579 } \ 580 } 581 tc_mem_write_region_N(1,u_int8_t) 582 tc_mem_write_region_N(2,u_int16_t) 583 tc_mem_write_region_N(4,u_int32_t) 584 tc_mem_write_region_N(8,u_int64_t) 585 586 #define tc_mem_set_multi_N(BYTES,TYPE) \ 587 void \ 588 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c) \ 589 void *v; \ 590 bus_space_handle_t h; \ 591 bus_size_t o, c; \ 592 TYPE val; \ 593 { \ 594 \ 595 while (c-- > 0) { \ 596 __C(tc_mem_write_,BYTES)(v, h, o, val); \ 597 tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \ 598 } \ 599 } 600 tc_mem_set_multi_N(1,u_int8_t) 601 tc_mem_set_multi_N(2,u_int16_t) 602 tc_mem_set_multi_N(4,u_int32_t) 603 tc_mem_set_multi_N(8,u_int64_t) 604 605 #define tc_mem_set_region_N(BYTES,TYPE) \ 606 void \ 607 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c) \ 608 void *v; \ 609 bus_space_handle_t h; \ 610 bus_size_t o, c; \ 611 TYPE val; \ 612 { \ 613 \ 614 while (c-- > 0) { \ 615 __C(tc_mem_write_,BYTES)(v, h, o, val); \ 616 o += sizeof val; \ 617 } \ 618 } 619 tc_mem_set_region_N(1,u_int8_t) 620 tc_mem_set_region_N(2,u_int16_t) 621 tc_mem_set_region_N(4,u_int32_t) 622 tc_mem_set_region_N(8,u_int64_t) 623 624 #define tc_mem_copy_N(BYTES) \ 625 void \ 626 __C(tc_mem_copy_,BYTES)(v, h1, o1, h2, o2, c) \ 627 void *v; \ 628 bus_space_handle_t h1, h2; \ 629 bus_size_t o1, o2, c; \ 630 { \ 631 bus_size_t o; \ 632 \ 633 if ((h1 & TC_SPACE_SPARSE) != 0 && \ 634 (h2 & TC_SPACE_SPARSE) != 0) { \ 635 bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \ 636 return; \ 637 } \ 638 \ 639 if (h1 + o1 >= h2 + o2) \ 640 /* src after dest: copy forward */ \ 641 for (o = 0; c > 0; c--, o += BYTES) \ 642 __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 643 __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 644 else \ 645 /* dest after src: copy backwards */ \ 646 for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES) \ 647 __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 648 __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 649 } 650 tc_mem_copy_N(1) 651 tc_mem_copy_N(2) 652 tc_mem_copy_N(4) 653 tc_mem_copy_N(8) 654