1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 /*
28 * This plugin creates memory configuration nodes and properties in the
29 * PICL tree for Grover/Grover+ platform.
30 *
31 * Subtree of memory-controller in the physical aspect.
32 * memory-controller --- memory-module
33 * However, there is no memory controller node on Grover. Thus we need to
34 * create it under platform.
35 *
36 * Subtree of memory in the logical aspect.
37 * memory --- memory-segment
38 * Add property _memory-module_ at memory-segment referring to the
39 * memory-module since memory-segment equals to memory-module on Grover.
40 *
41 * Undo strategy:
42 * Create all nodes and properties, or none if it fails in physical and
43 * logical memory tree respectively. It keeps on creating logical
44 * memory tree although it falis on physical logical tree, but no link to
45 * memory module.
46 *
47 * NOTE:
48 * It depends on PICL devtree plugin.
49 */
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <alloca.h>
55 #include <syslog.h>
56 #include <string.h>
57 #include <libintl.h>
58 #include <picl.h>
59 #include <picltree.h>
60 #include <sys/types.h>
61 #include <sys/obpdefs.h>
62 #include "piclmemcfg.h"
63 #include "memcfg_impl.h"
64
65 static void piclmemcfg_register(void);
66 static void piclmemcfg_init(void);
67 static void piclmemcfg_fini(void);
68
69 #pragma init(piclmemcfg_register)
70
71 static picld_plugin_reg_t my_reg_info = {
72 PICLD_PLUGIN_VERSION_1,
73 PICLD_PLUGIN_NON_CRITICAL,
74 "SUNW_piclmemcfg",
75 piclmemcfg_init,
76 piclmemcfg_fini
77 };
78
79 /*
80 * Create logical memory tree
81 * memory --- memory-segment
82 */
83 static int
create_logical_tree(picl_nodehdl_t memh,mmodinfo_t * mmodinfo)84 create_logical_tree(picl_nodehdl_t memh, mmodinfo_t *mmodinfo)
85 {
86 picl_nodehdl_t msegh;
87 picl_nodehdl_t *memsegh;
88 ptree_propinfo_t propinfo;
89 uint32_t ifactor = INTERLEAVEFACTOR;
90 int i;
91 int err = PICL_SUCCESS;
92
93 if ((memsegh = alloca(sizeof (picl_nodehdl_t) * TOTAL_MEM_SLOTS)) ==
94 NULL)
95 return (PICL_FAILURE);
96
97 for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
98 /*
99 * It means no segment for the slot if size is zero
100 */
101 if (mmodinfo[i].size == 0) {
102 memsegh[i] = 0;
103 continue;
104 }
105
106 /*
107 * Create memory-segment node under memory
108 */
109 err = ptree_create_and_add_node(memh, PICL_NAME_MEMORY_SEGMENT,
110 PICL_CLASS_MEMORY_SEGMENT, &msegh);
111 if (err != PICL_SUCCESS)
112 break;
113
114 /*
115 * For undo easily later
116 */
117 memsegh[i] = msegh;
118
119 /*
120 * Add property, Size to memory-segment node
121 */
122 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
123 PICL_PTYPE_UNSIGNED_INT, PICL_READ,
124 sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL);
125 if (err != PICL_SUCCESS)
126 break;
127
128 err = ptree_create_and_add_prop(msegh, &propinfo,
129 &mmodinfo[i].size, NULL);
130 if (err != PICL_SUCCESS)
131 break;
132
133 /*
134 * Add property, BaseAddress to memory-segment node
135 */
136 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
137 PICL_PTYPE_UNSIGNED_INT, PICL_READ,
138 sizeof (mmodinfo[i].base), PICL_PROP_BASEADDRESS, NULL,
139 NULL);
140 if (err != PICL_SUCCESS)
141 break;
142
143 err = ptree_create_and_add_prop(msegh, &propinfo,
144 &mmodinfo[i].base, NULL);
145 if (err != PICL_SUCCESS)
146 break;
147
148 /*
149 * Add property, InterleaveFactor to memory-segment node
150 */
151 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
152 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (ifactor),
153 PICL_PROP_INTERLEAVE_FACTOR, NULL, NULL);
154 if (err != PICL_SUCCESS)
155 break;
156
157 err = ptree_create_and_add_prop(msegh, &propinfo, &ifactor,
158 NULL);
159 if (err != PICL_SUCCESS)
160 break;
161
162 /*
163 * Add reference property to the memory module if memory
164 * module node handle is not NULL.
165 */
166 if (mmodinfo[i].memmodh == 0)
167 continue;
168
169 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
170 PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
171 PICL_REFPROP_MEMORY_MODULE, NULL, NULL);
172 if (err != PICL_SUCCESS)
173 break;
174
175 err = ptree_create_and_add_prop(msegh, &propinfo,
176 &mmodinfo[i].memmodh, NULL);
177 if (err != PICL_SUCCESS)
178 break;
179 }
180
181 if (err != PICL_SUCCESS) {
182 /*
183 * Undo in the logical memory tree
184 */
185 for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
186 if (memsegh[i] == 0)
187 continue;
188
189 (void) ptree_delete_node(memsegh[i]);
190 (void) ptree_destroy_node(memsegh[i]);
191 }
192 }
193
194 return (err);
195 }
196
197 /*
198 * Create physical memory tree
199 * memory-controller --- memory-module
200 */
201 static int
create_physical_tree(picl_nodehdl_t plfh,mmodinfo_t * mmodinfo)202 create_physical_tree(picl_nodehdl_t plfh, mmodinfo_t *mmodinfo)
203 {
204 picl_nodehdl_t mch, memmodh;
205 ptree_propinfo_t propinfo;
206 int i;
207 int err = PICL_SUCCESS;
208 uint32_t id;
209
210 /*
211 * Create memory-controller node under platform
212 */
213 err = ptree_create_and_add_node(plfh, PICL_NAME_MEMORY_CONTROLLER,
214 PICL_CLASS_MEMORY_CONTROLLER, &mch);
215 if (err != PICL_SUCCESS)
216 return (err);
217
218 /*
219 * Create memory-module nodes and properties
220 * Get all memory modules with dimm
221 */
222 for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
223 /*
224 * It means no dimm on the slot if size is zero
225 */
226 if (mmodinfo[i].size == 0)
227 continue;
228
229 /* Create memory-module node under memory-controller */
230 err = ptree_create_and_add_node(mch, PICL_NAME_MEMORY_MODULE,
231 PICL_CLASS_MEMORY_MODULE, &memmodh);
232 if (err != PICL_SUCCESS)
233 break;
234
235 /*
236 * Update memory module node handle at mmodinfo
237 */
238 mmodinfo[i].memmodh = memmodh;
239
240 /*
241 * Add property, Size to memory-module node
242 */
243 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
244 PICL_PTYPE_UNSIGNED_INT, PICL_READ,
245 sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL);
246 if (err != PICL_SUCCESS)
247 break;
248
249 err = ptree_create_and_add_prop(memmodh, &propinfo,
250 &mmodinfo[i].size, NULL);
251 if (err != PICL_SUCCESS)
252 break;
253
254 /*
255 * Add property, ID to memory-module node
256 */
257 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
258 PICL_PTYPE_INT, PICL_READ, sizeof (id), PICL_PROP_ID,
259 NULL, NULL);
260 if (err != PICL_SUCCESS)
261 break;
262
263 id = i;
264 err = ptree_create_and_add_prop(memmodh, &propinfo, &id, NULL);
265 if (err != PICL_SUCCESS)
266 break;
267 }
268
269 if (err != PICL_SUCCESS) {
270 /*
271 * Clear out the saved memory module node handle so that
272 * logical memory tree won't link to memory module.
273 */
274 for (i = 0; i < TOTAL_MEM_SLOTS; i++)
275 mmodinfo[i].memmodh = 0;
276
277 /*
278 * Undo in the physical memory tree
279 */
280 (void) ptree_delete_node(mch);
281 (void) ptree_destroy_node(mch);
282 }
283
284 return (err);
285 }
286
287 /*
288 * Get the memory module and memory segment information from
289 * property reg of memory node.
290 *
291 * mmodinfo will be updated. Also, the pointers to mseginfo and
292 * the number of segments will be passed to the caller.
293 */
294 static int
get_reg_info(picl_nodehdl_t plfh,picl_nodehdl_t memh,mmodinfo_t * mmodinfo)295 get_reg_info(picl_nodehdl_t plfh, picl_nodehdl_t memh,
296 mmodinfo_t *mmodinfo)
297 {
298 picl_prophdl_t proph;
299 ptree_propinfo_t pinfo;
300 regspec_t *memspec;
301 int i, err;
302 int pval;
303 int nregspec;
304
305
306 /*
307 * Check if the #size-cells of the platform node is 2
308 */
309 err = ptree_get_propval_by_name(plfh, OBP_PROP_SIZE_CELLS, &pval,
310 sizeof (pval));
311
312 if (err == PICL_PROPNOTFOUND)
313 pval = SUPPORTED_NUM_CELL_SIZE;
314 else if (err != PICL_SUCCESS)
315 return (err);
316
317 /*
318 * don't know to handle other vals
319 */
320 if (pval != SUPPORTED_NUM_CELL_SIZE)
321 return (PICL_FAILURE);
322
323 /*
324 * Get property reg of memory node
325 */
326 err = ptree_get_prop_by_name(memh, OBP_REG, &proph);
327 if (err != PICL_SUCCESS)
328 return (err);
329
330 err = ptree_get_propinfo(proph, &pinfo);
331 if (err != PICL_SUCCESS)
332 return (err);
333
334 if ((memspec = alloca(pinfo.piclinfo.size)) == NULL)
335 return (PICL_FAILURE);
336
337 nregspec = pinfo.piclinfo.size / sizeof (*memspec);
338
339 if ((nregspec == 0) || (nregspec > TOTAL_MEM_SLOTS))
340 return (PICL_FAILURE);
341
342 err = ptree_get_propval(proph, memspec, pinfo.piclinfo.size);
343 if (err != PICL_SUCCESS)
344 return (err);
345
346
347 for (i = 0; i < nregspec; i++) {
348
349 mmodinfo[i].base = memspec[i].physaddr;
350 mmodinfo[i].size = memspec[i].size;
351
352 }
353
354 return (PICL_SUCCESS);
355 }
356
357 /*
358 * executed as part of .init when the plugin is dlopen()ed
359 */
360 static void
piclmemcfg_register(void)361 piclmemcfg_register(void)
362 {
363 (void) picld_plugin_register(&my_reg_info);
364 }
365
366 /*
367 * Init entry point of the plugin
368 * Creates the PICL nodes and properties in the physical and logical aspects.
369 */
370 static void
piclmemcfg_init(void)371 piclmemcfg_init(void)
372 {
373 picl_nodehdl_t plfh, memh;
374 mmodinfo_t mmodinfo[TOTAL_MEM_SLOTS];
375
376 /*
377 * Get platform node
378 */
379 if ((ptree_get_node_by_path(PLATFORM_PATH, &plfh)) != PICL_SUCCESS) {
380 syslog(LOG_ERR, EM_INIT_FAILED);
381 return;
382 }
383
384 /*
385 * Find the memory node
386 */
387 if ((ptree_get_node_by_path(MEMORY_PATH, &memh)) != PICL_SUCCESS) {
388 syslog(LOG_ERR, EM_INIT_FAILED);
389 return;
390 }
391
392 /*
393 * Initialize the mmodinfo and get segment information from reg
394 */
395 (void) memset(mmodinfo, 0, sizeof (mmodinfo));
396
397 if ((get_reg_info(plfh, memh, mmodinfo)) != PICL_SUCCESS) {
398 syslog(LOG_ERR, EM_INIT_FAILED);
399 return;
400 }
401
402 /*
403 * Create subtree of memory-controller in the physical aspect.
404 * memory-controller --- memory-module
405 */
406 if ((create_physical_tree(plfh, mmodinfo)) != PICL_SUCCESS)
407 syslog(LOG_ERR, EM_PHYSIC_MEM_TREE_FAILED);
408
409 /*
410 * Create subtree of memory in the logical aspect.
411 * memory --- memory-segment
412 */
413 if ((create_logical_tree(memh, mmodinfo)) != PICL_SUCCESS)
414 syslog(LOG_ERR, EM_LOGIC_MEM_TREE_FAILED);
415 }
416
417 /*
418 * fini entry point of the plugin
419 */
420 static void
piclmemcfg_fini(void)421 piclmemcfg_fini(void)
422 {
423 }
424