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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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