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 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * PICL plug-in that creates the FRU Hierarchy for the
31 * SUNW,Sun-Fire-880 (Daktari) platform
32 */
33
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>
42
43 /*
44 * Plugin registration entry points
45 */
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);
51
52 #pragma init(picl_frutree_register)
53
54 /*
55 * Log message texts
56 */
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")
64
65 /*
66 * Viewpoints property field used by SunMC
67 */
68 #define CHASSIS_VIEWPOINTS gettext("front left right rear")
69
70 /*
71 * Ref prop values
72 */
73 #define SEEPROM_SOURCE "_seeprom_source"
74 #define FRU_PARENT "_fru_parent"
75
76 /*
77 * List of all the FRU locations in the platform_frupath[] array, and
78 * location_label[] array
79 */
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
97
98
99 /*
100 * Local variables
101 */
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
108 };
109
110 /*
111 * List of all the FRUs in the /platform tree with SEEPROMs
112 */
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};
193
194 /*
195 * List of Labels for FRU locations (uses the #define's from above)
196 */
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};
231
232 /*
233 * List of all the FRU slots for power supplies (hotpluggable)
234 */
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};
240
241 /*
242 * List of all the FRU slots for CPU Memory modules (hotpluggable)
243 */
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};
250
251 /* PICL handle for the root node of the "frutree" */
252 static picl_nodehdl_t frutreeh;
253
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);
261
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);
269
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);
278
279 /*
280 * This function is executed as part of .init when the plugin is
281 * dlopen()ed
282 */
283 static void
picl_frutree_register()284 picl_frutree_register()
285 {
286 (void) picld_plugin_register(&my_reg_info);
287 }
288
289 /*
290 * This function is the init entry point of the plugin.
291 * It initializes the /frutree tree
292 */
293 static void
picl_frutree_init()294 picl_frutree_init()
295 {
296 int err;
297
298 err = add_all_nodes();
299 if (err != PICL_SUCCESS) {
300 (void) remove_all_nodes(frutreeh);
301 return;
302 }
303
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);
309 }
310
311 /*
312 * This function is the fini entry point of the plugin
313 */
314 static void
picl_frutree_fini(void)315 picl_frutree_fini(void)
316 {
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);
322
323 (void) remove_all_nodes(frutreeh);
324 }
325
326 /*
327 * This function is the event handler of this plug-in.
328 *
329 * It processes the following events:
330 *
331 * PICLEVENT_SYSEVENT_DEVICE_ADDED
332 * PICLEVENT_SYSEVENT_DEVICE_REMOVED
333 */
334 /* ARGSUSED */
335 static void
picl_frutree_evhandler(const char * ename,const void * earg,size_t size,void * cookie)336 picl_frutree_evhandler(const char *ename, const void *earg, size_t size,
337 void *cookie)
338 {
339 if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
340 /* Check for and add any hotplugged device(s) */
341 (void) add_hotplug_fru_device();
342
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();
346 }
347 }
348
349 /* Initializes the FRU nodes for the IO board */
350 static int
do_ioboard_init(picl_nodehdl_t rooth)351 do_ioboard_init(picl_nodehdl_t rooth)
352 {
353 picl_nodehdl_t iobrdh;
354 picl_nodehdl_t tmph;
355 int err;
356
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);
363
364 err = add_ref_prop(iobrdh, tmph, SEEPROM_SOURCE);
365 if (err != PICL_SUCCESS)
366 return (err);
367
368 err = add_void_fda_prop(iobrdh);
369 if (err != PICL_SUCCESS)
370 return (err);
371
372 err = ptree_add_node(rooth, iobrdh);
373 if (err != PICL_SUCCESS)
374 return (err);
375
376 err = add_ref_prop(tmph, iobrdh, FRU_PARENT);
377 if (err != PICL_SUCCESS)
378 return (err);
379 }
380 return (PICL_SUCCESS);
381 }
382
383 /* Initializes the FRU node for the RSC card */
384 static int
do_rscboard_init(picl_nodehdl_t rooth)385 do_rscboard_init(picl_nodehdl_t rooth)
386 {
387 picl_nodehdl_t rscbrdh;
388 picl_nodehdl_t tmph;
389 int err;
390
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);
397
398 err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE);
399 if (err != PICL_SUCCESS)
400 return (err);
401
402 err = add_void_fda_prop(rscbrdh);
403 if (err != PICL_SUCCESS)
404 return (err);
405
406 err = ptree_add_node(rooth, rscbrdh);
407 if (err != PICL_SUCCESS)
408 return (err);
409
410 err = add_ref_prop(tmph, rscbrdh, FRU_PARENT);
411 if (err != PICL_SUCCESS)
412 return (err);
413 }
414 return (PICL_SUCCESS);
415 }
416
417 /* Initializes the FRU nodes for the FCAL backplanes and GBIC card */
418 static int
do_fcal_init(picl_nodehdl_t rooth)419 do_fcal_init(picl_nodehdl_t rooth)
420 {
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;
426
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);
433
434 slotnum = i - FCAL0;
435 err = add_slot_prop(fcalsloth, slotnum);
436 if (err != PICL_SUCCESS)
437 return (err);
438
439 err = add_label_prop(fcalsloth, location_label[i]);
440 if (err != PICL_SUCCESS)
441 return (err);
442
443 err = ptree_add_node(rooth, fcalsloth);
444 if (err != PICL_SUCCESS)
445 return (err);
446
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);
454
455 err = add_ref_prop(fcalmodh, tmph, SEEPROM_SOURCE);
456 if (err != PICL_SUCCESS)
457 return (err);
458
459 err = add_void_fda_prop(fcalmodh);
460 if (err != PICL_SUCCESS)
461 return (err);
462
463 err = ptree_add_node(fcalsloth, fcalmodh);
464 if (err != PICL_SUCCESS)
465 return (err);
466
467 err = add_ref_prop(tmph, fcalmodh, FRU_PARENT);
468 if (err != PICL_SUCCESS)
469 return (err);
470 }
471 }
472
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);
480
481 err = add_ref_prop(fcalgbich, tmph, SEEPROM_SOURCE);
482 if (err != PICL_SUCCESS)
483 return (err);
484
485 err = add_void_fda_prop(fcalgbich);
486 if (err != PICL_SUCCESS)
487 return (err);
488
489 err = ptree_add_node(rooth, fcalgbich);
490 if (err != PICL_SUCCESS)
491 return (err);
492
493 err = add_ref_prop(tmph, fcalgbich, FRU_PARENT);
494 if (err != PICL_SUCCESS)
495 return (err);
496 }
497 return (PICL_SUCCESS);
498 }
499
500 /* Initializes the FRU nodes for the PDB and the power supplies */
501 static int
do_power_supplies_init(picl_nodehdl_t rooth)502 do_power_supplies_init(picl_nodehdl_t rooth)
503 {
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;
509
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);
516
517 err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE);
518 if (err != PICL_SUCCESS)
519 return (err);
520
521 err = add_void_fda_prop(powerbrdh);
522 if (err != PICL_SUCCESS)
523 return (err);
524
525 err = ptree_add_node(rooth, powerbrdh);
526 if (err != PICL_SUCCESS)
527 return (err);
528
529 err = add_ref_prop(tmph, powerbrdh, FRU_PARENT);
530 if (err != PICL_SUCCESS)
531 return (err);
532
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);
539
540 slotnum = i - PS0;
541 err = add_slot_prop(powersloth, slotnum);
542 if (err != PICL_SUCCESS)
543 return (err);
544
545 err = add_label_prop(powersloth, location_label[i]);
546 if (err != PICL_SUCCESS)
547 return (err);
548
549 err = ptree_add_node(powerbrdh, powersloth);
550 if (err != PICL_SUCCESS)
551 return (err);
552
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);
560
561 err = add_ref_prop(powermodh, tmph,
562 SEEPROM_SOURCE);
563 if (err != PICL_SUCCESS)
564 return (err);
565
566 err = add_void_fda_prop(powermodh);
567 if (err != PICL_SUCCESS)
568 return (err);
569
570 err = ptree_add_node(powersloth, powermodh);
571 if (err != PICL_SUCCESS)
572 return (err);
573
574 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
575 if (err != PICL_SUCCESS)
576 return (err);
577 }
578 }
579 }
580 return (PICL_SUCCESS);
581 }
582
583 /* Initializes the FRU nodes for the motherboard and CPU Memory modules */
584 static int
do_motherboard_init(picl_nodehdl_t rooth)585 do_motherboard_init(picl_nodehdl_t rooth)
586 {
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;
592
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);
600
601 err = add_ref_prop(sysboardh, tmph, SEEPROM_SOURCE);
602 if (err != PICL_SUCCESS)
603 return (err);
604
605 err = add_void_fda_prop(sysboardh);
606 if (err != PICL_SUCCESS)
607 return (err);
608
609 err = ptree_add_node(rooth, sysboardh);
610 if (err != PICL_SUCCESS)
611 return (err);
612
613 err = add_ref_prop(tmph, sysboardh, FRU_PARENT);
614 if (err != PICL_SUCCESS)
615 return (err);
616
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);
623
624 slotnum = i - CPUMOD0;
625 err = add_slot_prop(cpumemsloth, slotnum);
626 if (err != PICL_SUCCESS)
627 return (err);
628
629 err = add_label_prop(cpumemsloth, location_label[i]);
630 if (err != PICL_SUCCESS)
631 return (err);
632
633 err = ptree_add_node(sysboardh, cpumemsloth);
634 if (err != PICL_SUCCESS)
635 return (err);
636
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);
644
645 err = add_ref_prop(cpumemmodh, tmph,
646 SEEPROM_SOURCE);
647 if (err != PICL_SUCCESS)
648 return (err);
649
650 err = add_void_fda_prop(cpumemmodh);
651 if (err != PICL_SUCCESS)
652 return (err);
653
654 err = ptree_add_node(cpumemsloth, cpumemmodh);
655 if (err != PICL_SUCCESS)
656 return (err);
657
658 err = add_ref_prop(tmph, cpumemmodh,
659 FRU_PARENT);
660 if (err != PICL_SUCCESS)
661 return (err);
662
663 err = do_cpu_module_init(cpumemmodh, slotnum);
664 if (err != PICL_SUCCESS)
665 return (err);
666 }
667 }
668 }
669 return (PICL_SUCCESS);
670 }
671
672 /* Creates the FRU nodes for the CPU Module and associated DIMMs */
673 static int
do_cpu_module_init(picl_nodehdl_t rooth,int slot)674 do_cpu_module_init(picl_nodehdl_t rooth, int slot)
675 {
676 picl_nodehdl_t cpumodh;
677 int i, c, err;
678
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);
684
685 err = add_slot_prop(cpumodh, i);
686 if (err != PICL_SUCCESS)
687 return (err);
688
689 c = CPU0_DIMM0 + DIMMS_PER_SLOT + i;
690
691 err = add_label_prop(cpumodh, location_label[c]);
692 if (err != PICL_SUCCESS)
693 return (err);
694
695 err = ptree_add_node(rooth, cpumodh);
696 if (err != PICL_SUCCESS)
697 return (err);
698
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);
703 }
704 return (PICL_SUCCESS);
705 }
706
707 /* Creates the FRU nodes for the DIMMs on a particular CPU Module */
708 static int
do_dimms_init(picl_nodehdl_t rooth,int slot,int module)709 do_dimms_init(picl_nodehdl_t rooth, int slot, int module)
710 {
711 picl_nodehdl_t dimmsloth;
712 picl_nodehdl_t dimmmodh;
713 picl_nodehdl_t tmph;
714 int i, c, l, err;
715
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);
722
723 err = add_slot_prop(dimmsloth, i);
724 if (err != PICL_SUCCESS)
725 return (err);
726
727 c = ((slot * DIMMS_PER_SLOT) +
728 (module * DIMMS_PER_MOD) + i) + CPU0_DIMM0;
729
730 l = c - (DIMMS_PER_SLOT * slot);
731
732 err = add_label_prop(dimmsloth, location_label[l]);
733 if (err != PICL_SUCCESS)
734 return (err);
735
736 err = ptree_add_node(rooth, dimmsloth);
737 if (err != PICL_SUCCESS)
738 return (err);
739
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);
747
748 err = add_ref_prop(dimmmodh, tmph, SEEPROM_SOURCE);
749 if (err != PICL_SUCCESS)
750 return (err);
751
752 err = add_void_fda_prop(dimmmodh);
753 if (err != PICL_SUCCESS)
754 return (err);
755
756 err = ptree_add_node(dimmsloth, dimmmodh);
757 if (err != PICL_SUCCESS)
758 return (err);
759
760 err = add_ref_prop(tmph, dimmmodh, FRU_PARENT);
761 if (err != PICL_SUCCESS)
762 return (err);
763 }
764 }
765 return (PICL_SUCCESS);
766 }
767
768 /* Creates a "reference" property between two PICL nodes */
769 static int
add_ref_prop(picl_nodehdl_t nodeh,picl_nodehdl_t tmph,char * str)770 add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str)
771 {
772 picl_prophdl_t proph;
773 ptree_propinfo_t propinfo;
774 int err;
775
776 if (str == NULL)
777 return (PICL_FAILURE);
778
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);
784
785 err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph);
786 if (err != PICL_SUCCESS)
787 return (err);
788
789 return (PICL_SUCCESS);
790 }
791
792 /* Creates a "slot" property for a given PICL node */
793 static int
add_slot_prop(picl_nodehdl_t nodeh,int slotnum)794 add_slot_prop(picl_nodehdl_t nodeh, int slotnum)
795 {
796 picl_prophdl_t proph;
797 ptree_propinfo_t propinfo;
798 int err;
799
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);
804
805 err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph);
806 if (err != PICL_SUCCESS)
807 return (err);
808
809 return (PICL_SUCCESS);
810 }
811
812 /* Creates a "Label" property for a given PICL node */
813 static int
add_label_prop(picl_nodehdl_t nodeh,char * label)814 add_label_prop(picl_nodehdl_t nodeh, char *label)
815 {
816 picl_prophdl_t proph;
817 ptree_propinfo_t propinfo;
818 int err;
819
820 if (label == NULL)
821 return (PICL_FAILURE);
822
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);
828
829 err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph);
830 if (err != PICL_SUCCESS)
831 return (err);
832
833 return (PICL_SUCCESS);
834 }
835
836 /* Creates a "FRUDataAvailable" void property for the given PICL node */
837 static int
add_void_fda_prop(picl_nodehdl_t nodeh)838 add_void_fda_prop(picl_nodehdl_t nodeh)
839 {
840 picl_prophdl_t proph;
841 ptree_propinfo_t propinfo;
842 int err;
843
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);
848
849 err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
850 if (err != PICL_SUCCESS)
851 return (err);
852
853 return (PICL_SUCCESS);
854 }
855
856 /* Creates a "ViewPoints" property -- used for chassis */
857 static int
add_viewpoints_prop(picl_nodehdl_t nodeh,char * string)858 add_viewpoints_prop(picl_nodehdl_t nodeh, char *string)
859 {
860 picl_prophdl_t proph;
861 ptree_propinfo_t propinfo;
862 int err;
863
864 if (string == NULL)
865 return (PICL_FAILURE);
866
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);
872
873 err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph);
874 if (err != PICL_SUCCESS)
875 return (err);
876
877 return (PICL_SUCCESS);
878 }
879
880 /* Creates and adds all of the frutree nodes */
881 static int
add_all_nodes()882 add_all_nodes()
883 {
884 picl_nodehdl_t rooth;
885 picl_nodehdl_t chassish;
886 int err;
887
888 /* Get the root node of the PICL tree */
889 err = ptree_get_root(&rooth);
890 if (err != PICL_SUCCESS) {
891 return (err);
892 }
893
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);
899 }
900
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);
906 }
907
908 /* Add ViewPoints prop to chassis node */
909 err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS);
910 if (err != PICL_SUCCESS)
911 return (err);
912
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);
918 }
919
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);
925 }
926
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);
932 }
933
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);
939 }
940
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);
946 }
947
948 return (PICL_SUCCESS);
949 }
950
951 /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
952 static int
remove_all_nodes(picl_nodehdl_t rooth)953 remove_all_nodes(picl_nodehdl_t rooth)
954 {
955 picl_nodehdl_t chdh;
956 int err, done = 0;
957
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);
969 }
970 done = 1;
971 }
972 }
973 return (PICL_SUCCESS);
974 }
975
976 /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */
977 static int
add_hotplug_fru_device()978 add_hotplug_fru_device()
979 {
980 int i, err, slotnum;
981
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;
990
991 /* If they are different, then add a power supply */
992 err = add_power_supply(slotnum);
993 if (err != PICL_SUCCESS)
994 continue;
995 }
996
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;
1005
1006 /* If they are different, then add a CPU Mem module */
1007 err = add_cpu_module(slotnum);
1008 if (err != PICL_SUCCESS)
1009 continue;
1010 }
1011 return (PICL_SUCCESS);
1012 }
1013
1014 /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */
1015 static int
rem_hotplug_fru_device()1016 rem_hotplug_fru_device()
1017 {
1018 int i, err, slotnum;
1019
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;
1028
1029 /* If they are different, then remove a power supply */
1030 err = remove_power_supply(slotnum);
1031 if (err != PICL_SUCCESS)
1032 continue;
1033 }
1034
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;
1043
1044 /* If they are different, then remove a CPU Mem module */
1045 err = remove_cpu_module(slotnum);
1046 if (err != PICL_SUCCESS)
1047 continue;
1048 }
1049 return (PICL_SUCCESS);
1050 }
1051
1052 /*
1053 * Compare the /platform tree to the /frutree to determine if a
1054 * new device has been added
1055 */
1056 static int
is_added_device(char * plat,char * fru)1057 is_added_device(char *plat, char *fru)
1058 {
1059 int err;
1060 picl_nodehdl_t plath, frusloth, frumodh;
1061
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);
1066
1067 /*
1068 * The node is in /platform, so find the corresponding slot in
1069 * the frutree
1070 */
1071 err = ptree_get_node_by_path(fru, &frusloth);
1072 if (err != PICL_SUCCESS)
1073 return (err);
1074
1075 /*
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
1081 */
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);
1086
1087 return (PICL_SUCCESS);
1088 }
1089
1090 /*
1091 * Compare the /platform tree to the /frutree to determine if a
1092 * device has been removed
1093 */
1094 static int
is_removed_device(char * plat,char * fru)1095 is_removed_device(char *plat, char *fru)
1096 {
1097 int err;
1098 picl_nodehdl_t plath, frusloth, frumodh;
1099
1100
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);
1105
1106 /*
1107 * The node is not in /platform, so find the corresponding slot in
1108 * the frutree
1109 */
1110 err = ptree_get_node_by_path(fru, &frusloth);
1111 if (err != PICL_SUCCESS)
1112 return (err);
1113
1114 /*
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
1120 */
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);
1125
1126 return (PICL_SUCCESS);
1127 }
1128
1129 static int
remove_picl_node(picl_nodehdl_t nodeh)1130 remove_picl_node(picl_nodehdl_t nodeh)
1131 {
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);
1138 }
1139
1140 /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
1141 /*ARGSUSED2*/
1142 static void
frudr_completion_handler(char * ename,void * earg,size_t size)1143 frudr_completion_handler(char *ename, void *earg, size_t size)
1144 {
1145 picl_nodehdl_t fruh;
1146
1147 if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
1148 /*
1149 * now frudata has been notified that the node is to be
1150 * removed, we can actually remove it
1151 */
1152 fruh = NULL;
1153 (void) nvlist_lookup_uint64(earg,
1154 PICLEVENTARG_FRUHANDLE, &fruh);
1155 if (fruh != NULL) {
1156 (void) remove_picl_node(fruh);
1157 }
1158 }
1159 nvlist_free(earg);
1160 free(earg);
1161 free(ename);
1162 }
1163
1164 /*
1165 * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
1166 */
1167 static void
post_frudr_event(char * ename,picl_nodehdl_t parenth,picl_nodehdl_t fruh)1168 post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh)
1169 {
1170 nvlist_t *nvl;
1171 char *ev_name;
1172
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;
1179 }
1180 if (parenth != 0L &&
1181 nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) {
1182 free(ev_name);
1183 nvlist_free(nvl);
1184 return;
1185 }
1186 if (fruh != 0L &&
1187 nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) {
1188 free(ev_name);
1189 nvlist_free(nvl);
1190 return;
1191 }
1192 if (ptree_post_event(ev_name, nvl, sizeof (nvl),
1193 frudr_completion_handler) != 0) {
1194 free(ev_name);
1195 nvlist_free(nvl);
1196 }
1197 }
1198
1199 /* Hotplug routine used to add a new power supply */
1200 static int
add_power_supply(int slotnum)1201 add_power_supply(int slotnum)
1202 {
1203 picl_nodehdl_t powersloth;
1204 picl_nodehdl_t powermodh;
1205 picl_nodehdl_t tmph;
1206 int i, err;
1207
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) {
1211
1212 i = slotnum + PS0;
1213
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);
1221
1222 err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE);
1223 if (err != PICL_SUCCESS)
1224 return (err);
1225
1226 err = add_void_fda_prop(powermodh);
1227 if (err != PICL_SUCCESS)
1228 return (err);
1229
1230 err = ptree_add_node(powersloth, powermodh);
1231 if (err != PICL_SUCCESS)
1232 return (err);
1233
1234 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
1235 if (err != PICL_SUCCESS)
1236 return (err);
1237
1238 /* Post picl-fru-added event */
1239 post_frudr_event(PICL_FRU_ADDED, NULL, powermodh);
1240 }
1241 }
1242 return (PICL_SUCCESS);
1243 }
1244
1245 /* Hotplug routine used to remove an existing power supply */
1246 static int
remove_power_supply(int slotnum)1247 remove_power_supply(int slotnum)
1248 {
1249 picl_nodehdl_t powersloth;
1250 picl_nodehdl_t powermodh;
1251 int err;
1252
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);
1261 }
1262
1263 err = ptree_delete_node(powermodh);
1264 if (err != PICL_SUCCESS) {
1265 return (err);
1266 } else {
1267 (void) ptree_destroy_node(powermodh);
1268 }
1269
1270 /* Post picl-fru-removed event */
1271 post_frudr_event(PICL_FRU_REMOVED, NULL, powermodh);
1272
1273 }
1274 return (PICL_SUCCESS);
1275 }
1276
1277 /* Hotplug routine used to add a new CPU Mem Module (with associated DIMMs) */
1278 static int
add_cpu_module(int slotnum)1279 add_cpu_module(int slotnum)
1280 {
1281 picl_nodehdl_t cpumemsloth;
1282 picl_nodehdl_t cpumemmodh;
1283 picl_nodehdl_t tmph;
1284 int i, err;
1285
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) {
1289
1290 i = slotnum + CPUMOD0;
1291
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);
1299
1300 err = add_ref_prop(cpumemmodh, tmph, SEEPROM_SOURCE);
1301 if (err != PICL_SUCCESS)
1302 return (err);
1303
1304 err = add_void_fda_prop(cpumemmodh);
1305 if (err != PICL_SUCCESS)
1306 return (err);
1307
1308 err = ptree_add_node(cpumemsloth, cpumemmodh);
1309 if (err != PICL_SUCCESS)
1310 return (err);
1311
1312 err = add_ref_prop(tmph, cpumemmodh, FRU_PARENT);
1313 if (err != PICL_SUCCESS)
1314 return (err);
1315 }
1316
1317 err = do_cpu_module_init(cpumemmodh, slotnum);
1318 if (err != PICL_SUCCESS)
1319 return (err);
1320 }
1321 return (PICL_SUCCESS);
1322 }
1323
1324 /* Hotplug routine used to remove an existing CPU Mem Module */
1325 static int
remove_cpu_module(int slotnum)1326 remove_cpu_module(int slotnum)
1327 {
1328 picl_nodehdl_t cpumemsloth;
1329 picl_nodehdl_t cpumemmodh;
1330 int err;
1331
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);
1340 }
1341
1342 err = remove_all_nodes(cpumemmodh);
1343 if (err != PICL_SUCCESS) {
1344 return (err);
1345 }
1346 }
1347 return (PICL_SUCCESS);
1348 }
1349