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
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]
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
37 #include <libnvpair.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)
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")
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
95 #define DIMMS_PER_MOD 8
96 #define DIMMS_PER_SLOT 16
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",
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 */
195 * List of Labels for FRU locations (uses the #define's from above)
197 static char *location_label
[] = {
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 */
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",
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",
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
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
298 err
= add_all_nodes();
299 if (err
!= PICL_SUCCESS
) {
300 (void) remove_all_nodes(frutreeh
);
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
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
336 picl_frutree_evhandler(const char *ename
, const void *earg
, size_t size
,
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 */
351 do_ioboard_init(picl_nodehdl_t rooth
)
353 picl_nodehdl_t iobrdh
;
357 /* Create the node for the IO board (if it exists) */
358 if (ptree_get_node_by_path(platform_frupath
[IOBRD
], &tmph
) ==
360 err
= ptree_create_node("io-board", "fru", &iobrdh
);
361 if (err
!= PICL_SUCCESS
)
364 err
= add_ref_prop(iobrdh
, tmph
, SEEPROM_SOURCE
);
365 if (err
!= PICL_SUCCESS
)
368 err
= add_void_fda_prop(iobrdh
);
369 if (err
!= PICL_SUCCESS
)
372 err
= ptree_add_node(rooth
, iobrdh
);
373 if (err
!= PICL_SUCCESS
)
376 err
= add_ref_prop(tmph
, iobrdh
, FRU_PARENT
);
377 if (err
!= PICL_SUCCESS
)
380 return (PICL_SUCCESS
);
383 /* Initializes the FRU node for the RSC card */
385 do_rscboard_init(picl_nodehdl_t rooth
)
387 picl_nodehdl_t rscbrdh
;
391 /* Create the node for the RSC board (if it exists) */
392 if (ptree_get_node_by_path(platform_frupath
[RSC
], &tmph
) ==
394 err
= ptree_create_node("rsc-board", "fru", &rscbrdh
);
395 if (err
!= PICL_SUCCESS
)
398 err
= add_ref_prop(rscbrdh
, tmph
, SEEPROM_SOURCE
);
399 if (err
!= PICL_SUCCESS
)
402 err
= add_void_fda_prop(rscbrdh
);
403 if (err
!= PICL_SUCCESS
)
406 err
= ptree_add_node(rooth
, rscbrdh
);
407 if (err
!= PICL_SUCCESS
)
410 err
= add_ref_prop(tmph
, rscbrdh
, FRU_PARENT
);
411 if (err
!= PICL_SUCCESS
)
414 return (PICL_SUCCESS
);
417 /* Initializes the FRU nodes for the FCAL backplanes and GBIC card */
419 do_fcal_init(picl_nodehdl_t rooth
)
421 picl_nodehdl_t fcalsloth
;
422 picl_nodehdl_t fcalmodh
;
423 picl_nodehdl_t fcalgbich
;
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
)
435 err
= add_slot_prop(fcalsloth
, slotnum
);
436 if (err
!= PICL_SUCCESS
)
439 err
= add_label_prop(fcalsloth
, location_label
[i
]);
440 if (err
!= PICL_SUCCESS
)
443 err
= ptree_add_node(rooth
, fcalsloth
);
444 if (err
!= PICL_SUCCESS
)
447 /* If the FCAL backplane exists, create a node for it */
448 if (ptree_get_node_by_path(platform_frupath
[i
], &tmph
) ==
450 err
= ptree_create_node("fcal-backplane", "fru",
452 if (err
!= PICL_SUCCESS
)
455 err
= add_ref_prop(fcalmodh
, tmph
, SEEPROM_SOURCE
);
456 if (err
!= PICL_SUCCESS
)
459 err
= add_void_fda_prop(fcalmodh
);
460 if (err
!= PICL_SUCCESS
)
463 err
= ptree_add_node(fcalsloth
, fcalmodh
);
464 if (err
!= PICL_SUCCESS
)
467 err
= add_ref_prop(tmph
, fcalmodh
, FRU_PARENT
);
468 if (err
!= PICL_SUCCESS
)
473 /* If the FCAL GBIC board exists, create a node for it */
474 if (ptree_get_node_by_path(platform_frupath
[FCALGBIC
], &tmph
) ==
476 err
= ptree_create_node("fcal-gbic-board", "fru",
478 if (err
!= PICL_SUCCESS
)
481 err
= add_ref_prop(fcalgbich
, tmph
, SEEPROM_SOURCE
);
482 if (err
!= PICL_SUCCESS
)
485 err
= add_void_fda_prop(fcalgbich
);
486 if (err
!= PICL_SUCCESS
)
489 err
= ptree_add_node(rooth
, fcalgbich
);
490 if (err
!= PICL_SUCCESS
)
493 err
= add_ref_prop(tmph
, fcalgbich
, FRU_PARENT
);
494 if (err
!= PICL_SUCCESS
)
497 return (PICL_SUCCESS
);
500 /* Initializes the FRU nodes for the PDB and the power supplies */
502 do_power_supplies_init(picl_nodehdl_t rooth
)
504 picl_nodehdl_t powerbrdh
;
505 picl_nodehdl_t powersloth
;
506 picl_nodehdl_t powermodh
;
510 /* Create the node for the PDB (if it exists) */
511 if (ptree_get_node_by_path(platform_frupath
[PDB
], &tmph
) ==
513 err
= ptree_create_node("power-dist-board", "fru", &powerbrdh
);
514 if (err
!= PICL_SUCCESS
)
517 err
= add_ref_prop(powerbrdh
, tmph
, SEEPROM_SOURCE
);
518 if (err
!= PICL_SUCCESS
)
521 err
= add_void_fda_prop(powerbrdh
);
522 if (err
!= PICL_SUCCESS
)
525 err
= ptree_add_node(rooth
, powerbrdh
);
526 if (err
!= PICL_SUCCESS
)
529 err
= add_ref_prop(tmph
, powerbrdh
, FRU_PARENT
);
530 if (err
!= PICL_SUCCESS
)
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
)
541 err
= add_slot_prop(powersloth
, slotnum
);
542 if (err
!= PICL_SUCCESS
)
545 err
= add_label_prop(powersloth
, location_label
[i
]);
546 if (err
!= PICL_SUCCESS
)
549 err
= ptree_add_node(powerbrdh
, powersloth
);
550 if (err
!= PICL_SUCCESS
)
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",
558 if (err
!= PICL_SUCCESS
)
561 err
= add_ref_prop(powermodh
, tmph
,
563 if (err
!= PICL_SUCCESS
)
566 err
= add_void_fda_prop(powermodh
);
567 if (err
!= PICL_SUCCESS
)
570 err
= ptree_add_node(powersloth
, powermodh
);
571 if (err
!= PICL_SUCCESS
)
574 err
= add_ref_prop(tmph
, powermodh
, FRU_PARENT
);
575 if (err
!= PICL_SUCCESS
)
580 return (PICL_SUCCESS
);
583 /* Initializes the FRU nodes for the motherboard and CPU Memory modules */
585 do_motherboard_init(picl_nodehdl_t rooth
)
587 picl_nodehdl_t sysboardh
;
588 picl_nodehdl_t cpumemsloth
;
589 picl_nodehdl_t cpumemmodh
;
593 /* Create the node for the system board (if it exists) */
594 if (ptree_get_node_by_path(platform_frupath
[SYSBRD
], &tmph
) ==
596 err
= ptree_create_node("system-board", "fru",
598 if (err
!= PICL_SUCCESS
)
601 err
= add_ref_prop(sysboardh
, tmph
, SEEPROM_SOURCE
);
602 if (err
!= PICL_SUCCESS
)
605 err
= add_void_fda_prop(sysboardh
);
606 if (err
!= PICL_SUCCESS
)
609 err
= ptree_add_node(rooth
, sysboardh
);
610 if (err
!= PICL_SUCCESS
)
613 err
= add_ref_prop(tmph
, sysboardh
, FRU_PARENT
);
614 if (err
!= PICL_SUCCESS
)
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",
621 if (err
!= PICL_SUCCESS
)
624 slotnum
= i
- CPUMOD0
;
625 err
= add_slot_prop(cpumemsloth
, slotnum
);
626 if (err
!= PICL_SUCCESS
)
629 err
= add_label_prop(cpumemsloth
, location_label
[i
]);
630 if (err
!= PICL_SUCCESS
)
633 err
= ptree_add_node(sysboardh
, cpumemsloth
);
634 if (err
!= PICL_SUCCESS
)
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",
642 if (err
!= PICL_SUCCESS
)
645 err
= add_ref_prop(cpumemmodh
, tmph
,
647 if (err
!= PICL_SUCCESS
)
650 err
= add_void_fda_prop(cpumemmodh
);
651 if (err
!= PICL_SUCCESS
)
654 err
= ptree_add_node(cpumemsloth
, cpumemmodh
);
655 if (err
!= PICL_SUCCESS
)
658 err
= add_ref_prop(tmph
, cpumemmodh
,
660 if (err
!= PICL_SUCCESS
)
663 err
= do_cpu_module_init(cpumemmodh
, slotnum
);
664 if (err
!= PICL_SUCCESS
)
669 return (PICL_SUCCESS
);
672 /* Creates the FRU nodes for the CPU Module and associated DIMMs */
674 do_cpu_module_init(picl_nodehdl_t rooth
, int slot
)
676 picl_nodehdl_t cpumodh
;
679 for (i
= 0; i
<= 1; i
++) {
680 err
= ptree_create_node("cpu-module", "location",
682 if (err
!= PICL_SUCCESS
)
685 err
= add_slot_prop(cpumodh
, i
);
686 if (err
!= PICL_SUCCESS
)
689 c
= CPU0_DIMM0
+ DIMMS_PER_SLOT
+ i
;
691 err
= add_label_prop(cpumodh
, location_label
[c
]);
692 if (err
!= PICL_SUCCESS
)
695 err
= ptree_add_node(rooth
, cpumodh
);
696 if (err
!= PICL_SUCCESS
)
699 /* Create the nodes for the memory (if they exist) */
700 err
= do_dimms_init(cpumodh
, slot
, i
);
701 if (err
!= PICL_SUCCESS
)
704 return (PICL_SUCCESS
);
707 /* Creates the FRU nodes for the DIMMs on a particular CPU Module */
709 do_dimms_init(picl_nodehdl_t rooth
, int slot
, int module
)
711 picl_nodehdl_t dimmsloth
;
712 picl_nodehdl_t dimmmodh
;
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",
720 if (err
!= PICL_SUCCESS
)
723 err
= add_slot_prop(dimmsloth
, i
);
724 if (err
!= PICL_SUCCESS
)
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
)
736 err
= ptree_add_node(rooth
, dimmsloth
);
737 if (err
!= PICL_SUCCESS
)
740 /* If the memory module exists, create a node for it */
741 if (ptree_get_node_by_path(platform_frupath
[c
], &tmph
) ==
743 err
= ptree_create_node("dimm-module", "fru",
745 if (err
!= PICL_SUCCESS
)
748 err
= add_ref_prop(dimmmodh
, tmph
, SEEPROM_SOURCE
);
749 if (err
!= PICL_SUCCESS
)
752 err
= add_void_fda_prop(dimmmodh
);
753 if (err
!= PICL_SUCCESS
)
756 err
= ptree_add_node(dimmsloth
, dimmmodh
);
757 if (err
!= PICL_SUCCESS
)
760 err
= add_ref_prop(tmph
, dimmmodh
, FRU_PARENT
);
761 if (err
!= PICL_SUCCESS
)
765 return (PICL_SUCCESS
);
768 /* Creates a "reference" property between two PICL nodes */
770 add_ref_prop(picl_nodehdl_t nodeh
, picl_nodehdl_t tmph
, char *str
)
772 picl_prophdl_t proph
;
773 ptree_propinfo_t propinfo
;
777 return (PICL_FAILURE
);
779 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
780 PICL_PTYPE_REFERENCE
, PICL_READ
, sizeof (picl_nodehdl_t
),
782 if (err
!= PICL_SUCCESS
)
785 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &tmph
, &proph
);
786 if (err
!= PICL_SUCCESS
)
789 return (PICL_SUCCESS
);
792 /* Creates a "slot" property for a given PICL node */
794 add_slot_prop(picl_nodehdl_t nodeh
, int slotnum
)
796 picl_prophdl_t proph
;
797 ptree_propinfo_t propinfo
;
800 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
801 PICL_PTYPE_INT
, PICL_READ
, 4, "Slot", NULL
, NULL
);
802 if (err
!= PICL_SUCCESS
)
805 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &slotnum
, &proph
);
806 if (err
!= PICL_SUCCESS
)
809 return (PICL_SUCCESS
);
812 /* Creates a "Label" property for a given PICL node */
814 add_label_prop(picl_nodehdl_t nodeh
, char *label
)
816 picl_prophdl_t proph
;
817 ptree_propinfo_t propinfo
;
821 return (PICL_FAILURE
);
823 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
824 PICL_PTYPE_CHARSTRING
, PICL_READ
, strlen(label
)+1, "Label",
826 if (err
!= PICL_SUCCESS
)
829 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, label
, &proph
);
830 if (err
!= PICL_SUCCESS
)
833 return (PICL_SUCCESS
);
836 /* Creates a "FRUDataAvailable" void property for the given PICL node */
838 add_void_fda_prop(picl_nodehdl_t nodeh
)
840 picl_prophdl_t proph
;
841 ptree_propinfo_t propinfo
;
844 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
845 PICL_PTYPE_VOID
, PICL_READ
, 0, "FRUDataAvailable", NULL
, NULL
);
846 if (err
!= PICL_SUCCESS
)
849 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, NULL
, &proph
);
850 if (err
!= PICL_SUCCESS
)
853 return (PICL_SUCCESS
);
856 /* Creates a "ViewPoints" property -- used for chassis */
858 add_viewpoints_prop(picl_nodehdl_t nodeh
, char *string
)
860 picl_prophdl_t proph
;
861 ptree_propinfo_t propinfo
;
865 return (PICL_FAILURE
);
867 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
868 PICL_PTYPE_CHARSTRING
, PICL_READ
, strlen(string
)+1, "ViewPoints",
870 if (err
!= PICL_SUCCESS
)
873 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, string
, &proph
);
874 if (err
!= PICL_SUCCESS
)
877 return (PICL_SUCCESS
);
880 /* Creates and adds all of the frutree nodes */
884 picl_nodehdl_t rooth
;
885 picl_nodehdl_t chassish
;
888 /* Get the root node of the PICL tree */
889 err
= ptree_get_root(&rooth
);
890 if (err
!= PICL_SUCCESS
) {
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
);
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
);
908 /* Add ViewPoints prop to chassis node */
909 err
= add_viewpoints_prop(chassish
, CHASSIS_VIEWPOINTS
);
910 if (err
!= PICL_SUCCESS
)
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
);
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
);
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
);
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
);
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
);
948 return (PICL_SUCCESS
);
951 /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
953 remove_all_nodes(picl_nodehdl_t rooth
)
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
);
964 err
= ptree_delete_node(rooth
);
965 if (err
!= PICL_SUCCESS
) {
968 (void) ptree_destroy_node(rooth
);
973 return (PICL_SUCCESS
);
976 /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */
978 add_hotplug_fru_device()
982 /* Check for hotplugged power supplies */
983 for (i
= PS0
; i
<= PS2
; i
++) {
984 /* Compare the /platform tree to the frutree */
986 err
= is_added_device(platform_frupath
[i
],
987 frutree_power_supply
[slotnum
]);
988 if (err
!= PICL_SUCCESS
)
991 /* If they are different, then add a power supply */
992 err
= add_power_supply(slotnum
);
993 if (err
!= PICL_SUCCESS
)
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
)
1006 /* If they are different, then add a CPU Mem module */
1007 err
= add_cpu_module(slotnum
);
1008 if (err
!= PICL_SUCCESS
)
1011 return (PICL_SUCCESS
);
1014 /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */
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 */
1024 err
= is_removed_device(platform_frupath
[i
],
1025 frutree_power_supply
[slotnum
]);
1026 if (err
!= PICL_SUCCESS
)
1029 /* If they are different, then remove a power supply */
1030 err
= remove_power_supply(slotnum
);
1031 if (err
!= PICL_SUCCESS
)
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
)
1044 /* If they are different, then remove a CPU Mem module */
1045 err
= remove_cpu_module(slotnum
);
1046 if (err
!= PICL_SUCCESS
)
1049 return (PICL_SUCCESS
);
1053 * Compare the /platform tree to the /frutree to determine if a
1054 * new device has been added
1057 is_added_device(char *plat
, char *fru
)
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
)
1068 * The node is in /platform, so find the corresponding slot in
1071 err
= ptree_get_node_by_path(fru
, &frusloth
);
1072 if (err
!= PICL_SUCCESS
)
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
1095 is_removed_device(char *plat
, char *fru
)
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
1110 err
= ptree_get_node_by_path(fru
, &frusloth
);
1111 if (err
!= PICL_SUCCESS
)
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
)
1126 return (PICL_SUCCESS
);
1130 remove_picl_node(picl_nodehdl_t nodeh
)
1133 err
= ptree_delete_node(nodeh
);
1134 if (err
!= PICL_SUCCESS
)
1136 (void) ptree_destroy_node(nodeh
);
1137 return (PICL_SUCCESS
);
1140 /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
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
1153 (void) nvlist_lookup_uint64(earg
,
1154 PICLEVENTARG_FRUHANDLE
, &fruh
);
1156 (void) remove_picl_node(fruh
);
1165 * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
1168 post_frudr_event(char *ename
, picl_nodehdl_t parenth
, picl_nodehdl_t fruh
)
1173 ev_name
= strdup(ename
);
1174 if (ev_name
== NULL
)
1176 if (nvlist_alloc(&nvl
, NV_UNIQUE_NAME_TYPE
, NULL
)) {
1180 if (parenth
!= 0L &&
1181 nvlist_add_uint64(nvl
, PICLEVENTARG_PARENTHANDLE
, parenth
)) {
1187 nvlist_add_uint64(nvl
, PICLEVENTARG_FRUHANDLE
, fruh
)) {
1192 if (ptree_post_event(ev_name
, nvl
, sizeof (nvl
),
1193 frudr_completion_handler
) != 0) {
1199 /* Hotplug routine used to add a new power supply */
1201 add_power_supply(int slotnum
)
1203 picl_nodehdl_t powersloth
;
1204 picl_nodehdl_t powermodh
;
1205 picl_nodehdl_t tmph
;
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
) {
1214 /* Make sure it's in /platform and create the frutree node */
1215 if (ptree_get_node_by_path(platform_frupath
[i
], &tmph
) ==
1217 err
= ptree_create_node("power-supply", "fru",
1219 if (err
!= PICL_SUCCESS
)
1222 err
= add_ref_prop(powermodh
, tmph
, SEEPROM_SOURCE
);
1223 if (err
!= PICL_SUCCESS
)
1226 err
= add_void_fda_prop(powermodh
);
1227 if (err
!= PICL_SUCCESS
)
1230 err
= ptree_add_node(powersloth
, powermodh
);
1231 if (err
!= PICL_SUCCESS
)
1234 err
= add_ref_prop(tmph
, powermodh
, FRU_PARENT
);
1235 if (err
!= PICL_SUCCESS
)
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 */
1247 remove_power_supply(int slotnum
)
1249 picl_nodehdl_t powersloth
;
1250 picl_nodehdl_t powermodh
;
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
) {
1263 err
= ptree_delete_node(powermodh
);
1264 if (err
!= PICL_SUCCESS
) {
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) */
1279 add_cpu_module(int slotnum
)
1281 picl_nodehdl_t cpumemsloth
;
1282 picl_nodehdl_t cpumemmodh
;
1283 picl_nodehdl_t tmph
;
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
) ==
1295 err
= ptree_create_node("cpu-mem-module", "fru",
1297 if (err
!= PICL_SUCCESS
)
1300 err
= add_ref_prop(cpumemmodh
, tmph
, SEEPROM_SOURCE
);
1301 if (err
!= PICL_SUCCESS
)
1304 err
= add_void_fda_prop(cpumemmodh
);
1305 if (err
!= PICL_SUCCESS
)
1308 err
= ptree_add_node(cpumemsloth
, cpumemmodh
);
1309 if (err
!= PICL_SUCCESS
)
1312 err
= add_ref_prop(tmph
, cpumemmodh
, FRU_PARENT
);
1313 if (err
!= PICL_SUCCESS
)
1317 err
= do_cpu_module_init(cpumemmodh
, slotnum
);
1318 if (err
!= PICL_SUCCESS
)
1321 return (PICL_SUCCESS
);
1324 /* Hotplug routine used to remove an existing CPU Mem Module */
1326 remove_cpu_module(int slotnum
)
1328 picl_nodehdl_t cpumemsloth
;
1329 picl_nodehdl_t cpumemmodh
;
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
) {
1342 err
= remove_all_nodes(cpumemmodh
);
1343 if (err
!= PICL_SUCCESS
) {
1347 return (PICL_SUCCESS
);