Pull button into test branch
[pandora-kernel.git] / arch / powerpc / platforms / ps3 / repository.c
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/ps3.h>
22 #include <asm/lv1call.h>
23
24 enum ps3_vendor_id {
25         PS3_VENDOR_ID_NONE = 0,
26         PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
27 };
28
29 enum ps3_lpar_id {
30         PS3_LPAR_ID_CURRENT = 0,
31         PS3_LPAR_ID_PME = 1,
32 };
33
34 #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
35 static void _dump_field(const char *hdr, u64 n, const char* func, int line)
36 {
37 #if defined(DEBUG)
38         char s[16];
39         const char *const in = (const char *)&n;
40         unsigned int i;
41
42         for (i = 0; i < 8; i++)
43                 s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
44         s[i] = 0;
45
46         pr_debug("%s:%d: %s%016lx : %s\n", func, line, hdr, n, s);
47 #endif
48 }
49
50 #define dump_node_name(_a, _b, _c, _d, _e) \
51         _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
52 static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
53         u64 n4, const char* func, int line)
54 {
55         pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
56         _dump_field("n1: ", n1, func, line);
57         _dump_field("n2: ", n2, func, line);
58         _dump_field("n3: ", n3, func, line);
59         _dump_field("n4: ", n4, func, line);
60 }
61
62 #define dump_node(_a, _b, _c, _d, _e, _f, _g) \
63         _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
64 static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
65         u64 v1, u64 v2, const char* func, int line)
66 {
67         pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
68         _dump_field("n1: ", n1, func, line);
69         _dump_field("n2: ", n2, func, line);
70         _dump_field("n3: ", n3, func, line);
71         _dump_field("n4: ", n4, func, line);
72         pr_debug("%s:%d: v1: %016lx\n", func, line, v1);
73         pr_debug("%s:%d: v2: %016lx\n", func, line, v2);
74 }
75
76 /**
77  * make_first_field - Make the first field of a repository node name.
78  * @text: Text portion of the field.
79  * @index: Numeric index portion of the field.  Use zero for 'don't care'.
80  *
81  * This routine sets the vendor id to zero (non-vendor specific).
82  * Returns field value.
83  */
84
85 static u64 make_first_field(const char *text, u64 index)
86 {
87         u64 n;
88
89         strncpy((char *)&n, text, 8);
90         return PS3_VENDOR_ID_NONE + (n >> 32) + index;
91 }
92
93 /**
94  * make_field - Make subsequent fields of a repository node name.
95  * @text: Text portion of the field.  Use "" for 'don't care'.
96  * @index: Numeric index portion of the field.  Use zero for 'don't care'.
97  *
98  * Returns field value.
99  */
100
101 static u64 make_field(const char *text, u64 index)
102 {
103         u64 n;
104
105         strncpy((char *)&n, text, 8);
106         return n + index;
107 }
108
109 /**
110  * read_node - Read a repository node from raw fields.
111  * @n1: First field of node name.
112  * @n2: Second field of node name.  Use zero for 'don't care'.
113  * @n3: Third field of node name.  Use zero for 'don't care'.
114  * @n4: Fourth field of node name.  Use zero for 'don't care'.
115  * @v1: First repository value (high word).
116  * @v2: Second repository value (low word).  Optional parameter, use zero
117  *      for 'don't care'.
118  */
119
120 static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
121         u64 *_v1, u64 *_v2)
122 {
123         int result;
124         u64 v1;
125         u64 v2;
126
127         if (lpar_id == PS3_LPAR_ID_CURRENT) {
128                 u64 id;
129                 lv1_get_logical_partition_id(&id);
130                 lpar_id = id;
131         }
132
133         result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1,
134                 &v2);
135
136         if (result) {
137                 pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
138                         __func__, __LINE__, ps3_result(result));
139                 dump_node_name(lpar_id, n1, n2, n3, n4);
140                 return result;
141         }
142
143         dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
144
145         if (_v1)
146                 *_v1 = v1;
147         if (_v2)
148                 *_v2 = v2;
149
150         if (v1 && !_v1)
151                 pr_debug("%s:%d: warning: discarding non-zero v1: %016lx\n",
152                         __func__, __LINE__, v1);
153         if (v2 && !_v2)
154                 pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
155                         __func__, __LINE__, v2);
156
157         return result;
158 }
159
160 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
161         u64 *value)
162 {
163         return read_node(PS3_LPAR_ID_PME,
164                 make_first_field("bus", bus_index),
165                 make_field(bus_str, 0),
166                 0, 0,
167                 value, 0);
168 }
169
170 int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id)
171 {
172         int result;
173         u64 v1;
174         u64 v2; /* unused */
175
176         result = read_node(PS3_LPAR_ID_PME,
177                 make_first_field("bus", bus_index),
178                 make_field("id", 0),
179                 0, 0,
180                 &v1, &v2);
181         *bus_id = v1;
182         return result;
183 }
184
185 int ps3_repository_read_bus_type(unsigned int bus_index,
186         enum ps3_bus_type *bus_type)
187 {
188         int result;
189         u64 v1;
190
191         result = read_node(PS3_LPAR_ID_PME,
192                 make_first_field("bus", bus_index),
193                 make_field("type", 0),
194                 0, 0,
195                 &v1, 0);
196         *bus_type = v1;
197         return result;
198 }
199
200 int ps3_repository_read_bus_num_dev(unsigned int bus_index,
201         unsigned int *num_dev)
202 {
203         int result;
204         u64 v1;
205
206         result = read_node(PS3_LPAR_ID_PME,
207                 make_first_field("bus", bus_index),
208                 make_field("num_dev", 0),
209                 0, 0,
210                 &v1, 0);
211         *num_dev = v1;
212         return result;
213 }
214
215 int ps3_repository_read_dev_str(unsigned int bus_index,
216         unsigned int dev_index, const char *dev_str, u64 *value)
217 {
218         return read_node(PS3_LPAR_ID_PME,
219                 make_first_field("bus", bus_index),
220                 make_field("dev", dev_index),
221                 make_field(dev_str, 0),
222                 0,
223                 value, 0);
224 }
225
226 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
227         unsigned int *dev_id)
228 {
229         int result;
230         u64 v1;
231
232         result = read_node(PS3_LPAR_ID_PME,
233                 make_first_field("bus", bus_index),
234                 make_field("dev", dev_index),
235                 make_field("id", 0),
236                 0,
237                 &v1, 0);
238         *dev_id = v1;
239         return result;
240 }
241
242 int ps3_repository_read_dev_type(unsigned int bus_index,
243         unsigned int dev_index, enum ps3_dev_type *dev_type)
244 {
245         int result;
246         u64 v1;
247
248         result = read_node(PS3_LPAR_ID_PME,
249                 make_first_field("bus", bus_index),
250                 make_field("dev", dev_index),
251                 make_field("type", 0),
252                 0,
253                 &v1, 0);
254         *dev_type = v1;
255         return result;
256 }
257
258 int ps3_repository_read_dev_intr(unsigned int bus_index,
259         unsigned int dev_index, unsigned int intr_index,
260         unsigned int *intr_type, unsigned int* interrupt_id)
261 {
262         int result;
263         u64 v1;
264         u64 v2;
265
266         result = read_node(PS3_LPAR_ID_PME,
267                 make_first_field("bus", bus_index),
268                 make_field("dev", dev_index),
269                 make_field("intr", intr_index),
270                 0,
271                 &v1, &v2);
272         *intr_type = v1;
273         *interrupt_id = v2;
274         return result;
275 }
276
277 int ps3_repository_read_dev_reg_type(unsigned int bus_index,
278         unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type)
279 {
280         int result;
281         u64 v1;
282
283         result = read_node(PS3_LPAR_ID_PME,
284                 make_first_field("bus", bus_index),
285                 make_field("dev", dev_index),
286                 make_field("reg", reg_index),
287                 make_field("type", 0),
288                 &v1, 0);
289         *reg_type = v1;
290         return result;
291 }
292
293 int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
294         unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)
295 {
296         return read_node(PS3_LPAR_ID_PME,
297                 make_first_field("bus", bus_index),
298                 make_field("dev", dev_index),
299                 make_field("reg", reg_index),
300                 make_field("data", 0),
301                 bus_addr, len);
302 }
303
304 int ps3_repository_read_dev_reg(unsigned int bus_index,
305         unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type,
306         u64 *bus_addr, u64 *len)
307 {
308         int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
309                 reg_index, reg_type);
310         return result ? result
311                 : ps3_repository_read_dev_reg_addr(bus_index, dev_index,
312                 reg_index, bus_addr, len);
313 }
314
315 #if defined(DEBUG)
316 int ps3_repository_dump_resource_info(unsigned int bus_index,
317         unsigned int dev_index)
318 {
319         int result = 0;
320         unsigned int res_index;
321
322         pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
323                 bus_index, dev_index);
324
325         for (res_index = 0; res_index < 10; res_index++) {
326                 enum ps3_interrupt_type intr_type;
327                 unsigned int interrupt_id;
328
329                 result = ps3_repository_read_dev_intr(bus_index, dev_index,
330                         res_index, &intr_type, &interrupt_id);
331
332                 if (result) {
333                         if (result !=  LV1_NO_ENTRY)
334                                 pr_debug("%s:%d ps3_repository_read_dev_intr"
335                                         " (%u:%u) failed\n", __func__, __LINE__,
336                                         bus_index, dev_index);
337                         break;
338                 }
339
340                 pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
341                         __func__, __LINE__, bus_index, dev_index, intr_type,
342                         interrupt_id);
343         }
344
345         for (res_index = 0; res_index < 10; res_index++) {
346                 enum ps3_region_type reg_type;
347                 u64 bus_addr;
348                 u64 len;
349
350                 result = ps3_repository_read_dev_reg(bus_index, dev_index,
351                         res_index, &reg_type, &bus_addr, &len);
352
353                 if (result) {
354                         if (result !=  LV1_NO_ENTRY)
355                                 pr_debug("%s:%d ps3_repository_read_dev_reg"
356                                         " (%u:%u) failed\n", __func__, __LINE__,
357                                         bus_index, dev_index);
358                         break;
359                 }
360
361                 pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
362                         __func__, __LINE__, bus_index, dev_index, reg_type,
363                         bus_addr, len);
364         }
365
366         pr_debug(" <- %s:%d\n", __func__, __LINE__);
367         return result;
368 }
369
370 static int dump_device_info(unsigned int bus_index, unsigned int num_dev)
371 {
372         int result = 0;
373         unsigned int dev_index;
374
375         pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
376
377         for (dev_index = 0; dev_index < num_dev; dev_index++) {
378                 enum ps3_dev_type dev_type;
379                 unsigned int dev_id;
380
381                 result = ps3_repository_read_dev_type(bus_index, dev_index,
382                         &dev_type);
383
384                 if (result) {
385                         pr_debug("%s:%d ps3_repository_read_dev_type"
386                                 " (%u:%u) failed\n", __func__, __LINE__,
387                                 bus_index, dev_index);
388                         break;
389                 }
390
391                 result = ps3_repository_read_dev_id(bus_index, dev_index,
392                         &dev_id);
393
394                 if (result) {
395                         pr_debug("%s:%d ps3_repository_read_dev_id"
396                                 " (%u:%u) failed\n", __func__, __LINE__,
397                                 bus_index, dev_index);
398                         continue;
399                 }
400
401                 pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
402                         __LINE__, bus_index, dev_index, dev_type, dev_id);
403
404                 ps3_repository_dump_resource_info(bus_index, dev_index);
405         }
406
407         pr_debug(" <- %s:%d\n", __func__, __LINE__);
408         return result;
409 }
410
411 int ps3_repository_dump_bus_info(void)
412 {
413         int result = 0;
414         unsigned int bus_index;
415
416         pr_debug(" -> %s:%d\n", __func__, __LINE__);
417
418         for (bus_index = 0; bus_index < 10; bus_index++) {
419                 enum ps3_bus_type bus_type;
420                 unsigned int bus_id;
421                 unsigned int num_dev;
422
423                 result = ps3_repository_read_bus_type(bus_index, &bus_type);
424
425                 if (result) {
426                         pr_debug("%s:%d read_bus_type(%u) failed\n",
427                                 __func__, __LINE__, bus_index);
428                         break;
429                 }
430
431                 result = ps3_repository_read_bus_id(bus_index, &bus_id);
432
433                 if (result) {
434                         pr_debug("%s:%d read_bus_id(%u) failed\n",
435                                 __func__, __LINE__, bus_index);
436                         continue;
437                 }
438
439                 if (bus_index != bus_id)
440                         pr_debug("%s:%d bus_index != bus_id\n",
441                                 __func__, __LINE__);
442
443                 result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
444
445                 if (result) {
446                         pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
447                                 __func__, __LINE__, bus_index);
448                         continue;
449                 }
450
451                 pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
452                         __func__, __LINE__, bus_index, bus_type, bus_id,
453                         num_dev);
454
455                 dump_device_info(bus_index, num_dev);
456         }
457
458         pr_debug(" <- %s:%d\n", __func__, __LINE__);
459         return result;
460 }
461 #endif /* defined(DEBUG) */
462
463 static int find_device(unsigned int bus_index, unsigned int num_dev,
464         unsigned int start_dev_index, enum ps3_dev_type dev_type,
465         struct ps3_repository_device *dev)
466 {
467         int result = 0;
468         unsigned int dev_index;
469
470         pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
471
472         dev->dev_index = UINT_MAX;
473
474         for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
475                 enum ps3_dev_type x;
476
477                 result = ps3_repository_read_dev_type(bus_index, dev_index,
478                         &x);
479
480                 if (result) {
481                         pr_debug("%s:%d read_dev_type failed\n",
482                                 __func__, __LINE__);
483                         return result;
484                 }
485
486                 if (x == dev_type)
487                         break;
488         }
489
490         BUG_ON(dev_index == num_dev);
491
492         pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
493                 __func__, __LINE__, dev_type, dev_index);
494
495         result = ps3_repository_read_dev_id(bus_index, dev_index,
496                 &dev->did.dev_id);
497
498         if (result) {
499                 pr_debug("%s:%d read_dev_id failed\n",
500                         __func__, __LINE__);
501                 return result;
502         }
503
504         dev->dev_index = dev_index;
505
506         pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
507                 dev->did.dev_id);
508
509         return result;
510 }
511
512 int ps3_repository_find_device (enum ps3_bus_type bus_type,
513         enum ps3_dev_type dev_type,
514         const struct ps3_repository_device *start_dev,
515         struct ps3_repository_device *dev)
516 {
517         int result = 0;
518         unsigned int bus_index;
519         unsigned int num_dev;
520
521         pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
522                 bus_type, dev_type);
523
524         dev->bus_index = UINT_MAX;
525
526         for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
527                 bus_index++) {
528                 enum ps3_bus_type x;
529
530                 result = ps3_repository_read_bus_type(bus_index, &x);
531
532                 if (result) {
533                         pr_debug("%s:%d read_bus_type failed\n",
534                                 __func__, __LINE__);
535                         return result;
536                 }
537                 if (x == bus_type)
538                         break;
539         }
540
541         BUG_ON(bus_index == 10);
542
543         pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
544                 __func__, __LINE__, bus_type, bus_index);
545
546         result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
547
548         if (result) {
549                 pr_debug("%s:%d read_bus_num_dev failed\n",
550                         __func__, __LINE__);
551                 return result;
552         }
553
554         result = find_device(bus_index, num_dev, start_dev
555                 ? start_dev->dev_index + 1 : 0, dev_type, dev);
556
557         if (result) {
558                 pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
559                 return result;
560         }
561
562         result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
563
564         if (result) {
565                 pr_debug("%s:%d read_bus_id failed\n",
566                         __func__, __LINE__);
567                 return result;
568         }
569
570         dev->bus_index = bus_index;
571
572         pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
573                 __func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
574
575         return result;
576 }
577
578 int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
579         enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
580 {
581         int result = 0;
582         unsigned int res_index;
583
584         pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
585
586         *interrupt_id = UINT_MAX;
587
588         for (res_index = 0; res_index < 10; res_index++) {
589                 enum ps3_interrupt_type t;
590                 unsigned int id;
591
592                 result = ps3_repository_read_dev_intr(dev->bus_index,
593                         dev->dev_index, res_index, &t, &id);
594
595                 if (result) {
596                         pr_debug("%s:%d read_dev_intr failed\n",
597                                 __func__, __LINE__);
598                         return result;
599                 }
600
601                 if (t == intr_type) {
602                         *interrupt_id = id;
603                         break;
604                 }
605         }
606
607         BUG_ON(res_index == 10);
608
609         pr_debug("%s:%d: found intr_type %u at res_index %u\n",
610                 __func__, __LINE__, intr_type, res_index);
611
612         return result;
613 }
614
615 int ps3_repository_find_region(const struct ps3_repository_device *dev,
616         enum ps3_region_type reg_type, u64 *bus_addr, u64 *len)
617 {
618         int result = 0;
619         unsigned int res_index;
620
621         pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
622
623         *bus_addr = *len = 0;
624
625         for (res_index = 0; res_index < 10; res_index++) {
626                 enum ps3_region_type t;
627                 u64 a;
628                 u64 l;
629
630                 result = ps3_repository_read_dev_reg(dev->bus_index,
631                         dev->dev_index, res_index, &t, &a, &l);
632
633                 if (result) {
634                         pr_debug("%s:%d read_dev_reg failed\n",
635                                 __func__, __LINE__);
636                         return result;
637                 }
638
639                 if (t == reg_type) {
640                         *bus_addr = a;
641                         *len = l;
642                         break;
643                 }
644         }
645
646         BUG_ON(res_index == 10);
647
648         pr_debug("%s:%d: found reg_type %u at res_index %u\n",
649                 __func__, __LINE__, reg_type, res_index);
650
651         return result;
652 }
653
654 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
655 {
656         return read_node(PS3_LPAR_ID_CURRENT,
657                 make_first_field("bi", 0),
658                 make_field("pu", 0),
659                 ppe_id,
660                 make_field("rm_size", 0),
661                 rm_size, 0);
662 }
663
664 int ps3_repository_read_region_total(u64 *region_total)
665 {
666         return read_node(PS3_LPAR_ID_CURRENT,
667                 make_first_field("bi", 0),
668                 make_field("rgntotal", 0),
669                 0, 0,
670                 region_total, 0);
671 }
672
673 /**
674  * ps3_repository_read_mm_info - Read mm info for single pu system.
675  * @rm_base: Real mode memory base address.
676  * @rm_size: Real mode memory size.
677  * @region_total: Maximum memory region size.
678  */
679
680 int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
681 {
682         int result;
683         u64 ppe_id;
684
685         lv1_get_logical_ppe_id(&ppe_id);
686         *rm_base = 0;
687         result = ps3_repository_read_rm_size(ppe_id, rm_size);
688         return result ? result
689                 : ps3_repository_read_region_total(region_total);
690 }
691
692 /**
693  * ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
694  * @num_spu: Number of physical spus.
695  */
696
697 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
698 {
699         int result;
700         u64 v1;
701
702         result = read_node(PS3_LPAR_ID_CURRENT,
703                 make_first_field("bi", 0),
704                 make_field("spun", 0),
705                 0, 0,
706                 &v1, 0);
707         *num_spu_reserved = v1;
708         return result;
709 }
710
711 /**
712  * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations.
713  * @num_resource_id: Number of spu resource ids.
714  */
715
716 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
717 {
718         int result;
719         u64 v1;
720
721         result = read_node(PS3_LPAR_ID_CURRENT,
722                 make_first_field("bi", 0),
723                 make_field("spursvn", 0),
724                 0, 0,
725                 &v1, 0);
726         *num_resource_id = v1;
727         return result;
728 }
729
730 /**
731  * ps3_repository_read_spu_resource_id - spu resource reservation id value.
732  * @res_index: Resource reservation index.
733  * @resource_type: Resource reservation type.
734  * @resource_id: Resource reservation id.
735  */
736
737 int ps3_repository_read_spu_resource_id(unsigned int res_index,
738         enum ps3_spu_resource_type* resource_type, unsigned int *resource_id)
739 {
740         int result;
741         u64 v1;
742         u64 v2;
743
744         result = read_node(PS3_LPAR_ID_CURRENT,
745                 make_first_field("bi", 0),
746                 make_field("spursv", 0),
747                 res_index,
748                 0,
749                 &v1, &v2);
750         *resource_type = v1;
751         *resource_id = v2;
752         return result;
753 }
754
755 int ps3_repository_read_boot_dat_address(u64 *address)
756 {
757         return read_node(PS3_LPAR_ID_CURRENT,
758                 make_first_field("bi", 0),
759                 make_field("boot_dat", 0),
760                 make_field("address", 0),
761                 0,
762                 address, 0);
763 }
764
765 int ps3_repository_read_boot_dat_size(unsigned int *size)
766 {
767         int result;
768         u64 v1;
769
770         result = read_node(PS3_LPAR_ID_CURRENT,
771                 make_first_field("bi", 0),
772                 make_field("boot_dat", 0),
773                 make_field("size", 0),
774                 0,
775                 &v1, 0);
776         *size = v1;
777         return result;
778 }
779
780 /**
781   * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
782   * address: lpar address of cell_ext_os_area
783   * @size: size of cell_ext_os_area
784   */
785
786 int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
787 {
788         int result;
789
790         *size = 0;
791         result = ps3_repository_read_boot_dat_address(lpar_addr);
792         return result ? result
793                 : ps3_repository_read_boot_dat_size(size);
794 }
795
796 int ps3_repository_read_num_be(unsigned int *num_be)
797 {
798         int result;
799         u64 v1;
800
801         result = read_node(PS3_LPAR_ID_PME,
802                 make_first_field("ben", 0),
803                 0,
804                 0,
805                 0,
806                 &v1, 0);
807         *num_be = v1;
808         return result;
809 }
810
811 int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
812 {
813         return read_node(PS3_LPAR_ID_PME,
814                 make_first_field("be", be_index),
815                 0,
816                 0,
817                 0,
818                 node_id, 0);
819 }
820
821 int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
822 {
823         return read_node(PS3_LPAR_ID_PME,
824                 make_first_field("be", 0),
825                 node_id,
826                 make_field("clock", 0),
827                 0,
828                 tb_freq, 0);
829 }
830
831 int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
832 {
833         int result;
834         u64 node_id;
835
836         *tb_freq = 0;
837         result = ps3_repository_read_be_node_id(0, &node_id);
838         return result ? result
839                 : ps3_repository_read_tb_freq(node_id, tb_freq);
840 }