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 /*
28 * PICL plug-in that creates the FRU Hierarchy for the
29 * SUNW,Sun-Fire-880 (Daktari) platform
30 */
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <libintl.h>
35 #include <libnvpair.h>
36 #include <syslog.h>
37 #include <picl.h>
38 #include <picltree.h>
39 #include <picldefs.h>
40
41 /*
42 * Plugin registration entry points
43 */
44 static void picl_frutree_register(void);
45 static void picl_frutree_init(void);
46 static void picl_frutree_fini(void);
47 static void picl_frutree_evhandler(const char *ename, const void *earg,
48 size_t size, void *cookie);
49
50 #pragma init(picl_frutree_register)
51
52 /*
53 * Log message texts
54 */
55 #define CREATE_FRUTREE_FAIL gettext("Failed to create frutree node\n")
56 #define CREATE_CHASSIS_FAIL gettext("Failed to create chassis node\n")
57 #define IOBRD_INIT_FAIL gettext("do_ioboard_init() failed\n")
58 #define RSCBRD_INIT_FAIL gettext("do_rscboard_init() failed\n")
59 #define FCAL_INIT_FAIL gettext("do_fcal_init() failed\n")
60 #define PS_INIT_FAIL gettext("do_power_supplies_init() failed\n")
61 #define SYSBOARD_INIT_FAIL gettext("do_motherboard_init() failed\n")
62
63 /*
64 * Viewpoints property field used by SunMC
65 */
66 #define CHASSIS_VIEWPOINTS gettext("front left right rear")
67
68 /*
69 * Ref prop values
70 */
71 #define SEEPROM_SOURCE "_seeprom_source"
72 #define FRU_PARENT "_fru_parent"
73
74 /*
75 * List of all the FRU locations in the platform_frupath[] array, and
76 * location_label[] array
77 */
78 #define IOBRD 0
79 #define RSC 1
80 #define FCAL0 2
81 #define FCAL1 3
82 #define FCALGBIC 4
83 #define PDB 5
84 #define PS0 6
85 #define PS1 7
86 #define PS2 8
87 #define SYSBRD 9
88 #define CPUMOD0 10
89 #define CPUMOD1 11
90 #define CPUMOD2 12
91 #define CPUMOD3 13
92 #define CPU0_DIMM0 14
93 #define DIMMS_PER_MOD 8
94 #define DIMMS_PER_SLOT 16
95
96
97 /*
98 * Local variables
99 */
100 static picld_plugin_reg_t my_reg_info = {
101 PICLD_PLUGIN_VERSION_1,
102 PICLD_PLUGIN_NON_CRITICAL,
103 "SUNW_Sun-Fire-880_frutree",
104 picl_frutree_init,
105 picl_frutree_fini
106 };
107
108 /*
109 * List of all the FRUs in the /platform tree with SEEPROMs
110 */
111 static char *platform_frupath[] = {
112 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,aa", /* IO */
113 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6", /* RSC */
114 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a8", /* FCAL 0 */
115 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ac", /* FCAL 1 */
116 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,aa", /* FCAL-GBIC */
117 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ae", /* PDB */
118 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a0", /* PS 0 */
119 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a2", /* PS 1 */
120 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a4", /* PS 2 */
121 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a8", /* SYS BRD */
122 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0", /* CPU MOD 0 */
123 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2", /* CPU MOD 1 */
124 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a4", /* CPU MOD 2 */
125 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a6", /* CPU MOD 3 */
126 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0", /* CPU0 DIMM0 */
127 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2", /* CPU0 DIMM1 */
128 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4", /* CPU0 DIMM2 */
129 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6", /* CPU0 DIMM3 */
130 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8", /* CPU0 DIMM4 */
131 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa", /* CPU0 DIMM5 */
132 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac", /* CPU0 DIMM6 */
133 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae", /* CPU0 DIMM7 */
134 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0", /* CPU2 DIMM0 */
135 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2", /* CPU2 DIMM1 */
136 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4", /* CPU2 DIMM2 */
137 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6", /* CPU2 DIMM3 */
138 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8", /* CPU2 DIMM4 */
139 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa", /* CPU2 DIMM5 */
140 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac", /* CPU2 DIMM6 */
141 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae", /* CPU2 DIMM7 */
142 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0", /* CPU1 DIMM0 */
143 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2", /* CPU1 DIMM1 */
144 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4", /* CPU1 DIMM2 */
145 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6", /* CPU1 DIMM3 */
146 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8", /* CPU1 DIMM4 */
147 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa", /* CPU1 DIMM5 */
148 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac", /* CPU1 DIMM6 */
149 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae", /* CPU1 DIMM7 */
150 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0", /* CPU3 DIMM0 */
151 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2", /* CPU3 DIMM1 */
152 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4", /* CPU3 DIMM2 */
153 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6", /* CPU3 DIMM3 */
154 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8", /* CPU3 DIMM4 */
155 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa", /* CPU3 DIMM5 */
156 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac", /* CPU3 DIMM6 */
157 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae", /* CPU3 DIMM7 */
158 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a0", /* CPU4 DIMM0 */
159 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a2", /* CPU4 DIMM1 */
160 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a4", /* CPU4 DIMM2 */
161 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a6", /* CPU4 DIMM3 */
162 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a8", /* CPU4 DIMM4 */
163 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,aa", /* CPU4 DIMM5 */
164 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ac", /* CPU4 DIMM6 */
165 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ae", /* CPU4 DIMM7 */
166 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a0", /* CPU6 DIMM0 */
167 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a2", /* CPU6 DIMM1 */
168 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a4", /* CPU6 DIMM2 */
169 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a6", /* CPU6 DIMM3 */
170 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a8", /* CPU6 DIMM4 */
171 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,aa", /* CPU6 DIMM5 */
172 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ac", /* CPU6 DIMM6 */
173 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ae", /* CPU6 DIMM7 */
174 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a0", /* CPU5 DIMM0 */
175 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a2", /* CPU5 DIMM1 */
176 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a4", /* CPU5 DIMM2 */
177 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a6", /* CPU5 DIMM3 */
178 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a8", /* CPU5 DIMM4 */
179 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,aa", /* CPU5 DIMM5 */
180 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ac", /* CPU5 DIMM6 */
181 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ae", /* CPU5 DIMM7 */
182 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a0", /* CPU7 DIMM0 */
183 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a2", /* CPU7 DIMM1 */
184 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a4", /* CPU7 DIMM2 */
185 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a6", /* CPU7 DIMM3 */
186 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a8", /* CPU7 DIMM4 */
187 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,aa", /* CPU7 DIMM5 */
188 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ac", /* CPU7 DIMM6 */
189 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ae", /* CPU7 DIMM7 */
190 NULL};
191
192 /*
193 * List of Labels for FRU locations (uses the #define's from above)
194 */
195 static char *location_label[] = {
196 NULL, /* IOBRD */
197 NULL, /* RSC */
198 "0", /* FCAL0 */
199 "1", /* FCAL1 */
200 NULL, /* FCALGBIC */
201 NULL, /* PDB */
202 "0", /* PS0 */
203 "1", /* PS1 */
204 "2", /* PS2 */
205 NULL, /* SYSBRD */
206 "A", /* CPUMOD0 */
207 "B", /* CPUMOD1 */
208 "C", /* CPUMOD2 */
209 "D", /* CPUMOD3 */
210 "J2900", /* CPU0 DIMM0 */
211 "J3100", /* CPU0 DIMM1 */
212 "J2901", /* CPU0 DIMM2 */
213 "J3101", /* CPU0 DIMM3 */
214 "J3000", /* CPU0 DIMM4 */
215 "J3200", /* CPU0 DIMM5 */
216 "J3001", /* CPU0 DIMM6 */
217 "J3201", /* CPU0 DIMM7 */
218 "J7900", /* CPU1 DIMM0 */
219 "J8100", /* CPU1 DIMM1 */
220 "J7901", /* CPU1 DIMM2 */
221 "J8101", /* CPU1 DIMM3 */
222 "J8000", /* CPU1 DIMM4 */
223 "J8200", /* CPU1 DIMM5 */
224 "J8001", /* CPU1 DIMM6 */
225 "J8201", /* CPU1 DIMM7 */
226 "0", /* CPU0 label */
227 "1", /* CPU1 label */
228 NULL};
229
230 /*
231 * List of all the FRU slots for power supplies (hotpluggable)
232 */
233 static char *frutree_power_supply[] = {
234 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=0",
235 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=1",
236 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=2",
237 NULL};
238
239 /*
240 * List of all the FRU slots for CPU Memory modules (hotpluggable)
241 */
242 static char *frutree_cpu_module[] = {
243 "/frutree/chassis/system-board/cpu-mem-slot?Slot=0",
244 "/frutree/chassis/system-board/cpu-mem-slot?Slot=1",
245 "/frutree/chassis/system-board/cpu-mem-slot?Slot=2",
246 "/frutree/chassis/system-board/cpu-mem-slot?Slot=3",
247 NULL};
248
249 /* PICL handle for the root node of the "frutree" */
250 static picl_nodehdl_t frutreeh;
251
252 static int do_ioboard_init(picl_nodehdl_t);
253 static int do_rscboard_init(picl_nodehdl_t);
254 static int do_fcal_init(picl_nodehdl_t);
255 static int do_power_supplies_init(picl_nodehdl_t);
256 static int do_motherboard_init(picl_nodehdl_t);
257 static int do_cpu_module_init(picl_nodehdl_t, int);
258 static int do_dimms_init(picl_nodehdl_t, int, int);
259
260 static int add_ref_prop(picl_nodehdl_t, picl_nodehdl_t, char *);
261 static int add_slot_prop(picl_nodehdl_t, int);
262 static int add_label_prop(picl_nodehdl_t, char *);
263 static int add_void_fda_prop(picl_nodehdl_t);
264 static int add_viewpoints_prop(picl_nodehdl_t, char *);
265 static int add_all_nodes();
266 static int remove_all_nodes(picl_nodehdl_t);
267
268 static int add_hotplug_fru_device(void);
269 static int rem_hotplug_fru_device(void);
270 static int is_added_device(char *, char *);
271 static int is_removed_device(char *, char *);
272 static int add_power_supply(int);
273 static int remove_power_supply(int);
274 static int add_cpu_module(int);
275 static int remove_cpu_module(int);
276
277 /*
278 * This function is executed as part of .init when the plugin is
279 * dlopen()ed
280 */
281 static void
picl_frutree_register()282 picl_frutree_register()
283 {
284 (void) picld_plugin_register(&my_reg_info);
285 }
286
287 /*
288 * This function is the init entry point of the plugin.
289 * It initializes the /frutree tree
290 */
291 static void
picl_frutree_init()292 picl_frutree_init()
293 {
294 int err;
295
296 err = add_all_nodes();
297 if (err != PICL_SUCCESS) {
298 (void) remove_all_nodes(frutreeh);
299 return;
300 }
301
302 /* Register the event handler routine */
303 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
304 picl_frutree_evhandler, NULL);
305 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
306 picl_frutree_evhandler, NULL);
307 }
308
309 /*
310 * This function is the fini entry point of the plugin
311 */
312 static void
picl_frutree_fini(void)313 picl_frutree_fini(void)
314 {
315 /* Unregister the event handler routine */
316 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
317 picl_frutree_evhandler, NULL);
318 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
319 picl_frutree_evhandler, NULL);
320
321 (void) remove_all_nodes(frutreeh);
322 }
323
324 /*
325 * This function is the event handler of this plug-in.
326 *
327 * It processes the following events:
328 *
329 * PICLEVENT_SYSEVENT_DEVICE_ADDED
330 * PICLEVENT_SYSEVENT_DEVICE_REMOVED
331 */
332 /* ARGSUSED */
333 static void
picl_frutree_evhandler(const char * ename,const void * earg,size_t size,void * cookie)334 picl_frutree_evhandler(const char *ename, const void *earg, size_t size,
335 void *cookie)
336 {
337 if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
338 /* Check for and add any hotplugged device(s) */
339 (void) add_hotplug_fru_device();
340
341 } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
342 /* Check for and remove any hotplugged device(s) */
343 (void) rem_hotplug_fru_device();
344 }
345 }
346
347 /* Initializes the FRU nodes for the IO board */
348 static int
do_ioboard_init(picl_nodehdl_t rooth)349 do_ioboard_init(picl_nodehdl_t rooth)
350 {
351 picl_nodehdl_t iobrdh;
352 picl_nodehdl_t tmph;
353 int err;
354
355 /* Create the node for the IO board (if it exists) */
356 if (ptree_get_node_by_path(platform_frupath[IOBRD], &tmph) ==
357 PICL_SUCCESS) {
358 err = ptree_create_node("io-board", "fru", &iobrdh);
359 if (err != PICL_SUCCESS)
360 return (err);
361
362 err = add_ref_prop(iobrdh, tmph, SEEPROM_SOURCE);
363 if (err != PICL_SUCCESS)
364 return (err);
365
366 err = add_void_fda_prop(iobrdh);
367 if (err != PICL_SUCCESS)
368 return (err);
369
370 err = ptree_add_node(rooth, iobrdh);
371 if (err != PICL_SUCCESS)
372 return (err);
373
374 err = add_ref_prop(tmph, iobrdh, FRU_PARENT);
375 if (err != PICL_SUCCESS)
376 return (err);
377 }
378 return (PICL_SUCCESS);
379 }
380
381 /* Initializes the FRU node for the RSC card */
382 static int
do_rscboard_init(picl_nodehdl_t rooth)383 do_rscboard_init(picl_nodehdl_t rooth)
384 {
385 picl_nodehdl_t rscbrdh;
386 picl_nodehdl_t tmph;
387 int err;
388
389 /* Create the node for the RSC board (if it exists) */
390 if (ptree_get_node_by_path(platform_frupath[RSC], &tmph) ==
391 PICL_SUCCESS) {
392 err = ptree_create_node("rsc-board", "fru", &rscbrdh);
393 if (err != PICL_SUCCESS)
394 return (err);
395
396 err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE);
397 if (err != PICL_SUCCESS)
398 return (err);
399
400 err = add_void_fda_prop(rscbrdh);
401 if (err != PICL_SUCCESS)
402 return (err);
403
404 err = ptree_add_node(rooth, rscbrdh);
405 if (err != PICL_SUCCESS)
406 return (err);
407
408 err = add_ref_prop(tmph, rscbrdh, FRU_PARENT);
409 if (err != PICL_SUCCESS)
410 return (err);
411 }
412 return (PICL_SUCCESS);
413 }
414
415 /* Initializes the FRU nodes for the FCAL backplanes and GBIC card */
416 static int
do_fcal_init(picl_nodehdl_t rooth)417 do_fcal_init(picl_nodehdl_t rooth)
418 {
419 picl_nodehdl_t fcalsloth;
420 picl_nodehdl_t fcalmodh;
421 picl_nodehdl_t fcalgbich;
422 picl_nodehdl_t tmph;
423 int i, err, slotnum;
424
425 for (i = FCAL0; i <= FCAL1; i++) {
426 /* Create the node for the FCAL backplane slot */
427 err = ptree_create_node("fcal-backplane-slot",
428 "location", &fcalsloth);
429 if (err != PICL_SUCCESS)
430 return (err);
431
432 slotnum = i - FCAL0;
433 err = add_slot_prop(fcalsloth, slotnum);
434 if (err != PICL_SUCCESS)
435 return (err);
436
437 err = add_label_prop(fcalsloth, location_label[i]);
438 if (err != PICL_SUCCESS)
439 return (err);
440
441 err = ptree_add_node(rooth, fcalsloth);
442 if (err != PICL_SUCCESS)
443 return (err);
444
445 /* If the FCAL backplane exists, create a node for it */
446 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
447 PICL_SUCCESS) {
448 err = ptree_create_node("fcal-backplane", "fru",
449 &fcalmodh);
450 if (err != PICL_SUCCESS)
451 return (err);
452
453 err = add_ref_prop(fcalmodh, tmph, SEEPROM_SOURCE);
454 if (err != PICL_SUCCESS)
455 return (err);
456
457 err = add_void_fda_prop(fcalmodh);
458 if (err != PICL_SUCCESS)
459 return (err);
460
461 err = ptree_add_node(fcalsloth, fcalmodh);
462 if (err != PICL_SUCCESS)
463 return (err);
464
465 err = add_ref_prop(tmph, fcalmodh, FRU_PARENT);
466 if (err != PICL_SUCCESS)
467 return (err);
468 }
469 }
470
471 /* If the FCAL GBIC board exists, create a node for it */
472 if (ptree_get_node_by_path(platform_frupath[FCALGBIC], &tmph) ==
473 PICL_SUCCESS) {
474 err = ptree_create_node("fcal-gbic-board", "fru",
475 &fcalgbich);
476 if (err != PICL_SUCCESS)
477 return (err);
478
479 err = add_ref_prop(fcalgbich, tmph, SEEPROM_SOURCE);
480 if (err != PICL_SUCCESS)
481 return (err);
482
483 err = add_void_fda_prop(fcalgbich);
484 if (err != PICL_SUCCESS)
485 return (err);
486
487 err = ptree_add_node(rooth, fcalgbich);
488 if (err != PICL_SUCCESS)
489 return (err);
490
491 err = add_ref_prop(tmph, fcalgbich, FRU_PARENT);
492 if (err != PICL_SUCCESS)
493 return (err);
494 }
495 return (PICL_SUCCESS);
496 }
497
498 /* Initializes the FRU nodes for the PDB and the power supplies */
499 static int
do_power_supplies_init(picl_nodehdl_t rooth)500 do_power_supplies_init(picl_nodehdl_t rooth)
501 {
502 picl_nodehdl_t powerbrdh;
503 picl_nodehdl_t powersloth;
504 picl_nodehdl_t powermodh;
505 picl_nodehdl_t tmph;
506 int i, err, slotnum;
507
508 /* Create the node for the PDB (if it exists) */
509 if (ptree_get_node_by_path(platform_frupath[PDB], &tmph) ==
510 PICL_SUCCESS) {
511 err = ptree_create_node("power-dist-board", "fru", &powerbrdh);
512 if (err != PICL_SUCCESS)
513 return (err);
514
515 err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE);
516 if (err != PICL_SUCCESS)
517 return (err);
518
519 err = add_void_fda_prop(powerbrdh);
520 if (err != PICL_SUCCESS)
521 return (err);
522
523 err = ptree_add_node(rooth, powerbrdh);
524 if (err != PICL_SUCCESS)
525 return (err);
526
527 err = add_ref_prop(tmph, powerbrdh, FRU_PARENT);
528 if (err != PICL_SUCCESS)
529 return (err);
530
531 for (i = PS0; i <= PS2; i++) {
532 /* Create the node for the power supply slot */
533 err = ptree_create_node("power-supply-slot",
534 "location", &powersloth);
535 if (err != PICL_SUCCESS)
536 return (err);
537
538 slotnum = i - PS0;
539 err = add_slot_prop(powersloth, slotnum);
540 if (err != PICL_SUCCESS)
541 return (err);
542
543 err = add_label_prop(powersloth, location_label[i]);
544 if (err != PICL_SUCCESS)
545 return (err);
546
547 err = ptree_add_node(powerbrdh, powersloth);
548 if (err != PICL_SUCCESS)
549 return (err);
550
551 /* If the PS exists, create a node for it */
552 if (ptree_get_node_by_path(platform_frupath[i],
553 &tmph) == PICL_SUCCESS) {
554 err = ptree_create_node("power-supply",
555 "fru", &powermodh);
556 if (err != PICL_SUCCESS)
557 return (err);
558
559 err = add_ref_prop(powermodh, tmph,
560 SEEPROM_SOURCE);
561 if (err != PICL_SUCCESS)
562 return (err);
563
564 err = add_void_fda_prop(powermodh);
565 if (err != PICL_SUCCESS)
566 return (err);
567
568 err = ptree_add_node(powersloth, powermodh);
569 if (err != PICL_SUCCESS)
570 return (err);
571
572 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
573 if (err != PICL_SUCCESS)
574 return (err);
575 }
576 }
577 }
578 return (PICL_SUCCESS);
579 }
580
581 /* Initializes the FRU nodes for the motherboard and CPU Memory modules */
582 static int
do_motherboard_init(picl_nodehdl_t rooth)583 do_motherboard_init(picl_nodehdl_t rooth)
584 {
585 picl_nodehdl_t sysboardh;
586 picl_nodehdl_t cpumemsloth;
587 picl_nodehdl_t cpumemmodh;
588 picl_nodehdl_t tmph;
589 int i, err, slotnum;
590
591 /* Create the node for the system board (if it exists) */
592 if (ptree_get_node_by_path(platform_frupath[SYSBRD], &tmph) ==
593 PICL_SUCCESS) {
594 err = ptree_create_node("system-board", "fru",
595 &sysboardh);
596 if (err != PICL_SUCCESS)
597 return (err);
598
599 err = add_ref_prop(sysboardh, tmph, SEEPROM_SOURCE);
600 if (err != PICL_SUCCESS)
601 return (err);
602
603 err = add_void_fda_prop(sysboardh);
604 if (err != PICL_SUCCESS)
605 return (err);
606
607 err = ptree_add_node(rooth, sysboardh);
608 if (err != PICL_SUCCESS)
609 return (err);
610
611 err = add_ref_prop(tmph, sysboardh, FRU_PARENT);
612 if (err != PICL_SUCCESS)
613 return (err);
614
615 for (i = CPUMOD0; i <= CPUMOD3; i++) {
616 /* Create the node for the CPU Memory slot */
617 err = ptree_create_node("cpu-mem-slot", "location",
618 &cpumemsloth);
619 if (err != PICL_SUCCESS)
620 return (err);
621
622 slotnum = i - CPUMOD0;
623 err = add_slot_prop(cpumemsloth, slotnum);
624 if (err != PICL_SUCCESS)
625 return (err);
626
627 err = add_label_prop(cpumemsloth, location_label[i]);
628 if (err != PICL_SUCCESS)
629 return (err);
630
631 err = ptree_add_node(sysboardh, cpumemsloth);
632 if (err != PICL_SUCCESS)
633 return (err);
634
635 /* If CPU Mem module exists, create a node for it */
636 if (ptree_get_node_by_path(platform_frupath[i],
637 &tmph) == PICL_SUCCESS) {
638 err = ptree_create_node("cpu-mem-module",
639 "fru", &cpumemmodh);
640 if (err != PICL_SUCCESS)
641 return (err);
642
643 err = add_ref_prop(cpumemmodh, tmph,
644 SEEPROM_SOURCE);
645 if (err != PICL_SUCCESS)
646 return (err);
647
648 err = add_void_fda_prop(cpumemmodh);
649 if (err != PICL_SUCCESS)
650 return (err);
651
652 err = ptree_add_node(cpumemsloth, cpumemmodh);
653 if (err != PICL_SUCCESS)
654 return (err);
655
656 err = add_ref_prop(tmph, cpumemmodh,
657 FRU_PARENT);
658 if (err != PICL_SUCCESS)
659 return (err);
660
661 err = do_cpu_module_init(cpumemmodh, slotnum);
662 if (err != PICL_SUCCESS)
663 return (err);
664 }
665 }
666 }
667 return (PICL_SUCCESS);
668 }
669
670 /* Creates the FRU nodes for the CPU Module and associated DIMMs */
671 static int
do_cpu_module_init(picl_nodehdl_t rooth,int slot)672 do_cpu_module_init(picl_nodehdl_t rooth, int slot)
673 {
674 picl_nodehdl_t cpumodh;
675 int i, c, err;
676
677 for (i = 0; i <= 1; i++) {
678 err = ptree_create_node("cpu-module", "location",
679 &cpumodh);
680 if (err != PICL_SUCCESS)
681 return (err);
682
683 err = add_slot_prop(cpumodh, i);
684 if (err != PICL_SUCCESS)
685 return (err);
686
687 c = CPU0_DIMM0 + DIMMS_PER_SLOT + i;
688
689 err = add_label_prop(cpumodh, location_label[c]);
690 if (err != PICL_SUCCESS)
691 return (err);
692
693 err = ptree_add_node(rooth, cpumodh);
694 if (err != PICL_SUCCESS)
695 return (err);
696
697 /* Create the nodes for the memory (if they exist) */
698 err = do_dimms_init(cpumodh, slot, i);
699 if (err != PICL_SUCCESS)
700 return (err);
701 }
702 return (PICL_SUCCESS);
703 }
704
705 /* Creates the FRU nodes for the DIMMs on a particular CPU Module */
706 static int
do_dimms_init(picl_nodehdl_t rooth,int slot,int module)707 do_dimms_init(picl_nodehdl_t rooth, int slot, int module)
708 {
709 picl_nodehdl_t dimmsloth;
710 picl_nodehdl_t dimmmodh;
711 picl_nodehdl_t tmph;
712 int i, c, l, err;
713
714 for (i = 0; i < DIMMS_PER_MOD; i++) {
715 /* Create the node for the memory slot */
716 err = ptree_create_node("dimm-slot", "location",
717 &dimmsloth);
718 if (err != PICL_SUCCESS)
719 return (err);
720
721 err = add_slot_prop(dimmsloth, i);
722 if (err != PICL_SUCCESS)
723 return (err);
724
725 c = ((slot * DIMMS_PER_SLOT) +
726 (module * DIMMS_PER_MOD) + i) + CPU0_DIMM0;
727
728 l = c - (DIMMS_PER_SLOT * slot);
729
730 err = add_label_prop(dimmsloth, location_label[l]);
731 if (err != PICL_SUCCESS)
732 return (err);
733
734 err = ptree_add_node(rooth, dimmsloth);
735 if (err != PICL_SUCCESS)
736 return (err);
737
738 /* If the memory module exists, create a node for it */
739 if (ptree_get_node_by_path(platform_frupath[c], &tmph) ==
740 PICL_SUCCESS) {
741 err = ptree_create_node("dimm-module", "fru",
742 &dimmmodh);
743 if (err != PICL_SUCCESS)
744 return (err);
745
746 err = add_ref_prop(dimmmodh, tmph, SEEPROM_SOURCE);
747 if (err != PICL_SUCCESS)
748 return (err);
749
750 err = add_void_fda_prop(dimmmodh);
751 if (err != PICL_SUCCESS)
752 return (err);
753
754 err = ptree_add_node(dimmsloth, dimmmodh);
755 if (err != PICL_SUCCESS)
756 return (err);
757
758 err = add_ref_prop(tmph, dimmmodh, FRU_PARENT);
759 if (err != PICL_SUCCESS)
760 return (err);
761 }
762 }
763 return (PICL_SUCCESS);
764 }
765
766 /* Creates a "reference" property between two PICL nodes */
767 static int
add_ref_prop(picl_nodehdl_t nodeh,picl_nodehdl_t tmph,char * str)768 add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str)
769 {
770 picl_prophdl_t proph;
771 ptree_propinfo_t propinfo;
772 int err;
773
774 if (str == NULL)
775 return (PICL_FAILURE);
776
777 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
778 PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
779 str, NULL, NULL);
780 if (err != PICL_SUCCESS)
781 return (err);
782
783 err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph);
784 if (err != PICL_SUCCESS)
785 return (err);
786
787 return (PICL_SUCCESS);
788 }
789
790 /* Creates a "slot" property for a given PICL node */
791 static int
add_slot_prop(picl_nodehdl_t nodeh,int slotnum)792 add_slot_prop(picl_nodehdl_t nodeh, int slotnum)
793 {
794 picl_prophdl_t proph;
795 ptree_propinfo_t propinfo;
796 int err;
797
798 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
799 PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL);
800 if (err != PICL_SUCCESS)
801 return (err);
802
803 err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph);
804 if (err != PICL_SUCCESS)
805 return (err);
806
807 return (PICL_SUCCESS);
808 }
809
810 /* Creates a "Label" property for a given PICL node */
811 static int
add_label_prop(picl_nodehdl_t nodeh,char * label)812 add_label_prop(picl_nodehdl_t nodeh, char *label)
813 {
814 picl_prophdl_t proph;
815 ptree_propinfo_t propinfo;
816 int err;
817
818 if (label == NULL)
819 return (PICL_FAILURE);
820
821 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
822 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label",
823 NULL, NULL);
824 if (err != PICL_SUCCESS)
825 return (err);
826
827 err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph);
828 if (err != PICL_SUCCESS)
829 return (err);
830
831 return (PICL_SUCCESS);
832 }
833
834 /* Creates a "FRUDataAvailable" void property for the given PICL node */
835 static int
add_void_fda_prop(picl_nodehdl_t nodeh)836 add_void_fda_prop(picl_nodehdl_t nodeh)
837 {
838 picl_prophdl_t proph;
839 ptree_propinfo_t propinfo;
840 int err;
841
842 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
843 PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL);
844 if (err != PICL_SUCCESS)
845 return (err);
846
847 err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
848 if (err != PICL_SUCCESS)
849 return (err);
850
851 return (PICL_SUCCESS);
852 }
853
854 /* Creates a "ViewPoints" property -- used for chassis */
855 static int
add_viewpoints_prop(picl_nodehdl_t nodeh,char * string)856 add_viewpoints_prop(picl_nodehdl_t nodeh, char *string)
857 {
858 picl_prophdl_t proph;
859 ptree_propinfo_t propinfo;
860 int err;
861
862 if (string == NULL)
863 return (PICL_FAILURE);
864
865 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
866 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints",
867 NULL, NULL);
868 if (err != PICL_SUCCESS)
869 return (err);
870
871 err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph);
872 if (err != PICL_SUCCESS)
873 return (err);
874
875 return (PICL_SUCCESS);
876 }
877
878 /* Creates and adds all of the frutree nodes */
879 static int
add_all_nodes()880 add_all_nodes()
881 {
882 picl_nodehdl_t rooth;
883 picl_nodehdl_t chassish;
884 int err;
885
886 /* Get the root node of the PICL tree */
887 err = ptree_get_root(&rooth);
888 if (err != PICL_SUCCESS) {
889 return (err);
890 }
891
892 /* Create and add the root node of the FRU subtree */
893 err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh);
894 if (err != PICL_SUCCESS) {
895 syslog(LOG_ERR, CREATE_FRUTREE_FAIL);
896 return (err);
897 }
898
899 /* Create and add the chassis node */
900 err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish);
901 if (err != PICL_SUCCESS) {
902 syslog(LOG_ERR, CREATE_CHASSIS_FAIL);
903 return (err);
904 }
905
906 /* Add ViewPoints prop to chassis node */
907 err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS);
908 if (err != PICL_SUCCESS)
909 return (err);
910
911 /* Initialize the FRU nodes for the IO board */
912 err = do_ioboard_init(chassish);
913 if (err != PICL_SUCCESS) {
914 syslog(LOG_ERR, IOBRD_INIT_FAIL);
915 return (err);
916 }
917
918 /* Initialize the FRU node for the RSC card */
919 err = do_rscboard_init(chassish);
920 if (err != PICL_SUCCESS) {
921 syslog(LOG_ERR, RSCBRD_INIT_FAIL);
922 return (err);
923 }
924
925 /* Initialize the FRU nodes for the FCAL backplanes and GBIC board */
926 err = do_fcal_init(chassish);
927 if (err != PICL_SUCCESS) {
928 syslog(LOG_ERR, FCAL_INIT_FAIL);
929 return (err);
930 }
931
932 /* Initialize the FRU nodes for the PDB and the power supplies */
933 err = do_power_supplies_init(chassish);
934 if (err != PICL_SUCCESS) {
935 syslog(LOG_ERR, PS_INIT_FAIL);
936 return (err);
937 }
938
939 /* Initialize the FRU nodes for the CPU Memory modules */
940 err = do_motherboard_init(chassish);
941 if (err != PICL_SUCCESS) {
942 syslog(LOG_ERR, SYSBOARD_INIT_FAIL);
943 return (err);
944 }
945
946 return (PICL_SUCCESS);
947 }
948
949 /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
950 static int
remove_all_nodes(picl_nodehdl_t rooth)951 remove_all_nodes(picl_nodehdl_t rooth)
952 {
953 picl_nodehdl_t chdh;
954 int err, done = 0;
955
956 while (!done) {
957 err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
958 sizeof (picl_nodehdl_t));
959 if (err != PICL_PROPNOTFOUND) {
960 (void) remove_all_nodes(chdh);
961 } else {
962 err = ptree_delete_node(rooth);
963 if (err != PICL_SUCCESS) {
964 return (err);
965 } else {
966 (void) ptree_destroy_node(rooth);
967 }
968 done = 1;
969 }
970 }
971 return (PICL_SUCCESS);
972 }
973
974 /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */
975 static int
add_hotplug_fru_device()976 add_hotplug_fru_device()
977 {
978 int i, err, slotnum;
979
980 /* Check for hotplugged power supplies */
981 for (i = PS0; i <= PS2; i++) {
982 /* Compare the /platform tree to the frutree */
983 slotnum = i - PS0;
984 err = is_added_device(platform_frupath[i],
985 frutree_power_supply[slotnum]);
986 if (err != PICL_SUCCESS)
987 continue;
988
989 /* If they are different, then add a power supply */
990 err = add_power_supply(slotnum);
991 if (err != PICL_SUCCESS)
992 continue;
993 }
994
995 /* Check for hotplugged CPU Memory modules */
996 for (i = CPUMOD0; i <= CPUMOD3; i++) {
997 /* Compare the /platform tree to the frutree */
998 slotnum = i - CPUMOD0;
999 err = is_added_device(platform_frupath[i],
1000 frutree_cpu_module[slotnum]);
1001 if (err != PICL_SUCCESS)
1002 continue;
1003
1004 /* If they are different, then add a CPU Mem module */
1005 err = add_cpu_module(slotnum);
1006 if (err != PICL_SUCCESS)
1007 continue;
1008 }
1009 return (PICL_SUCCESS);
1010 }
1011
1012 /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */
1013 static int
rem_hotplug_fru_device()1014 rem_hotplug_fru_device()
1015 {
1016 int i, err, slotnum;
1017
1018 /* Check for hotplugged power supplies */
1019 for (i = PS0; i <= PS2; i++) {
1020 /* Compare the /platform tree to the frutree */
1021 slotnum = i - PS0;
1022 err = is_removed_device(platform_frupath[i],
1023 frutree_power_supply[slotnum]);
1024 if (err != PICL_SUCCESS)
1025 continue;
1026
1027 /* If they are different, then remove a power supply */
1028 err = remove_power_supply(slotnum);
1029 if (err != PICL_SUCCESS)
1030 continue;
1031 }
1032
1033 /* Check for hotplugged CPU Memory modules */
1034 for (i = CPUMOD0; i <= CPUMOD3; i++) {
1035 /* Compare the /platform tree to the frutree */
1036 slotnum = i - CPUMOD0;
1037 err = is_removed_device(platform_frupath[i],
1038 frutree_cpu_module[slotnum]);
1039 if (err != PICL_SUCCESS)
1040 continue;
1041
1042 /* If they are different, then remove a CPU Mem module */
1043 err = remove_cpu_module(slotnum);
1044 if (err != PICL_SUCCESS)
1045 continue;
1046 }
1047 return (PICL_SUCCESS);
1048 }
1049
1050 /*
1051 * Compare the /platform tree to the /frutree to determine if a
1052 * new device has been added
1053 */
1054 static int
is_added_device(char * plat,char * fru)1055 is_added_device(char *plat, char *fru)
1056 {
1057 int err;
1058 picl_nodehdl_t plath, frusloth, frumodh;
1059
1060 /* Check for node in the /platform tree */
1061 err = ptree_get_node_by_path(plat, &plath);
1062 if (err != PICL_SUCCESS)
1063 return (err);
1064
1065 /*
1066 * The node is in /platform, so find the corresponding slot in
1067 * the frutree
1068 */
1069 err = ptree_get_node_by_path(fru, &frusloth);
1070 if (err != PICL_SUCCESS)
1071 return (err);
1072
1073 /*
1074 * If the slot in the frutree has a child, then return
1075 * PICL_FAILURE. This means that the /platform tree and
1076 * the frutree are consistent and no action is necessary.
1077 * Otherwise return PICL_SUCCESS to indicate that a node needs
1078 * to be added to the frutree
1079 */
1080 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
1081 &frumodh, sizeof (picl_nodehdl_t));
1082 if (err == PICL_SUCCESS)
1083 return (PICL_FAILURE);
1084
1085 return (PICL_SUCCESS);
1086 }
1087
1088 /*
1089 * Compare the /platform tree to the /frutree to determine if a
1090 * device has been removed
1091 */
1092 static int
is_removed_device(char * plat,char * fru)1093 is_removed_device(char *plat, char *fru)
1094 {
1095 int err;
1096 picl_nodehdl_t plath, frusloth, frumodh;
1097
1098
1099 /* Check for node in /platform tree */
1100 err = ptree_get_node_by_path(plat, &plath);
1101 if (err == PICL_SUCCESS)
1102 return (PICL_FAILURE);
1103
1104 /*
1105 * The node is not in /platform, so find the corresponding slot in
1106 * the frutree
1107 */
1108 err = ptree_get_node_by_path(fru, &frusloth);
1109 if (err != PICL_SUCCESS)
1110 return (err);
1111
1112 /*
1113 * If the slot in the frutree does not have a child, then return
1114 * PICL_FAILURE. This means that the /platform tree and
1115 * the frutree are consistent and no action is necessary.
1116 * Otherwise return PICL_SUCCESS to indicate that the needs
1117 * to be removed from the frutree
1118 */
1119 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
1120 &frumodh, sizeof (picl_nodehdl_t));
1121 if (err != PICL_SUCCESS)
1122 return (err);
1123
1124 return (PICL_SUCCESS);
1125 }
1126
1127 static int
remove_picl_node(picl_nodehdl_t nodeh)1128 remove_picl_node(picl_nodehdl_t nodeh)
1129 {
1130 int err;
1131 err = ptree_delete_node(nodeh);
1132 if (err != PICL_SUCCESS)
1133 return (err);
1134 (void) ptree_destroy_node(nodeh);
1135 return (PICL_SUCCESS);
1136 }
1137
1138 /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
1139 /*ARGSUSED2*/
1140 static void
frudr_completion_handler(char * ename,void * earg,size_t size)1141 frudr_completion_handler(char *ename, void *earg, size_t size)
1142 {
1143 picl_nodehdl_t fruh;
1144
1145 if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
1146 /*
1147 * now frudata has been notified that the node is to be
1148 * removed, we can actually remove it
1149 */
1150 fruh = 0;
1151 (void) nvlist_lookup_uint64(earg,
1152 PICLEVENTARG_FRUHANDLE, &fruh);
1153 if (fruh != 0) {
1154 (void) remove_picl_node(fruh);
1155 }
1156 }
1157 nvlist_free(earg);
1158 free(earg);
1159 free(ename);
1160 }
1161
1162 /*
1163 * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
1164 */
1165 static void
post_frudr_event(char * ename,picl_nodehdl_t parenth,picl_nodehdl_t fruh)1166 post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh)
1167 {
1168 nvlist_t *nvl;
1169 char *ev_name;
1170
1171 ev_name = strdup(ename);
1172 if (ev_name == NULL)
1173 return;
1174 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, 0)) {
1175 free(ev_name);
1176 return;
1177 }
1178 if (parenth != 0L &&
1179 nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) {
1180 free(ev_name);
1181 nvlist_free(nvl);
1182 return;
1183 }
1184 if (fruh != 0L &&
1185 nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) {
1186 free(ev_name);
1187 nvlist_free(nvl);
1188 return;
1189 }
1190 if (ptree_post_event(ev_name, nvl, sizeof (nvl),
1191 frudr_completion_handler) != 0) {
1192 free(ev_name);
1193 nvlist_free(nvl);
1194 }
1195 }
1196
1197 /* Hotplug routine used to add a new power supply */
1198 static int
add_power_supply(int slotnum)1199 add_power_supply(int slotnum)
1200 {
1201 picl_nodehdl_t powersloth;
1202 picl_nodehdl_t powermodh;
1203 picl_nodehdl_t tmph;
1204 int i, err;
1205
1206 /* Find the node for the given power supply slot */
1207 if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1208 &powersloth) == PICL_SUCCESS) {
1209
1210 i = slotnum + PS0;
1211
1212 /* Make sure it's in /platform and create the frutree node */
1213 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
1214 PICL_SUCCESS) {
1215 err = ptree_create_node("power-supply", "fru",
1216 &powermodh);
1217 if (err != PICL_SUCCESS)
1218 return (err);
1219
1220 err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE);
1221 if (err != PICL_SUCCESS)
1222 return (err);
1223
1224 err = add_void_fda_prop(powermodh);
1225 if (err != PICL_SUCCESS)
1226 return (err);
1227
1228 err = ptree_add_node(powersloth, powermodh);
1229 if (err != PICL_SUCCESS)
1230 return (err);
1231
1232 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
1233 if (err != PICL_SUCCESS)
1234 return (err);
1235
1236 /* Post picl-fru-added event */
1237 post_frudr_event(PICL_FRU_ADDED, 0, powermodh);
1238 }
1239 }
1240 return (PICL_SUCCESS);
1241 }
1242
1243 /* Hotplug routine used to remove an existing power supply */
1244 static int
remove_power_supply(int slotnum)1245 remove_power_supply(int slotnum)
1246 {
1247 picl_nodehdl_t powersloth;
1248 picl_nodehdl_t powermodh;
1249 int err;
1250
1251 /* Find the node for the given power supply slot */
1252 if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1253 &powersloth) == PICL_SUCCESS) {
1254 /* Make sure it's got a child, then delete it */
1255 err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD,
1256 &powermodh, sizeof (picl_nodehdl_t));
1257 if (err != PICL_SUCCESS) {
1258 return (err);
1259 }
1260
1261 err = ptree_delete_node(powermodh);
1262 if (err != PICL_SUCCESS) {
1263 return (err);
1264 } else {
1265 (void) ptree_destroy_node(powermodh);
1266 }
1267
1268 /* Post picl-fru-removed event */
1269 post_frudr_event(PICL_FRU_REMOVED, 0, powermodh);
1270
1271 }
1272 return (PICL_SUCCESS);
1273 }
1274
1275 /* Hotplug routine used to add a new CPU Mem Module (with associated DIMMs) */
1276 static int
add_cpu_module(int slotnum)1277 add_cpu_module(int slotnum)
1278 {
1279 picl_nodehdl_t cpumemsloth;
1280 picl_nodehdl_t cpumemmodh;
1281 picl_nodehdl_t tmph;
1282 int i, err;
1283
1284 /* Find the node for the given CPU Memory module slot */
1285 if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
1286 &cpumemsloth) == PICL_SUCCESS) {
1287
1288 i = slotnum + CPUMOD0;
1289
1290 /* Make sure it's in /platform and create the frutree nodes */
1291 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
1292 PICL_SUCCESS) {
1293 err = ptree_create_node("cpu-mem-module", "fru",
1294 &cpumemmodh);
1295 if (err != PICL_SUCCESS)
1296 return (err);
1297
1298 err = add_ref_prop(cpumemmodh, tmph, SEEPROM_SOURCE);
1299 if (err != PICL_SUCCESS)
1300 return (err);
1301
1302 err = add_void_fda_prop(cpumemmodh);
1303 if (err != PICL_SUCCESS)
1304 return (err);
1305
1306 err = ptree_add_node(cpumemsloth, cpumemmodh);
1307 if (err != PICL_SUCCESS)
1308 return (err);
1309
1310 err = add_ref_prop(tmph, cpumemmodh, FRU_PARENT);
1311 if (err != PICL_SUCCESS)
1312 return (err);
1313 }
1314
1315 err = do_cpu_module_init(cpumemmodh, slotnum);
1316 if (err != PICL_SUCCESS)
1317 return (err);
1318 }
1319 return (PICL_SUCCESS);
1320 }
1321
1322 /* Hotplug routine used to remove an existing CPU Mem Module */
1323 static int
remove_cpu_module(int slotnum)1324 remove_cpu_module(int slotnum)
1325 {
1326 picl_nodehdl_t cpumemsloth;
1327 picl_nodehdl_t cpumemmodh;
1328 int err;
1329
1330 /* Find the node for the given CPU Memory module slot */
1331 if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
1332 &cpumemsloth) == PICL_SUCCESS) {
1333 /* Make sure it's got a child, then delete it */
1334 err = ptree_get_propval_by_name(cpumemsloth, PICL_PROP_CHILD,
1335 &cpumemmodh, sizeof (picl_nodehdl_t));
1336 if (err != PICL_SUCCESS) {
1337 return (err);
1338 }
1339
1340 err = remove_all_nodes(cpumemmodh);
1341 if (err != PICL_SUCCESS) {
1342 return (err);
1343 }
1344 }
1345 return (PICL_SUCCESS);
1346 }
1347