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