1 /* $OpenBSD: tc_bus_mem.c,v 1.13 2002/05/02 22:56:06 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 /* barrier */ 62 inline void tc_mem_barrier(void *, bus_space_handle_t, 63 bus_size_t, bus_size_t, int); 64 65 /* read (single) */ 66 inline u_int8_t tc_mem_read_1(void *, bus_space_handle_t, bus_size_t); 67 inline u_int16_t tc_mem_read_2(void *, bus_space_handle_t, bus_size_t); 68 inline u_int32_t tc_mem_read_4(void *, bus_space_handle_t, bus_size_t); 69 inline u_int64_t tc_mem_read_8(void *, bus_space_handle_t, bus_size_t); 70 71 /* read multiple */ 72 void tc_mem_read_multi_1(void *, bus_space_handle_t, 73 bus_size_t, u_int8_t *, bus_size_t); 74 void tc_mem_read_multi_2(void *, bus_space_handle_t, 75 bus_size_t, u_int16_t *, bus_size_t); 76 void tc_mem_read_multi_4(void *, bus_space_handle_t, 77 bus_size_t, u_int32_t *, bus_size_t); 78 void tc_mem_read_multi_8(void *, bus_space_handle_t, 79 bus_size_t, u_int64_t *, bus_size_t); 80 81 /* read region */ 82 void tc_mem_read_region_1(void *, bus_space_handle_t, 83 bus_size_t, u_int8_t *, bus_size_t); 84 void tc_mem_read_region_2(void *, bus_space_handle_t, 85 bus_size_t, u_int16_t *, bus_size_t); 86 void tc_mem_read_region_4(void *, bus_space_handle_t, 87 bus_size_t, u_int32_t *, bus_size_t); 88 void tc_mem_read_region_8(void *, bus_space_handle_t, 89 bus_size_t, u_int64_t *, bus_size_t); 90 91 /* write (single) */ 92 inline void tc_mem_write_1(void *, bus_space_handle_t, bus_size_t, 93 u_int8_t); 94 inline void tc_mem_write_2(void *, bus_space_handle_t, bus_size_t, 95 u_int16_t); 96 inline void tc_mem_write_4(void *, bus_space_handle_t, bus_size_t, 97 u_int32_t); 98 inline void tc_mem_write_8(void *, bus_space_handle_t, bus_size_t, 99 u_int64_t); 100 101 /* write multiple */ 102 void tc_mem_write_multi_1(void *, bus_space_handle_t, 103 bus_size_t, const u_int8_t *, bus_size_t); 104 void tc_mem_write_multi_2(void *, bus_space_handle_t, 105 bus_size_t, const u_int16_t *, bus_size_t); 106 void tc_mem_write_multi_4(void *, bus_space_handle_t, 107 bus_size_t, const u_int32_t *, bus_size_t); 108 void tc_mem_write_multi_8(void *, bus_space_handle_t, 109 bus_size_t, const u_int64_t *, bus_size_t); 110 111 /* write region */ 112 void tc_mem_write_region_1(void *, bus_space_handle_t, 113 bus_size_t, const u_int8_t *, bus_size_t); 114 void tc_mem_write_region_2(void *, bus_space_handle_t, 115 bus_size_t, const u_int16_t *, bus_size_t); 116 void tc_mem_write_region_4(void *, bus_space_handle_t, 117 bus_size_t, const u_int32_t *, bus_size_t); 118 void tc_mem_write_region_8(void *, bus_space_handle_t, 119 bus_size_t, const u_int64_t *, bus_size_t); 120 121 /* set multiple */ 122 void tc_mem_set_multi_1(void *, bus_space_handle_t, 123 bus_size_t, u_int8_t, bus_size_t); 124 void tc_mem_set_multi_2(void *, bus_space_handle_t, 125 bus_size_t, u_int16_t, bus_size_t); 126 void tc_mem_set_multi_4(void *, bus_space_handle_t, 127 bus_size_t, u_int32_t, bus_size_t); 128 void tc_mem_set_multi_8(void *, bus_space_handle_t, 129 bus_size_t, u_int64_t, bus_size_t); 130 131 /* set region */ 132 void tc_mem_set_region_1(void *, bus_space_handle_t, 133 bus_size_t, u_int8_t, bus_size_t); 134 void tc_mem_set_region_2(void *, bus_space_handle_t, 135 bus_size_t, u_int16_t, bus_size_t); 136 void tc_mem_set_region_4(void *, bus_space_handle_t, 137 bus_size_t, u_int32_t, bus_size_t); 138 void tc_mem_set_region_8(void *, bus_space_handle_t, 139 bus_size_t, u_int64_t, bus_size_t); 140 141 /* copy */ 142 void tc_mem_copy_region_1(void *, bus_space_handle_t, 143 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 144 void tc_mem_copy_region_2(void *, bus_space_handle_t, 145 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 146 void tc_mem_copy_region_4(void *, bus_space_handle_t, 147 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 148 void tc_mem_copy_region_8(void *, bus_space_handle_t, 149 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 150 151 struct alpha_bus_space tc_mem_space = { 152 /* cookie */ 153 NULL, 154 155 /* mapping/unmapping */ 156 tc_mem_map, 157 tc_mem_unmap, 158 tc_mem_subregion, 159 160 /* allocation/deallocation */ 161 tc_mem_alloc, 162 tc_mem_free, 163 164 /* barrier */ 165 tc_mem_barrier, 166 167 /* read (single) */ 168 tc_mem_read_1, 169 tc_mem_read_2, 170 tc_mem_read_4, 171 tc_mem_read_8, 172 173 /* read multiple */ 174 tc_mem_read_multi_1, 175 tc_mem_read_multi_2, 176 tc_mem_read_multi_4, 177 tc_mem_read_multi_8, 178 179 /* read region */ 180 tc_mem_read_region_1, 181 tc_mem_read_region_2, 182 tc_mem_read_region_4, 183 tc_mem_read_region_8, 184 185 /* write (single) */ 186 tc_mem_write_1, 187 tc_mem_write_2, 188 tc_mem_write_4, 189 tc_mem_write_8, 190 191 /* write multiple */ 192 tc_mem_write_multi_1, 193 tc_mem_write_multi_2, 194 tc_mem_write_multi_4, 195 tc_mem_write_multi_8, 196 197 /* write region */ 198 tc_mem_write_region_1, 199 tc_mem_write_region_2, 200 tc_mem_write_region_4, 201 tc_mem_write_region_8, 202 203 /* set multiple */ 204 tc_mem_set_multi_1, 205 tc_mem_set_multi_2, 206 tc_mem_set_multi_4, 207 tc_mem_set_multi_8, 208 209 /* set region */ 210 tc_mem_set_region_1, 211 tc_mem_set_region_2, 212 tc_mem_set_region_4, 213 tc_mem_set_region_8, 214 215 /* copy */ 216 tc_mem_copy_region_1, 217 tc_mem_copy_region_2, 218 tc_mem_copy_region_4, 219 tc_mem_copy_region_8, 220 }; 221 222 bus_space_tag_t 223 tc_bus_mem_init(memv) 224 void *memv; 225 { 226 bus_space_tag_t h = &tc_mem_space; 227 228 h->abs_cookie = memv; 229 return (h); 230 } 231 232 /* ARGSUSED */ 233 int 234 tc_mem_map(v, memaddr, memsize, cacheable, memhp) 235 void *v; 236 bus_addr_t memaddr; 237 bus_size_t memsize; 238 int cacheable; 239 bus_space_handle_t *memhp; 240 { 241 242 if (memaddr & 0x7) 243 panic("tc_mem_map needs 8 byte alignment"); 244 if (cacheable) 245 *memhp = ALPHA_PHYS_TO_K0SEG(memaddr); 246 else 247 *memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr)); 248 return (0); 249 } 250 251 /* ARGSUSED */ 252 void 253 tc_mem_unmap(v, memh, memsize) 254 void *v; 255 bus_space_handle_t memh; 256 bus_size_t memsize; 257 { 258 259 /* XXX XX XXX nothing to do. */ 260 } 261 262 int 263 tc_mem_subregion(v, memh, offset, size, nmemh) 264 void *v; 265 bus_space_handle_t memh, *nmemh; 266 bus_size_t offset, size; 267 { 268 269 /* Disallow subregioning that would make the handle unaligned. */ 270 if ((offset & 0x7) != 0) 271 return (1); 272 273 if ((memh & TC_SPACE_SPARSE) != 0) 274 *nmemh = memh + (offset << 1); 275 else 276 *nmemh = memh + offset; 277 278 return (0); 279 } 280 281 int 282 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp) 283 void *v; 284 bus_addr_t rstart, rend, *addrp; 285 bus_size_t size, align, boundary; 286 int flags; 287 bus_space_handle_t *bshp; 288 { 289 290 /* XXX XXX XXX XXX XXX XXX */ 291 panic("tc_mem_alloc unimplemented"); 292 } 293 294 void 295 tc_mem_free(v, bsh, size) 296 void *v; 297 bus_space_handle_t bsh; 298 bus_size_t size; 299 { 300 301 /* XXX XXX XXX XXX XXX XXX */ 302 panic("tc_mem_free unimplemented"); 303 } 304 305 inline void 306 tc_mem_barrier(v, h, o, l, f) 307 void *v; 308 bus_space_handle_t h; 309 bus_size_t o, l; 310 int f; 311 { 312 313 if ((f & BUS_SPACE_BARRIER_READ) != 0) 314 alpha_mb(); 315 else if ((f & BUS_SPACE_BARRIER_WRITE) != 0) 316 alpha_wmb(); 317 } 318 319 inline u_int8_t 320 tc_mem_read_1(v, memh, off) 321 void *v; 322 bus_space_handle_t memh; 323 bus_size_t off; 324 { 325 volatile u_int8_t *p; 326 327 alpha_mb(); /* XXX XXX XXX */ 328 329 if ((memh & TC_SPACE_SPARSE) != 0) 330 panic("tc_mem_read_1 not implemented for sparse space"); 331 332 p = (u_int8_t *)(memh + off); 333 return (*p); 334 } 335 336 inline u_int16_t 337 tc_mem_read_2(v, memh, off) 338 void *v; 339 bus_space_handle_t memh; 340 bus_size_t off; 341 { 342 volatile u_int16_t *p; 343 344 alpha_mb(); /* XXX XXX XXX */ 345 346 if ((memh & TC_SPACE_SPARSE) != 0) 347 panic("tc_mem_read_2 not implemented for sparse space"); 348 349 p = (u_int16_t *)(memh + off); 350 return (*p); 351 } 352 353 inline u_int32_t 354 tc_mem_read_4(v, memh, off) 355 void *v; 356 bus_space_handle_t memh; 357 bus_size_t off; 358 { 359 volatile u_int32_t *p; 360 361 alpha_mb(); /* XXX XXX XXX */ 362 363 if ((memh & TC_SPACE_SPARSE) != 0) 364 /* Nothing special to do for 4-byte sparse space accesses */ 365 p = (u_int32_t *)(memh + (off << 1)); 366 else 367 p = (u_int32_t *)(memh + off); 368 return (*p); 369 } 370 371 inline u_int64_t 372 tc_mem_read_8(v, memh, off) 373 void *v; 374 bus_space_handle_t memh; 375 bus_size_t off; 376 { 377 volatile u_int64_t *p; 378 379 alpha_mb(); /* XXX XXX XXX */ 380 381 if ((memh & TC_SPACE_SPARSE) != 0) 382 panic("tc_mem_read_8 not implemented for sparse space"); 383 384 p = (u_int64_t *)(memh + off); 385 return (*p); 386 } 387 388 #define tc_mem_read_multi_N(BYTES,TYPE) \ 389 void \ 390 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c) \ 391 void *v; \ 392 bus_space_handle_t h; \ 393 bus_size_t o, c; \ 394 TYPE *a; \ 395 { \ 396 \ 397 while (c-- > 0) { \ 398 tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \ 399 *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 400 } \ 401 } 402 tc_mem_read_multi_N(1,u_int8_t) 403 tc_mem_read_multi_N(2,u_int16_t) 404 tc_mem_read_multi_N(4,u_int32_t) 405 tc_mem_read_multi_N(8,u_int64_t) 406 407 #define tc_mem_read_region_N(BYTES,TYPE) \ 408 void \ 409 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c) \ 410 void *v; \ 411 bus_space_handle_t h; \ 412 bus_size_t o, c; \ 413 TYPE *a; \ 414 { \ 415 \ 416 while (c-- > 0) { \ 417 *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 418 o += sizeof *a; \ 419 } \ 420 } 421 tc_mem_read_region_N(1,u_int8_t) 422 tc_mem_read_region_N(2,u_int16_t) 423 tc_mem_read_region_N(4,u_int32_t) 424 tc_mem_read_region_N(8,u_int64_t) 425 426 inline void 427 tc_mem_write_1(v, memh, off, val) 428 void *v; 429 bus_space_handle_t memh; 430 bus_size_t off; 431 u_int8_t val; 432 { 433 434 if ((memh & TC_SPACE_SPARSE) != 0) { 435 volatile u_int64_t *p, v; 436 u_int64_t shift, msk; 437 438 shift = off & 0x3; 439 off &= 0x3; 440 441 p = (u_int64_t *)(memh + (off << 1)); 442 443 msk = ~(0x1 << shift) & 0xf; 444 v = (msk << 32) | (((u_int64_t)val) << (shift * 8)); 445 446 *p = val; 447 } else { 448 volatile u_int8_t *p; 449 450 p = (u_int8_t *)(memh + off); 451 *p = val; 452 } 453 alpha_mb(); /* XXX XXX XXX */ 454 } 455 456 inline void 457 tc_mem_write_2(v, memh, off, val) 458 void *v; 459 bus_space_handle_t memh; 460 bus_size_t off; 461 u_int16_t val; 462 { 463 464 if ((memh & TC_SPACE_SPARSE) != 0) { 465 volatile u_int64_t *p, v; 466 u_int64_t shift, msk; 467 468 shift = off & 0x2; 469 off &= 0x3; 470 471 p = (u_int64_t *)(memh + (off << 1)); 472 473 msk = ~(0x3 << shift) & 0xf; 474 v = (msk << 32) | (((u_int64_t)val) << (shift * 8)); 475 476 *p = val; 477 } else { 478 volatile u_int16_t *p; 479 480 p = (u_int16_t *)(memh + off); 481 *p = val; 482 } 483 alpha_mb(); /* XXX XXX XXX */ 484 } 485 486 inline void 487 tc_mem_write_4(v, memh, off, val) 488 void *v; 489 bus_space_handle_t memh; 490 bus_size_t off; 491 u_int32_t val; 492 { 493 volatile u_int32_t *p; 494 495 if ((memh & TC_SPACE_SPARSE) != 0) 496 /* Nothing special to do for 4-byte sparse space accesses */ 497 p = (u_int32_t *)(memh + (off << 1)); 498 else 499 p = (u_int32_t *)(memh + off); 500 *p = val; 501 alpha_mb(); /* XXX XXX XXX */ 502 } 503 504 inline void 505 tc_mem_write_8(v, memh, off, val) 506 void *v; 507 bus_space_handle_t memh; 508 bus_size_t off; 509 u_int64_t val; 510 { 511 volatile u_int64_t *p; 512 513 if ((memh & TC_SPACE_SPARSE) != 0) 514 panic("tc_mem_read_8 not implemented for sparse space"); 515 516 p = (u_int64_t *)(memh + off); 517 *p = val; 518 alpha_mb(); /* XXX XXX XXX */ 519 } 520 521 #define tc_mem_write_multi_N(BYTES,TYPE) \ 522 void \ 523 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c) \ 524 void *v; \ 525 bus_space_handle_t h; \ 526 bus_size_t o, c; \ 527 const TYPE *a; \ 528 { \ 529 \ 530 while (c-- > 0) { \ 531 __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 532 tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \ 533 } \ 534 } 535 tc_mem_write_multi_N(1,u_int8_t) 536 tc_mem_write_multi_N(2,u_int16_t) 537 tc_mem_write_multi_N(4,u_int32_t) 538 tc_mem_write_multi_N(8,u_int64_t) 539 540 #define tc_mem_write_region_N(BYTES,TYPE) \ 541 void \ 542 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c) \ 543 void *v; \ 544 bus_space_handle_t h; \ 545 bus_size_t o, c; \ 546 const TYPE *a; \ 547 { \ 548 \ 549 while (c-- > 0) { \ 550 __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 551 o += sizeof *a; \ 552 } \ 553 } 554 tc_mem_write_region_N(1,u_int8_t) 555 tc_mem_write_region_N(2,u_int16_t) 556 tc_mem_write_region_N(4,u_int32_t) 557 tc_mem_write_region_N(8,u_int64_t) 558 559 #define tc_mem_set_multi_N(BYTES,TYPE) \ 560 void \ 561 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c) \ 562 void *v; \ 563 bus_space_handle_t h; \ 564 bus_size_t o, c; \ 565 TYPE val; \ 566 { \ 567 \ 568 while (c-- > 0) { \ 569 __C(tc_mem_write_,BYTES)(v, h, o, val); \ 570 tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \ 571 } \ 572 } 573 tc_mem_set_multi_N(1,u_int8_t) 574 tc_mem_set_multi_N(2,u_int16_t) 575 tc_mem_set_multi_N(4,u_int32_t) 576 tc_mem_set_multi_N(8,u_int64_t) 577 578 #define tc_mem_set_region_N(BYTES,TYPE) \ 579 void \ 580 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c) \ 581 void *v; \ 582 bus_space_handle_t h; \ 583 bus_size_t o, c; \ 584 TYPE val; \ 585 { \ 586 \ 587 while (c-- > 0) { \ 588 __C(tc_mem_write_,BYTES)(v, h, o, val); \ 589 o += sizeof val; \ 590 } \ 591 } 592 tc_mem_set_region_N(1,u_int8_t) 593 tc_mem_set_region_N(2,u_int16_t) 594 tc_mem_set_region_N(4,u_int32_t) 595 tc_mem_set_region_N(8,u_int64_t) 596 597 #define tc_mem_copy_region_N(BYTES) \ 598 void \ 599 __C(tc_mem_copy_region_,BYTES)(v, h1, o1, h2, o2, c) \ 600 void *v; \ 601 bus_space_handle_t h1, h2; \ 602 bus_size_t o1, o2, c; \ 603 { \ 604 bus_size_t o; \ 605 \ 606 if ((h1 & TC_SPACE_SPARSE) != 0 && \ 607 (h2 & TC_SPACE_SPARSE) != 0) { \ 608 bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \ 609 return; \ 610 } \ 611 \ 612 if (h1 + o1 >= h2 + o2) \ 613 /* src after dest: copy forward */ \ 614 for (o = 0; c > 0; c--, o += BYTES) \ 615 __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 616 __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 617 else \ 618 /* dest after src: copy backwards */ \ 619 for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES) \ 620 __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 621 __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 622 } 623 tc_mem_copy_region_N(1) 624 tc_mem_copy_region_N(2) 625 tc_mem_copy_region_N(4) 626 tc_mem_copy_region_N(8) 627