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%016lx : %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: %016lx\n", func, line, v1); 74 pr_debug("%s:%d: v2: %016lx\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: %016lx\n", 153 __func__, __LINE__, v1); 154 if (v2 && !_v2) 155 pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\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, 0); 169 } 170 171 int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id) 172 { 173 int result; 174 u64 v1; 175 u64 v2; /* unused */ 176 177 result = read_node(PS3_LPAR_ID_PME, 178 make_first_field("bus", bus_index), 179 make_field("id", 0), 180 0, 0, 181 &v1, &v2); 182 *bus_id = v1; 183 return result; 184 } 185 186 int ps3_repository_read_bus_type(unsigned int bus_index, 187 enum ps3_bus_type *bus_type) 188 { 189 int result; 190 u64 v1; 191 192 result = read_node(PS3_LPAR_ID_PME, 193 make_first_field("bus", bus_index), 194 make_field("type", 0), 195 0, 0, 196 &v1, 0); 197 *bus_type = v1; 198 return result; 199 } 200 201 int ps3_repository_read_bus_num_dev(unsigned int bus_index, 202 unsigned int *num_dev) 203 { 204 int result; 205 u64 v1; 206 207 result = read_node(PS3_LPAR_ID_PME, 208 make_first_field("bus", bus_index), 209 make_field("num_dev", 0), 210 0, 0, 211 &v1, 0); 212 *num_dev = v1; 213 return result; 214 } 215 216 int ps3_repository_read_dev_str(unsigned int bus_index, 217 unsigned int dev_index, const char *dev_str, u64 *value) 218 { 219 return read_node(PS3_LPAR_ID_PME, 220 make_first_field("bus", bus_index), 221 make_field("dev", dev_index), 222 make_field(dev_str, 0), 223 0, 224 value, 0); 225 } 226 227 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, 228 unsigned int *dev_id) 229 { 230 int result; 231 u64 v1; 232 233 result = read_node(PS3_LPAR_ID_PME, 234 make_first_field("bus", bus_index), 235 make_field("dev", dev_index), 236 make_field("id", 0), 237 0, 238 &v1, 0); 239 *dev_id = v1; 240 return result; 241 } 242 243 int ps3_repository_read_dev_type(unsigned int bus_index, 244 unsigned int dev_index, enum ps3_dev_type *dev_type) 245 { 246 int result; 247 u64 v1; 248 249 result = read_node(PS3_LPAR_ID_PME, 250 make_first_field("bus", bus_index), 251 make_field("dev", dev_index), 252 make_field("type", 0), 253 0, 254 &v1, 0); 255 *dev_type = v1; 256 return result; 257 } 258 259 int ps3_repository_read_dev_intr(unsigned int bus_index, 260 unsigned int dev_index, unsigned int intr_index, 261 enum ps3_interrupt_type *intr_type, unsigned int* interrupt_id) 262 { 263 int result; 264 u64 v1; 265 u64 v2; 266 267 result = read_node(PS3_LPAR_ID_PME, 268 make_first_field("bus", bus_index), 269 make_field("dev", dev_index), 270 make_field("intr", intr_index), 271 0, 272 &v1, &v2); 273 *intr_type = v1; 274 *interrupt_id = v2; 275 return result; 276 } 277 278 int ps3_repository_read_dev_reg_type(unsigned int bus_index, 279 unsigned int dev_index, unsigned int reg_index, 280 enum ps3_reg_type *reg_type) 281 { 282 int result; 283 u64 v1; 284 285 result = read_node(PS3_LPAR_ID_PME, 286 make_first_field("bus", bus_index), 287 make_field("dev", dev_index), 288 make_field("reg", reg_index), 289 make_field("type", 0), 290 &v1, 0); 291 *reg_type = v1; 292 return result; 293 } 294 295 int ps3_repository_read_dev_reg_addr(unsigned int bus_index, 296 unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len) 297 { 298 return read_node(PS3_LPAR_ID_PME, 299 make_first_field("bus", bus_index), 300 make_field("dev", dev_index), 301 make_field("reg", reg_index), 302 make_field("data", 0), 303 bus_addr, len); 304 } 305 306 int ps3_repository_read_dev_reg(unsigned int bus_index, 307 unsigned int dev_index, unsigned int reg_index, 308 enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len) 309 { 310 int result = ps3_repository_read_dev_reg_type(bus_index, dev_index, 311 reg_index, reg_type); 312 return result ? result 313 : ps3_repository_read_dev_reg_addr(bus_index, dev_index, 314 reg_index, bus_addr, len); 315 } 316 317 318 319 int ps3_repository_find_device(struct ps3_repository_device *repo) 320 { 321 int result; 322 struct ps3_repository_device tmp = *repo; 323 unsigned int num_dev; 324 325 BUG_ON(repo->bus_index > 10); 326 BUG_ON(repo->dev_index > 10); 327 328 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); 329 330 if (result) { 331 pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); 332 return result; 333 } 334 335 pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n", 336 __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, 337 num_dev); 338 339 if (tmp.dev_index >= num_dev) { 340 pr_debug("%s:%d: no device found\n", __func__, __LINE__); 341 return -ENODEV; 342 } 343 344 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, 345 &tmp.dev_type); 346 347 if (result) { 348 pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__); 349 return result; 350 } 351 352 if (tmp.bus_type == PS3_BUS_TYPE_STORAGE) { 353 /* 354 * A storage device may show up in the repository before the 355 * hypervisor has finished probing its type and regions 356 */ 357 unsigned int num_regions; 358 359 if (tmp.dev_type == PS3_DEV_TYPE_STOR_DUMMY) { 360 pr_debug("%s:%u storage device not ready\n", __func__, 361 __LINE__); 362 return -ENODEV; 363 } 364 365 result = ps3_repository_read_stor_dev_num_regions(tmp.bus_index, 366 tmp.dev_index, 367 &num_regions); 368 if (result) { 369 pr_debug("%s:%d read_stor_dev_num_regions failed\n", 370 __func__, __LINE__); 371 return result; 372 } 373 374 if (!num_regions) { 375 pr_debug("%s:%u storage device has no regions yet\n", 376 __func__, __LINE__); 377 return -ENODEV; 378 } 379 } 380 381 result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, 382 &tmp.dev_id); 383 384 if (result) { 385 pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, 386 __LINE__); 387 return result; 388 } 389 390 pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n", 391 __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); 392 393 *repo = tmp; 394 return 0; 395 } 396 397 int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, 398 int (*callback)(const struct ps3_repository_device *repo)) 399 { 400 int result = 0; 401 struct ps3_repository_device repo; 402 403 pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); 404 405 for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { 406 407 result = ps3_repository_read_bus_type(repo.bus_index, 408 &repo.bus_type); 409 410 if (result) { 411 pr_debug("%s:%d read_bus_type(%u) failed\n", 412 __func__, __LINE__, repo.bus_index); 413 break; 414 } 415 416 if (repo.bus_type != bus_type) { 417 pr_debug("%s:%d: skip, bus_type %u\n", __func__, 418 __LINE__, repo.bus_type); 419 continue; 420 } 421 422 result = ps3_repository_read_bus_id(repo.bus_index, 423 &repo.bus_id); 424 425 if (result) { 426 pr_debug("%s:%d read_bus_id(%u) failed\n", 427 __func__, __LINE__, repo.bus_index); 428 continue; 429 } 430 431 for (repo.dev_index = 0; ; repo.dev_index++) { 432 result = ps3_repository_find_device(&repo); 433 434 if (result == -ENODEV) { 435 result = 0; 436 break; 437 } else if (result) 438 break; 439 440 result = callback(&repo); 441 442 if (result) { 443 pr_debug("%s:%d: abort at callback\n", __func__, 444 __LINE__); 445 break; 446 } 447 } 448 break; 449 } 450 451 pr_debug(" <- %s:%d\n", __func__, __LINE__); 452 return result; 453 } 454 455 int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, 456 unsigned int *bus_index) 457 { 458 unsigned int i; 459 enum ps3_bus_type type; 460 int error; 461 462 for (i = from; i < 10; i++) { 463 error = ps3_repository_read_bus_type(i, &type); 464 if (error) { 465 pr_debug("%s:%d read_bus_type failed\n", 466 __func__, __LINE__); 467 *bus_index = UINT_MAX; 468 return error; 469 } 470 if (type == bus_type) { 471 *bus_index = i; 472 return 0; 473 } 474 } 475 *bus_index = UINT_MAX; 476 return -ENODEV; 477 } 478 479 int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, 480 enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) 481 { 482 int result = 0; 483 unsigned int res_index; 484 485 pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type); 486 487 *interrupt_id = UINT_MAX; 488 489 for (res_index = 0; res_index < 10; res_index++) { 490 enum ps3_interrupt_type t; 491 unsigned int id; 492 493 result = ps3_repository_read_dev_intr(repo->bus_index, 494 repo->dev_index, res_index, &t, &id); 495 496 if (result) { 497 pr_debug("%s:%d read_dev_intr failed\n", 498 __func__, __LINE__); 499 return result; 500 } 501 502 if (t == intr_type) { 503 *interrupt_id = id; 504 break; 505 } 506 } 507 508 if (res_index == 10) 509 return -ENODEV; 510 511 pr_debug("%s:%d: found intr_type %u at res_index %u\n", 512 __func__, __LINE__, intr_type, res_index); 513 514 return result; 515 } 516 517 int ps3_repository_find_reg(const struct ps3_repository_device *repo, 518 enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) 519 { 520 int result = 0; 521 unsigned int res_index; 522 523 pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type); 524 525 *bus_addr = *len = 0; 526 527 for (res_index = 0; res_index < 10; res_index++) { 528 enum ps3_reg_type t; 529 u64 a; 530 u64 l; 531 532 result = ps3_repository_read_dev_reg(repo->bus_index, 533 repo->dev_index, res_index, &t, &a, &l); 534 535 if (result) { 536 pr_debug("%s:%d read_dev_reg failed\n", 537 __func__, __LINE__); 538 return result; 539 } 540 541 if (t == reg_type) { 542 *bus_addr = a; 543 *len = l; 544 break; 545 } 546 } 547 548 if (res_index == 10) 549 return -ENODEV; 550 551 pr_debug("%s:%d: found reg_type %u at res_index %u\n", 552 __func__, __LINE__, reg_type, res_index); 553 554 return result; 555 } 556 557 int ps3_repository_read_stor_dev_port(unsigned int bus_index, 558 unsigned int dev_index, u64 *port) 559 { 560 return read_node(PS3_LPAR_ID_PME, 561 make_first_field("bus", bus_index), 562 make_field("dev", dev_index), 563 make_field("port", 0), 564 0, port, 0); 565 } 566 567 int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index, 568 unsigned int dev_index, u64 *blk_size) 569 { 570 return read_node(PS3_LPAR_ID_PME, 571 make_first_field("bus", bus_index), 572 make_field("dev", dev_index), 573 make_field("blk_size", 0), 574 0, blk_size, 0); 575 } 576 577 int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index, 578 unsigned int dev_index, u64 *num_blocks) 579 { 580 return read_node(PS3_LPAR_ID_PME, 581 make_first_field("bus", bus_index), 582 make_field("dev", dev_index), 583 make_field("n_blocks", 0), 584 0, num_blocks, 0); 585 } 586 587 int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, 588 unsigned int dev_index, unsigned int *num_regions) 589 { 590 int result; 591 u64 v1; 592 593 result = read_node(PS3_LPAR_ID_PME, 594 make_first_field("bus", bus_index), 595 make_field("dev", dev_index), 596 make_field("n_regs", 0), 597 0, &v1, 0); 598 *num_regions = v1; 599 return result; 600 } 601 602 int ps3_repository_read_stor_dev_region_id(unsigned int bus_index, 603 unsigned int dev_index, unsigned int region_index, 604 unsigned int *region_id) 605 { 606 int result; 607 u64 v1; 608 609 result = read_node(PS3_LPAR_ID_PME, 610 make_first_field("bus", bus_index), 611 make_field("dev", dev_index), 612 make_field("region", region_index), 613 make_field("id", 0), 614 &v1, 0); 615 *region_id = v1; 616 return result; 617 } 618 619 int ps3_repository_read_stor_dev_region_size(unsigned int bus_index, 620 unsigned int dev_index, unsigned int region_index, u64 *region_size) 621 { 622 return read_node(PS3_LPAR_ID_PME, 623 make_first_field("bus", bus_index), 624 make_field("dev", dev_index), 625 make_field("region", region_index), 626 make_field("size", 0), 627 region_size, 0); 628 } 629 630 int ps3_repository_read_stor_dev_region_start(unsigned int bus_index, 631 unsigned int dev_index, unsigned int region_index, u64 *region_start) 632 { 633 return read_node(PS3_LPAR_ID_PME, 634 make_first_field("bus", bus_index), 635 make_field("dev", dev_index), 636 make_field("region", region_index), 637 make_field("start", 0), 638 region_start, 0); 639 } 640 641 int ps3_repository_read_stor_dev_info(unsigned int bus_index, 642 unsigned int dev_index, u64 *port, u64 *blk_size, 643 u64 *num_blocks, unsigned int *num_regions) 644 { 645 int result; 646 647 result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port); 648 if (result) 649 return result; 650 651 result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index, 652 blk_size); 653 if (result) 654 return result; 655 656 result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index, 657 num_blocks); 658 if (result) 659 return result; 660 661 result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index, 662 num_regions); 663 return result; 664 } 665 666 int ps3_repository_read_stor_dev_region(unsigned int bus_index, 667 unsigned int dev_index, unsigned int region_index, 668 unsigned int *region_id, u64 *region_start, u64 *region_size) 669 { 670 int result; 671 672 result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index, 673 region_index, region_id); 674 if (result) 675 return result; 676 677 result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index, 678 region_index, region_start); 679 if (result) 680 return result; 681 682 result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index, 683 region_index, region_size); 684 return result; 685 } 686 687 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) 688 { 689 return read_node(PS3_LPAR_ID_CURRENT, 690 make_first_field("bi", 0), 691 make_field("pu", 0), 692 ppe_id, 693 make_field("rm_size", 0), 694 rm_size, 0); 695 } 696 697 int ps3_repository_read_region_total(u64 *region_total) 698 { 699 return read_node(PS3_LPAR_ID_CURRENT, 700 make_first_field("bi", 0), 701 make_field("rgntotal", 0), 702 0, 0, 703 region_total, 0); 704 } 705 706 /** 707 * ps3_repository_read_mm_info - Read mm info for single pu system. 708 * @rm_base: Real mode memory base address. 709 * @rm_size: Real mode memory size. 710 * @region_total: Maximum memory region size. 711 */ 712 713 int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) 714 { 715 int result; 716 u64 ppe_id; 717 718 lv1_get_logical_ppe_id(&ppe_id); 719 *rm_base = 0; 720 result = ps3_repository_read_rm_size(ppe_id, rm_size); 721 return result ? result 722 : ps3_repository_read_region_total(region_total); 723 } 724 725 /** 726 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved. 727 * @num_spu: Number of physical spus. 728 */ 729 730 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) 731 { 732 int result; 733 u64 v1; 734 735 result = read_node(PS3_LPAR_ID_CURRENT, 736 make_first_field("bi", 0), 737 make_field("spun", 0), 738 0, 0, 739 &v1, 0); 740 *num_spu_reserved = v1; 741 return result; 742 } 743 744 /** 745 * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations. 746 * @num_resource_id: Number of spu resource ids. 747 */ 748 749 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) 750 { 751 int result; 752 u64 v1; 753 754 result = read_node(PS3_LPAR_ID_CURRENT, 755 make_first_field("bi", 0), 756 make_field("spursvn", 0), 757 0, 0, 758 &v1, 0); 759 *num_resource_id = v1; 760 return result; 761 } 762 763 /** 764 * ps3_repository_read_spu_resource_id - spu resource reservation id value. 765 * @res_index: Resource reservation index. 766 * @resource_type: Resource reservation type. 767 * @resource_id: Resource reservation id. 768 */ 769 770 int ps3_repository_read_spu_resource_id(unsigned int res_index, 771 enum ps3_spu_resource_type* resource_type, unsigned int *resource_id) 772 { 773 int result; 774 u64 v1; 775 u64 v2; 776 777 result = read_node(PS3_LPAR_ID_CURRENT, 778 make_first_field("bi", 0), 779 make_field("spursv", 0), 780 res_index, 781 0, 782 &v1, &v2); 783 *resource_type = v1; 784 *resource_id = v2; 785 return result; 786 } 787 788 int ps3_repository_read_boot_dat_address(u64 *address) 789 { 790 return read_node(PS3_LPAR_ID_CURRENT, 791 make_first_field("bi", 0), 792 make_field("boot_dat", 0), 793 make_field("address", 0), 794 0, 795 address, 0); 796 } 797 798 int ps3_repository_read_boot_dat_size(unsigned int *size) 799 { 800 int result; 801 u64 v1; 802 803 result = read_node(PS3_LPAR_ID_CURRENT, 804 make_first_field("bi", 0), 805 make_field("boot_dat", 0), 806 make_field("size", 0), 807 0, 808 &v1, 0); 809 *size = v1; 810 return result; 811 } 812 813 int ps3_repository_read_vuart_av_port(unsigned int *port) 814 { 815 int result; 816 u64 v1; 817 818 result = read_node(PS3_LPAR_ID_CURRENT, 819 make_first_field("bi", 0), 820 make_field("vir_uart", 0), 821 make_field("port", 0), 822 make_field("avset", 0), 823 &v1, 0); 824 *port = v1; 825 return result; 826 } 827 828 int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) 829 { 830 int result; 831 u64 v1; 832 833 result = read_node(PS3_LPAR_ID_CURRENT, 834 make_first_field("bi", 0), 835 make_field("vir_uart", 0), 836 make_field("port", 0), 837 make_field("sysmgr", 0), 838 &v1, 0); 839 *port = v1; 840 return result; 841 } 842 843 /** 844 * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. 845 * address: lpar address of cell_ext_os_area 846 * @size: size of cell_ext_os_area 847 */ 848 849 int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) 850 { 851 int result; 852 853 *size = 0; 854 result = ps3_repository_read_boot_dat_address(lpar_addr); 855 return result ? result 856 : ps3_repository_read_boot_dat_size(size); 857 } 858 859 int ps3_repository_read_num_be(unsigned int *num_be) 860 { 861 int result; 862 u64 v1; 863 864 result = read_node(PS3_LPAR_ID_PME, 865 make_first_field("ben", 0), 866 0, 867 0, 868 0, 869 &v1, 0); 870 *num_be = v1; 871 return result; 872 } 873 874 int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) 875 { 876 return read_node(PS3_LPAR_ID_PME, 877 make_first_field("be", be_index), 878 0, 879 0, 880 0, 881 node_id, 0); 882 } 883 884 int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) 885 { 886 return read_node(PS3_LPAR_ID_PME, 887 make_first_field("be", 0), 888 node_id, 889 make_field("clock", 0), 890 0, 891 tb_freq, 0); 892 } 893 894 int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) 895 { 896 int result; 897 u64 node_id; 898 899 *tb_freq = 0; 900 result = ps3_repository_read_be_node_id(0, &node_id); 901 return result ? result 902 : ps3_repository_read_tb_freq(node_id, tb_freq); 903 } 904 905 #if defined(DEBUG) 906 907 int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) 908 { 909 int result = 0; 910 unsigned int res_index; 911 912 pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, 913 repo->bus_index, repo->dev_index); 914 915 for (res_index = 0; res_index < 10; res_index++) { 916 enum ps3_interrupt_type intr_type; 917 unsigned int interrupt_id; 918 919 result = ps3_repository_read_dev_intr(repo->bus_index, 920 repo->dev_index, res_index, &intr_type, &interrupt_id); 921 922 if (result) { 923 if (result != LV1_NO_ENTRY) 924 pr_debug("%s:%d ps3_repository_read_dev_intr" 925 " (%u:%u) failed\n", __func__, __LINE__, 926 repo->bus_index, repo->dev_index); 927 break; 928 } 929 930 pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", 931 __func__, __LINE__, repo->bus_index, repo->dev_index, 932 intr_type, interrupt_id); 933 } 934 935 for (res_index = 0; res_index < 10; res_index++) { 936 enum ps3_reg_type reg_type; 937 u64 bus_addr; 938 u64 len; 939 940 result = ps3_repository_read_dev_reg(repo->bus_index, 941 repo->dev_index, res_index, ®_type, &bus_addr, &len); 942 943 if (result) { 944 if (result != LV1_NO_ENTRY) 945 pr_debug("%s:%d ps3_repository_read_dev_reg" 946 " (%u:%u) failed\n", __func__, __LINE__, 947 repo->bus_index, repo->dev_index); 948 break; 949 } 950 951 pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", 952 __func__, __LINE__, repo->bus_index, repo->dev_index, 953 reg_type, bus_addr, len); 954 } 955 956 pr_debug(" <- %s:%d\n", __func__, __LINE__); 957 return result; 958 } 959 960 static int dump_stor_dev_info(struct ps3_repository_device *repo) 961 { 962 int result = 0; 963 unsigned int num_regions, region_index; 964 u64 port, blk_size, num_blocks; 965 966 pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, 967 repo->bus_index, repo->dev_index); 968 969 result = ps3_repository_read_stor_dev_info(repo->bus_index, 970 repo->dev_index, &port, &blk_size, &num_blocks, &num_regions); 971 if (result) { 972 pr_debug("%s:%d ps3_repository_read_stor_dev_info" 973 " (%u:%u) failed\n", __func__, __LINE__, 974 repo->bus_index, repo->dev_index); 975 goto out; 976 } 977 978 pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " 979 "%lu, num_regions %u\n", 980 __func__, __LINE__, repo->bus_index, repo->dev_index, port, 981 blk_size, num_blocks, num_regions); 982 983 for (region_index = 0; region_index < num_regions; region_index++) { 984 unsigned int region_id; 985 u64 region_start, region_size; 986 987 result = ps3_repository_read_stor_dev_region(repo->bus_index, 988 repo->dev_index, region_index, ®ion_id, 989 ®ion_start, ®ion_size); 990 if (result) { 991 pr_debug("%s:%d ps3_repository_read_stor_dev_region" 992 " (%u:%u) failed\n", __func__, __LINE__, 993 repo->bus_index, repo->dev_index); 994 break; 995 } 996 997 pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", 998 __func__, __LINE__, repo->bus_index, repo->dev_index, 999 region_id, region_start, region_size); 1000 } 1001 1002 out: 1003 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1004 return result; 1005 } 1006 1007 static int dump_device_info(struct ps3_repository_device *repo, 1008 unsigned int num_dev) 1009 { 1010 int result = 0; 1011 1012 pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); 1013 1014 for (repo->dev_index = 0; repo->dev_index < num_dev; 1015 repo->dev_index++) { 1016 1017 result = ps3_repository_read_dev_type(repo->bus_index, 1018 repo->dev_index, &repo->dev_type); 1019 1020 if (result) { 1021 pr_debug("%s:%d ps3_repository_read_dev_type" 1022 " (%u:%u) failed\n", __func__, __LINE__, 1023 repo->bus_index, repo->dev_index); 1024 break; 1025 } 1026 1027 result = ps3_repository_read_dev_id(repo->bus_index, 1028 repo->dev_index, &repo->dev_id); 1029 1030 if (result) { 1031 pr_debug("%s:%d ps3_repository_read_dev_id" 1032 " (%u:%u) failed\n", __func__, __LINE__, 1033 repo->bus_index, repo->dev_index); 1034 continue; 1035 } 1036 1037 pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, 1038 __LINE__, repo->bus_index, repo->dev_index, 1039 repo->dev_type, repo->dev_id); 1040 1041 ps3_repository_dump_resource_info(repo); 1042 1043 if (repo->bus_type == PS3_BUS_TYPE_STORAGE) 1044 dump_stor_dev_info(repo); 1045 } 1046 1047 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1048 return result; 1049 } 1050 1051 int ps3_repository_dump_bus_info(void) 1052 { 1053 int result = 0; 1054 struct ps3_repository_device repo; 1055 1056 pr_debug(" -> %s:%d\n", __func__, __LINE__); 1057 1058 memset(&repo, 0, sizeof(repo)); 1059 1060 for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { 1061 unsigned int num_dev; 1062 1063 result = ps3_repository_read_bus_type(repo.bus_index, 1064 &repo.bus_type); 1065 1066 if (result) { 1067 pr_debug("%s:%d read_bus_type(%u) failed\n", 1068 __func__, __LINE__, repo.bus_index); 1069 break; 1070 } 1071 1072 result = ps3_repository_read_bus_id(repo.bus_index, 1073 &repo.bus_id); 1074 1075 if (result) { 1076 pr_debug("%s:%d read_bus_id(%u) failed\n", 1077 __func__, __LINE__, repo.bus_index); 1078 continue; 1079 } 1080 1081 if (repo.bus_index != repo.bus_id) 1082 pr_debug("%s:%d bus_index != bus_id\n", 1083 __func__, __LINE__); 1084 1085 result = ps3_repository_read_bus_num_dev(repo.bus_index, 1086 &num_dev); 1087 1088 if (result) { 1089 pr_debug("%s:%d read_bus_num_dev(%u) failed\n", 1090 __func__, __LINE__, repo.bus_index); 1091 continue; 1092 } 1093 1094 pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", 1095 __func__, __LINE__, repo.bus_index, repo.bus_type, 1096 repo.bus_id, num_dev); 1097 1098 dump_device_info(&repo, num_dev); 1099 } 1100 1101 pr_debug(" <- %s:%d\n", __func__, __LINE__); 1102 return result; 1103 } 1104 1105 #endif /* defined(DEBUG) */ 1106