1 /* 2 * PS3 repository routines. 3 * 4 * Copyright (C) 2006 Sony Computer Entertainment Inc. 5 * Copyright 2006 Sony Corp. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <asm/lv1call.h> 22 23 #include "platform.h" 24 25 enum ps3_vendor_id { 26 PS3_VENDOR_ID_NONE = 0, 27 PS3_VENDOR_ID_SONY = 0x8000000000000000UL, 28 }; 29 30 enum ps3_lpar_id { 31 PS3_LPAR_ID_CURRENT = 0, 32 PS3_LPAR_ID_PME = 1, 33 }; 34 35 #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__) 36 static void _dump_field(const char *hdr, u64 n, const char *func, int line) 37 { 38 #if defined(DEBUG) 39 char s[16]; 40 const char *const in = (const char *)&n; 41 unsigned int i; 42 43 for (i = 0; i < 8; i++) 44 s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.'; 45 s[i] = 0; 46 47 pr_debug("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s); 48 #endif 49 } 50 51 #define dump_node_name(_a, _b, _c, _d, _e) \ 52 _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__) 53 static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, 54 u64 n4, const char *func, int line) 55 { 56 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); 57 _dump_field("n1: ", n1, func, line); 58 _dump_field("n2: ", n2, func, line); 59 _dump_field("n3: ", n3, func, line); 60 _dump_field("n4: ", n4, func, line); 61 } 62 63 #define dump_node(_a, _b, _c, _d, _e, _f, _g) \ 64 _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) 65 static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, 66 u64 v1, u64 v2, const char *func, int line) 67 { 68 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); 69 _dump_field("n1: ", n1, func, line); 70 _dump_field("n2: ", n2, func, line); 71 _dump_field("n3: ", n3, func, line); 72 _dump_field("n4: ", n4, func, line); 73 pr_debug("%s:%d: v1: %016llx\n", func, line, v1); 74 pr_debug("%s:%d: v2: %016llx\n", func, line, v2); 75 } 76 77 /** 78 * make_first_field - Make the first field of a repository node name. 79 * @text: Text portion of the field. 80 * @index: Numeric index portion of the field. Use zero for 'don't care'. 81 * 82 * This routine sets the vendor id to zero (non-vendor specific). 83 * Returns field value. 84 */ 85 86 static u64 make_first_field(const char *text, u64 index) 87 { 88 u64 n; 89 90 strncpy((char *)&n, text, 8); 91 return PS3_VENDOR_ID_NONE + (n >> 32) + index; 92 } 93 94 /** 95 * make_field - Make subsequent fields of a repository node name. 96 * @text: Text portion of the field. Use "" for 'don't care'. 97 * @index: Numeric index portion of the field. Use zero for 'don't care'. 98 * 99 * Returns field value. 100 */ 101 102 static u64 make_field(const char *text, u64 index) 103 { 104 u64 n; 105 106 strncpy((char *)&n, text, 8); 107 return n + index; 108 } 109 110 /** 111 * read_node - Read a repository node from raw fields. 112 * @n1: First field of node name. 113 * @n2: Second field of node name. Use zero for 'don't care'. 114 * @n3: Third field of node name. Use zero for 'don't care'. 115 * @n4: Fourth field of node name. Use zero for 'don't care'. 116 * @v1: First repository value (high word). 117 * @v2: Second repository value (low word). Optional parameter, use zero 118 * for 'don't care'. 119 */ 120 121 static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, 122 u64 *_v1, u64 *_v2) 123 { 124 int result; 125 u64 v1; 126 u64 v2; 127 128 if (lpar_id == PS3_LPAR_ID_CURRENT) { 129 u64 id; 130 lv1_get_logical_partition_id(&id); 131 lpar_id = id; 132 } 133 134 result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1, 135 &v2); 136 137 if (result) { 138 pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", 139 __func__, __LINE__, ps3_result(result)); 140 dump_node_name(lpar_id, n1, n2, n3, n4); 141 return -ENOENT; 142 } 143 144 dump_node(lpar_id, n1, n2, n3, n4, v1, v2); 145 146 if (_v1) 147 *_v1 = v1; 148 if (_v2) 149 *_v2 = v2; 150 151 if (v1 && !_v1) 152 pr_debug("%s:%d: warning: discarding non-zero v1: %016llx\n", 153 __func__, __LINE__, v1); 154 if (v2 && !_v2) 155 pr_debug("%s:%d: warning: discarding non-zero v2: %016llx\n", 156 __func__, __LINE__, v2); 157 158 return 0; 159 } 160 161 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, 162 u64 *value) 163 { 164 return read_node(PS3_LPAR_ID_PME, 165 make_first_field("bus", bus_index), 166 make_field(bus_str, 0), 167 0, 0, 168 value, NULL); 169 } 170 171 int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id) 172 { 173 int result; 174 175 result = read_node(PS3_LPAR_ID_PME, 176 make_first_field("bus", bus_index), 177 make_field("id", 0), 178 0, 0, 179 bus_id, NULL); 180 return result; 181 } 182 183 int ps3_repository_read_bus_type(unsigned int bus_index, 184 enum ps3_bus_type *bus_type) 185 { 186 int result; 187 u64 v1; 188 189 result = read_node(PS3_LPAR_ID_PME, 190 make_first_field("bus", bus_index), 191 make_field("type", 0), 192 0, 0, 193 &v1, NULL); 194 *bus_type = v1; 195 return result; 196 } 197 198 int ps3_repository_read_bus_num_dev(unsigned int bus_index, 199 unsigned int *num_dev) 200 { 201 int result; 202 u64 v1; 203 204 result = read_node(PS3_LPAR_ID_PME, 205 make_first_field("bus", bus_index), 206 make_field("num_dev", 0), 207 0, 0, 208 &v1, NULL); 209 *num_dev = v1; 210 return result; 211 } 212 213 int ps3_repository_read_dev_str(unsigned int bus_index, 214 unsigned int dev_index, const char *dev_str, u64 *value) 215 { 216 return read_node(PS3_LPAR_ID_PME, 217 make_first_field("bus", bus_index), 218 make_field("dev", dev_index), 219 make_field(dev_str, 0), 220 0, 221 value, NULL); 222 } 223 224 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, 225 u64 *dev_id) 226 { 227 int result; 228 229 result = read_node(PS3_LPAR_ID_PME, 230 make_first_field("bus", bus_index), 231 make_field("dev", dev_index), 232 make_field("id", 0), 233 0, 234 dev_id, NULL); 235 return result; 236 } 237 238 int ps3_repository_read_dev_type(unsigned int bus_index, 239 unsigned int dev_index, enum ps3_dev_type *dev_type) 240 { 241 int result; 242 u64 v1; 243 244 result = read_node(PS3_LPAR_ID_PME, 245 make_first_field("bus", bus_index), 246 make_field("dev", dev_index), 247 make_field("type", 0), 248 0, 249 &v1, NULL); 250 *dev_type = v1; 251 return result; 252 } 253 254 int ps3_repository_read_dev_intr(unsigned int bus_index, 255 unsigned int dev_index, unsigned int intr_index, 256 enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id) 257 { 258 int result; 259 u64 v1; 260 u64 v2; 261 262 result = read_node(PS3_LPAR_ID_PME, 263 make_first_field("bus", bus_index), 264 make_field("dev", dev_index), 265 make_field("intr", intr_index), 266 0, 267 &v1, &v2); 268 *intr_type = v1; 269 *interrupt_id = v2; 270 return result; 271 } 272 273 int ps3_repository_read_dev_reg_type(unsigned int bus_index, 274 unsigned int dev_index, unsigned int reg_index, 275 enum ps3_reg_type *reg_type) 276 { 277 int result; 278 u64 v1; 279 280 result = read_node(PS3_LPAR_ID_PME, 281 make_first_field("bus", bus_index), 282 make_field("dev", dev_index), 283 make_field("reg", reg_index), 284 make_field("type", 0), 285 &v1, NULL); 286 *reg_type = v1; 287 return result; 288 } 289 290 int ps3_repository_read_dev_reg_addr(unsigned int bus_index, 291 unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len) 292 { 293 return read_node(PS3_LPAR_ID_PME, 294 make_first_field("bus", bus_index), 295 make_field("dev", dev_index), 296 make_field("reg", reg_index), 297 make_field("data", 0), 298 bus_addr, len); 299 } 300 301 int ps3_repository_read_dev_reg(unsigned int bus_index, 302 unsigned int dev_index, unsigned int reg_index, 303 enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len) 304 { 305 int result = ps3_repository_read_dev_reg_type(bus_index, dev_index, 306 reg_index, reg_type); 307 return result ? result 308 : ps3_repository_read_dev_reg_addr(bus_index, dev_index, 309 reg_index, bus_addr, len); 310 } 311 312 313 314 int ps3_repository_find_device(struct ps3_repository_device *repo) 315 { 316 int result; 317 struct ps3_repository_device tmp = *repo; 318 unsigned int num_dev; 319 320 BUG_ON(repo->bus_index > 10); 321 BUG_ON(repo->dev_index > 10); 322 323 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); 324 325 if (result) { 326 pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); 327 return result; 328 } 329 330 pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n", 331 __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, 332 num_dev); 333 334 if (tmp.dev_index >= num_dev) { 335 pr_debug("%s:%d: no device found\n", __func__, __LINE__); 336 return -ENODEV; 337 } 338 339 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, 340 &tmp.dev_type); 341 342 if (result) { 343 pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__); 344 return result; 345 } 346 347 result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, 348 &tmp.dev_id); 349 350 if (result) { 351 pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, 352 __LINE__); 353 return result; 354 } 355 356 pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n", 357 __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); 358 359 *repo = tmp; 360 return 0; 361 } 362 363 int ps3_repository_find_device_by_id(struct ps3_repository_device *repo, 364 u64 bus_id, u64 dev_id) 365 { 366 int result = -ENODEV; 367 struct ps3_repository_device tmp; 368 unsigned int num_dev; 369 370 pr_debug(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__, 371 bus_id, dev_id); 372 373 for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) { 374 result = ps3_repository_read_bus_id(tmp.bus_index, 375 &tmp.bus_id); 376 if (result) { 377 pr_debug("%s:%u read_bus_id(%u) failed\n", __func__, 378 __LINE__, tmp.bus_index); 379 return result; 380 } 381 382 if (tmp.bus_id == bus_id) 383 goto found_bus; 384 385 pr_debug("%s:%u: skip, bus_id %llu\n", __func__, __LINE__, 386 tmp.bus_id); 387 } 388 pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__); 389 return result; 390 391 found_bus: 392 result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type); 393 if (result) { 394 pr_debug("%s:%u read_bus_type(%u) failed\n", __func__, 395 __LINE__, tmp.bus_index); 396 return result; 397 } 398 399 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); 400 if (result) { 401 pr_debug("%s:%u read_bus_num_dev failed\n", __func__, 402 __LINE__); 403 return result; 404 } 405 406 for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) { 407 result = ps3_repository_read_dev_id(tmp.bus_index, 408 tmp.dev_index, 409 &tmp.dev_id); 410 if (result) { 411 pr_debug("%s:%u read_dev_id(%u:%u) failed\n", __func__, 412 __LINE__, tmp.bus_index, tmp.dev_index); 413 return result; 414 } 415 416 if (tmp.dev_id == dev_id) 417 goto found_dev; 418 419 pr_debug("%s:%u: skip, dev_id %llu\n", __func__, __LINE__, 420 tmp.dev_id); 421 } 422 pr_debug(" <- %s:%u: dev not found\n", __func__, __LINE__); 423 return result; 424 425 found_dev: 426 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, 427 &tmp.dev_type); 428 if (result) { 429 pr_debug("%s:%u read_dev_type failed\n", __func__, __LINE__); 430 return result; 431 } 432 433 pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n", 434 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index, 435 tmp.dev_index, tmp.bus_id, tmp.dev_id); 436 *repo = tmp; 437 return 0; 438 } 439 440 int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, 441 int (*callback)(const struct ps3_repository_device *repo)) 442 { 443 int result = 0; 444 struct ps3_repository_device repo; 445 446 pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); 447 448 repo.bus_type = bus_type; 449 result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index); 450 if (result) { 451 pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__); 452 return result; 453 } 454 455 result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id); 456 if (result) { 457 pr_debug("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__, 458 repo.bus_index); 459 return result; 460 } 461 462 for (repo.dev_index = 0; ; repo.dev_index++) { 463 result = ps3_repository_find_device(&repo); 464 if (result == -ENODEV) { 465 result = 0; 466 break; 467 } else if (result) 468 break; 469 470 result = callback(&repo); 471 if (result) { 472 pr_debug("%s:%d: abort at callback\n", __func__, 473 __LINE__); 474 break; 475 } 476 } 477 478 pr_debug(" <- %s:%d\n", __func__, __LINE__); 479 return result; 480 } 481 482 int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, 483 unsigned int *bus_index) 484 { 485 unsigned int i; 486 enum ps3_bus_type type; 487 int error; 488 489 for (i = from; i < 10; i++) { 490 error = ps3_repository_read_bus_type(i, &type); 491 if (error) { 492 pr_debug("%s:%d read_bus_type failed\n", 493 __func__, __LINE__); 494 *bus_index = UINT_MAX; 495 return error; 496 } 497 if (type == bus_type) { 498 *bus_index = i; 499 return 0; 500 } 501 } 502 *bus_index = UINT_MAX; 503 return -ENODEV; 504 } 505 506 int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, 507 enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) 508 { 509 int result = 0; 510 unsigned int res_index; 511 512 pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type); 513 514 *interrupt_id = UINT_MAX; 515 516 for (res_index = 0; res_index < 10; res_index++) { 517 enum ps3_interrupt_type t; 518 unsigned int id; 519 520 result = ps3_repository_read_dev_intr(repo->bus_index, 521 repo->dev_index, res_index, &t, &id); 522 523 if (result) { 524 pr_debug("%s:%d read_dev_intr failed\n", 525 __func__, __LINE__); 526 return result; 527 } 528 529 if (t == intr_type) { 530 *interrupt_id = id; 531 break; 532 } 533 } 534 535 if (res_index == 10) 536 return -ENODEV; 537 538 pr_debug("%s:%d: found intr_type %u at res_index %u\n", 539 __func__, __LINE__, intr_type, res_index); 540 541 return result; 542 } 543 544 int ps3_repository_find_reg(const struct ps3_repository_device *repo, 545 enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) 546 { 547 int result = 0; 548 unsigned int res_index; 549 550 pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type); 551 552 *bus_addr = *len = 0; 553 554 for (res_index = 0; res_index < 10; res_index++) { 555 enum ps3_reg_type t; 556 u64 a; 557 u64 l; 558 559 result = ps3_repository_read_dev_reg(repo->bus_index, 560 repo->dev_index, res_index, &t, &a, &l); 561 562 if (result) { 563 pr_debug("%s:%d read_dev_reg failed\n", 564 __func__, __LINE__); 565 return result; 566 } 567 568 if (t == reg_type) { 569 *bus_addr = a; 570 *len = l; 571 break; 572 } 573 } 574 575 if (res_index == 10) 576 return -ENODEV; 577 578 pr_debug("%s:%d: found reg_type %u at res_index %u\n", 579 __func__, __LINE__, reg_type, res_index); 580 581 return result; 582 } 583 584 int ps3_repository_read_stor_dev_port(unsigned int bus_index, 585 unsigned int dev_index, u64 *port) 586 { 587 return read_node(PS3_LPAR_ID_PME, 588 make_first_field("bus", bus_index), 589 make_field("dev", dev_index), 590 make_field("port", 0), 591 0, port, NULL); 592 } 593 594 int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index, 595 unsigned int dev_index, u64 *blk_size) 596 { 597 return read_node(PS3_LPAR_ID_PME, 598 make_first_field("bus", bus_index), 599 make_field("dev", dev_index), 600 make_field("blk_size", 0), 601 0, blk_size, NULL); 602 } 603 604 int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index, 605 unsigned int dev_index, u64 *num_blocks) 606 { 607 return read_node(PS3_LPAR_ID_PME, 608 make_first_field("bus", bus_index), 609 make_field("dev", dev_index), 610 make_field("n_blocks", 0), 611 0, num_blocks, NULL); 612 } 613 614 int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, 615 unsigned int dev_index, unsigned int *num_regions) 616 { 617 int result; 618 u64 v1; 619 620 result = read_node(PS3_LPAR_ID_PME, 621 make_first_field("bus", bus_index), 622 make_field("dev", dev_index), 623 make_field("n_regs", 0), 624 0, &v1, NULL); 625 *num_regions = v1; 626 return result; 627 } 628 629 int ps3_repository_read_stor_dev_region_id(unsigned int bus_index, 630 unsigned int dev_index, unsigned int region_index, 631 unsigned int *region_id) 632 { 633 int result; 634 u64 v1; 635 636 result = read_node(PS3_LPAR_ID_PME, 637 make_first_field("bus", bus_index), 638 make_field("dev", dev_index), 639 make_field("region", region_index), 640 make_field("id", 0), 641 &v1, NULL); 642 *region_id = v1; 643 return result; 644 } 645 646 int ps3_repository_read_stor_dev_region_size(unsigned int bus_index, 647 unsigned int dev_index, unsigned int region_index, u64 *region_size) 648 { 649 return read_node(PS3_LPAR_ID_PME, 650 make_first_field("bus", bus_index), 651 make_field("dev", dev_index), 652 make_field("region", region_index), 653 make_field("size", 0), 654 region_size, NULL); 655 } 656 657 int ps3_repository_read_stor_dev_region_start(unsigned int bus_index, 658 unsigned int dev_index, unsigned int region_index, u64 *region_start) 659 { 660 return read_node(PS3_LPAR_ID_PME, 661 make_first_field("bus", bus_index), 662 make_field("dev", dev_index), 663 make_field("region", region_index), 664 make_field("start", 0), 665 region_start, NULL); 666 } 667 668 int ps3_repository_read_stor_dev_info(unsigned int bus_index, 669 unsigned int dev_index, u64 *port, u64 *blk_size, 670 u64 *num_blocks, unsigned int *num_regions) 671 { 672 int result; 673 674 result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port); 675 if (result) 676 return result; 677 678 result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index, 679 blk_size); 680 if (result) 681 return result; 682 683 result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index, 684 num_blocks); 685 if (result) 686 return result; 687 688 result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index, 689 num_regions); 690 return result; 691 } 692 693 int ps3_repository_read_stor_dev_region(unsigned int bus_index, 694 unsigned int dev_index, unsigned int region_index, 695 unsigned int *region_id, u64 *region_start, u64 *region_size) 696 { 697 int result; 698 699 result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index, 700 region_index, region_id); 701 if (result) 702 return result; 703 704 result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index, 705 region_index, region_start); 706 if (result) 707 return result; 708 709 result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index, 710 region_index, region_size); 711 return result; 712 } 713 714 /** 715 * ps3_repository_read_num_pu - Number of logical PU processors for this lpar. 716 */ 717 718 int ps3_repository_read_num_pu(u64 *num_pu) 719 { 720 *num_pu = 0; 721 return read_node(PS3_LPAR_ID_CURRENT, 722 make_first_field("bi", 0), 723 make_field("pun", 0), 724 0, 0, 725 num_pu, NULL); 726 } 727 728 /** 729 * ps3_repository_read_pu_id - Read the logical PU id. 730 * @pu_index: Zero based index. 731 * @pu_id: The logical PU id. 732 */ 733 734 int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id) 735 { 736 return read_node(PS3_LPAR_ID_CURRENT, 737 make_first_field("bi", 0), 738 make_field("pu", pu_index), 739 0, 0, 740 pu_id, NULL); 741 } 742 743 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) 744 { 745 return read_node(PS3_LPAR_ID_CURRENT, 746 make_first_field("bi", 0), 747 make_field("pu", 0), 748 ppe_id, 749 make_field("rm_size", 0), 750 rm_size, NULL); 751 } 752 753 int ps3_repository_read_region_total(u64 *region_total) 754 { 755 return read_node(PS3_LPAR_ID_CURRENT, 756 make_first_field("bi", 0), 757 make_field("rgntotal", 0), 758 0, 0, 759 region_total, NULL); 760 } 761 762 /** 763 * ps3_repository_read_mm_info - Read mm info for single pu system. 764 * @rm_base: Real mode memory base address. 765 * @rm_size: Real mode memory size. 766 * @region_total: Maximum memory region size. 767 */ 768 769 int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) 770 { 771 int result; 772 u64 ppe_id; 773 774 lv1_get_logical_ppe_id(&ppe_id); 775 *rm_base = 0; 776 result = ps3_repository_read_rm_size(ppe_id, rm_size); 777 return result ? result 778 : ps3_repository_read_region_total(region_total); 779 } 780 781 /** 782 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved. 783 * @num_spu: Number of physical spus. 784 */ 785 786 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) 787 { 788 int result; 789 u64 v1; 790 791 result = read_node(PS3_LPAR_ID_CURRENT, 792 make_first_field("bi", 0), 793 make_field("spun", 0), 794 0, 0, 795 &v1, NULL); 796 *num_spu_reserved = v1; 797 return result; 798 } 799 800 /** 801 * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations. 802 * @num_resource_id: Number of spu resource ids. 803 */ 804 805 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) 806 { 807 int result; 808 u64 v1; 809 810 result = read_node(PS3_LPAR_ID_CURRENT, 811 make_first_field("bi", 0), 812 make_field("spursvn", 0), 813 0, 0, 814 &v1, NULL); 815 *num_resource_id = v1; 816 return result; 817 } 818 819 /** 820 * ps3_repository_read_spu_resource_id - spu resource reservation id value. 821 * @res_index: Resource reservation index. 822 * @resource_type: Resource reservation type. 823 * @resource_id: Resource reservation id. 824 */ 825 826 int ps3_repository_read_spu_resource_id(unsigned int res_index, 827 enum ps3_spu_resource_type *resource_type, unsigned int *resource_id) 828 { 829 int result; 830 u64 v1; 831 u64 v2; 832 833 result = read_node(PS3_LPAR_ID_CURRENT, 834 make_first_field("bi", 0), 835 make_field("spursv", 0), 836 res_index, 837 0, 838 &v1, &v2); 839 *resource_type = v1; 840 *resource_id = v2; 841 return result; 842 } 843 844 static int ps3_repository_read_boot_dat_address(u64 *address) 845 { 846 return read_node(PS3_LPAR_ID_CURRENT, 847 make_first_field("bi", 0), 848 make_field("boot_dat", 0), 849 make_field("address", 0), 850 0, 851 address, NULL); 852 } 853 854 int ps3_repository_read_boot_dat_size(unsigned int *size) 855 { 856 int result; 857 u64 v1; 858 859 result = read_node(PS3_LPAR_ID_CURRENT, 860 make_first_field("bi", 0), 861 make_field("boot_dat", 0), 862 make_field("size", 0), 863 0, 864 &v1, NULL); 865 *size = v1; 866 return result; 867 } 868 869 int ps3_repository_read_vuart_av_port(unsigned int *port) 870 { 871 int result; 872 u64 v1; 873 874 result = read_node(PS3_LPAR_ID_CURRENT, 875 make_first_field("bi", 0), 876 make_field("vir_uart", 0), 877 make_field("port", 0), 878 make_field("avset", 0), 879 &v1, NULL); 880 *port = v1; 881 return result; 882 } 883 884 int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) 885 { 886 int result; 887 u64 v1; 888 889 result = read_node(PS3_LPAR_ID_CURRENT, 890 make_first_field("bi", 0), 891 make_field("vir_uart", 0), 892 make_field("port", 0), 893 make_field("sysmgr", 0), 894 &v1, NULL); 895 *port = v1; 896 return result; 897 } 898 899 /** 900 * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. 901 * address: lpar address of cell_ext_os_area 902 * @size: size of cell_ext_os_area 903 */ 904 905 int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) 906 { 907 int result; 908 909 *size = 0; 910 result = ps3_repository_read_boot_dat_address(lpar_addr); 911 return result ? result 912 : ps3_repository_read_boot_dat_size(size); 913 } 914 915 /** 916 * ps3_repository_read_num_be - Number of physical BE processors in the system. 917 */ 918 919 int ps3_repository_read_num_be(unsigned int *num_be) 920 { 921 int result; 922 u64 v1; 923 924 result = read_node(PS3_LPAR_ID_PME, 925 make_first_field("ben", 0), 926 0, 927 0, 928 0, 929 &v1, NULL); 930 *num_be = v1; 931 return result; 932 } 933 934 /** 935 * ps3_repository_read_be_node_id - Read the physical BE processor node id. 936 * @be_index: Zero based index. 937 * @node_id: The BE processor node id. 938 */ 939 940 int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) 941 { 942 return read_node(PS3_LPAR_ID_PME, 943 make_first_field("be", be_index), 944 0, 945 0, 946 0, 947 node_id, NULL); 948 } 949 950 /** 951 * ps3_repository_read_be_id - Read the physical BE processor id. 952 * @node_id: The BE processor node id. 953 * @be_id: The BE processor id. 954 */ 955 956 int ps3_repository_read_be_id(u64 node_id, u64 *be_id) 957 { 958 return read_node(PS3_LPAR_ID_PME, 959 make_first_field("be", 0), 960 node_id, 961 0, 962 0, 963 be_id, NULL); 964 } 965 966 int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) 967 { 968 return read_node(PS3_LPAR_ID_PME, 969 make_first_field("be", 0), 970 node_id, 971 make_field("clock", 0), 972 0, 973 tb_freq, NULL); 974 } 975 976 int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) 977 { 978 int result; 979 u64 node_id; 980 981 *tb_freq = 0; 982 result = ps3_repository_read_be_node_id(be_index, &node_id); 983 return result ? result 984 : ps3_repository_read_tb_freq(node_id, tb_freq); 985 } 986 987 int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar, 988 u64 *rights) 989 { 990 int result; 991 u64 node_id; 992 993 *lpar = 0; 994 *rights = 0; 995 result = ps3_repository_read_be_node_id(be_index, &node_id); 996 return result ? result 997 : read_node(PS3_LPAR_ID_PME, 998 make_first_field("be", 0), 999 node_id, 1000 make_field("lpm", 0), 1001 make_field("priv", 0), 1002 lpar, rights); 1003 } 1004 1005 #if defined(DEBUG) 1006 1007 int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) 1008 { 1009 int result = 0; 1010 unsigned int res_index; 1011 1012 pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, 1013 repo->bus_index, repo->dev_index); 1014 1015 for (res_index = 0; res_index < 10; res_index++) { 1016 enum ps3_interrupt_type intr_type; 1017 unsigned int interrupt_id; 1018 1019 result = ps3_repository_read_dev_intr(repo->bus_index, 1020 repo->dev_index, res_index, &intr_type, &interrupt_id); 1021 1022 if (result) { 1023 if (result != LV1_NO_ENTRY) 1024 pr_debug("%s:%d ps3_repository_read_dev_intr" 1025 " (%u:%u) failed\n", __func__, __LINE__, 1026 repo->bus_index, repo->dev_index); 1027 break; 1028 } 1029 1030 pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", 1031 __func__, __LINE__, repo->bus_index, repo->dev_index, 1032 intr_type, interrupt_id); 1033 } 1034 1035 for (res_index = 0; res_index < 10; res_index++) { 1036 enum ps3_reg_type reg_type; 1037 u64 bus_addr; 1038 u64 len; 1039 1040 result = ps3_repository_read_dev_reg(repo->bus_index, 1041 repo->dev_index, res_index, ®_type, &bus_addr, &len); 1042 1043 if (result) { 1044 if (result != LV1_NO_ENTRY) 1045 pr_debug("%s:%d ps3_repository_read_dev_reg" 1046 " (%u:%u) failed\n", __func__, __LINE__, 1047 repo->bus_index, repo->dev_index); 1048 break; 1049 } 1050 1051 pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", 1052 __func__, __LINE__, repo->bus_index, repo->dev_index, 1053 reg_type, bus_addr, len); 1054 } 1055 1056 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1057 return result; 1058 } 1059 1060 static int dump_stor_dev_info(struct ps3_repository_device *repo) 1061 { 1062 int result = 0; 1063 unsigned int num_regions, region_index; 1064 u64 port, blk_size, num_blocks; 1065 1066 pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, 1067 repo->bus_index, repo->dev_index); 1068 1069 result = ps3_repository_read_stor_dev_info(repo->bus_index, 1070 repo->dev_index, &port, &blk_size, &num_blocks, &num_regions); 1071 if (result) { 1072 pr_debug("%s:%d ps3_repository_read_stor_dev_info" 1073 " (%u:%u) failed\n", __func__, __LINE__, 1074 repo->bus_index, repo->dev_index); 1075 goto out; 1076 } 1077 1078 pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " 1079 "%lu, num_regions %u\n", 1080 __func__, __LINE__, repo->bus_index, repo->dev_index, port, 1081 blk_size, num_blocks, num_regions); 1082 1083 for (region_index = 0; region_index < num_regions; region_index++) { 1084 unsigned int region_id; 1085 u64 region_start, region_size; 1086 1087 result = ps3_repository_read_stor_dev_region(repo->bus_index, 1088 repo->dev_index, region_index, ®ion_id, 1089 ®ion_start, ®ion_size); 1090 if (result) { 1091 pr_debug("%s:%d ps3_repository_read_stor_dev_region" 1092 " (%u:%u) failed\n", __func__, __LINE__, 1093 repo->bus_index, repo->dev_index); 1094 break; 1095 } 1096 1097 pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", 1098 __func__, __LINE__, repo->bus_index, repo->dev_index, 1099 region_id, region_start, region_size); 1100 } 1101 1102 out: 1103 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1104 return result; 1105 } 1106 1107 static int dump_device_info(struct ps3_repository_device *repo, 1108 unsigned int num_dev) 1109 { 1110 int result = 0; 1111 1112 pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); 1113 1114 for (repo->dev_index = 0; repo->dev_index < num_dev; 1115 repo->dev_index++) { 1116 1117 result = ps3_repository_read_dev_type(repo->bus_index, 1118 repo->dev_index, &repo->dev_type); 1119 1120 if (result) { 1121 pr_debug("%s:%d ps3_repository_read_dev_type" 1122 " (%u:%u) failed\n", __func__, __LINE__, 1123 repo->bus_index, repo->dev_index); 1124 break; 1125 } 1126 1127 result = ps3_repository_read_dev_id(repo->bus_index, 1128 repo->dev_index, &repo->dev_id); 1129 1130 if (result) { 1131 pr_debug("%s:%d ps3_repository_read_dev_id" 1132 " (%u:%u) failed\n", __func__, __LINE__, 1133 repo->bus_index, repo->dev_index); 1134 continue; 1135 } 1136 1137 pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__, 1138 __LINE__, repo->bus_index, repo->dev_index, 1139 repo->dev_type, repo->dev_id); 1140 1141 ps3_repository_dump_resource_info(repo); 1142 1143 if (repo->bus_type == PS3_BUS_TYPE_STORAGE) 1144 dump_stor_dev_info(repo); 1145 } 1146 1147 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1148 return result; 1149 } 1150 1151 int ps3_repository_dump_bus_info(void) 1152 { 1153 int result = 0; 1154 struct ps3_repository_device repo; 1155 1156 pr_debug(" -> %s:%d\n", __func__, __LINE__); 1157 1158 memset(&repo, 0, sizeof(repo)); 1159 1160 for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { 1161 unsigned int num_dev; 1162 1163 result = ps3_repository_read_bus_type(repo.bus_index, 1164 &repo.bus_type); 1165 1166 if (result) { 1167 pr_debug("%s:%d read_bus_type(%u) failed\n", 1168 __func__, __LINE__, repo.bus_index); 1169 break; 1170 } 1171 1172 result = ps3_repository_read_bus_id(repo.bus_index, 1173 &repo.bus_id); 1174 1175 if (result) { 1176 pr_debug("%s:%d read_bus_id(%u) failed\n", 1177 __func__, __LINE__, repo.bus_index); 1178 continue; 1179 } 1180 1181 if (repo.bus_index != repo.bus_id) 1182 pr_debug("%s:%d bus_index != bus_id\n", 1183 __func__, __LINE__); 1184 1185 result = ps3_repository_read_bus_num_dev(repo.bus_index, 1186 &num_dev); 1187 1188 if (result) { 1189 pr_debug("%s:%d read_bus_num_dev(%u) failed\n", 1190 __func__, __LINE__, repo.bus_index); 1191 continue; 1192 } 1193 1194 pr_debug("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n", 1195 __func__, __LINE__, repo.bus_index, repo.bus_type, 1196 repo.bus_id, num_dev); 1197 1198 dump_device_info(&repo, num_dev); 1199 } 1200 1201 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1202 return result; 1203 } 1204 1205 #endif /* defined(DEBUG) */ 1206