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