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 2001-2002 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-480R (Cherrystone) 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_centerplane_init() failed\n")
66 * Viewpoints property field used by SunMC
68 #define CHASSIS_VIEWPOINTS gettext("front top 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
83 #define DISKBACKPLANE 3
90 #define DIMMS_PER_MOD 8
91 #define DIMMS_PER_SLOT 16
96 static picld_plugin_reg_t my_reg_info
= {
97 PICLD_PLUGIN_VERSION_1
,
98 PICLD_PLUGIN_NON_CRITICAL
,
99 "SUNW_Cherrystone_frutree",
105 * List of all the FRUs in the /platform tree with SEEPROMs
107 static char *platform_frupath
[] = {
108 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a2", /* PS 0 */
109 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a0", /* PS 1 */
110 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6", /* RSC */
111 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a8", /* Disk Backplane */
112 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ae", /* PDB */
113 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a8", /* Centerplane */
114 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,aa", /* IO */
115 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0", /* CPU MOD 0 */
116 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2", /* CPU MOD 1 */
117 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0", /* CPU0 DIMM0 */
118 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2", /* CPU0 DIMM1 */
119 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4", /* CPU0 DIMM2 */
120 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6", /* CPU0 DIMM3 */
121 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8", /* CPU0 DIMM4 */
122 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa", /* CPU0 DIMM5 */
123 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac", /* CPU0 DIMM6 */
124 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae", /* CPU0 DIMM7 */
125 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0", /* CPU2 DIMM0 */
126 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2", /* CPU2 DIMM1 */
127 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4", /* CPU2 DIMM2 */
128 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6", /* CPU2 DIMM3 */
129 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8", /* CPU2 DIMM4 */
130 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa", /* CPU2 DIMM5 */
131 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac", /* CPU2 DIMM6 */
132 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae", /* CPU2 DIMM7 */
133 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0", /* CPU1 DIMM0 */
134 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2", /* CPU1 DIMM1 */
135 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4", /* CPU1 DIMM2 */
136 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6", /* CPU1 DIMM3 */
137 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8", /* CPU1 DIMM4 */
138 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa", /* CPU1 DIMM5 */
139 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac", /* CPU1 DIMM6 */
140 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae", /* CPU1 DIMM7 */
141 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0", /* CPU3 DIMM0 */
142 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2", /* CPU3 DIMM1 */
143 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4", /* CPU3 DIMM2 */
144 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6", /* CPU3 DIMM3 */
145 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8", /* CPU3 DIMM4 */
146 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa", /* CPU3 DIMM5 */
147 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac", /* CPU3 DIMM6 */
148 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae", /* CPU3 DIMM7 */
152 * List of Labels for FRU locations (uses the #define's from above)
154 static char *location_label
[] = {
158 NULL
, /* DISKBACKPLANE */
160 NULL
, /* CENTERPLANE */
164 "J2900", /* CPU0 DIMM0 */
165 "J3100", /* CPU0 DIMM1 */
166 "J2901", /* CPU0 DIMM2 */
167 "J3101", /* CPU0 DIMM3 */
168 "J3000", /* CPU0 DIMM4 */
169 "J3200", /* CPU0 DIMM5 */
170 "J3001", /* CPU0 DIMM6 */
171 "J3201", /* CPU0 DIMM7 */
172 "J7900", /* CPU1 DIMM0 */
173 "J8100", /* CPU1 DIMM1 */
174 "J7901", /* CPU1 DIMM2 */
175 "J8101", /* CPU1 DIMM3 */
176 "J8000", /* CPU1 DIMM4 */
177 "J8200", /* CPU1 DIMM5 */
178 "J8001", /* CPU1 DIMM6 */
179 "J8201", /* CPU1 DIMM7 */
180 "0", /* CPU0 label */
181 "1", /* CPU1 label */
185 * List of all the FRU slots for power supplies (hotpluggable)
187 static char *frutree_power_supply
[] = {
188 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=0",
189 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=1",
192 /* PICL handle for the root node of the "frutree" */
193 static picl_nodehdl_t frutreeh
;
195 static int do_ioboard_init(picl_nodehdl_t
);
196 static int do_rscboard_init(picl_nodehdl_t
);
197 static int do_fcal_init(picl_nodehdl_t
);
198 static int do_power_supplies_init(picl_nodehdl_t
);
199 static int do_centerplane_init(picl_nodehdl_t
);
200 static int do_cpu_module_init(picl_nodehdl_t
, int);
201 static int do_dimms_init(picl_nodehdl_t
, int, int);
203 static int add_ref_prop(picl_nodehdl_t
, picl_nodehdl_t
, char *);
204 static int add_slot_prop(picl_nodehdl_t
, int);
205 static int add_label_prop(picl_nodehdl_t
, char *);
206 static int add_void_fda_prop(picl_nodehdl_t
);
207 static int add_viewpoints_prop(picl_nodehdl_t
, char *);
208 static int add_all_nodes();
209 static int remove_all_nodes(picl_nodehdl_t
);
211 static int add_hotplug_fru_device(void);
212 static int rem_hotplug_fru_device(void);
213 static int is_added_device(char *, char *);
214 static int is_removed_device(char *, char *);
215 static int add_power_supply(int);
216 static int remove_power_supply(int);
219 * This function is executed as part of .init when the plugin is
223 picl_frutree_register()
225 (void) picld_plugin_register(&my_reg_info
);
229 * This function is the init entry point of the plugin.
230 * It initializes the /frutree tree
237 err
= add_all_nodes();
238 if (err
!= PICL_SUCCESS
) {
239 (void) remove_all_nodes(frutreeh
);
243 /* Register the event handler routine */
244 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED
,
245 picl_frutree_evhandler
, NULL
);
246 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED
,
247 picl_frutree_evhandler
, NULL
);
251 * This function is the fini entry point of the plugin
254 picl_frutree_fini(void)
256 /* Unregister the event handler routine */
257 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED
,
258 picl_frutree_evhandler
, NULL
);
259 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED
,
260 picl_frutree_evhandler
, NULL
);
262 (void) remove_all_nodes(frutreeh
);
266 * This function is the event handler of this plug-in.
268 * It processes the following events:
270 * PICLEVENT_SYSEVENT_DEVICE_ADDED
271 * PICLEVENT_SYSEVENT_DEVICE_REMOVED
275 picl_frutree_evhandler(const char *ename
, const void *earg
, size_t size
,
278 if (strcmp(ename
, PICLEVENT_SYSEVENT_DEVICE_ADDED
) == 0) {
279 /* Check for and add any hotplugged device(s) */
280 (void) add_hotplug_fru_device();
282 } else if (strcmp(ename
, PICLEVENT_SYSEVENT_DEVICE_REMOVED
) == 0) {
283 /* Check for and remove any hotplugged device(s) */
284 (void) rem_hotplug_fru_device();
288 /* Initializes the FRU nodes for the IO board */
290 do_ioboard_init(picl_nodehdl_t rooth
)
292 picl_nodehdl_t iobrdh
;
296 /* Create the node for the IO board (if it exists) */
297 if (ptree_get_node_by_path(platform_frupath
[IOBRD
], &tmph
) ==
299 err
= ptree_create_node("io-board", "fru", &iobrdh
);
300 if (err
!= PICL_SUCCESS
)
303 err
= add_ref_prop(iobrdh
, tmph
, SEEPROM_SOURCE
);
304 if (err
!= PICL_SUCCESS
)
307 err
= add_void_fda_prop(iobrdh
);
308 if (err
!= PICL_SUCCESS
)
311 err
= ptree_add_node(rooth
, iobrdh
);
312 if (err
!= PICL_SUCCESS
)
315 err
= add_ref_prop(tmph
, iobrdh
, FRU_PARENT
);
316 if (err
!= PICL_SUCCESS
)
319 return (PICL_SUCCESS
);
322 /* Initializes the FRU node for the RSC card */
324 do_rscboard_init(picl_nodehdl_t rooth
)
326 picl_nodehdl_t rscbrdh
;
330 /* Create the node for the RSC board (if it exists) */
331 if (ptree_get_node_by_path(platform_frupath
[RSC
], &tmph
) ==
333 err
= ptree_create_node("rsc-board", "fru", &rscbrdh
);
334 if (err
!= PICL_SUCCESS
)
337 err
= add_ref_prop(rscbrdh
, tmph
, SEEPROM_SOURCE
);
338 if (err
!= PICL_SUCCESS
)
341 err
= add_void_fda_prop(rscbrdh
);
342 if (err
!= PICL_SUCCESS
)
345 err
= ptree_add_node(rooth
, rscbrdh
);
346 if (err
!= PICL_SUCCESS
)
349 err
= add_ref_prop(tmph
, rscbrdh
, FRU_PARENT
);
350 if (err
!= PICL_SUCCESS
)
353 return (PICL_SUCCESS
);
356 /* Initializes the FRU nodes for the FCAL backplaned */
358 do_fcal_init(picl_nodehdl_t rooth
)
360 picl_nodehdl_t fcalsloth
;
361 picl_nodehdl_t fcalmodh
;
365 /* Create the node for the FCAL backplane slot */
366 err
= ptree_create_node("fcal-backplane-slot",
367 "location", &fcalsloth
);
368 if (err
!= PICL_SUCCESS
)
371 err
= add_slot_prop(fcalsloth
, 0);
372 if (err
!= PICL_SUCCESS
)
375 err
= ptree_add_node(rooth
, fcalsloth
);
376 if (err
!= PICL_SUCCESS
)
379 /* If the FCAL backplane exists, create a node for it */
380 if (ptree_get_node_by_path(platform_frupath
[DISKBACKPLANE
], &tmph
) ==
382 err
= ptree_create_node("fcal-backplane", "fru",
384 if (err
!= PICL_SUCCESS
)
387 err
= add_ref_prop(fcalmodh
, tmph
, SEEPROM_SOURCE
);
388 if (err
!= PICL_SUCCESS
)
391 err
= add_void_fda_prop(fcalmodh
);
392 if (err
!= PICL_SUCCESS
)
395 err
= ptree_add_node(fcalsloth
, fcalmodh
);
396 if (err
!= PICL_SUCCESS
)
399 err
= add_ref_prop(tmph
, fcalmodh
, FRU_PARENT
);
400 if (err
!= PICL_SUCCESS
)
403 return (PICL_SUCCESS
);
406 /* Initializes the FRU nodes for the PDB and the power supplies */
408 do_power_supplies_init(picl_nodehdl_t rooth
)
410 picl_nodehdl_t powerbrdh
;
411 picl_nodehdl_t powersloth
;
412 picl_nodehdl_t powermodh
;
416 /* Create the node for the PDB (if it exists) */
417 if (ptree_get_node_by_path(platform_frupath
[PDB
], &tmph
) ==
419 err
= ptree_create_node("power-dist-board", "fru", &powerbrdh
);
420 if (err
!= PICL_SUCCESS
)
423 err
= add_ref_prop(powerbrdh
, tmph
, SEEPROM_SOURCE
);
424 if (err
!= PICL_SUCCESS
)
427 err
= add_void_fda_prop(powerbrdh
);
428 if (err
!= PICL_SUCCESS
)
431 err
= ptree_add_node(rooth
, powerbrdh
);
432 if (err
!= PICL_SUCCESS
)
435 err
= add_ref_prop(tmph
, powerbrdh
, FRU_PARENT
);
436 if (err
!= PICL_SUCCESS
)
439 for (i
= PS0
; i
<= PS1
; i
++) {
440 /* Create the node for the power supply slot */
441 err
= ptree_create_node("power-supply-slot",
442 "location", &powersloth
);
443 if (err
!= PICL_SUCCESS
)
447 err
= add_slot_prop(powersloth
, slotnum
);
448 if (err
!= PICL_SUCCESS
)
451 err
= add_label_prop(powersloth
, location_label
[i
]);
452 if (err
!= PICL_SUCCESS
)
455 err
= ptree_add_node(powerbrdh
, powersloth
);
456 if (err
!= PICL_SUCCESS
)
459 /* If the PS exists, create a node for it */
460 if (ptree_get_node_by_path(platform_frupath
[i
],
461 &tmph
) == PICL_SUCCESS
) {
462 err
= ptree_create_node("power-supply",
464 if (err
!= PICL_SUCCESS
)
467 err
= add_ref_prop(powermodh
, tmph
,
469 if (err
!= PICL_SUCCESS
)
472 err
= add_void_fda_prop(powermodh
);
473 if (err
!= PICL_SUCCESS
)
476 err
= ptree_add_node(powersloth
, powermodh
);
477 if (err
!= PICL_SUCCESS
)
480 err
= add_ref_prop(tmph
, powermodh
, FRU_PARENT
);
481 if (err
!= PICL_SUCCESS
)
486 return (PICL_SUCCESS
);
489 /* Initializes the FRU nodes for the centerplane and CPU Memory modules */
491 do_centerplane_init(picl_nodehdl_t rooth
)
493 picl_nodehdl_t sysboardh
;
494 picl_nodehdl_t cpumemsloth
;
495 picl_nodehdl_t cpumemmodh
;
499 /* Create the node for the system board (if it exists) */
500 if (ptree_get_node_by_path(platform_frupath
[CENTERPLANE
], &tmph
) ==
502 err
= ptree_create_node("centerplane", "fru",
504 if (err
!= PICL_SUCCESS
)
507 err
= add_ref_prop(sysboardh
, tmph
, SEEPROM_SOURCE
);
508 if (err
!= PICL_SUCCESS
)
511 err
= add_void_fda_prop(sysboardh
);
512 if (err
!= PICL_SUCCESS
)
515 err
= ptree_add_node(rooth
, sysboardh
);
516 if (err
!= PICL_SUCCESS
)
519 err
= add_ref_prop(tmph
, sysboardh
, FRU_PARENT
);
520 if (err
!= PICL_SUCCESS
)
523 for (i
= CPUMOD0
; i
<= CPUMOD1
; i
++) {
524 /* Create the node for the CPU Memory slot */
525 err
= ptree_create_node("cpu-mem-slot", "location",
527 if (err
!= PICL_SUCCESS
)
530 slotnum
= i
- CPUMOD0
;
531 err
= add_slot_prop(cpumemsloth
, slotnum
);
532 if (err
!= PICL_SUCCESS
)
535 err
= add_label_prop(cpumemsloth
, location_label
[i
]);
536 if (err
!= PICL_SUCCESS
)
539 err
= ptree_add_node(sysboardh
, cpumemsloth
);
540 if (err
!= PICL_SUCCESS
)
543 /* If CPU Mem module exists, create a node for it */
544 if (ptree_get_node_by_path(platform_frupath
[i
],
545 &tmph
) == PICL_SUCCESS
) {
546 err
= ptree_create_node("cpu-mem-module",
548 if (err
!= PICL_SUCCESS
)
551 err
= add_ref_prop(cpumemmodh
, tmph
,
553 if (err
!= PICL_SUCCESS
)
556 err
= add_void_fda_prop(cpumemmodh
);
557 if (err
!= PICL_SUCCESS
)
560 err
= ptree_add_node(cpumemsloth
, cpumemmodh
);
561 if (err
!= PICL_SUCCESS
)
564 err
= add_ref_prop(tmph
, cpumemmodh
,
566 if (err
!= PICL_SUCCESS
)
569 err
= do_cpu_module_init(cpumemmodh
, slotnum
);
570 if (err
!= PICL_SUCCESS
)
575 return (PICL_SUCCESS
);
578 /* Creates the FRU nodes for the CPU Module and associated DIMMs */
580 do_cpu_module_init(picl_nodehdl_t rooth
, int slot
)
582 picl_nodehdl_t cpumodh
;
585 for (i
= 0; i
<= 1; i
++) {
586 err
= ptree_create_node("cpu-module", "location",
588 if (err
!= PICL_SUCCESS
)
591 err
= add_slot_prop(cpumodh
, i
);
592 if (err
!= PICL_SUCCESS
)
595 c
= CPU0_DIMM0
+ DIMMS_PER_SLOT
+ i
;
597 err
= add_label_prop(cpumodh
, location_label
[c
]);
598 if (err
!= PICL_SUCCESS
)
601 err
= ptree_add_node(rooth
, cpumodh
);
602 if (err
!= PICL_SUCCESS
)
605 /* Create the nodes for the memory (if they exist) */
606 err
= do_dimms_init(cpumodh
, slot
, i
);
607 if (err
!= PICL_SUCCESS
)
610 return (PICL_SUCCESS
);
613 /* Creates the FRU nodes for the DIMMs on a particular CPU Module */
615 do_dimms_init(picl_nodehdl_t rooth
, int slot
, int module
)
617 picl_nodehdl_t dimmsloth
;
618 picl_nodehdl_t dimmmodh
;
622 for (i
= 0; i
< DIMMS_PER_MOD
; i
++) {
623 /* Create the node for the memory slot */
624 err
= ptree_create_node("dimm-slot", "location",
626 if (err
!= PICL_SUCCESS
)
629 err
= add_slot_prop(dimmsloth
, i
);
630 if (err
!= PICL_SUCCESS
)
633 c
= ((slot
* DIMMS_PER_SLOT
) +
634 (module
* DIMMS_PER_MOD
) + i
) + CPU0_DIMM0
;
636 l
= c
- (DIMMS_PER_SLOT
* slot
);
638 err
= add_label_prop(dimmsloth
, location_label
[l
]);
639 if (err
!= PICL_SUCCESS
)
642 err
= ptree_add_node(rooth
, dimmsloth
);
643 if (err
!= PICL_SUCCESS
)
646 /* If the memory module exists, create a node for it */
647 if (ptree_get_node_by_path(platform_frupath
[c
], &tmph
) ==
649 err
= ptree_create_node("dimm-module", "fru",
651 if (err
!= PICL_SUCCESS
)
654 err
= add_ref_prop(dimmmodh
, tmph
, SEEPROM_SOURCE
);
655 if (err
!= PICL_SUCCESS
)
658 err
= add_void_fda_prop(dimmmodh
);
659 if (err
!= PICL_SUCCESS
)
662 err
= ptree_add_node(dimmsloth
, dimmmodh
);
663 if (err
!= PICL_SUCCESS
)
666 err
= add_ref_prop(tmph
, dimmmodh
, FRU_PARENT
);
667 if (err
!= PICL_SUCCESS
)
671 return (PICL_SUCCESS
);
674 /* Creates a "reference" property between two PICL nodes */
676 add_ref_prop(picl_nodehdl_t nodeh
, picl_nodehdl_t tmph
, char *str
)
678 picl_prophdl_t proph
;
679 ptree_propinfo_t propinfo
;
683 return (PICL_FAILURE
);
685 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
686 PICL_PTYPE_REFERENCE
, PICL_READ
, sizeof (picl_nodehdl_t
),
688 if (err
!= PICL_SUCCESS
)
691 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &tmph
, &proph
);
692 if (err
!= PICL_SUCCESS
)
695 return (PICL_SUCCESS
);
698 /* Creates a "slot" property for a given PICL node */
700 add_slot_prop(picl_nodehdl_t nodeh
, int slotnum
)
702 picl_prophdl_t proph
;
703 ptree_propinfo_t propinfo
;
706 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
707 PICL_PTYPE_INT
, PICL_READ
, 4, "Slot", NULL
, NULL
);
708 if (err
!= PICL_SUCCESS
)
711 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, &slotnum
, &proph
);
712 if (err
!= PICL_SUCCESS
)
715 return (PICL_SUCCESS
);
718 /* Creates a "Label" property for a given PICL node */
720 add_label_prop(picl_nodehdl_t nodeh
, char *label
)
722 picl_prophdl_t proph
;
723 ptree_propinfo_t propinfo
;
727 return (PICL_FAILURE
);
729 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
730 PICL_PTYPE_CHARSTRING
, PICL_READ
, strlen(label
)+1, "Label",
732 if (err
!= PICL_SUCCESS
)
735 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, label
, &proph
);
736 if (err
!= PICL_SUCCESS
)
739 return (PICL_SUCCESS
);
742 /* Creates a "FRUDataAvailable" void property for the given PICL node */
744 add_void_fda_prop(picl_nodehdl_t nodeh
)
746 picl_prophdl_t proph
;
747 ptree_propinfo_t propinfo
;
750 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
751 PICL_PTYPE_VOID
, PICL_READ
, 0, "FRUDataAvailable", NULL
, NULL
);
752 if (err
!= PICL_SUCCESS
)
755 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, NULL
, &proph
);
756 if (err
!= PICL_SUCCESS
)
759 return (PICL_SUCCESS
);
762 /* Creates a "ViewPoints" property -- used for chassis */
764 add_viewpoints_prop(picl_nodehdl_t nodeh
, char *string
)
766 picl_prophdl_t proph
;
767 ptree_propinfo_t propinfo
;
771 return (PICL_FAILURE
);
773 err
= ptree_init_propinfo(&propinfo
, PTREE_PROPINFO_VERSION
,
774 PICL_PTYPE_CHARSTRING
, PICL_READ
, strlen(string
)+1, "ViewPoints",
776 if (err
!= PICL_SUCCESS
)
779 err
= ptree_create_and_add_prop(nodeh
, &propinfo
, string
, &proph
);
780 if (err
!= PICL_SUCCESS
)
783 return (PICL_SUCCESS
);
786 /* Creates and adds all of the frutree nodes */
790 picl_nodehdl_t rooth
;
791 picl_nodehdl_t chassish
;
794 /* Get the root node of the PICL tree */
795 err
= ptree_get_root(&rooth
);
796 if (err
!= PICL_SUCCESS
) {
800 /* Create and add the root node of the FRU subtree */
801 err
= ptree_create_and_add_node(rooth
, "frutree", "picl", &frutreeh
);
802 if (err
!= PICL_SUCCESS
) {
803 syslog(LOG_ERR
, CREATE_FRUTREE_FAIL
);
807 /* Create and add the chassis node */
808 err
= ptree_create_and_add_node(frutreeh
, "chassis", "fru", &chassish
);
809 if (err
!= PICL_SUCCESS
) {
810 syslog(LOG_ERR
, CREATE_CHASSIS_FAIL
);
814 /* Add ViewPoints prop to chassis node */
815 err
= add_viewpoints_prop(chassish
, CHASSIS_VIEWPOINTS
);
816 if (err
!= PICL_SUCCESS
)
819 /* Initialize the FRU nodes for the IO board */
820 err
= do_ioboard_init(chassish
);
821 if (err
!= PICL_SUCCESS
) {
822 syslog(LOG_ERR
, IOBRD_INIT_FAIL
);
826 /* Initialize the FRU node for the RSC card */
827 err
= do_rscboard_init(chassish
);
828 if (err
!= PICL_SUCCESS
) {
829 syslog(LOG_ERR
, RSCBRD_INIT_FAIL
);
833 /* Initialize the FRU nodes for the DISK backplane */
834 err
= do_fcal_init(chassish
);
835 if (err
!= PICL_SUCCESS
) {
836 syslog(LOG_ERR
, FCAL_INIT_FAIL
);
840 /* Initialize the FRU nodes for the PDB and the power supplies */
841 err
= do_power_supplies_init(chassish
);
842 if (err
!= PICL_SUCCESS
) {
843 syslog(LOG_ERR
, PS_INIT_FAIL
);
847 /* Initialize the FRU nodes for the CPU Memory modules */
848 err
= do_centerplane_init(chassish
);
849 if (err
!= PICL_SUCCESS
) {
850 syslog(LOG_ERR
, SYSBOARD_INIT_FAIL
);
854 return (PICL_SUCCESS
);
857 /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
859 remove_all_nodes(picl_nodehdl_t rooth
)
865 err
= ptree_get_propval_by_name(rooth
, PICL_PROP_CHILD
, &chdh
,
866 sizeof (picl_nodehdl_t
));
867 if (err
!= PICL_PROPNOTFOUND
) {
868 (void) remove_all_nodes(chdh
);
870 err
= ptree_delete_node(rooth
);
871 if (err
!= PICL_SUCCESS
) {
874 (void) ptree_destroy_node(rooth
);
879 return (PICL_SUCCESS
);
882 /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */
884 add_hotplug_fru_device()
888 /* Check for hotplugged power supplies */
889 for (i
= PS0
; i
<= PS1
; i
++) {
890 /* Compare the /platform tree to the frutree */
892 err
= is_added_device(platform_frupath
[i
],
893 frutree_power_supply
[slotnum
]);
894 if (err
!= PICL_SUCCESS
)
897 /* If they are different, then add a power supply */
898 err
= add_power_supply(slotnum
);
899 if (err
!= PICL_SUCCESS
)
902 return (PICL_SUCCESS
);
905 /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */
907 rem_hotplug_fru_device()
911 /* Check for hotplugged power supplies */
912 for (i
= PS0
; i
<= PS1
; i
++) {
913 /* Compare the /platform tree to the frutree */
915 err
= is_removed_device(platform_frupath
[i
],
916 frutree_power_supply
[slotnum
]);
917 if (err
!= PICL_SUCCESS
)
920 /* If they are different, then remove a power supply */
921 err
= remove_power_supply(slotnum
);
922 if (err
!= PICL_SUCCESS
)
925 return (PICL_SUCCESS
);
929 * Compare the /platform tree to the /frutree to determine if a
930 * new device has been added
933 is_added_device(char *plat
, char *fru
)
936 picl_nodehdl_t plath
, frusloth
, frumodh
;
938 /* Check for node in the /platform tree */
939 err
= ptree_get_node_by_path(plat
, &plath
);
940 if (err
!= PICL_SUCCESS
)
944 * The node is in /platform, so find the corresponding slot in
947 err
= ptree_get_node_by_path(fru
, &frusloth
);
948 if (err
!= PICL_SUCCESS
)
952 * If the slot in the frutree has a child, then return
953 * PICL_FAILURE. This means that the /platform tree and
954 * the frutree are consistent and no action is necessary.
955 * Otherwise return PICL_SUCCESS to indicate that a node needs
956 * to be added to the frutree
958 err
= ptree_get_propval_by_name(frusloth
, PICL_PROP_CHILD
,
959 &frumodh
, sizeof (picl_nodehdl_t
));
960 if (err
== PICL_SUCCESS
)
961 return (PICL_FAILURE
);
963 return (PICL_SUCCESS
);
967 * Compare the /platform tree to the /frutree to determine if a
968 * device has been removed
971 is_removed_device(char *plat
, char *fru
)
974 picl_nodehdl_t plath
, frusloth
, frumodh
;
977 /* Check for node in /platform tree */
978 err
= ptree_get_node_by_path(plat
, &plath
);
979 if (err
== PICL_SUCCESS
)
980 return (PICL_FAILURE
);
983 * The node is not in /platform, so find the corresponding slot in
986 err
= ptree_get_node_by_path(fru
, &frusloth
);
987 if (err
!= PICL_SUCCESS
)
991 * If the slot in the frutree does not have a child, then return
992 * PICL_FAILURE. This means that the /platform tree and
993 * the frutree are consistent and no action is necessary.
994 * Otherwise return PICL_SUCCESS to indicate that the needs
995 * to be removed from the frutree
997 err
= ptree_get_propval_by_name(frusloth
, PICL_PROP_CHILD
,
998 &frumodh
, sizeof (picl_nodehdl_t
));
999 if (err
!= PICL_SUCCESS
)
1002 return (PICL_SUCCESS
);
1006 remove_picl_node(picl_nodehdl_t nodeh
)
1009 err
= ptree_delete_node(nodeh
);
1010 if (err
!= PICL_SUCCESS
)
1012 (void) ptree_destroy_node(nodeh
);
1013 return (PICL_SUCCESS
);
1016 /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
1018 frudr_completion_handler(char *ename
, void *earg
, size_t size
)
1020 picl_nodehdl_t fruh
;
1022 if (strcmp(ename
, PICL_FRU_REMOVED
) == 0) {
1024 * now frudata has been notified that the node is to be
1025 * removed, we can actually remove it
1028 (void) nvlist_lookup_uint64(earg
,
1029 PICLEVENTARG_FRUHANDLE
, &fruh
);
1031 (void) remove_picl_node(fruh
);
1040 * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
1043 post_frudr_event(char *ename
, picl_nodehdl_t parenth
, picl_nodehdl_t fruh
)
1048 ev_name
= strdup(ename
);
1049 if (ev_name
== NULL
)
1051 if (nvlist_alloc(&nvl
, NV_UNIQUE_NAME_TYPE
, NULL
)) {
1055 if (parenth
!= 0L &&
1056 nvlist_add_uint64(nvl
, PICLEVENTARG_PARENTHANDLE
, parenth
)) {
1062 nvlist_add_uint64(nvl
, PICLEVENTARG_FRUHANDLE
, fruh
)) {
1067 if (ptree_post_event(ev_name
, nvl
, sizeof (nvl
),
1068 frudr_completion_handler
) != 0) {
1074 /* Hotplug routine used to add a new power supply */
1076 add_power_supply(int slotnum
)
1078 picl_nodehdl_t powersloth
;
1079 picl_nodehdl_t powermodh
;
1080 picl_nodehdl_t tmph
;
1083 /* Find the node for the given power supply slot */
1084 if (ptree_get_node_by_path(frutree_power_supply
[slotnum
],
1085 &powersloth
) == PICL_SUCCESS
) {
1089 /* Make sure it's in /platform and create the frutree node */
1090 if (ptree_get_node_by_path(platform_frupath
[i
], &tmph
) ==
1092 err
= ptree_create_node("power-supply", "fru",
1094 if (err
!= PICL_SUCCESS
)
1097 err
= add_ref_prop(powermodh
, tmph
, SEEPROM_SOURCE
);
1098 if (err
!= PICL_SUCCESS
)
1101 err
= add_void_fda_prop(powermodh
);
1102 if (err
!= PICL_SUCCESS
)
1105 err
= ptree_add_node(powersloth
, powermodh
);
1106 if (err
!= PICL_SUCCESS
)
1109 err
= add_ref_prop(tmph
, powermodh
, FRU_PARENT
);
1110 if (err
!= PICL_SUCCESS
)
1113 /* Post picl-fru-added event */
1114 post_frudr_event(PICL_FRU_ADDED
, NULL
, powermodh
);
1117 return (PICL_SUCCESS
);
1120 /* Hotplug routine used to remove an existing power supply */
1122 remove_power_supply(int slotnum
)
1124 picl_nodehdl_t powersloth
;
1125 picl_nodehdl_t powermodh
;
1128 /* Find the node for the given power supply slot */
1129 if (ptree_get_node_by_path(frutree_power_supply
[slotnum
],
1130 &powersloth
) == PICL_SUCCESS
) {
1131 /* Make sure it's got a child, then delete it */
1132 err
= ptree_get_propval_by_name(powersloth
, PICL_PROP_CHILD
,
1133 &powermodh
, sizeof (picl_nodehdl_t
));
1134 if (err
!= PICL_SUCCESS
) {
1138 err
= ptree_delete_node(powermodh
);
1139 if (err
!= PICL_SUCCESS
) {
1142 (void) ptree_destroy_node(powermodh
);
1143 /* Post picl-fru-removed event */
1144 post_frudr_event(PICL_FRU_REMOVED
, NULL
, powermodh
);
1146 return (PICL_SUCCESS
);