0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <asm/lv1call.h>
0010
0011 #include "platform.h"
0012
0013 enum ps3_vendor_id {
0014 PS3_VENDOR_ID_NONE = 0,
0015 PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
0016 };
0017
0018 enum ps3_lpar_id {
0019 PS3_LPAR_ID_CURRENT = 0,
0020 PS3_LPAR_ID_PME = 1,
0021 };
0022
0023 #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
0024 static void _dump_field(const char *hdr, u64 n, const char *func, int line)
0025 {
0026 #if defined(DEBUG)
0027 char s[16];
0028 const char *const in = (const char *)&n;
0029 unsigned int i;
0030
0031 for (i = 0; i < 8; i++)
0032 s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
0033 s[i] = 0;
0034
0035 pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);
0036 #endif
0037 }
0038
0039 #define dump_node_name(_a, _b, _c, _d, _e) \
0040 _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
0041 static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
0042 u64 n4, const char *func, int line)
0043 {
0044 pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
0045 _dump_field("n1: ", n1, func, line);
0046 _dump_field("n2: ", n2, func, line);
0047 _dump_field("n3: ", n3, func, line);
0048 _dump_field("n4: ", n4, func, line);
0049 }
0050
0051 #define dump_node(_a, _b, _c, _d, _e, _f, _g) \
0052 _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
0053 static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
0054 u64 v1, u64 v2, const char *func, int line)
0055 {
0056 pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
0057 _dump_field("n1: ", n1, func, line);
0058 _dump_field("n2: ", n2, func, line);
0059 _dump_field("n3: ", n3, func, line);
0060 _dump_field("n4: ", n4, func, line);
0061 pr_devel("%s:%d: v1: %016llx\n", func, line, v1);
0062 pr_devel("%s:%d: v2: %016llx\n", func, line, v2);
0063 }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 static u64 make_first_field(const char *text, u64 index)
0075 {
0076 u64 n;
0077
0078 strncpy((char *)&n, text, 8);
0079 return PS3_VENDOR_ID_NONE + (n >> 32) + index;
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 static u64 make_field(const char *text, u64 index)
0091 {
0092 u64 n = 0;
0093
0094 memcpy((char *)&n, text, strnlen(text, sizeof(n)));
0095 return n + index;
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
0110 u64 *_v1, u64 *_v2)
0111 {
0112 int result;
0113 u64 v1;
0114 u64 v2;
0115
0116 if (lpar_id == PS3_LPAR_ID_CURRENT) {
0117 u64 id;
0118 lv1_get_logical_partition_id(&id);
0119 lpar_id = id;
0120 }
0121
0122 result = lv1_read_repository_node(lpar_id, n1, n2, n3, n4, &v1,
0123 &v2);
0124
0125 if (result) {
0126 pr_warn("%s:%d: lv1_read_repository_node failed: %s\n",
0127 __func__, __LINE__, ps3_result(result));
0128 dump_node_name(lpar_id, n1, n2, n3, n4);
0129 return -ENOENT;
0130 }
0131
0132 dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
0133
0134 if (_v1)
0135 *_v1 = v1;
0136 if (_v2)
0137 *_v2 = v2;
0138
0139 if (v1 && !_v1)
0140 pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n",
0141 __func__, __LINE__, v1);
0142 if (v2 && !_v2)
0143 pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n",
0144 __func__, __LINE__, v2);
0145
0146 return 0;
0147 }
0148
0149 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
0150 u64 *value)
0151 {
0152 return read_node(PS3_LPAR_ID_PME,
0153 make_first_field("bus", bus_index),
0154 make_field(bus_str, 0),
0155 0, 0,
0156 value, NULL);
0157 }
0158
0159 int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id)
0160 {
0161 return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
0162 make_field("id", 0), 0, 0, bus_id, NULL);
0163 }
0164
0165 int ps3_repository_read_bus_type(unsigned int bus_index,
0166 enum ps3_bus_type *bus_type)
0167 {
0168 int result;
0169 u64 v1 = 0;
0170
0171 result = read_node(PS3_LPAR_ID_PME,
0172 make_first_field("bus", bus_index),
0173 make_field("type", 0),
0174 0, 0,
0175 &v1, NULL);
0176 *bus_type = v1;
0177 return result;
0178 }
0179
0180 int ps3_repository_read_bus_num_dev(unsigned int bus_index,
0181 unsigned int *num_dev)
0182 {
0183 int result;
0184 u64 v1 = 0;
0185
0186 result = read_node(PS3_LPAR_ID_PME,
0187 make_first_field("bus", bus_index),
0188 make_field("num_dev", 0),
0189 0, 0,
0190 &v1, NULL);
0191 *num_dev = v1;
0192 return result;
0193 }
0194
0195 int ps3_repository_read_dev_str(unsigned int bus_index,
0196 unsigned int dev_index, const char *dev_str, u64 *value)
0197 {
0198 return read_node(PS3_LPAR_ID_PME,
0199 make_first_field("bus", bus_index),
0200 make_field("dev", dev_index),
0201 make_field(dev_str, 0),
0202 0,
0203 value, NULL);
0204 }
0205
0206 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
0207 u64 *dev_id)
0208 {
0209 return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
0210 make_field("dev", dev_index), make_field("id", 0), 0,
0211 dev_id, NULL);
0212 }
0213
0214 int ps3_repository_read_dev_type(unsigned int bus_index,
0215 unsigned int dev_index, enum ps3_dev_type *dev_type)
0216 {
0217 int result;
0218 u64 v1 = 0;
0219
0220 result = read_node(PS3_LPAR_ID_PME,
0221 make_first_field("bus", bus_index),
0222 make_field("dev", dev_index),
0223 make_field("type", 0),
0224 0,
0225 &v1, NULL);
0226 *dev_type = v1;
0227 return result;
0228 }
0229
0230 int ps3_repository_read_dev_intr(unsigned int bus_index,
0231 unsigned int dev_index, unsigned int intr_index,
0232 enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
0233 {
0234 int result;
0235 u64 v1 = 0;
0236 u64 v2 = 0;
0237
0238 result = read_node(PS3_LPAR_ID_PME,
0239 make_first_field("bus", bus_index),
0240 make_field("dev", dev_index),
0241 make_field("intr", intr_index),
0242 0,
0243 &v1, &v2);
0244 *intr_type = v1;
0245 *interrupt_id = v2;
0246 return result;
0247 }
0248
0249 int ps3_repository_read_dev_reg_type(unsigned int bus_index,
0250 unsigned int dev_index, unsigned int reg_index,
0251 enum ps3_reg_type *reg_type)
0252 {
0253 int result;
0254 u64 v1 = 0;
0255
0256 result = read_node(PS3_LPAR_ID_PME,
0257 make_first_field("bus", bus_index),
0258 make_field("dev", dev_index),
0259 make_field("reg", reg_index),
0260 make_field("type", 0),
0261 &v1, NULL);
0262 *reg_type = v1;
0263 return result;
0264 }
0265
0266 int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
0267 unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)
0268 {
0269 return read_node(PS3_LPAR_ID_PME,
0270 make_first_field("bus", bus_index),
0271 make_field("dev", dev_index),
0272 make_field("reg", reg_index),
0273 make_field("data", 0),
0274 bus_addr, len);
0275 }
0276
0277 int ps3_repository_read_dev_reg(unsigned int bus_index,
0278 unsigned int dev_index, unsigned int reg_index,
0279 enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len)
0280 {
0281 int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
0282 reg_index, reg_type);
0283 return result ? result
0284 : ps3_repository_read_dev_reg_addr(bus_index, dev_index,
0285 reg_index, bus_addr, len);
0286 }
0287
0288
0289
0290 int ps3_repository_find_device(struct ps3_repository_device *repo)
0291 {
0292 int result;
0293 struct ps3_repository_device tmp = *repo;
0294 unsigned int num_dev;
0295
0296 BUG_ON(repo->bus_index > 10);
0297 BUG_ON(repo->dev_index > 10);
0298
0299 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
0300
0301 if (result) {
0302 pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
0303 return result;
0304 }
0305
0306 pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",
0307 __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
0308 num_dev);
0309
0310 if (tmp.dev_index >= num_dev) {
0311 pr_devel("%s:%d: no device found\n", __func__, __LINE__);
0312 return -ENODEV;
0313 }
0314
0315 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
0316 &tmp.dev_type);
0317
0318 if (result) {
0319 pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__);
0320 return result;
0321 }
0322
0323 result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
0324 &tmp.dev_id);
0325
0326 if (result) {
0327 pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__,
0328 __LINE__);
0329 return result;
0330 }
0331
0332 pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",
0333 __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
0334
0335 *repo = tmp;
0336 return 0;
0337 }
0338
0339 int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
0340 u64 bus_id, u64 dev_id)
0341 {
0342 int result = -ENODEV;
0343 struct ps3_repository_device tmp;
0344 unsigned int num_dev;
0345
0346 pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,
0347 bus_id, dev_id);
0348
0349 for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
0350 result = ps3_repository_read_bus_id(tmp.bus_index,
0351 &tmp.bus_id);
0352 if (result) {
0353 pr_devel("%s:%u read_bus_id(%u) failed\n", __func__,
0354 __LINE__, tmp.bus_index);
0355 return result;
0356 }
0357
0358 if (tmp.bus_id == bus_id)
0359 goto found_bus;
0360
0361 pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,
0362 tmp.bus_id);
0363 }
0364 pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
0365 return result;
0366
0367 found_bus:
0368 result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);
0369 if (result) {
0370 pr_devel("%s:%u read_bus_type(%u) failed\n", __func__,
0371 __LINE__, tmp.bus_index);
0372 return result;
0373 }
0374
0375 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
0376 if (result) {
0377 pr_devel("%s:%u read_bus_num_dev failed\n", __func__,
0378 __LINE__);
0379 return result;
0380 }
0381
0382 for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) {
0383 result = ps3_repository_read_dev_id(tmp.bus_index,
0384 tmp.dev_index,
0385 &tmp.dev_id);
0386 if (result) {
0387 pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__,
0388 __LINE__, tmp.bus_index, tmp.dev_index);
0389 return result;
0390 }
0391
0392 if (tmp.dev_id == dev_id)
0393 goto found_dev;
0394
0395 pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,
0396 tmp.dev_id);
0397 }
0398 pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__);
0399 return result;
0400
0401 found_dev:
0402 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
0403 &tmp.dev_type);
0404 if (result) {
0405 pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__);
0406 return result;
0407 }
0408
0409 pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",
0410 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
0411 tmp.dev_index, tmp.bus_id, tmp.dev_id);
0412 *repo = tmp;
0413 return 0;
0414 }
0415
0416 int __init ps3_repository_find_devices(enum ps3_bus_type bus_type,
0417 int (*callback)(const struct ps3_repository_device *repo))
0418 {
0419 int result = 0;
0420 struct ps3_repository_device repo;
0421
0422 pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
0423
0424 repo.bus_type = bus_type;
0425 result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
0426 if (result) {
0427 pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
0428 return result;
0429 }
0430
0431 result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
0432 if (result) {
0433 pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
0434 repo.bus_index);
0435 return result;
0436 }
0437
0438 for (repo.dev_index = 0; ; repo.dev_index++) {
0439 result = ps3_repository_find_device(&repo);
0440 if (result == -ENODEV) {
0441 result = 0;
0442 break;
0443 } else if (result)
0444 break;
0445
0446 result = callback(&repo);
0447 if (result) {
0448 pr_devel("%s:%d: abort at callback\n", __func__,
0449 __LINE__);
0450 break;
0451 }
0452 }
0453
0454 pr_devel(" <- %s:%d\n", __func__, __LINE__);
0455 return result;
0456 }
0457
0458 int __init ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
0459 unsigned int *bus_index)
0460 {
0461 unsigned int i;
0462 enum ps3_bus_type type;
0463 int error;
0464
0465 for (i = from; i < 10; i++) {
0466 error = ps3_repository_read_bus_type(i, &type);
0467 if (error) {
0468 pr_devel("%s:%d read_bus_type failed\n",
0469 __func__, __LINE__);
0470 *bus_index = UINT_MAX;
0471 return error;
0472 }
0473 if (type == bus_type) {
0474 *bus_index = i;
0475 return 0;
0476 }
0477 }
0478 *bus_index = UINT_MAX;
0479 return -ENODEV;
0480 }
0481
0482 int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
0483 enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
0484 {
0485 int result = 0;
0486 unsigned int res_index;
0487
0488 pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
0489
0490 *interrupt_id = UINT_MAX;
0491
0492 for (res_index = 0; res_index < 10; res_index++) {
0493 enum ps3_interrupt_type t;
0494 unsigned int id;
0495
0496 result = ps3_repository_read_dev_intr(repo->bus_index,
0497 repo->dev_index, res_index, &t, &id);
0498
0499 if (result) {
0500 pr_devel("%s:%d read_dev_intr failed\n",
0501 __func__, __LINE__);
0502 return result;
0503 }
0504
0505 if (t == intr_type) {
0506 *interrupt_id = id;
0507 break;
0508 }
0509 }
0510
0511 if (res_index == 10)
0512 return -ENODEV;
0513
0514 pr_devel("%s:%d: found intr_type %u at res_index %u\n",
0515 __func__, __LINE__, intr_type, res_index);
0516
0517 return result;
0518 }
0519
0520 int ps3_repository_find_reg(const struct ps3_repository_device *repo,
0521 enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
0522 {
0523 int result = 0;
0524 unsigned int res_index;
0525
0526 pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
0527
0528 *bus_addr = *len = 0;
0529
0530 for (res_index = 0; res_index < 10; res_index++) {
0531 enum ps3_reg_type t;
0532 u64 a;
0533 u64 l;
0534
0535 result = ps3_repository_read_dev_reg(repo->bus_index,
0536 repo->dev_index, res_index, &t, &a, &l);
0537
0538 if (result) {
0539 pr_devel("%s:%d read_dev_reg failed\n",
0540 __func__, __LINE__);
0541 return result;
0542 }
0543
0544 if (t == reg_type) {
0545 *bus_addr = a;
0546 *len = l;
0547 break;
0548 }
0549 }
0550
0551 if (res_index == 10)
0552 return -ENODEV;
0553
0554 pr_devel("%s:%d: found reg_type %u at res_index %u\n",
0555 __func__, __LINE__, reg_type, res_index);
0556
0557 return result;
0558 }
0559
0560 int ps3_repository_read_stor_dev_port(unsigned int bus_index,
0561 unsigned int dev_index, u64 *port)
0562 {
0563 return read_node(PS3_LPAR_ID_PME,
0564 make_first_field("bus", bus_index),
0565 make_field("dev", dev_index),
0566 make_field("port", 0),
0567 0, port, NULL);
0568 }
0569
0570 int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
0571 unsigned int dev_index, u64 *blk_size)
0572 {
0573 return read_node(PS3_LPAR_ID_PME,
0574 make_first_field("bus", bus_index),
0575 make_field("dev", dev_index),
0576 make_field("blk_size", 0),
0577 0, blk_size, NULL);
0578 }
0579
0580 int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
0581 unsigned int dev_index, u64 *num_blocks)
0582 {
0583 return read_node(PS3_LPAR_ID_PME,
0584 make_first_field("bus", bus_index),
0585 make_field("dev", dev_index),
0586 make_field("n_blocks", 0),
0587 0, num_blocks, NULL);
0588 }
0589
0590 int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
0591 unsigned int dev_index, unsigned int *num_regions)
0592 {
0593 int result;
0594 u64 v1 = 0;
0595
0596 result = read_node(PS3_LPAR_ID_PME,
0597 make_first_field("bus", bus_index),
0598 make_field("dev", dev_index),
0599 make_field("n_regs", 0),
0600 0, &v1, NULL);
0601 *num_regions = v1;
0602 return result;
0603 }
0604
0605 int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
0606 unsigned int dev_index, unsigned int region_index,
0607 unsigned int *region_id)
0608 {
0609 int result;
0610 u64 v1 = 0;
0611
0612 result = read_node(PS3_LPAR_ID_PME,
0613 make_first_field("bus", bus_index),
0614 make_field("dev", dev_index),
0615 make_field("region", region_index),
0616 make_field("id", 0),
0617 &v1, NULL);
0618 *region_id = v1;
0619 return result;
0620 }
0621
0622 int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,
0623 unsigned int dev_index, unsigned int region_index, u64 *region_size)
0624 {
0625 return read_node(PS3_LPAR_ID_PME,
0626 make_first_field("bus", bus_index),
0627 make_field("dev", dev_index),
0628 make_field("region", region_index),
0629 make_field("size", 0),
0630 region_size, NULL);
0631 }
0632
0633 int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
0634 unsigned int dev_index, unsigned int region_index, u64 *region_start)
0635 {
0636 return read_node(PS3_LPAR_ID_PME,
0637 make_first_field("bus", bus_index),
0638 make_field("dev", dev_index),
0639 make_field("region", region_index),
0640 make_field("start", 0),
0641 region_start, NULL);
0642 }
0643
0644 int ps3_repository_read_stor_dev_info(unsigned int bus_index,
0645 unsigned int dev_index, u64 *port, u64 *blk_size,
0646 u64 *num_blocks, unsigned int *num_regions)
0647 {
0648 int result;
0649
0650 result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port);
0651 if (result)
0652 return result;
0653
0654 result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index,
0655 blk_size);
0656 if (result)
0657 return result;
0658
0659 result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index,
0660 num_blocks);
0661 if (result)
0662 return result;
0663
0664 result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index,
0665 num_regions);
0666 return result;
0667 }
0668
0669 int ps3_repository_read_stor_dev_region(unsigned int bus_index,
0670 unsigned int dev_index, unsigned int region_index,
0671 unsigned int *region_id, u64 *region_start, u64 *region_size)
0672 {
0673 int result;
0674
0675 result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index,
0676 region_index, region_id);
0677 if (result)
0678 return result;
0679
0680 result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index,
0681 region_index, region_start);
0682 if (result)
0683 return result;
0684
0685 result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index,
0686 region_index, region_size);
0687 return result;
0688 }
0689
0690
0691
0692
0693
0694 int ps3_repository_read_num_pu(u64 *num_pu)
0695 {
0696 *num_pu = 0;
0697 return read_node(PS3_LPAR_ID_CURRENT,
0698 make_first_field("bi", 0),
0699 make_field("pun", 0),
0700 0, 0,
0701 num_pu, NULL);
0702 }
0703
0704
0705
0706
0707
0708
0709
0710 int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id)
0711 {
0712 return read_node(PS3_LPAR_ID_CURRENT,
0713 make_first_field("bi", 0),
0714 make_field("pu", pu_index),
0715 0, 0,
0716 pu_id, NULL);
0717 }
0718
0719 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
0720 {
0721 return read_node(PS3_LPAR_ID_CURRENT,
0722 make_first_field("bi", 0),
0723 make_field("pu", 0),
0724 ppe_id,
0725 make_field("rm_size", 0),
0726 rm_size, NULL);
0727 }
0728
0729 int ps3_repository_read_region_total(u64 *region_total)
0730 {
0731 return read_node(PS3_LPAR_ID_CURRENT,
0732 make_first_field("bi", 0),
0733 make_field("rgntotal", 0),
0734 0, 0,
0735 region_total, NULL);
0736 }
0737
0738
0739
0740
0741
0742
0743
0744
0745 int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
0746 {
0747 int result;
0748 u64 ppe_id;
0749
0750 lv1_get_logical_ppe_id(&ppe_id);
0751 *rm_base = 0;
0752 result = ps3_repository_read_rm_size(ppe_id, rm_size);
0753 return result ? result
0754 : ps3_repository_read_region_total(region_total);
0755 }
0756
0757
0758
0759
0760
0761
0762
0763
0764 int ps3_repository_read_highmem_region_count(unsigned int *region_count)
0765 {
0766 int result;
0767 u64 v1 = 0;
0768
0769 result = read_node(PS3_LPAR_ID_CURRENT,
0770 make_first_field("highmem", 0),
0771 make_field("region", 0),
0772 make_field("count", 0),
0773 0,
0774 &v1, NULL);
0775 *region_count = v1;
0776 return result;
0777 }
0778
0779
0780 int ps3_repository_read_highmem_base(unsigned int region_index,
0781 u64 *highmem_base)
0782 {
0783 return read_node(PS3_LPAR_ID_CURRENT,
0784 make_first_field("highmem", 0),
0785 make_field("region", region_index),
0786 make_field("base", 0),
0787 0,
0788 highmem_base, NULL);
0789 }
0790
0791 int ps3_repository_read_highmem_size(unsigned int region_index,
0792 u64 *highmem_size)
0793 {
0794 return read_node(PS3_LPAR_ID_CURRENT,
0795 make_first_field("highmem", 0),
0796 make_field("region", region_index),
0797 make_field("size", 0),
0798 0,
0799 highmem_size, NULL);
0800 }
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812 int ps3_repository_read_highmem_info(unsigned int region_index,
0813 u64 *highmem_base, u64 *highmem_size)
0814 {
0815 int result;
0816
0817 *highmem_base = 0;
0818 result = ps3_repository_read_highmem_base(region_index, highmem_base);
0819 return result ? result
0820 : ps3_repository_read_highmem_size(region_index, highmem_size);
0821 }
0822
0823
0824
0825
0826
0827
0828 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
0829 {
0830 int result;
0831 u64 v1 = 0;
0832
0833 result = read_node(PS3_LPAR_ID_CURRENT,
0834 make_first_field("bi", 0),
0835 make_field("spun", 0),
0836 0, 0,
0837 &v1, NULL);
0838 *num_spu_reserved = v1;
0839 return result;
0840 }
0841
0842
0843
0844
0845
0846
0847 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
0848 {
0849 int result;
0850 u64 v1 = 0;
0851
0852 result = read_node(PS3_LPAR_ID_CURRENT,
0853 make_first_field("bi", 0),
0854 make_field("spursvn", 0),
0855 0, 0,
0856 &v1, NULL);
0857 *num_resource_id = v1;
0858 return result;
0859 }
0860
0861
0862
0863
0864
0865
0866
0867
0868 int ps3_repository_read_spu_resource_id(unsigned int res_index,
0869 enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
0870 {
0871 int result;
0872 u64 v1 = 0;
0873 u64 v2 = 0;
0874
0875 result = read_node(PS3_LPAR_ID_CURRENT,
0876 make_first_field("bi", 0),
0877 make_field("spursv", 0),
0878 res_index,
0879 0,
0880 &v1, &v2);
0881 *resource_type = v1;
0882 *resource_id = v2;
0883 return result;
0884 }
0885
0886 static int ps3_repository_read_boot_dat_address(u64 *address)
0887 {
0888 return read_node(PS3_LPAR_ID_CURRENT,
0889 make_first_field("bi", 0),
0890 make_field("boot_dat", 0),
0891 make_field("address", 0),
0892 0,
0893 address, NULL);
0894 }
0895
0896 int ps3_repository_read_boot_dat_size(unsigned int *size)
0897 {
0898 int result;
0899 u64 v1 = 0;
0900
0901 result = read_node(PS3_LPAR_ID_CURRENT,
0902 make_first_field("bi", 0),
0903 make_field("boot_dat", 0),
0904 make_field("size", 0),
0905 0,
0906 &v1, NULL);
0907 *size = v1;
0908 return result;
0909 }
0910
0911 int __init ps3_repository_read_vuart_av_port(unsigned int *port)
0912 {
0913 int result;
0914 u64 v1 = 0;
0915
0916 result = read_node(PS3_LPAR_ID_CURRENT,
0917 make_first_field("bi", 0),
0918 make_field("vir_uart", 0),
0919 make_field("port", 0),
0920 make_field("avset", 0),
0921 &v1, NULL);
0922 *port = v1;
0923 return result;
0924 }
0925
0926 int __init ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
0927 {
0928 int result;
0929 u64 v1 = 0;
0930
0931 result = read_node(PS3_LPAR_ID_CURRENT,
0932 make_first_field("bi", 0),
0933 make_field("vir_uart", 0),
0934 make_field("port", 0),
0935 make_field("sysmgr", 0),
0936 &v1, NULL);
0937 *port = v1;
0938 return result;
0939 }
0940
0941
0942
0943
0944
0945
0946
0947 int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
0948 {
0949 int result;
0950
0951 *size = 0;
0952 result = ps3_repository_read_boot_dat_address(lpar_addr);
0953 return result ? result
0954 : ps3_repository_read_boot_dat_size(size);
0955 }
0956
0957
0958
0959
0960
0961 int ps3_repository_read_num_be(unsigned int *num_be)
0962 {
0963 int result;
0964 u64 v1 = 0;
0965
0966 result = read_node(PS3_LPAR_ID_PME,
0967 make_first_field("ben", 0),
0968 0,
0969 0,
0970 0,
0971 &v1, NULL);
0972 *num_be = v1;
0973 return result;
0974 }
0975
0976
0977
0978
0979
0980
0981
0982 int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
0983 {
0984 return read_node(PS3_LPAR_ID_PME,
0985 make_first_field("be", be_index),
0986 0,
0987 0,
0988 0,
0989 node_id, NULL);
0990 }
0991
0992
0993
0994
0995
0996
0997
0998 int ps3_repository_read_be_id(u64 node_id, u64 *be_id)
0999 {
1000 return read_node(PS3_LPAR_ID_PME,
1001 make_first_field("be", 0),
1002 node_id,
1003 0,
1004 0,
1005 be_id, NULL);
1006 }
1007
1008 int __init ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
1009 {
1010 return read_node(PS3_LPAR_ID_PME,
1011 make_first_field("be", 0),
1012 node_id,
1013 make_field("clock", 0),
1014 0,
1015 tb_freq, NULL);
1016 }
1017
1018 int __init ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
1019 {
1020 int result;
1021 u64 node_id;
1022
1023 *tb_freq = 0;
1024 result = ps3_repository_read_be_node_id(be_index, &node_id);
1025 return result ? result
1026 : ps3_repository_read_tb_freq(node_id, tb_freq);
1027 }
1028
1029 int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
1030 u64 *rights)
1031 {
1032 int result;
1033 u64 node_id;
1034
1035 *lpar = 0;
1036 *rights = 0;
1037 result = ps3_repository_read_be_node_id(be_index, &node_id);
1038 return result ? result
1039 : read_node(PS3_LPAR_ID_PME,
1040 make_first_field("be", 0),
1041 node_id,
1042 make_field("lpm", 0),
1043 make_field("priv", 0),
1044 lpar, rights);
1045 }
1046
1047 #if defined(CONFIG_PS3_REPOSITORY_WRITE)
1048
1049 static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1050 {
1051 int result;
1052
1053 dump_node(0, n1, n2, n3, n4, v1, v2);
1054
1055 result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2);
1056
1057 if (result) {
1058 pr_devel("%s:%d: lv1_create_repository_node failed: %s\n",
1059 __func__, __LINE__, ps3_result(result));
1060 return -ENOENT;
1061 }
1062
1063 return 0;
1064 }
1065
1066 static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4)
1067 {
1068 int result;
1069
1070 dump_node(0, n1, n2, n3, n4, 0, 0);
1071
1072 result = lv1_delete_repository_node(n1, n2, n3, n4);
1073
1074 if (result) {
1075 pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n",
1076 __func__, __LINE__, ps3_result(result));
1077 return -ENOENT;
1078 }
1079
1080 return 0;
1081 }
1082
1083 static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1084 {
1085 int result;
1086
1087 result = create_node(n1, n2, n3, n4, v1, v2);
1088
1089 if (!result)
1090 return 0;
1091
1092 result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2);
1093
1094 if (result) {
1095 pr_devel("%s:%d: lv1_write_repository_node failed: %s\n",
1096 __func__, __LINE__, ps3_result(result));
1097 return -ENOENT;
1098 }
1099
1100 return 0;
1101 }
1102
1103 int ps3_repository_write_highmem_region_count(unsigned int region_count)
1104 {
1105 int result;
1106 u64 v1 = (u64)region_count;
1107
1108 result = write_node(
1109 make_first_field("highmem", 0),
1110 make_field("region", 0),
1111 make_field("count", 0),
1112 0,
1113 v1, 0);
1114 return result;
1115 }
1116
1117 int ps3_repository_write_highmem_base(unsigned int region_index,
1118 u64 highmem_base)
1119 {
1120 return write_node(
1121 make_first_field("highmem", 0),
1122 make_field("region", region_index),
1123 make_field("base", 0),
1124 0,
1125 highmem_base, 0);
1126 }
1127
1128 int ps3_repository_write_highmem_size(unsigned int region_index,
1129 u64 highmem_size)
1130 {
1131 return write_node(
1132 make_first_field("highmem", 0),
1133 make_field("region", region_index),
1134 make_field("size", 0),
1135 0,
1136 highmem_size, 0);
1137 }
1138
1139 int ps3_repository_write_highmem_info(unsigned int region_index,
1140 u64 highmem_base, u64 highmem_size)
1141 {
1142 int result;
1143
1144 result = ps3_repository_write_highmem_base(region_index, highmem_base);
1145 return result ? result
1146 : ps3_repository_write_highmem_size(region_index, highmem_size);
1147 }
1148
1149 static int ps3_repository_delete_highmem_base(unsigned int region_index)
1150 {
1151 return delete_node(
1152 make_first_field("highmem", 0),
1153 make_field("region", region_index),
1154 make_field("base", 0),
1155 0);
1156 }
1157
1158 static int ps3_repository_delete_highmem_size(unsigned int region_index)
1159 {
1160 return delete_node(
1161 make_first_field("highmem", 0),
1162 make_field("region", region_index),
1163 make_field("size", 0),
1164 0);
1165 }
1166
1167 int ps3_repository_delete_highmem_info(unsigned int region_index)
1168 {
1169 int result;
1170
1171 result = ps3_repository_delete_highmem_base(region_index);
1172 result += ps3_repository_delete_highmem_size(region_index);
1173
1174 return result ? -1 : 0;
1175 }
1176
1177 #endif
1178
1179 #if defined(DEBUG)
1180
1181 int __init ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
1182 {
1183 int result = 0;
1184 unsigned int res_index;
1185
1186 pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
1187 repo->bus_index, repo->dev_index);
1188
1189 for (res_index = 0; res_index < 10; res_index++) {
1190 enum ps3_interrupt_type intr_type;
1191 unsigned int interrupt_id;
1192
1193 result = ps3_repository_read_dev_intr(repo->bus_index,
1194 repo->dev_index, res_index, &intr_type, &interrupt_id);
1195
1196 if (result) {
1197 if (result != LV1_NO_ENTRY)
1198 pr_devel("%s:%d ps3_repository_read_dev_intr"
1199 " (%u:%u) failed\n", __func__, __LINE__,
1200 repo->bus_index, repo->dev_index);
1201 break;
1202 }
1203
1204 pr_devel("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
1205 __func__, __LINE__, repo->bus_index, repo->dev_index,
1206 intr_type, interrupt_id);
1207 }
1208
1209 for (res_index = 0; res_index < 10; res_index++) {
1210 enum ps3_reg_type reg_type;
1211 u64 bus_addr;
1212 u64 len;
1213
1214 result = ps3_repository_read_dev_reg(repo->bus_index,
1215 repo->dev_index, res_index, ®_type, &bus_addr, &len);
1216
1217 if (result) {
1218 if (result != LV1_NO_ENTRY)
1219 pr_devel("%s:%d ps3_repository_read_dev_reg"
1220 " (%u:%u) failed\n", __func__, __LINE__,
1221 repo->bus_index, repo->dev_index);
1222 break;
1223 }
1224
1225 pr_devel("%s:%d (%u:%u) reg_type %u, bus_addr %llxh, len %llxh\n",
1226 __func__, __LINE__, repo->bus_index, repo->dev_index,
1227 reg_type, bus_addr, len);
1228 }
1229
1230 pr_devel(" <- %s:%d\n", __func__, __LINE__);
1231 return result;
1232 }
1233
1234 static int __init dump_stor_dev_info(struct ps3_repository_device *repo)
1235 {
1236 int result = 0;
1237 unsigned int num_regions, region_index;
1238 u64 port, blk_size, num_blocks;
1239
1240 pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
1241 repo->bus_index, repo->dev_index);
1242
1243 result = ps3_repository_read_stor_dev_info(repo->bus_index,
1244 repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
1245 if (result) {
1246 pr_devel("%s:%d ps3_repository_read_stor_dev_info"
1247 " (%u:%u) failed\n", __func__, __LINE__,
1248 repo->bus_index, repo->dev_index);
1249 goto out;
1250 }
1251
1252 pr_devel("%s:%d (%u:%u): port %llu, blk_size %llu, num_blocks "
1253 "%llu, num_regions %u\n",
1254 __func__, __LINE__, repo->bus_index, repo->dev_index,
1255 port, blk_size, num_blocks, num_regions);
1256
1257 for (region_index = 0; region_index < num_regions; region_index++) {
1258 unsigned int region_id;
1259 u64 region_start, region_size;
1260
1261 result = ps3_repository_read_stor_dev_region(repo->bus_index,
1262 repo->dev_index, region_index, ®ion_id,
1263 ®ion_start, ®ion_size);
1264 if (result) {
1265 pr_devel("%s:%d ps3_repository_read_stor_dev_region"
1266 " (%u:%u) failed\n", __func__, __LINE__,
1267 repo->bus_index, repo->dev_index);
1268 break;
1269 }
1270
1271 pr_devel("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
1272 __func__, __LINE__, repo->bus_index, repo->dev_index,
1273 region_id, (unsigned long)region_start,
1274 (unsigned long)region_size);
1275 }
1276
1277 out:
1278 pr_devel(" <- %s:%d\n", __func__, __LINE__);
1279 return result;
1280 }
1281
1282 static int __init dump_device_info(struct ps3_repository_device *repo,
1283 unsigned int num_dev)
1284 {
1285 int result = 0;
1286
1287 pr_devel(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
1288
1289 for (repo->dev_index = 0; repo->dev_index < num_dev;
1290 repo->dev_index++) {
1291
1292 result = ps3_repository_read_dev_type(repo->bus_index,
1293 repo->dev_index, &repo->dev_type);
1294
1295 if (result) {
1296 pr_devel("%s:%d ps3_repository_read_dev_type"
1297 " (%u:%u) failed\n", __func__, __LINE__,
1298 repo->bus_index, repo->dev_index);
1299 break;
1300 }
1301
1302 result = ps3_repository_read_dev_id(repo->bus_index,
1303 repo->dev_index, &repo->dev_id);
1304
1305 if (result) {
1306 pr_devel("%s:%d ps3_repository_read_dev_id"
1307 " (%u:%u) failed\n", __func__, __LINE__,
1308 repo->bus_index, repo->dev_index);
1309 continue;
1310 }
1311
1312 pr_devel("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__,
1313 __LINE__, repo->bus_index, repo->dev_index,
1314 repo->dev_type, (unsigned long)repo->dev_id);
1315
1316 ps3_repository_dump_resource_info(repo);
1317
1318 if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
1319 dump_stor_dev_info(repo);
1320 }
1321
1322 pr_devel(" <- %s:%d\n", __func__, __LINE__);
1323 return result;
1324 }
1325
1326 int __init ps3_repository_dump_bus_info(void)
1327 {
1328 int result = 0;
1329 struct ps3_repository_device repo;
1330
1331 pr_devel(" -> %s:%d\n", __func__, __LINE__);
1332
1333 memset(&repo, 0, sizeof(repo));
1334
1335 for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
1336 unsigned int num_dev;
1337
1338 result = ps3_repository_read_bus_type(repo.bus_index,
1339 &repo.bus_type);
1340
1341 if (result) {
1342 pr_devel("%s:%d read_bus_type(%u) failed\n",
1343 __func__, __LINE__, repo.bus_index);
1344 break;
1345 }
1346
1347 result = ps3_repository_read_bus_id(repo.bus_index,
1348 &repo.bus_id);
1349
1350 if (result) {
1351 pr_devel("%s:%d read_bus_id(%u) failed\n",
1352 __func__, __LINE__, repo.bus_index);
1353 continue;
1354 }
1355
1356 if (repo.bus_index != repo.bus_id)
1357 pr_devel("%s:%d bus_index != bus_id\n",
1358 __func__, __LINE__);
1359
1360 result = ps3_repository_read_bus_num_dev(repo.bus_index,
1361 &num_dev);
1362
1363 if (result) {
1364 pr_devel("%s:%d read_bus_num_dev(%u) failed\n",
1365 __func__, __LINE__, repo.bus_index);
1366 continue;
1367 }
1368
1369 pr_devel("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",
1370 __func__, __LINE__, repo.bus_index, repo.bus_type,
1371 (unsigned long)repo.bus_id, num_dev);
1372
1373 dump_device_info(&repo, num_dev);
1374 }
1375
1376 pr_devel(" <- %s:%d\n", __func__, __LINE__);
1377 return result;
1378 }
1379
1380 #endif