dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / picl / plugins / sun4u / daktari / frutree / piclfrutree.c
blobd9a2264f394059d65c53669d7cbc2f7891779166
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * PICL plug-in that creates the FRU Hierarchy for the
31 * SUNW,Sun-Fire-880 (Daktari) platform
34 #include <stdio.h>
35 #include <string.h>
36 #include <libintl.h>
37 #include <libnvpair.h>
38 #include <syslog.h>
39 #include <picl.h>
40 #include <picltree.h>
41 #include <picldefs.h>
44 * Plugin registration entry points
46 static void picl_frutree_register(void);
47 static void picl_frutree_init(void);
48 static void picl_frutree_fini(void);
49 static void picl_frutree_evhandler(const char *ename, const void *earg,
50 size_t size, void *cookie);
52 #pragma init(picl_frutree_register)
55 * Log message texts
57 #define CREATE_FRUTREE_FAIL gettext("Failed to create frutree node\n")
58 #define CREATE_CHASSIS_FAIL gettext("Failed to create chassis node\n")
59 #define IOBRD_INIT_FAIL gettext("do_ioboard_init() failed\n")
60 #define RSCBRD_INIT_FAIL gettext("do_rscboard_init() failed\n")
61 #define FCAL_INIT_FAIL gettext("do_fcal_init() failed\n")
62 #define PS_INIT_FAIL gettext("do_power_supplies_init() failed\n")
63 #define SYSBOARD_INIT_FAIL gettext("do_motherboard_init() failed\n")
66 * Viewpoints property field used by SunMC
68 #define CHASSIS_VIEWPOINTS gettext("front left right rear")
71 * Ref prop values
73 #define SEEPROM_SOURCE "_seeprom_source"
74 #define FRU_PARENT "_fru_parent"
77 * List of all the FRU locations in the platform_frupath[] array, and
78 * location_label[] array
80 #define IOBRD 0
81 #define RSC 1
82 #define FCAL0 2
83 #define FCAL1 3
84 #define FCALGBIC 4
85 #define PDB 5
86 #define PS0 6
87 #define PS1 7
88 #define PS2 8
89 #define SYSBRD 9
90 #define CPUMOD0 10
91 #define CPUMOD1 11
92 #define CPUMOD2 12
93 #define CPUMOD3 13
94 #define CPU0_DIMM0 14
95 #define DIMMS_PER_MOD 8
96 #define DIMMS_PER_SLOT 16
100 * Local variables
102 static picld_plugin_reg_t my_reg_info = {
103 PICLD_PLUGIN_VERSION_1,
104 PICLD_PLUGIN_NON_CRITICAL,
105 "SUNW_Sun-Fire-880_frutree",
106 picl_frutree_init,
107 picl_frutree_fini
111 * List of all the FRUs in the /platform tree with SEEPROMs
113 static char *platform_frupath[] = {
114 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,aa", /* IO */
115 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6", /* RSC */
116 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a8", /* FCAL 0 */
117 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ac", /* FCAL 1 */
118 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,aa", /* FCAL-GBIC */
119 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ae", /* PDB */
120 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a0", /* PS 0 */
121 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a2", /* PS 1 */
122 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a4", /* PS 2 */
123 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a8", /* SYS BRD */
124 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0", /* CPU MOD 0 */
125 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2", /* CPU MOD 1 */
126 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a4", /* CPU MOD 2 */
127 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a6", /* CPU MOD 3 */
128 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0", /* CPU0 DIMM0 */
129 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2", /* CPU0 DIMM1 */
130 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4", /* CPU0 DIMM2 */
131 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6", /* CPU0 DIMM3 */
132 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8", /* CPU0 DIMM4 */
133 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa", /* CPU0 DIMM5 */
134 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac", /* CPU0 DIMM6 */
135 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae", /* CPU0 DIMM7 */
136 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0", /* CPU2 DIMM0 */
137 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2", /* CPU2 DIMM1 */
138 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4", /* CPU2 DIMM2 */
139 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6", /* CPU2 DIMM3 */
140 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8", /* CPU2 DIMM4 */
141 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa", /* CPU2 DIMM5 */
142 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac", /* CPU2 DIMM6 */
143 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae", /* CPU2 DIMM7 */
144 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0", /* CPU1 DIMM0 */
145 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2", /* CPU1 DIMM1 */
146 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4", /* CPU1 DIMM2 */
147 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6", /* CPU1 DIMM3 */
148 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8", /* CPU1 DIMM4 */
149 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa", /* CPU1 DIMM5 */
150 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac", /* CPU1 DIMM6 */
151 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae", /* CPU1 DIMM7 */
152 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0", /* CPU3 DIMM0 */
153 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2", /* CPU3 DIMM1 */
154 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4", /* CPU3 DIMM2 */
155 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6", /* CPU3 DIMM3 */
156 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8", /* CPU3 DIMM4 */
157 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa", /* CPU3 DIMM5 */
158 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac", /* CPU3 DIMM6 */
159 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae", /* CPU3 DIMM7 */
160 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a0", /* CPU4 DIMM0 */
161 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a2", /* CPU4 DIMM1 */
162 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a4", /* CPU4 DIMM2 */
163 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a6", /* CPU4 DIMM3 */
164 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a8", /* CPU4 DIMM4 */
165 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,aa", /* CPU4 DIMM5 */
166 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ac", /* CPU4 DIMM6 */
167 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ae", /* CPU4 DIMM7 */
168 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a0", /* CPU6 DIMM0 */
169 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a2", /* CPU6 DIMM1 */
170 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a4", /* CPU6 DIMM2 */
171 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a6", /* CPU6 DIMM3 */
172 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a8", /* CPU6 DIMM4 */
173 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,aa", /* CPU6 DIMM5 */
174 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ac", /* CPU6 DIMM6 */
175 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ae", /* CPU6 DIMM7 */
176 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a0", /* CPU5 DIMM0 */
177 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a2", /* CPU5 DIMM1 */
178 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a4", /* CPU5 DIMM2 */
179 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a6", /* CPU5 DIMM3 */
180 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a8", /* CPU5 DIMM4 */
181 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,aa", /* CPU5 DIMM5 */
182 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ac", /* CPU5 DIMM6 */
183 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ae", /* CPU5 DIMM7 */
184 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a0", /* CPU7 DIMM0 */
185 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a2", /* CPU7 DIMM1 */
186 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a4", /* CPU7 DIMM2 */
187 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a6", /* CPU7 DIMM3 */
188 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a8", /* CPU7 DIMM4 */
189 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,aa", /* CPU7 DIMM5 */
190 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ac", /* CPU7 DIMM6 */
191 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ae", /* CPU7 DIMM7 */
192 NULL};
195 * List of Labels for FRU locations (uses the #define's from above)
197 static char *location_label[] = {
198 NULL, /* IOBRD */
199 NULL, /* RSC */
200 "0", /* FCAL0 */
201 "1", /* FCAL1 */
202 NULL, /* FCALGBIC */
203 NULL, /* PDB */
204 "0", /* PS0 */
205 "1", /* PS1 */
206 "2", /* PS2 */
207 NULL, /* SYSBRD */
208 "A", /* CPUMOD0 */
209 "B", /* CPUMOD1 */
210 "C", /* CPUMOD2 */
211 "D", /* CPUMOD3 */
212 "J2900", /* CPU0 DIMM0 */
213 "J3100", /* CPU0 DIMM1 */
214 "J2901", /* CPU0 DIMM2 */
215 "J3101", /* CPU0 DIMM3 */
216 "J3000", /* CPU0 DIMM4 */
217 "J3200", /* CPU0 DIMM5 */
218 "J3001", /* CPU0 DIMM6 */
219 "J3201", /* CPU0 DIMM7 */
220 "J7900", /* CPU1 DIMM0 */
221 "J8100", /* CPU1 DIMM1 */
222 "J7901", /* CPU1 DIMM2 */
223 "J8101", /* CPU1 DIMM3 */
224 "J8000", /* CPU1 DIMM4 */
225 "J8200", /* CPU1 DIMM5 */
226 "J8001", /* CPU1 DIMM6 */
227 "J8201", /* CPU1 DIMM7 */
228 "0", /* CPU0 label */
229 "1", /* CPU1 label */
230 NULL};
233 * List of all the FRU slots for power supplies (hotpluggable)
235 static char *frutree_power_supply[] = {
236 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=0",
237 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=1",
238 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=2",
239 NULL};
242 * List of all the FRU slots for CPU Memory modules (hotpluggable)
244 static char *frutree_cpu_module[] = {
245 "/frutree/chassis/system-board/cpu-mem-slot?Slot=0",
246 "/frutree/chassis/system-board/cpu-mem-slot?Slot=1",
247 "/frutree/chassis/system-board/cpu-mem-slot?Slot=2",
248 "/frutree/chassis/system-board/cpu-mem-slot?Slot=3",
249 NULL};
251 /* PICL handle for the root node of the "frutree" */
252 static picl_nodehdl_t frutreeh;
254 static int do_ioboard_init(picl_nodehdl_t);
255 static int do_rscboard_init(picl_nodehdl_t);
256 static int do_fcal_init(picl_nodehdl_t);
257 static int do_power_supplies_init(picl_nodehdl_t);
258 static int do_motherboard_init(picl_nodehdl_t);
259 static int do_cpu_module_init(picl_nodehdl_t, int);
260 static int do_dimms_init(picl_nodehdl_t, int, int);
262 static int add_ref_prop(picl_nodehdl_t, picl_nodehdl_t, char *);
263 static int add_slot_prop(picl_nodehdl_t, int);
264 static int add_label_prop(picl_nodehdl_t, char *);
265 static int add_void_fda_prop(picl_nodehdl_t);
266 static int add_viewpoints_prop(picl_nodehdl_t, char *);
267 static int add_all_nodes();
268 static int remove_all_nodes(picl_nodehdl_t);
270 static int add_hotplug_fru_device(void);
271 static int rem_hotplug_fru_device(void);
272 static int is_added_device(char *, char *);
273 static int is_removed_device(char *, char *);
274 static int add_power_supply(int);
275 static int remove_power_supply(int);
276 static int add_cpu_module(int);
277 static int remove_cpu_module(int);
280 * This function is executed as part of .init when the plugin is
281 * dlopen()ed
283 static void
284 picl_frutree_register()
286 (void) picld_plugin_register(&my_reg_info);
290 * This function is the init entry point of the plugin.
291 * It initializes the /frutree tree
293 static void
294 picl_frutree_init()
296 int err;
298 err = add_all_nodes();
299 if (err != PICL_SUCCESS) {
300 (void) remove_all_nodes(frutreeh);
301 return;
304 /* Register the event handler routine */
305 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
306 picl_frutree_evhandler, NULL);
307 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
308 picl_frutree_evhandler, NULL);
312 * This function is the fini entry point of the plugin
314 static void
315 picl_frutree_fini(void)
317 /* Unregister the event handler routine */
318 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
319 picl_frutree_evhandler, NULL);
320 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
321 picl_frutree_evhandler, NULL);
323 (void) remove_all_nodes(frutreeh);
327 * This function is the event handler of this plug-in.
329 * It processes the following events:
331 * PICLEVENT_SYSEVENT_DEVICE_ADDED
332 * PICLEVENT_SYSEVENT_DEVICE_REMOVED
334 /* ARGSUSED */
335 static void
336 picl_frutree_evhandler(const char *ename, const void *earg, size_t size,
337 void *cookie)
339 if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
340 /* Check for and add any hotplugged device(s) */
341 (void) add_hotplug_fru_device();
343 } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
344 /* Check for and remove any hotplugged device(s) */
345 (void) rem_hotplug_fru_device();
349 /* Initializes the FRU nodes for the IO board */
350 static int
351 do_ioboard_init(picl_nodehdl_t rooth)
353 picl_nodehdl_t iobrdh;
354 picl_nodehdl_t tmph;
355 int err;
357 /* Create the node for the IO board (if it exists) */
358 if (ptree_get_node_by_path(platform_frupath[IOBRD], &tmph) ==
359 PICL_SUCCESS) {
360 err = ptree_create_node("io-board", "fru", &iobrdh);
361 if (err != PICL_SUCCESS)
362 return (err);
364 err = add_ref_prop(iobrdh, tmph, SEEPROM_SOURCE);
365 if (err != PICL_SUCCESS)
366 return (err);
368 err = add_void_fda_prop(iobrdh);
369 if (err != PICL_SUCCESS)
370 return (err);
372 err = ptree_add_node(rooth, iobrdh);
373 if (err != PICL_SUCCESS)
374 return (err);
376 err = add_ref_prop(tmph, iobrdh, FRU_PARENT);
377 if (err != PICL_SUCCESS)
378 return (err);
380 return (PICL_SUCCESS);
383 /* Initializes the FRU node for the RSC card */
384 static int
385 do_rscboard_init(picl_nodehdl_t rooth)
387 picl_nodehdl_t rscbrdh;
388 picl_nodehdl_t tmph;
389 int err;
391 /* Create the node for the RSC board (if it exists) */
392 if (ptree_get_node_by_path(platform_frupath[RSC], &tmph) ==
393 PICL_SUCCESS) {
394 err = ptree_create_node("rsc-board", "fru", &rscbrdh);
395 if (err != PICL_SUCCESS)
396 return (err);
398 err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE);
399 if (err != PICL_SUCCESS)
400 return (err);
402 err = add_void_fda_prop(rscbrdh);
403 if (err != PICL_SUCCESS)
404 return (err);
406 err = ptree_add_node(rooth, rscbrdh);
407 if (err != PICL_SUCCESS)
408 return (err);
410 err = add_ref_prop(tmph, rscbrdh, FRU_PARENT);
411 if (err != PICL_SUCCESS)
412 return (err);
414 return (PICL_SUCCESS);
417 /* Initializes the FRU nodes for the FCAL backplanes and GBIC card */
418 static int
419 do_fcal_init(picl_nodehdl_t rooth)
421 picl_nodehdl_t fcalsloth;
422 picl_nodehdl_t fcalmodh;
423 picl_nodehdl_t fcalgbich;
424 picl_nodehdl_t tmph;
425 int i, err, slotnum;
427 for (i = FCAL0; i <= FCAL1; i++) {
428 /* Create the node for the FCAL backplane slot */
429 err = ptree_create_node("fcal-backplane-slot",
430 "location", &fcalsloth);
431 if (err != PICL_SUCCESS)
432 return (err);
434 slotnum = i - FCAL0;
435 err = add_slot_prop(fcalsloth, slotnum);
436 if (err != PICL_SUCCESS)
437 return (err);
439 err = add_label_prop(fcalsloth, location_label[i]);
440 if (err != PICL_SUCCESS)
441 return (err);
443 err = ptree_add_node(rooth, fcalsloth);
444 if (err != PICL_SUCCESS)
445 return (err);
447 /* If the FCAL backplane exists, create a node for it */
448 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
449 PICL_SUCCESS) {
450 err = ptree_create_node("fcal-backplane", "fru",
451 &fcalmodh);
452 if (err != PICL_SUCCESS)
453 return (err);
455 err = add_ref_prop(fcalmodh, tmph, SEEPROM_SOURCE);
456 if (err != PICL_SUCCESS)
457 return (err);
459 err = add_void_fda_prop(fcalmodh);
460 if (err != PICL_SUCCESS)
461 return (err);
463 err = ptree_add_node(fcalsloth, fcalmodh);
464 if (err != PICL_SUCCESS)
465 return (err);
467 err = add_ref_prop(tmph, fcalmodh, FRU_PARENT);
468 if (err != PICL_SUCCESS)
469 return (err);
473 /* If the FCAL GBIC board exists, create a node for it */
474 if (ptree_get_node_by_path(platform_frupath[FCALGBIC], &tmph) ==
475 PICL_SUCCESS) {
476 err = ptree_create_node("fcal-gbic-board", "fru",
477 &fcalgbich);
478 if (err != PICL_SUCCESS)
479 return (err);
481 err = add_ref_prop(fcalgbich, tmph, SEEPROM_SOURCE);
482 if (err != PICL_SUCCESS)
483 return (err);
485 err = add_void_fda_prop(fcalgbich);
486 if (err != PICL_SUCCESS)
487 return (err);
489 err = ptree_add_node(rooth, fcalgbich);
490 if (err != PICL_SUCCESS)
491 return (err);
493 err = add_ref_prop(tmph, fcalgbich, FRU_PARENT);
494 if (err != PICL_SUCCESS)
495 return (err);
497 return (PICL_SUCCESS);
500 /* Initializes the FRU nodes for the PDB and the power supplies */
501 static int
502 do_power_supplies_init(picl_nodehdl_t rooth)
504 picl_nodehdl_t powerbrdh;
505 picl_nodehdl_t powersloth;
506 picl_nodehdl_t powermodh;
507 picl_nodehdl_t tmph;
508 int i, err, slotnum;
510 /* Create the node for the PDB (if it exists) */
511 if (ptree_get_node_by_path(platform_frupath[PDB], &tmph) ==
512 PICL_SUCCESS) {
513 err = ptree_create_node("power-dist-board", "fru", &powerbrdh);
514 if (err != PICL_SUCCESS)
515 return (err);
517 err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE);
518 if (err != PICL_SUCCESS)
519 return (err);
521 err = add_void_fda_prop(powerbrdh);
522 if (err != PICL_SUCCESS)
523 return (err);
525 err = ptree_add_node(rooth, powerbrdh);
526 if (err != PICL_SUCCESS)
527 return (err);
529 err = add_ref_prop(tmph, powerbrdh, FRU_PARENT);
530 if (err != PICL_SUCCESS)
531 return (err);
533 for (i = PS0; i <= PS2; i++) {
534 /* Create the node for the power supply slot */
535 err = ptree_create_node("power-supply-slot",
536 "location", &powersloth);
537 if (err != PICL_SUCCESS)
538 return (err);
540 slotnum = i - PS0;
541 err = add_slot_prop(powersloth, slotnum);
542 if (err != PICL_SUCCESS)
543 return (err);
545 err = add_label_prop(powersloth, location_label[i]);
546 if (err != PICL_SUCCESS)
547 return (err);
549 err = ptree_add_node(powerbrdh, powersloth);
550 if (err != PICL_SUCCESS)
551 return (err);
553 /* If the PS exists, create a node for it */
554 if (ptree_get_node_by_path(platform_frupath[i],
555 &tmph) == PICL_SUCCESS) {
556 err = ptree_create_node("power-supply",
557 "fru", &powermodh);
558 if (err != PICL_SUCCESS)
559 return (err);
561 err = add_ref_prop(powermodh, tmph,
562 SEEPROM_SOURCE);
563 if (err != PICL_SUCCESS)
564 return (err);
566 err = add_void_fda_prop(powermodh);
567 if (err != PICL_SUCCESS)
568 return (err);
570 err = ptree_add_node(powersloth, powermodh);
571 if (err != PICL_SUCCESS)
572 return (err);
574 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
575 if (err != PICL_SUCCESS)
576 return (err);
580 return (PICL_SUCCESS);
583 /* Initializes the FRU nodes for the motherboard and CPU Memory modules */
584 static int
585 do_motherboard_init(picl_nodehdl_t rooth)
587 picl_nodehdl_t sysboardh;
588 picl_nodehdl_t cpumemsloth;
589 picl_nodehdl_t cpumemmodh;
590 picl_nodehdl_t tmph;
591 int i, err, slotnum;
593 /* Create the node for the system board (if it exists) */
594 if (ptree_get_node_by_path(platform_frupath[SYSBRD], &tmph) ==
595 PICL_SUCCESS) {
596 err = ptree_create_node("system-board", "fru",
597 &sysboardh);
598 if (err != PICL_SUCCESS)
599 return (err);
601 err = add_ref_prop(sysboardh, tmph, SEEPROM_SOURCE);
602 if (err != PICL_SUCCESS)
603 return (err);
605 err = add_void_fda_prop(sysboardh);
606 if (err != PICL_SUCCESS)
607 return (err);
609 err = ptree_add_node(rooth, sysboardh);
610 if (err != PICL_SUCCESS)
611 return (err);
613 err = add_ref_prop(tmph, sysboardh, FRU_PARENT);
614 if (err != PICL_SUCCESS)
615 return (err);
617 for (i = CPUMOD0; i <= CPUMOD3; i++) {
618 /* Create the node for the CPU Memory slot */
619 err = ptree_create_node("cpu-mem-slot", "location",
620 &cpumemsloth);
621 if (err != PICL_SUCCESS)
622 return (err);
624 slotnum = i - CPUMOD0;
625 err = add_slot_prop(cpumemsloth, slotnum);
626 if (err != PICL_SUCCESS)
627 return (err);
629 err = add_label_prop(cpumemsloth, location_label[i]);
630 if (err != PICL_SUCCESS)
631 return (err);
633 err = ptree_add_node(sysboardh, cpumemsloth);
634 if (err != PICL_SUCCESS)
635 return (err);
637 /* If CPU Mem module exists, create a node for it */
638 if (ptree_get_node_by_path(platform_frupath[i],
639 &tmph) == PICL_SUCCESS) {
640 err = ptree_create_node("cpu-mem-module",
641 "fru", &cpumemmodh);
642 if (err != PICL_SUCCESS)
643 return (err);
645 err = add_ref_prop(cpumemmodh, tmph,
646 SEEPROM_SOURCE);
647 if (err != PICL_SUCCESS)
648 return (err);
650 err = add_void_fda_prop(cpumemmodh);
651 if (err != PICL_SUCCESS)
652 return (err);
654 err = ptree_add_node(cpumemsloth, cpumemmodh);
655 if (err != PICL_SUCCESS)
656 return (err);
658 err = add_ref_prop(tmph, cpumemmodh,
659 FRU_PARENT);
660 if (err != PICL_SUCCESS)
661 return (err);
663 err = do_cpu_module_init(cpumemmodh, slotnum);
664 if (err != PICL_SUCCESS)
665 return (err);
669 return (PICL_SUCCESS);
672 /* Creates the FRU nodes for the CPU Module and associated DIMMs */
673 static int
674 do_cpu_module_init(picl_nodehdl_t rooth, int slot)
676 picl_nodehdl_t cpumodh;
677 int i, c, err;
679 for (i = 0; i <= 1; i++) {
680 err = ptree_create_node("cpu-module", "location",
681 &cpumodh);
682 if (err != PICL_SUCCESS)
683 return (err);
685 err = add_slot_prop(cpumodh, i);
686 if (err != PICL_SUCCESS)
687 return (err);
689 c = CPU0_DIMM0 + DIMMS_PER_SLOT + i;
691 err = add_label_prop(cpumodh, location_label[c]);
692 if (err != PICL_SUCCESS)
693 return (err);
695 err = ptree_add_node(rooth, cpumodh);
696 if (err != PICL_SUCCESS)
697 return (err);
699 /* Create the nodes for the memory (if they exist) */
700 err = do_dimms_init(cpumodh, slot, i);
701 if (err != PICL_SUCCESS)
702 return (err);
704 return (PICL_SUCCESS);
707 /* Creates the FRU nodes for the DIMMs on a particular CPU Module */
708 static int
709 do_dimms_init(picl_nodehdl_t rooth, int slot, int module)
711 picl_nodehdl_t dimmsloth;
712 picl_nodehdl_t dimmmodh;
713 picl_nodehdl_t tmph;
714 int i, c, l, err;
716 for (i = 0; i < DIMMS_PER_MOD; i++) {
717 /* Create the node for the memory slot */
718 err = ptree_create_node("dimm-slot", "location",
719 &dimmsloth);
720 if (err != PICL_SUCCESS)
721 return (err);
723 err = add_slot_prop(dimmsloth, i);
724 if (err != PICL_SUCCESS)
725 return (err);
727 c = ((slot * DIMMS_PER_SLOT) +
728 (module * DIMMS_PER_MOD) + i) + CPU0_DIMM0;
730 l = c - (DIMMS_PER_SLOT * slot);
732 err = add_label_prop(dimmsloth, location_label[l]);
733 if (err != PICL_SUCCESS)
734 return (err);
736 err = ptree_add_node(rooth, dimmsloth);
737 if (err != PICL_SUCCESS)
738 return (err);
740 /* If the memory module exists, create a node for it */
741 if (ptree_get_node_by_path(platform_frupath[c], &tmph) ==
742 PICL_SUCCESS) {
743 err = ptree_create_node("dimm-module", "fru",
744 &dimmmodh);
745 if (err != PICL_SUCCESS)
746 return (err);
748 err = add_ref_prop(dimmmodh, tmph, SEEPROM_SOURCE);
749 if (err != PICL_SUCCESS)
750 return (err);
752 err = add_void_fda_prop(dimmmodh);
753 if (err != PICL_SUCCESS)
754 return (err);
756 err = ptree_add_node(dimmsloth, dimmmodh);
757 if (err != PICL_SUCCESS)
758 return (err);
760 err = add_ref_prop(tmph, dimmmodh, FRU_PARENT);
761 if (err != PICL_SUCCESS)
762 return (err);
765 return (PICL_SUCCESS);
768 /* Creates a "reference" property between two PICL nodes */
769 static int
770 add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str)
772 picl_prophdl_t proph;
773 ptree_propinfo_t propinfo;
774 int err;
776 if (str == NULL)
777 return (PICL_FAILURE);
779 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
780 PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
781 str, NULL, NULL);
782 if (err != PICL_SUCCESS)
783 return (err);
785 err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph);
786 if (err != PICL_SUCCESS)
787 return (err);
789 return (PICL_SUCCESS);
792 /* Creates a "slot" property for a given PICL node */
793 static int
794 add_slot_prop(picl_nodehdl_t nodeh, int slotnum)
796 picl_prophdl_t proph;
797 ptree_propinfo_t propinfo;
798 int err;
800 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
801 PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL);
802 if (err != PICL_SUCCESS)
803 return (err);
805 err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph);
806 if (err != PICL_SUCCESS)
807 return (err);
809 return (PICL_SUCCESS);
812 /* Creates a "Label" property for a given PICL node */
813 static int
814 add_label_prop(picl_nodehdl_t nodeh, char *label)
816 picl_prophdl_t proph;
817 ptree_propinfo_t propinfo;
818 int err;
820 if (label == NULL)
821 return (PICL_FAILURE);
823 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
824 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label",
825 NULL, NULL);
826 if (err != PICL_SUCCESS)
827 return (err);
829 err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph);
830 if (err != PICL_SUCCESS)
831 return (err);
833 return (PICL_SUCCESS);
836 /* Creates a "FRUDataAvailable" void property for the given PICL node */
837 static int
838 add_void_fda_prop(picl_nodehdl_t nodeh)
840 picl_prophdl_t proph;
841 ptree_propinfo_t propinfo;
842 int err;
844 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
845 PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL);
846 if (err != PICL_SUCCESS)
847 return (err);
849 err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
850 if (err != PICL_SUCCESS)
851 return (err);
853 return (PICL_SUCCESS);
856 /* Creates a "ViewPoints" property -- used for chassis */
857 static int
858 add_viewpoints_prop(picl_nodehdl_t nodeh, char *string)
860 picl_prophdl_t proph;
861 ptree_propinfo_t propinfo;
862 int err;
864 if (string == NULL)
865 return (PICL_FAILURE);
867 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
868 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints",
869 NULL, NULL);
870 if (err != PICL_SUCCESS)
871 return (err);
873 err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph);
874 if (err != PICL_SUCCESS)
875 return (err);
877 return (PICL_SUCCESS);
880 /* Creates and adds all of the frutree nodes */
881 static int
882 add_all_nodes()
884 picl_nodehdl_t rooth;
885 picl_nodehdl_t chassish;
886 int err;
888 /* Get the root node of the PICL tree */
889 err = ptree_get_root(&rooth);
890 if (err != PICL_SUCCESS) {
891 return (err);
894 /* Create and add the root node of the FRU subtree */
895 err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh);
896 if (err != PICL_SUCCESS) {
897 syslog(LOG_ERR, CREATE_FRUTREE_FAIL);
898 return (err);
901 /* Create and add the chassis node */
902 err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish);
903 if (err != PICL_SUCCESS) {
904 syslog(LOG_ERR, CREATE_CHASSIS_FAIL);
905 return (err);
908 /* Add ViewPoints prop to chassis node */
909 err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS);
910 if (err != PICL_SUCCESS)
911 return (err);
913 /* Initialize the FRU nodes for the IO board */
914 err = do_ioboard_init(chassish);
915 if (err != PICL_SUCCESS) {
916 syslog(LOG_ERR, IOBRD_INIT_FAIL);
917 return (err);
920 /* Initialize the FRU node for the RSC card */
921 err = do_rscboard_init(chassish);
922 if (err != PICL_SUCCESS) {
923 syslog(LOG_ERR, RSCBRD_INIT_FAIL);
924 return (err);
927 /* Initialize the FRU nodes for the FCAL backplanes and GBIC board */
928 err = do_fcal_init(chassish);
929 if (err != PICL_SUCCESS) {
930 syslog(LOG_ERR, FCAL_INIT_FAIL);
931 return (err);
934 /* Initialize the FRU nodes for the PDB and the power supplies */
935 err = do_power_supplies_init(chassish);
936 if (err != PICL_SUCCESS) {
937 syslog(LOG_ERR, PS_INIT_FAIL);
938 return (err);
941 /* Initialize the FRU nodes for the CPU Memory modules */
942 err = do_motherboard_init(chassish);
943 if (err != PICL_SUCCESS) {
944 syslog(LOG_ERR, SYSBOARD_INIT_FAIL);
945 return (err);
948 return (PICL_SUCCESS);
951 /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
952 static int
953 remove_all_nodes(picl_nodehdl_t rooth)
955 picl_nodehdl_t chdh;
956 int err, done = 0;
958 while (!done) {
959 err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
960 sizeof (picl_nodehdl_t));
961 if (err != PICL_PROPNOTFOUND) {
962 (void) remove_all_nodes(chdh);
963 } else {
964 err = ptree_delete_node(rooth);
965 if (err != PICL_SUCCESS) {
966 return (err);
967 } else {
968 (void) ptree_destroy_node(rooth);
970 done = 1;
973 return (PICL_SUCCESS);
976 /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */
977 static int
978 add_hotplug_fru_device()
980 int i, err, slotnum;
982 /* Check for hotplugged power supplies */
983 for (i = PS0; i <= PS2; i++) {
984 /* Compare the /platform tree to the frutree */
985 slotnum = i - PS0;
986 err = is_added_device(platform_frupath[i],
987 frutree_power_supply[slotnum]);
988 if (err != PICL_SUCCESS)
989 continue;
991 /* If they are different, then add a power supply */
992 err = add_power_supply(slotnum);
993 if (err != PICL_SUCCESS)
994 continue;
997 /* Check for hotplugged CPU Memory modules */
998 for (i = CPUMOD0; i <= CPUMOD3; i++) {
999 /* Compare the /platform tree to the frutree */
1000 slotnum = i - CPUMOD0;
1001 err = is_added_device(platform_frupath[i],
1002 frutree_cpu_module[slotnum]);
1003 if (err != PICL_SUCCESS)
1004 continue;
1006 /* If they are different, then add a CPU Mem module */
1007 err = add_cpu_module(slotnum);
1008 if (err != PICL_SUCCESS)
1009 continue;
1011 return (PICL_SUCCESS);
1014 /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */
1015 static int
1016 rem_hotplug_fru_device()
1018 int i, err, slotnum;
1020 /* Check for hotplugged power supplies */
1021 for (i = PS0; i <= PS2; i++) {
1022 /* Compare the /platform tree to the frutree */
1023 slotnum = i - PS0;
1024 err = is_removed_device(platform_frupath[i],
1025 frutree_power_supply[slotnum]);
1026 if (err != PICL_SUCCESS)
1027 continue;
1029 /* If they are different, then remove a power supply */
1030 err = remove_power_supply(slotnum);
1031 if (err != PICL_SUCCESS)
1032 continue;
1035 /* Check for hotplugged CPU Memory modules */
1036 for (i = CPUMOD0; i <= CPUMOD3; i++) {
1037 /* Compare the /platform tree to the frutree */
1038 slotnum = i - CPUMOD0;
1039 err = is_removed_device(platform_frupath[i],
1040 frutree_cpu_module[slotnum]);
1041 if (err != PICL_SUCCESS)
1042 continue;
1044 /* If they are different, then remove a CPU Mem module */
1045 err = remove_cpu_module(slotnum);
1046 if (err != PICL_SUCCESS)
1047 continue;
1049 return (PICL_SUCCESS);
1053 * Compare the /platform tree to the /frutree to determine if a
1054 * new device has been added
1056 static int
1057 is_added_device(char *plat, char *fru)
1059 int err;
1060 picl_nodehdl_t plath, frusloth, frumodh;
1062 /* Check for node in the /platform tree */
1063 err = ptree_get_node_by_path(plat, &plath);
1064 if (err != PICL_SUCCESS)
1065 return (err);
1068 * The node is in /platform, so find the corresponding slot in
1069 * the frutree
1071 err = ptree_get_node_by_path(fru, &frusloth);
1072 if (err != PICL_SUCCESS)
1073 return (err);
1076 * If the slot in the frutree has a child, then return
1077 * PICL_FAILURE. This means that the /platform tree and
1078 * the frutree are consistent and no action is necessary.
1079 * Otherwise return PICL_SUCCESS to indicate that a node needs
1080 * to be added to the frutree
1082 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
1083 &frumodh, sizeof (picl_nodehdl_t));
1084 if (err == PICL_SUCCESS)
1085 return (PICL_FAILURE);
1087 return (PICL_SUCCESS);
1091 * Compare the /platform tree to the /frutree to determine if a
1092 * device has been removed
1094 static int
1095 is_removed_device(char *plat, char *fru)
1097 int err;
1098 picl_nodehdl_t plath, frusloth, frumodh;
1101 /* Check for node in /platform tree */
1102 err = ptree_get_node_by_path(plat, &plath);
1103 if (err == PICL_SUCCESS)
1104 return (PICL_FAILURE);
1107 * The node is not in /platform, so find the corresponding slot in
1108 * the frutree
1110 err = ptree_get_node_by_path(fru, &frusloth);
1111 if (err != PICL_SUCCESS)
1112 return (err);
1115 * If the slot in the frutree does not have a child, then return
1116 * PICL_FAILURE. This means that the /platform tree and
1117 * the frutree are consistent and no action is necessary.
1118 * Otherwise return PICL_SUCCESS to indicate that the needs
1119 * to be removed from the frutree
1121 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
1122 &frumodh, sizeof (picl_nodehdl_t));
1123 if (err != PICL_SUCCESS)
1124 return (err);
1126 return (PICL_SUCCESS);
1129 static int
1130 remove_picl_node(picl_nodehdl_t nodeh)
1132 int err;
1133 err = ptree_delete_node(nodeh);
1134 if (err != PICL_SUCCESS)
1135 return (err);
1136 (void) ptree_destroy_node(nodeh);
1137 return (PICL_SUCCESS);
1140 /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
1141 /*ARGSUSED2*/
1142 static void
1143 frudr_completion_handler(char *ename, void *earg, size_t size)
1145 picl_nodehdl_t fruh;
1147 if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
1149 * now frudata has been notified that the node is to be
1150 * removed, we can actually remove it
1152 fruh = NULL;
1153 (void) nvlist_lookup_uint64(earg,
1154 PICLEVENTARG_FRUHANDLE, &fruh);
1155 if (fruh != NULL) {
1156 (void) remove_picl_node(fruh);
1159 nvlist_free(earg);
1160 free(earg);
1161 free(ename);
1165 * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
1167 static void
1168 post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh)
1170 nvlist_t *nvl;
1171 char *ev_name;
1173 ev_name = strdup(ename);
1174 if (ev_name == NULL)
1175 return;
1176 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) {
1177 free(ev_name);
1178 return;
1180 if (parenth != 0L &&
1181 nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) {
1182 free(ev_name);
1183 nvlist_free(nvl);
1184 return;
1186 if (fruh != 0L &&
1187 nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) {
1188 free(ev_name);
1189 nvlist_free(nvl);
1190 return;
1192 if (ptree_post_event(ev_name, nvl, sizeof (nvl),
1193 frudr_completion_handler) != 0) {
1194 free(ev_name);
1195 nvlist_free(nvl);
1199 /* Hotplug routine used to add a new power supply */
1200 static int
1201 add_power_supply(int slotnum)
1203 picl_nodehdl_t powersloth;
1204 picl_nodehdl_t powermodh;
1205 picl_nodehdl_t tmph;
1206 int i, err;
1208 /* Find the node for the given power supply slot */
1209 if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1210 &powersloth) == PICL_SUCCESS) {
1212 i = slotnum + PS0;
1214 /* Make sure it's in /platform and create the frutree node */
1215 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
1216 PICL_SUCCESS) {
1217 err = ptree_create_node("power-supply", "fru",
1218 &powermodh);
1219 if (err != PICL_SUCCESS)
1220 return (err);
1222 err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE);
1223 if (err != PICL_SUCCESS)
1224 return (err);
1226 err = add_void_fda_prop(powermodh);
1227 if (err != PICL_SUCCESS)
1228 return (err);
1230 err = ptree_add_node(powersloth, powermodh);
1231 if (err != PICL_SUCCESS)
1232 return (err);
1234 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
1235 if (err != PICL_SUCCESS)
1236 return (err);
1238 /* Post picl-fru-added event */
1239 post_frudr_event(PICL_FRU_ADDED, NULL, powermodh);
1242 return (PICL_SUCCESS);
1245 /* Hotplug routine used to remove an existing power supply */
1246 static int
1247 remove_power_supply(int slotnum)
1249 picl_nodehdl_t powersloth;
1250 picl_nodehdl_t powermodh;
1251 int err;
1253 /* Find the node for the given power supply slot */
1254 if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1255 &powersloth) == PICL_SUCCESS) {
1256 /* Make sure it's got a child, then delete it */
1257 err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD,
1258 &powermodh, sizeof (picl_nodehdl_t));
1259 if (err != PICL_SUCCESS) {
1260 return (err);
1263 err = ptree_delete_node(powermodh);
1264 if (err != PICL_SUCCESS) {
1265 return (err);
1266 } else {
1267 (void) ptree_destroy_node(powermodh);
1270 /* Post picl-fru-removed event */
1271 post_frudr_event(PICL_FRU_REMOVED, NULL, powermodh);
1274 return (PICL_SUCCESS);
1277 /* Hotplug routine used to add a new CPU Mem Module (with associated DIMMs) */
1278 static int
1279 add_cpu_module(int slotnum)
1281 picl_nodehdl_t cpumemsloth;
1282 picl_nodehdl_t cpumemmodh;
1283 picl_nodehdl_t tmph;
1284 int i, err;
1286 /* Find the node for the given CPU Memory module slot */
1287 if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
1288 &cpumemsloth) == PICL_SUCCESS) {
1290 i = slotnum + CPUMOD0;
1292 /* Make sure it's in /platform and create the frutree nodes */
1293 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
1294 PICL_SUCCESS) {
1295 err = ptree_create_node("cpu-mem-module", "fru",
1296 &cpumemmodh);
1297 if (err != PICL_SUCCESS)
1298 return (err);
1300 err = add_ref_prop(cpumemmodh, tmph, SEEPROM_SOURCE);
1301 if (err != PICL_SUCCESS)
1302 return (err);
1304 err = add_void_fda_prop(cpumemmodh);
1305 if (err != PICL_SUCCESS)
1306 return (err);
1308 err = ptree_add_node(cpumemsloth, cpumemmodh);
1309 if (err != PICL_SUCCESS)
1310 return (err);
1312 err = add_ref_prop(tmph, cpumemmodh, FRU_PARENT);
1313 if (err != PICL_SUCCESS)
1314 return (err);
1317 err = do_cpu_module_init(cpumemmodh, slotnum);
1318 if (err != PICL_SUCCESS)
1319 return (err);
1321 return (PICL_SUCCESS);
1324 /* Hotplug routine used to remove an existing CPU Mem Module */
1325 static int
1326 remove_cpu_module(int slotnum)
1328 picl_nodehdl_t cpumemsloth;
1329 picl_nodehdl_t cpumemmodh;
1330 int err;
1332 /* Find the node for the given CPU Memory module slot */
1333 if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
1334 &cpumemsloth) == PICL_SUCCESS) {
1335 /* Make sure it's got a child, then delete it */
1336 err = ptree_get_propval_by_name(cpumemsloth, PICL_PROP_CHILD,
1337 &cpumemmodh, sizeof (picl_nodehdl_t));
1338 if (err != PICL_SUCCESS) {
1339 return (err);
1342 err = remove_all_nodes(cpumemmodh);
1343 if (err != PICL_SUCCESS) {
1344 return (err);
1347 return (PICL_SUCCESS);