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 (c) 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 /*
28 * PICL plug-in that creates the FRU Hierarchy for the
29 * SUNW,Sun-Fire-280R (Littleneck) platform
30 */
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <libintl.h>
35 #include <syslog.h>
36 #include <picl.h>
37 #include <picltree.h>
38 #include <picldefs.h>
39
40 /*
41 * Plugin registration entry points
42 */
43 static void picl_frutree_register(void);
44 static void picl_frutree_init(void);
45 static void picl_frutree_fini(void);
46 static void picl_frutree_evhandler(const char *ename, const void *earg,
47 size_t size, void *cookie);
48
49 #pragma init(picl_frutree_register)
50
51 /*
52 * Log message texts
53 */
54 #define CREATE_FRUTREE_FAIL gettext("Failed to create frutree node\n")
55 #define CREATE_CHASSIS_FAIL gettext("Failed to create chassis node\n")
56 #define SYSBRD_INIT_FAIL gettext("do_sysboard_init() failed\n")
57 #define CPUS_INIT_FAIL gettext("do_cpus_init() failed\n")
58 #define DIMMS_INIT_FAIL gettext("do_mem_init() failed\n")
59 #define PS_INIT_FAIL gettext("do_power_supplies_init() failed\n")
60 #define FCAL_INIT_FAIL gettext("do_fcal_init() failed\n")
61 #define RSC_INIT_FAIL gettext("do_rscboard_init() failed\n")
62
63 /*
64 * ViewPoints property field used by SunMC
65 */
66 #define CHASSIS_VIEWPOINTS gettext("front top 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 CPU0 0
79 #define CPU1 1
80 #define DIMM0 2
81 #define DIMM1 3
82 #define DIMM2 4
83 #define DIMM3 5
84 #define DIMM4 6
85 #define DIMM5 7
86 #define DIMM6 8
87 #define DIMM7 9
88 #define PDB 10
89 #define PS0 11
90 #define PS1 12
91 #define FCAL 13
92 #define RSC 14
93 #define SYSBRD 15
94
95 /*
96 * Local variables
97 */
98 static picld_plugin_reg_t my_reg_info = {
99 PICLD_PLUGIN_VERSION_1,
100 PICLD_PLUGIN_NON_CRITICAL,
101 "SUNW_Sun-Fire-280R_frutree",
102 picl_frutree_init,
103 picl_frutree_fini,
104 };
105
106 /*
107 * List of all the FRUs in the /platform tree with SEEPROMs
108 */
109 static char *platform_frupath[] = {
110 "/platform/pci@8,700000/ebus@5/i2c@1,30/cpu-fru@0,a0",
111 "/platform/pci@8,700000/ebus@5/i2c@1,30/cpu-fru@0,a2",
112 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,a0",
113 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,a2",
114 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,a4",
115 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,a6",
116 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,a8",
117 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,aa",
118 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,ac",
119 "/platform/pci@8,700000/ebus@5/i2c@1,2e/dimm-fru@1,ae",
120 "/platform/pci@8,700000/ebus@5/i2c@1,30/power-distribution-board@0,aa",
121 "/platform/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ac",
122 "/platform/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ae",
123 "/platform/pci@8,700000/ebus@5/i2c@1,30/fcal-backplane@0,a4",
124 "/platform/pci@8,700000/ebus@5/i2c@1,30/remote-system-console@0,a6",
125 "/platform/pci@8,700000/ebus@5/i2c@1,30/motherboard-fru@0,a8",
126 NULL};
127
128 /*
129 * List of all the FRU slots in the frutree that can be hotplugged
130 */
131 static char *frutree_power_supply[] = {
132 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=0",
133 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=1",
134 NULL};
135
136 /*
137 * List of Labels for FRU locations (uses the #define's from above)
138 */
139 static char *location_label[] = {
140 "0",
141 "1",
142 "J0100",
143 "J0101",
144 "J0202",
145 "J0203",
146 "J0304",
147 "J0305",
148 "J0406",
149 "J0407",
150 NULL, /* power distribution board placeholder */
151 "0",
152 "1",
153 NULL};
154
155 /* PICL handle for the root node of the "frutree" */
156 static picl_nodehdl_t frutreeh;
157
158 static int do_sysboard_init(picl_nodehdl_t, picl_nodehdl_t *);
159 static int do_cpus_init(picl_nodehdl_t);
160 static int do_mem_init(picl_nodehdl_t);
161 static int do_power_supplies_init(picl_nodehdl_t);
162 static int do_fcal_init(picl_nodehdl_t);
163 static int do_rscboard_init(picl_nodehdl_t);
164
165 static int add_ref_prop(picl_nodehdl_t, picl_nodehdl_t, char *);
166 static int add_slot_prop(picl_nodehdl_t, int);
167 static int add_label_prop(picl_nodehdl_t, char *);
168 static int add_void_fda_prop(picl_nodehdl_t);
169 static int add_viewpoints_prop(picl_nodehdl_t, char *);
170 static int add_all_nodes();
171 static int remove_all_nodes(picl_nodehdl_t);
172
173 static int add_hotplug_fru_device(void);
174 static int rem_hotplug_fru_device(void);
175 static int is_added_device(char *, char *);
176 static int is_removed_device(char *, char *);
177 static int add_power_supply(int);
178 static int remove_power_supply(int);
179
180 /*
181 * This function is executed as part of .init when the plugin is
182 * dlopen()ed
183 */
184 void
picl_frutree_register()185 picl_frutree_register()
186 {
187 (void) picld_plugin_register(&my_reg_info);
188 }
189
190 /*
191 * This function is the init entry point of the plugin.
192 * It initializes the /frutree tree
193 */
194 void
picl_frutree_init()195 picl_frutree_init()
196 {
197 int err;
198
199 err = add_all_nodes();
200 if (err != PICL_SUCCESS) {
201 (void) remove_all_nodes(frutreeh);
202 return;
203 }
204
205 /* Register the event handler routine */
206 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
207 picl_frutree_evhandler, NULL);
208 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
209 picl_frutree_evhandler, NULL);
210 }
211
212 /*
213 * This function is the fini entry point of the plugin
214 */
215 void
picl_frutree_fini(void)216 picl_frutree_fini(void)
217 {
218 /* Unregister the event handler routine */
219 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
220 picl_frutree_evhandler, NULL);
221 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
222 picl_frutree_evhandler, NULL);
223
224 (void) remove_all_nodes(frutreeh);
225 }
226
227 /*
228 * This function is the event handler of this plug-in.
229 *
230 * It processes the following events:
231 *
232 * PICLEVENT_SYSEVENT_DEVICE_ADDED
233 * PICLEVENT_SYSEVENT_DEVICE_REMOVED
234 */
235 /* ARGSUSED */
236 static void
picl_frutree_evhandler(const char * ename,const void * earg,size_t size,void * cookie)237 picl_frutree_evhandler(const char *ename, const void *earg, size_t size,
238 void *cookie)
239 {
240 if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
241 /* Check for and add any hotplugged device(s) */
242 (void) add_hotplug_fru_device();
243
244 } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
245 /* Check for and remove any hotplugged device(s) */
246 (void) rem_hotplug_fru_device();
247 }
248 }
249
250 /* Initialize the FRU node for the system board */
251 static int
do_sysboard_init(picl_nodehdl_t rooth,picl_nodehdl_t * childh)252 do_sysboard_init(picl_nodehdl_t rooth, picl_nodehdl_t *childh)
253 {
254 picl_nodehdl_t tmph;
255 int err;
256
257 /* Create the node for the system board */
258 if (ptree_get_node_by_path(platform_frupath[SYSBRD], &tmph) ==
259 PICL_SUCCESS) {
260 err = ptree_create_node("system-board", "fru", childh);
261 if (err != PICL_SUCCESS)
262 return (err);
263
264 err = add_ref_prop(*childh, tmph, SEEPROM_SOURCE);
265 if (err != PICL_SUCCESS)
266 return (err);
267
268 err = add_void_fda_prop(*childh);
269 if (err != PICL_SUCCESS)
270 return (err);
271
272 err = ptree_add_node(rooth, *childh);
273 if (err != PICL_SUCCESS)
274 return (err);
275
276 err = add_ref_prop(tmph, *childh, FRU_PARENT);
277 if (err != PICL_SUCCESS)
278 return (err);
279
280 }
281 return (PICL_SUCCESS);
282 }
283
284 /* Initializes the FRU nodes for the CPU modules */
285 static int
do_cpus_init(picl_nodehdl_t rooth)286 do_cpus_init(picl_nodehdl_t rooth)
287 {
288 picl_nodehdl_t cpusloth;
289 picl_nodehdl_t cpumodh;
290 picl_nodehdl_t tmph;
291 int i, err;
292
293 for (i = CPU0; i <= CPU1; i++) {
294 /* Create the node for the CPU slot */
295 err = ptree_create_node("cpu-slot", "location", &cpusloth);
296 if (err != PICL_SUCCESS)
297 return (err);
298
299 err = add_slot_prop(cpusloth, i);
300 if (err != PICL_SUCCESS)
301 return (err);
302
303 err = add_label_prop(cpusloth, location_label[i]);
304 if (err != PICL_SUCCESS)
305 return (err);
306
307 err = ptree_add_node(rooth, cpusloth);
308 if (err != PICL_SUCCESS)
309 return (err);
310
311 /* If the CPU module exists, create a node for it */
312 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
313 PICL_SUCCESS) {
314 err = ptree_create_node("cpu-module", "fru", &cpumodh);
315 if (err != PICL_SUCCESS)
316 return (err);
317
318 err = add_ref_prop(cpumodh, tmph, SEEPROM_SOURCE);
319 if (err != PICL_SUCCESS)
320 return (err);
321
322 err = add_void_fda_prop(cpumodh);
323 if (err != PICL_SUCCESS)
324 return (err);
325
326 err = ptree_add_node(cpusloth, cpumodh);
327 if (err != PICL_SUCCESS)
328 return (err);
329
330 err = add_ref_prop(tmph, cpumodh, FRU_PARENT);
331 if (err != PICL_SUCCESS)
332 return (err);
333 }
334 }
335 return (PICL_SUCCESS);
336 }
337
338 /* Initializes the FRU nodes for the memory modules */
339 static int
do_mem_init(picl_nodehdl_t rooth)340 do_mem_init(picl_nodehdl_t rooth)
341 {
342 picl_nodehdl_t memsloth;
343 picl_nodehdl_t memmodh;
344 picl_nodehdl_t tmph;
345 int i, err, slotnum;
346
347 for (i = DIMM0; i <= DIMM7; i++) {
348 /* Create the node for the memory slot */
349 err = ptree_create_node("mem-slot", "location", &memsloth);
350 if (err != PICL_SUCCESS)
351 return (err);
352
353 slotnum = i - DIMM0;
354 err = add_slot_prop(memsloth, slotnum);
355 if (err != PICL_SUCCESS)
356 return (err);
357
358 err = add_label_prop(memsloth, location_label[i]);
359 if (err != PICL_SUCCESS)
360 return (err);
361
362 err = ptree_add_node(rooth, memsloth);
363 if (err != PICL_SUCCESS)
364 return (err);
365
366 /* If the memory exists, create a node for it */
367 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
368 PICL_SUCCESS) {
369 err = ptree_create_node("mem-module", "fru", &memmodh);
370 if (err != PICL_SUCCESS)
371 return (err);
372
373 err = add_ref_prop(memmodh, tmph, SEEPROM_SOURCE);
374 if (err != PICL_SUCCESS)
375 return (err);
376
377 err = add_void_fda_prop(memmodh);
378 if (err != PICL_SUCCESS)
379 return (err);
380
381 err = ptree_add_node(memsloth, memmodh);
382 if (err != PICL_SUCCESS)
383 return (err);
384
385 err = add_ref_prop(tmph, memmodh, FRU_PARENT);
386 if (err != PICL_SUCCESS)
387 return (err);
388 }
389 }
390 return (PICL_SUCCESS);
391 }
392
393 /* Initializes the FRU nodes for the PDB and the power supplies */
394 static int
do_power_supplies_init(picl_nodehdl_t rooth)395 do_power_supplies_init(picl_nodehdl_t rooth)
396 {
397 picl_nodehdl_t powerbrdh;
398 picl_nodehdl_t powersloth;
399 picl_nodehdl_t powermodh;
400 picl_nodehdl_t tmph;
401 int i, err, slotnum;
402
403 /* Create the node for the PDB (if it exists) */
404 if (ptree_get_node_by_path(platform_frupath[PDB], &tmph) ==
405 PICL_SUCCESS) {
406 err = ptree_create_node("power-dist-board", "fru", &powerbrdh);
407 if (err != PICL_SUCCESS)
408 return (err);
409
410 err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE);
411 if (err != PICL_SUCCESS)
412 return (err);
413
414 err = add_void_fda_prop(powerbrdh);
415 if (err != PICL_SUCCESS)
416 return (err);
417
418 err = ptree_add_node(rooth, powerbrdh);
419 if (err != PICL_SUCCESS)
420 return (err);
421
422 err = add_ref_prop(tmph, powerbrdh, FRU_PARENT);
423 if (err != PICL_SUCCESS)
424 return (err);
425
426 for (i = PS0; i <= PS1; i++) {
427 /* Create the node for the power supply slot */
428 err = ptree_create_node("power-supply-slot",
429 "location", &powersloth);
430 if (err != PICL_SUCCESS)
431 return (err);
432
433 slotnum = i - PS0;
434 err = add_slot_prop(powersloth, slotnum);
435 if (err != PICL_SUCCESS)
436 return (err);
437
438 err = add_label_prop(powersloth, location_label[i]);
439 if (err != PICL_SUCCESS)
440 return (err);
441
442 err = ptree_add_node(powerbrdh, powersloth);
443 if (err != PICL_SUCCESS)
444 return (err);
445
446 /* If the PS exists, create a node for it */
447 if (ptree_get_node_by_path(platform_frupath[i],
448 &tmph) == PICL_SUCCESS) {
449 err = ptree_create_node("power-supply",
450 "fru", &powermodh);
451 if (err != PICL_SUCCESS)
452 return (err);
453
454 err = add_ref_prop(powermodh, tmph,
455 SEEPROM_SOURCE);
456 if (err != PICL_SUCCESS)
457 return (err);
458
459 err = add_void_fda_prop(powermodh);
460 if (err != PICL_SUCCESS)
461 return (err);
462
463 err = ptree_add_node(powersloth, powermodh);
464 if (err != PICL_SUCCESS)
465 return (err);
466
467 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
468 if (err != PICL_SUCCESS)
469 return (err);
470 }
471 }
472 }
473 return (PICL_SUCCESS);
474 }
475
476 /* Initializes the FRU nodes for the FCAL backplane */
477 static int
do_fcal_init(picl_nodehdl_t rooth)478 do_fcal_init(picl_nodehdl_t rooth)
479 {
480 picl_nodehdl_t fcalbrdh;
481 picl_nodehdl_t tmph;
482 int err;
483
484 /* Create the node for the FCAL backplane (if it exists) */
485 if (ptree_get_node_by_path(platform_frupath[FCAL], &tmph) ==
486 PICL_SUCCESS) {
487 err = ptree_create_node("fcal-backplane", "fru", &fcalbrdh);
488 if (err != PICL_SUCCESS)
489 return (err);
490
491 err = add_ref_prop(fcalbrdh, tmph, SEEPROM_SOURCE);
492 if (err != PICL_SUCCESS)
493 return (err);
494
495 err = add_void_fda_prop(fcalbrdh);
496 if (err != PICL_SUCCESS)
497 return (err);
498
499 err = ptree_add_node(rooth, fcalbrdh);
500 if (err != PICL_SUCCESS)
501 return (err);
502
503 err = add_ref_prop(tmph, fcalbrdh, FRU_PARENT);
504 if (err != PICL_SUCCESS)
505 return (err);
506 }
507 return (PICL_SUCCESS);
508 }
509
510 /* Initializes the FRU node for the RSC card */
511 static int
do_rscboard_init(picl_nodehdl_t rooth)512 do_rscboard_init(picl_nodehdl_t rooth)
513 {
514 picl_nodehdl_t rscbrdh;
515 picl_nodehdl_t tmph;
516 int err;
517
518 /* Create the node for the RSC board (if it exists) */
519 if (ptree_get_node_by_path(platform_frupath[RSC], &tmph) ==
520 PICL_SUCCESS) {
521 err = ptree_create_node("rsc-board", "fru", &rscbrdh);
522 if (err != PICL_SUCCESS)
523 return (err);
524
525 err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE);
526 if (err != PICL_SUCCESS)
527 return (err);
528
529 err = add_void_fda_prop(rscbrdh);
530 if (err != PICL_SUCCESS)
531 return (err);
532
533 err = ptree_add_node(rooth, rscbrdh);
534 if (err != PICL_SUCCESS)
535 return (err);
536
537 err = add_ref_prop(tmph, rscbrdh, FRU_PARENT);
538 if (err != PICL_SUCCESS)
539 return (err);
540 }
541 return (PICL_SUCCESS);
542 }
543
544 /* Creates a "reference" property between two PICL nodes */
545 static int
add_ref_prop(picl_nodehdl_t nodeh,picl_nodehdl_t tmph,char * str)546 add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str)
547 {
548 picl_prophdl_t proph;
549 ptree_propinfo_t propinfo;
550 int err;
551
552 if (str == NULL)
553 return (PICL_FAILURE);
554
555 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
556 PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
557 str, NULL, NULL);
558 if (err != PICL_SUCCESS)
559 return (err);
560
561 err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph);
562 if (err != PICL_SUCCESS)
563 return (err);
564
565 return (PICL_SUCCESS);
566 }
567
568 /* Creates a "Slot" property for a given PICL node */
569 static int
add_slot_prop(picl_nodehdl_t nodeh,int slotnum)570 add_slot_prop(picl_nodehdl_t nodeh, int slotnum)
571 {
572 picl_prophdl_t proph;
573 ptree_propinfo_t propinfo;
574 int err;
575
576 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
577 PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL);
578 if (err != PICL_SUCCESS)
579 return (err);
580
581 err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph);
582 if (err != PICL_SUCCESS)
583 return (err);
584
585 return (PICL_SUCCESS);
586 }
587
588 /* Creates a "Label" property for a given PICL node */
589 static int
add_label_prop(picl_nodehdl_t nodeh,char * label)590 add_label_prop(picl_nodehdl_t nodeh, char *label)
591 {
592 picl_prophdl_t proph;
593 ptree_propinfo_t propinfo;
594 int err;
595
596 if (label == NULL)
597 return (PICL_FAILURE);
598
599 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
600 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label",
601 NULL, NULL);
602 if (err != PICL_SUCCESS)
603 return (err);
604
605 err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph);
606 if (err != PICL_SUCCESS)
607 return (err);
608
609 return (PICL_SUCCESS);
610 }
611
612 /* Creates a "FRUDataAvailable" void property for the given PICL node */
613 static int
add_void_fda_prop(picl_nodehdl_t nodeh)614 add_void_fda_prop(picl_nodehdl_t nodeh)
615 {
616 picl_prophdl_t proph;
617 ptree_propinfo_t propinfo;
618 int err;
619
620 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
621 PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL);
622 if (err != PICL_SUCCESS)
623 return (err);
624
625 err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
626 if (err != PICL_SUCCESS)
627 return (err);
628
629 return (PICL_SUCCESS);
630 }
631
632 /* Creates a "ViewPoints" property -- used for chassis */
633 static int
add_viewpoints_prop(picl_nodehdl_t nodeh,char * string)634 add_viewpoints_prop(picl_nodehdl_t nodeh, char *string)
635 {
636 picl_prophdl_t proph;
637 ptree_propinfo_t propinfo;
638 int err;
639
640 if (string == NULL)
641 return (PICL_FAILURE);
642
643 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
644 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints",
645 NULL, NULL);
646 if (err != PICL_SUCCESS)
647 return (err);
648
649 err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph);
650 if (err != PICL_SUCCESS)
651 return (err);
652
653 return (PICL_SUCCESS);
654 }
655
656 /* Creates and adds all of the frutree nodes */
657 static int
add_all_nodes()658 add_all_nodes()
659 {
660 picl_nodehdl_t rooth;
661 picl_nodehdl_t chassish;
662 picl_nodehdl_t sysboardh;
663 int err;
664
665 /* Get the root node of the PICL tree */
666 err = ptree_get_root(&rooth);
667 if (err != PICL_SUCCESS) {
668 return (err);
669 }
670
671 /* Create and add the root node of the FRU subtree */
672 err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh);
673 if (err != PICL_SUCCESS) {
674 syslog(LOG_ERR, CREATE_FRUTREE_FAIL);
675 return (err);
676 }
677
678 /* Create and add the chassis node */
679 err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish);
680 if (err != PICL_SUCCESS) {
681 syslog(LOG_ERR, CREATE_CHASSIS_FAIL);
682 return (err);
683 }
684
685 /* Add ViewPoints prop to chassis node */
686 err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS);
687 if (err != PICL_SUCCESS)
688 return (err);
689
690 /* Initialize the FRU node for the system board */
691 err = do_sysboard_init(chassish, &sysboardh);
692 if (err != PICL_SUCCESS) {
693 syslog(LOG_ERR, SYSBRD_INIT_FAIL);
694 return (err);
695 }
696
697 /* Initialize the FRU nodes for the CPU modules */
698 err = do_cpus_init(sysboardh);
699 if (err != PICL_SUCCESS) {
700 syslog(LOG_ERR, CPUS_INIT_FAIL);
701 return (err);
702 }
703
704 /* Initialize the FRU nodes for the memory modules */
705 err = do_mem_init(sysboardh);
706 if (err != PICL_SUCCESS) {
707 syslog(LOG_ERR, DIMMS_INIT_FAIL);
708 return (err);
709 }
710
711 /* Initialize the FRU nodes for the PDB and the power supplies */
712 err = do_power_supplies_init(chassish);
713 if (err != PICL_SUCCESS) {
714 syslog(LOG_ERR, PS_INIT_FAIL);
715 return (err);
716 }
717
718 /* Initialize the FRU nodes for the FCAL backplane */
719 err = do_fcal_init(chassish);
720 if (err != PICL_SUCCESS) {
721 syslog(LOG_ERR, FCAL_INIT_FAIL);
722 return (err);
723 }
724
725 /* Initialize the FRU node for the RSC card */
726 err = do_rscboard_init(chassish);
727 if (err != PICL_SUCCESS) {
728 syslog(LOG_ERR, RSC_INIT_FAIL);
729 return (err);
730 }
731
732 return (PICL_SUCCESS);
733 }
734
735 /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
736 static int
remove_all_nodes(picl_nodehdl_t rooth)737 remove_all_nodes(picl_nodehdl_t rooth)
738 {
739 picl_nodehdl_t chdh;
740 int err, done = 0;
741
742 while (!done) {
743 err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
744 sizeof (picl_nodehdl_t));
745 if (err != PICL_PROPNOTFOUND) {
746 (void) remove_all_nodes(chdh);
747 } else {
748 err = ptree_delete_node(rooth);
749 if (err != PICL_SUCCESS) {
750 return (err);
751 } else {
752 (void) ptree_destroy_node(rooth);
753 }
754 done = 1;
755 }
756 }
757 return (PICL_SUCCESS);
758 }
759
760 /*
761 * Searches the list of hotpluggable FRUs for this platform and adds the
762 * appropriate node(s) to the frutree
763 */
764 static int
add_hotplug_fru_device()765 add_hotplug_fru_device()
766 {
767 int i, err, slotnum;
768
769 /* Check for hotplugged power supplies */
770 for (i = PS0; i <= PS1; i++) {
771 /* Compare the /platform tree to the frutree */
772 slotnum = i - PS0;
773 err = is_added_device(platform_frupath[i],
774 frutree_power_supply[slotnum]);
775 if (err != PICL_SUCCESS)
776 continue;
777
778 /* If they are different, then add a power supply */
779 err = add_power_supply(slotnum);
780 if (err != PICL_SUCCESS)
781 continue;
782 }
783 return (PICL_SUCCESS);
784 }
785
786 /*
787 * Searches the list of hotpluggable FRUs for this platform and removes the
788 * appropriate node(s) from the frutree
789 */
790 static int
rem_hotplug_fru_device()791 rem_hotplug_fru_device()
792 {
793 int i, err, slotnum;
794
795 /* Check for hotplugged power supplies */
796 for (i = PS0; i <= PS1; i++) {
797 /* Compare the /platform tree to the frutree */
798 slotnum = i - PS0;
799 err = is_removed_device(platform_frupath[i],
800 frutree_power_supply[slotnum]);
801 if (err != PICL_SUCCESS)
802 continue;
803
804 /* If they are different, then remove a power supply */
805 err = remove_power_supply(slotnum);
806 if (err != PICL_SUCCESS)
807 continue;
808 }
809 return (PICL_SUCCESS);
810 }
811
812 /*
813 * Compare the /platform tree to the /frutree to determine if a
814 * new device has been added
815 */
816 static int
is_added_device(char * plat,char * fru)817 is_added_device(char *plat, char *fru)
818 {
819 int err;
820 picl_nodehdl_t plath, frusloth, frumodh;
821
822 /* Check for node in the /platform tree */
823 err = ptree_get_node_by_path(plat, &plath);
824 if (err != PICL_SUCCESS)
825 return (err);
826
827 /*
828 * The node is in /platform, so find the corresponding slot in
829 * the frutree
830 */
831 err = ptree_get_node_by_path(fru, &frusloth);
832 if (err != PICL_SUCCESS)
833 return (err);
834
835 /*
836 * If the slot in the frutree has a child, then return
837 * PICL_FAILURE. This means that the /platform tree and
838 * the frutree are consistent and no action is necessary.
839 * Otherwise return PICL_SUCCESS to indicate that a node needs
840 * to be added to the frutree
841 */
842 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
843 &frumodh, sizeof (picl_nodehdl_t));
844 if (err == PICL_SUCCESS)
845 return (PICL_FAILURE);
846
847 return (PICL_SUCCESS);
848 }
849
850 /*
851 * Compare the /platform tree to the /frutree to determine if a
852 * device has been removed
853 */
854 static int
is_removed_device(char * plat,char * fru)855 is_removed_device(char *plat, char *fru)
856 {
857 int err;
858 picl_nodehdl_t plath, frusloth, frumodh;
859
860
861 /* Check for node in /platform tree */
862 err = ptree_get_node_by_path(plat, &plath);
863 if (err == PICL_SUCCESS)
864 return (PICL_FAILURE);
865
866 /*
867 * The node is not in /platform, so find the corresponding slot in
868 * the frutree
869 */
870 err = ptree_get_node_by_path(fru, &frusloth);
871 if (err != PICL_SUCCESS)
872 return (err);
873
874 /*
875 * If the slot in the frutree does not have a child, then return
876 * PICL_FAILURE. This means that the /platform tree and
877 * the frutree are consistent and no action is necessary.
878 * Otherwise return PICL_SUCCESS to indicate that the needs
879 * to be removed from the frutree
880 */
881 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
882 &frumodh, sizeof (picl_nodehdl_t));
883 if (err != PICL_SUCCESS)
884 return (PICL_FAILURE);
885
886 return (PICL_SUCCESS);
887 }
888
889 /* Hotplug routine used to add a new power supply */
890 static int
add_power_supply(int slotnum)891 add_power_supply(int slotnum)
892 {
893 picl_nodehdl_t powersloth;
894 picl_nodehdl_t powermodh;
895 picl_nodehdl_t tmph;
896 int i, err;
897
898 /* Find the node for the given power supply slot */
899 if (ptree_get_node_by_path(frutree_power_supply[slotnum],
900 &powersloth) == PICL_SUCCESS) {
901
902 i = slotnum + PS0;
903
904 /* Make sure it's in /platform and create the frutree node */
905 if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
906 PICL_SUCCESS) {
907 err = ptree_create_node("power-supply", "fru",
908 &powermodh);
909 if (err != PICL_SUCCESS)
910 return (err);
911
912 err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE);
913 if (err != PICL_SUCCESS)
914 return (err);
915
916 err = add_void_fda_prop(powermodh);
917 if (err != PICL_SUCCESS)
918 return (err);
919
920 err = ptree_add_node(powersloth, powermodh);
921 if (err != PICL_SUCCESS)
922 return (err);
923
924 err = add_ref_prop(tmph, powermodh, FRU_PARENT);
925 if (err != PICL_SUCCESS)
926 return (err);
927 }
928 }
929 return (PICL_SUCCESS);
930 }
931
932 /* Hotplug routine used to remove an existing power supply */
933 static int
remove_power_supply(int slotnum)934 remove_power_supply(int slotnum)
935 {
936 picl_nodehdl_t powersloth;
937 picl_nodehdl_t powermodh;
938 int err;
939
940 /* Find the node for the given power supply slot */
941 if (ptree_get_node_by_path(frutree_power_supply[slotnum],
942 &powersloth) == PICL_SUCCESS) {
943 /* Make sure it's got a child, then delete it */
944 err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD,
945 &powermodh, sizeof (picl_nodehdl_t));
946 if (err != PICL_SUCCESS) {
947 return (err);
948 }
949
950 err = ptree_delete_node(powermodh);
951 if (err != PICL_SUCCESS) {
952 return (err);
953 } else {
954 (void) ptree_destroy_node(powermodh);
955 }
956 }
957 return (PICL_SUCCESS);
958 }
959