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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 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-880 (Daktari) platform 32 */ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <libintl.h> 37 #include <libnvpair.h> 38 #include <syslog.h> 39 #include <picl.h> 40 #include <picltree.h> 41 #include <picldefs.h> 42 43 /* 44 * Plugin registration entry points 45 */ 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); 51 52 #pragma init(picl_frutree_register) 53 54 /* 55 * Log message texts 56 */ 57 #define CREATE_FRUTREE_FAIL gettext("Failed to create frutree node\n") 58 #define CREATE_CHASSIS_FAIL gettext("Failed to create chassis node\n") 59 #define IOBRD_INIT_FAIL gettext("do_ioboard_init() failed\n") 60 #define RSCBRD_INIT_FAIL gettext("do_rscboard_init() failed\n") 61 #define FCAL_INIT_FAIL gettext("do_fcal_init() failed\n") 62 #define PS_INIT_FAIL gettext("do_power_supplies_init() failed\n") 63 #define SYSBOARD_INIT_FAIL gettext("do_motherboard_init() failed\n") 64 65 /* 66 * Viewpoints property field used by SunMC 67 */ 68 #define CHASSIS_VIEWPOINTS gettext("front left right 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 IOBRD 0 81 #define RSC 1 82 #define FCAL0 2 83 #define FCAL1 3 84 #define FCALGBIC 4 85 #define PDB 5 86 #define PS0 6 87 #define PS1 7 88 #define PS2 8 89 #define SYSBRD 9 90 #define CPUMOD0 10 91 #define CPUMOD1 11 92 #define CPUMOD2 12 93 #define CPUMOD3 13 94 #define CPU0_DIMM0 14 95 #define DIMMS_PER_MOD 8 96 #define DIMMS_PER_SLOT 16 97 98 99 /* 100 * Local variables 101 */ 102 static picld_plugin_reg_t my_reg_info = { 103 PICLD_PLUGIN_VERSION_1, 104 PICLD_PLUGIN_NON_CRITICAL, 105 "SUNW_Sun-Fire-880_frutree", 106 picl_frutree_init, 107 picl_frutree_fini 108 }; 109 110 /* 111 * List of all the FRUs in the /platform tree with SEEPROMs 112 */ 113 static char *platform_frupath[] = { 114 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,aa", /* IO */ 115 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6", /* RSC */ 116 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a8", /* FCAL 0 */ 117 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ac", /* FCAL 1 */ 118 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,aa", /* FCAL-GBIC */ 119 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ae", /* PDB */ 120 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a0", /* PS 0 */ 121 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a2", /* PS 1 */ 122 "/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a4", /* PS 2 */ 123 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a8", /* SYS BRD */ 124 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0", /* CPU MOD 0 */ 125 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2", /* CPU MOD 1 */ 126 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a4", /* CPU MOD 2 */ 127 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a6", /* CPU MOD 3 */ 128 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0", /* CPU0 DIMM0 */ 129 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2", /* CPU0 DIMM1 */ 130 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4", /* CPU0 DIMM2 */ 131 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6", /* CPU0 DIMM3 */ 132 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8", /* CPU0 DIMM4 */ 133 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa", /* CPU0 DIMM5 */ 134 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac", /* CPU0 DIMM6 */ 135 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae", /* CPU0 DIMM7 */ 136 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0", /* CPU2 DIMM0 */ 137 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2", /* CPU2 DIMM1 */ 138 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4", /* CPU2 DIMM2 */ 139 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6", /* CPU2 DIMM3 */ 140 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8", /* CPU2 DIMM4 */ 141 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa", /* CPU2 DIMM5 */ 142 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac", /* CPU2 DIMM6 */ 143 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae", /* CPU2 DIMM7 */ 144 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0", /* CPU1 DIMM0 */ 145 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2", /* CPU1 DIMM1 */ 146 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4", /* CPU1 DIMM2 */ 147 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6", /* CPU1 DIMM3 */ 148 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8", /* CPU1 DIMM4 */ 149 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa", /* CPU1 DIMM5 */ 150 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac", /* CPU1 DIMM6 */ 151 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae", /* CPU1 DIMM7 */ 152 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0", /* CPU3 DIMM0 */ 153 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2", /* CPU3 DIMM1 */ 154 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4", /* CPU3 DIMM2 */ 155 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6", /* CPU3 DIMM3 */ 156 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8", /* CPU3 DIMM4 */ 157 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa", /* CPU3 DIMM5 */ 158 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac", /* CPU3 DIMM6 */ 159 "/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae", /* CPU3 DIMM7 */ 160 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a0", /* CPU4 DIMM0 */ 161 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a2", /* CPU4 DIMM1 */ 162 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a4", /* CPU4 DIMM2 */ 163 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a6", /* CPU4 DIMM3 */ 164 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a8", /* CPU4 DIMM4 */ 165 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,aa", /* CPU4 DIMM5 */ 166 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ac", /* CPU4 DIMM6 */ 167 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ae", /* CPU4 DIMM7 */ 168 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a0", /* CPU6 DIMM0 */ 169 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a2", /* CPU6 DIMM1 */ 170 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a4", /* CPU6 DIMM2 */ 171 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a6", /* CPU6 DIMM3 */ 172 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a8", /* CPU6 DIMM4 */ 173 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,aa", /* CPU6 DIMM5 */ 174 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ac", /* CPU6 DIMM6 */ 175 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ae", /* CPU6 DIMM7 */ 176 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a0", /* CPU5 DIMM0 */ 177 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a2", /* CPU5 DIMM1 */ 178 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a4", /* CPU5 DIMM2 */ 179 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a6", /* CPU5 DIMM3 */ 180 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a8", /* CPU5 DIMM4 */ 181 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,aa", /* CPU5 DIMM5 */ 182 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ac", /* CPU5 DIMM6 */ 183 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ae", /* CPU5 DIMM7 */ 184 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a0", /* CPU7 DIMM0 */ 185 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a2", /* CPU7 DIMM1 */ 186 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a4", /* CPU7 DIMM2 */ 187 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a6", /* CPU7 DIMM3 */ 188 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a8", /* CPU7 DIMM4 */ 189 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,aa", /* CPU7 DIMM5 */ 190 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ac", /* CPU7 DIMM6 */ 191 "/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ae", /* CPU7 DIMM7 */ 192 NULL}; 193 194 /* 195 * List of Labels for FRU locations (uses the #define's from above) 196 */ 197 static char *location_label[] = { 198 NULL, /* IOBRD */ 199 NULL, /* RSC */ 200 "0", /* FCAL0 */ 201 "1", /* FCAL1 */ 202 NULL, /* FCALGBIC */ 203 NULL, /* PDB */ 204 "0", /* PS0 */ 205 "1", /* PS1 */ 206 "2", /* PS2 */ 207 NULL, /* SYSBRD */ 208 "A", /* CPUMOD0 */ 209 "B", /* CPUMOD1 */ 210 "C", /* CPUMOD2 */ 211 "D", /* CPUMOD3 */ 212 "J2900", /* CPU0 DIMM0 */ 213 "J3100", /* CPU0 DIMM1 */ 214 "J2901", /* CPU0 DIMM2 */ 215 "J3101", /* CPU0 DIMM3 */ 216 "J3000", /* CPU0 DIMM4 */ 217 "J3200", /* CPU0 DIMM5 */ 218 "J3001", /* CPU0 DIMM6 */ 219 "J3201", /* CPU0 DIMM7 */ 220 "J7900", /* CPU1 DIMM0 */ 221 "J8100", /* CPU1 DIMM1 */ 222 "J7901", /* CPU1 DIMM2 */ 223 "J8101", /* CPU1 DIMM3 */ 224 "J8000", /* CPU1 DIMM4 */ 225 "J8200", /* CPU1 DIMM5 */ 226 "J8001", /* CPU1 DIMM6 */ 227 "J8201", /* CPU1 DIMM7 */ 228 "0", /* CPU0 label */ 229 "1", /* CPU1 label */ 230 NULL}; 231 232 /* 233 * List of all the FRU slots for power supplies (hotpluggable) 234 */ 235 static char *frutree_power_supply[] = { 236 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=0", 237 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=1", 238 "/frutree/chassis/power-dist-board/power-supply-slot?Slot=2", 239 NULL}; 240 241 /* 242 * List of all the FRU slots for CPU Memory modules (hotpluggable) 243 */ 244 static char *frutree_cpu_module[] = { 245 "/frutree/chassis/system-board/cpu-mem-slot?Slot=0", 246 "/frutree/chassis/system-board/cpu-mem-slot?Slot=1", 247 "/frutree/chassis/system-board/cpu-mem-slot?Slot=2", 248 "/frutree/chassis/system-board/cpu-mem-slot?Slot=3", 249 NULL}; 250 251 /* PICL handle for the root node of the "frutree" */ 252 static picl_nodehdl_t frutreeh; 253 254 static int do_ioboard_init(picl_nodehdl_t); 255 static int do_rscboard_init(picl_nodehdl_t); 256 static int do_fcal_init(picl_nodehdl_t); 257 static int do_power_supplies_init(picl_nodehdl_t); 258 static int do_motherboard_init(picl_nodehdl_t); 259 static int do_cpu_module_init(picl_nodehdl_t, int); 260 static int do_dimms_init(picl_nodehdl_t, int, int); 261 262 static int add_ref_prop(picl_nodehdl_t, picl_nodehdl_t, char *); 263 static int add_slot_prop(picl_nodehdl_t, int); 264 static int add_label_prop(picl_nodehdl_t, char *); 265 static int add_void_fda_prop(picl_nodehdl_t); 266 static int add_viewpoints_prop(picl_nodehdl_t, char *); 267 static int add_all_nodes(); 268 static int remove_all_nodes(picl_nodehdl_t); 269 270 static int add_hotplug_fru_device(void); 271 static int rem_hotplug_fru_device(void); 272 static int is_added_device(char *, char *); 273 static int is_removed_device(char *, char *); 274 static int add_power_supply(int); 275 static int remove_power_supply(int); 276 static int add_cpu_module(int); 277 static int remove_cpu_module(int); 278 279 /* 280 * This function is executed as part of .init when the plugin is 281 * dlopen()ed 282 */ 283 static void 284 picl_frutree_register() 285 { 286 (void) picld_plugin_register(&my_reg_info); 287 } 288 289 /* 290 * This function is the init entry point of the plugin. 291 * It initializes the /frutree tree 292 */ 293 static void 294 picl_frutree_init() 295 { 296 int err; 297 298 err = add_all_nodes(); 299 if (err != PICL_SUCCESS) { 300 (void) remove_all_nodes(frutreeh); 301 return; 302 } 303 304 /* Register the event handler routine */ 305 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 306 picl_frutree_evhandler, NULL); 307 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 308 picl_frutree_evhandler, NULL); 309 } 310 311 /* 312 * This function is the fini entry point of the plugin 313 */ 314 static void 315 picl_frutree_fini(void) 316 { 317 /* Unregister the event handler routine */ 318 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 319 picl_frutree_evhandler, NULL); 320 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 321 picl_frutree_evhandler, NULL); 322 323 (void) remove_all_nodes(frutreeh); 324 } 325 326 /* 327 * This function is the event handler of this plug-in. 328 * 329 * It processes the following events: 330 * 331 * PICLEVENT_SYSEVENT_DEVICE_ADDED 332 * PICLEVENT_SYSEVENT_DEVICE_REMOVED 333 */ 334 /* ARGSUSED */ 335 static void 336 picl_frutree_evhandler(const char *ename, const void *earg, size_t size, 337 void *cookie) 338 { 339 if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) { 340 /* Check for and add any hotplugged device(s) */ 341 (void) add_hotplug_fru_device(); 342 343 } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) { 344 /* Check for and remove any hotplugged device(s) */ 345 (void) rem_hotplug_fru_device(); 346 } 347 } 348 349 /* Initializes the FRU nodes for the IO board */ 350 static int 351 do_ioboard_init(picl_nodehdl_t rooth) 352 { 353 picl_nodehdl_t iobrdh; 354 picl_nodehdl_t tmph; 355 int err; 356 357 /* Create the node for the IO board (if it exists) */ 358 if (ptree_get_node_by_path(platform_frupath[IOBRD], &tmph) == 359 PICL_SUCCESS) { 360 err = ptree_create_node("io-board", "fru", &iobrdh); 361 if (err != PICL_SUCCESS) 362 return (err); 363 364 err = add_ref_prop(iobrdh, tmph, SEEPROM_SOURCE); 365 if (err != PICL_SUCCESS) 366 return (err); 367 368 err = add_void_fda_prop(iobrdh); 369 if (err != PICL_SUCCESS) 370 return (err); 371 372 err = ptree_add_node(rooth, iobrdh); 373 if (err != PICL_SUCCESS) 374 return (err); 375 376 err = add_ref_prop(tmph, iobrdh, FRU_PARENT); 377 if (err != PICL_SUCCESS) 378 return (err); 379 } 380 return (PICL_SUCCESS); 381 } 382 383 /* Initializes the FRU node for the RSC card */ 384 static int 385 do_rscboard_init(picl_nodehdl_t rooth) 386 { 387 picl_nodehdl_t rscbrdh; 388 picl_nodehdl_t tmph; 389 int err; 390 391 /* Create the node for the RSC board (if it exists) */ 392 if (ptree_get_node_by_path(platform_frupath[RSC], &tmph) == 393 PICL_SUCCESS) { 394 err = ptree_create_node("rsc-board", "fru", &rscbrdh); 395 if (err != PICL_SUCCESS) 396 return (err); 397 398 err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE); 399 if (err != PICL_SUCCESS) 400 return (err); 401 402 err = add_void_fda_prop(rscbrdh); 403 if (err != PICL_SUCCESS) 404 return (err); 405 406 err = ptree_add_node(rooth, rscbrdh); 407 if (err != PICL_SUCCESS) 408 return (err); 409 410 err = add_ref_prop(tmph, rscbrdh, FRU_PARENT); 411 if (err != PICL_SUCCESS) 412 return (err); 413 } 414 return (PICL_SUCCESS); 415 } 416 417 /* Initializes the FRU nodes for the FCAL backplanes and GBIC card */ 418 static int 419 do_fcal_init(picl_nodehdl_t rooth) 420 { 421 picl_nodehdl_t fcalsloth; 422 picl_nodehdl_t fcalmodh; 423 picl_nodehdl_t fcalgbich; 424 picl_nodehdl_t tmph; 425 int i, err, slotnum; 426 427 for (i = FCAL0; i <= FCAL1; i++) { 428 /* Create the node for the FCAL backplane slot */ 429 err = ptree_create_node("fcal-backplane-slot", 430 "location", &fcalsloth); 431 if (err != PICL_SUCCESS) 432 return (err); 433 434 slotnum = i - FCAL0; 435 err = add_slot_prop(fcalsloth, slotnum); 436 if (err != PICL_SUCCESS) 437 return (err); 438 439 err = add_label_prop(fcalsloth, location_label[i]); 440 if (err != PICL_SUCCESS) 441 return (err); 442 443 err = ptree_add_node(rooth, fcalsloth); 444 if (err != PICL_SUCCESS) 445 return (err); 446 447 /* If the FCAL backplane exists, create a node for it */ 448 if (ptree_get_node_by_path(platform_frupath[i], &tmph) == 449 PICL_SUCCESS) { 450 err = ptree_create_node("fcal-backplane", "fru", 451 &fcalmodh); 452 if (err != PICL_SUCCESS) 453 return (err); 454 455 err = add_ref_prop(fcalmodh, tmph, SEEPROM_SOURCE); 456 if (err != PICL_SUCCESS) 457 return (err); 458 459 err = add_void_fda_prop(fcalmodh); 460 if (err != PICL_SUCCESS) 461 return (err); 462 463 err = ptree_add_node(fcalsloth, fcalmodh); 464 if (err != PICL_SUCCESS) 465 return (err); 466 467 err = add_ref_prop(tmph, fcalmodh, FRU_PARENT); 468 if (err != PICL_SUCCESS) 469 return (err); 470 } 471 } 472 473 /* If the FCAL GBIC board exists, create a node for it */ 474 if (ptree_get_node_by_path(platform_frupath[FCALGBIC], &tmph) == 475 PICL_SUCCESS) { 476 err = ptree_create_node("fcal-gbic-board", "fru", 477 &fcalgbich); 478 if (err != PICL_SUCCESS) 479 return (err); 480 481 err = add_ref_prop(fcalgbich, tmph, SEEPROM_SOURCE); 482 if (err != PICL_SUCCESS) 483 return (err); 484 485 err = add_void_fda_prop(fcalgbich); 486 if (err != PICL_SUCCESS) 487 return (err); 488 489 err = ptree_add_node(rooth, fcalgbich); 490 if (err != PICL_SUCCESS) 491 return (err); 492 493 err = add_ref_prop(tmph, fcalgbich, FRU_PARENT); 494 if (err != PICL_SUCCESS) 495 return (err); 496 } 497 return (PICL_SUCCESS); 498 } 499 500 /* Initializes the FRU nodes for the PDB and the power supplies */ 501 static int 502 do_power_supplies_init(picl_nodehdl_t rooth) 503 { 504 picl_nodehdl_t powerbrdh; 505 picl_nodehdl_t powersloth; 506 picl_nodehdl_t powermodh; 507 picl_nodehdl_t tmph; 508 int i, err, slotnum; 509 510 /* Create the node for the PDB (if it exists) */ 511 if (ptree_get_node_by_path(platform_frupath[PDB], &tmph) == 512 PICL_SUCCESS) { 513 err = ptree_create_node("power-dist-board", "fru", &powerbrdh); 514 if (err != PICL_SUCCESS) 515 return (err); 516 517 err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE); 518 if (err != PICL_SUCCESS) 519 return (err); 520 521 err = add_void_fda_prop(powerbrdh); 522 if (err != PICL_SUCCESS) 523 return (err); 524 525 err = ptree_add_node(rooth, powerbrdh); 526 if (err != PICL_SUCCESS) 527 return (err); 528 529 err = add_ref_prop(tmph, powerbrdh, FRU_PARENT); 530 if (err != PICL_SUCCESS) 531 return (err); 532 533 for (i = PS0; i <= PS2; i++) { 534 /* Create the node for the power supply slot */ 535 err = ptree_create_node("power-supply-slot", 536 "location", &powersloth); 537 if (err != PICL_SUCCESS) 538 return (err); 539 540 slotnum = i - PS0; 541 err = add_slot_prop(powersloth, slotnum); 542 if (err != PICL_SUCCESS) 543 return (err); 544 545 err = add_label_prop(powersloth, location_label[i]); 546 if (err != PICL_SUCCESS) 547 return (err); 548 549 err = ptree_add_node(powerbrdh, powersloth); 550 if (err != PICL_SUCCESS) 551 return (err); 552 553 /* If the PS exists, create a node for it */ 554 if (ptree_get_node_by_path(platform_frupath[i], 555 &tmph) == PICL_SUCCESS) { 556 err = ptree_create_node("power-supply", 557 "fru", &powermodh); 558 if (err != PICL_SUCCESS) 559 return (err); 560 561 err = add_ref_prop(powermodh, tmph, 562 SEEPROM_SOURCE); 563 if (err != PICL_SUCCESS) 564 return (err); 565 566 err = add_void_fda_prop(powermodh); 567 if (err != PICL_SUCCESS) 568 return (err); 569 570 err = ptree_add_node(powersloth, powermodh); 571 if (err != PICL_SUCCESS) 572 return (err); 573 574 err = add_ref_prop(tmph, powermodh, FRU_PARENT); 575 if (err != PICL_SUCCESS) 576 return (err); 577 } 578 } 579 } 580 return (PICL_SUCCESS); 581 } 582 583 /* Initializes the FRU nodes for the motherboard and CPU Memory modules */ 584 static int 585 do_motherboard_init(picl_nodehdl_t rooth) 586 { 587 picl_nodehdl_t sysboardh; 588 picl_nodehdl_t cpumemsloth; 589 picl_nodehdl_t cpumemmodh; 590 picl_nodehdl_t tmph; 591 int i, err, slotnum; 592 593 /* Create the node for the system board (if it exists) */ 594 if (ptree_get_node_by_path(platform_frupath[SYSBRD], &tmph) == 595 PICL_SUCCESS) { 596 err = ptree_create_node("system-board", "fru", 597 &sysboardh); 598 if (err != PICL_SUCCESS) 599 return (err); 600 601 err = add_ref_prop(sysboardh, tmph, SEEPROM_SOURCE); 602 if (err != PICL_SUCCESS) 603 return (err); 604 605 err = add_void_fda_prop(sysboardh); 606 if (err != PICL_SUCCESS) 607 return (err); 608 609 err = ptree_add_node(rooth, sysboardh); 610 if (err != PICL_SUCCESS) 611 return (err); 612 613 err = add_ref_prop(tmph, sysboardh, FRU_PARENT); 614 if (err != PICL_SUCCESS) 615 return (err); 616 617 for (i = CPUMOD0; i <= CPUMOD3; i++) { 618 /* Create the node for the CPU Memory slot */ 619 err = ptree_create_node("cpu-mem-slot", "location", 620 &cpumemsloth); 621 if (err != PICL_SUCCESS) 622 return (err); 623 624 slotnum = i - CPUMOD0; 625 err = add_slot_prop(cpumemsloth, slotnum); 626 if (err != PICL_SUCCESS) 627 return (err); 628 629 err = add_label_prop(cpumemsloth, location_label[i]); 630 if (err != PICL_SUCCESS) 631 return (err); 632 633 err = ptree_add_node(sysboardh, cpumemsloth); 634 if (err != PICL_SUCCESS) 635 return (err); 636 637 /* If CPU Mem module exists, create a node for it */ 638 if (ptree_get_node_by_path(platform_frupath[i], 639 &tmph) == PICL_SUCCESS) { 640 err = ptree_create_node("cpu-mem-module", 641 "fru", &cpumemmodh); 642 if (err != PICL_SUCCESS) 643 return (err); 644 645 err = add_ref_prop(cpumemmodh, tmph, 646 SEEPROM_SOURCE); 647 if (err != PICL_SUCCESS) 648 return (err); 649 650 err = add_void_fda_prop(cpumemmodh); 651 if (err != PICL_SUCCESS) 652 return (err); 653 654 err = ptree_add_node(cpumemsloth, cpumemmodh); 655 if (err != PICL_SUCCESS) 656 return (err); 657 658 err = add_ref_prop(tmph, cpumemmodh, 659 FRU_PARENT); 660 if (err != PICL_SUCCESS) 661 return (err); 662 663 err = do_cpu_module_init(cpumemmodh, slotnum); 664 if (err != PICL_SUCCESS) 665 return (err); 666 } 667 } 668 } 669 return (PICL_SUCCESS); 670 } 671 672 /* Creates the FRU nodes for the CPU Module and associated DIMMs */ 673 static int 674 do_cpu_module_init(picl_nodehdl_t rooth, int slot) 675 { 676 picl_nodehdl_t cpumodh; 677 int i, c, err; 678 679 for (i = 0; i <= 1; i++) { 680 err = ptree_create_node("cpu-module", "location", 681 &cpumodh); 682 if (err != PICL_SUCCESS) 683 return (err); 684 685 err = add_slot_prop(cpumodh, i); 686 if (err != PICL_SUCCESS) 687 return (err); 688 689 c = CPU0_DIMM0 + DIMMS_PER_SLOT + i; 690 691 err = add_label_prop(cpumodh, location_label[c]); 692 if (err != PICL_SUCCESS) 693 return (err); 694 695 err = ptree_add_node(rooth, cpumodh); 696 if (err != PICL_SUCCESS) 697 return (err); 698 699 /* Create the nodes for the memory (if they exist) */ 700 err = do_dimms_init(cpumodh, slot, i); 701 if (err != PICL_SUCCESS) 702 return (err); 703 } 704 return (PICL_SUCCESS); 705 } 706 707 /* Creates the FRU nodes for the DIMMs on a particular CPU Module */ 708 static int 709 do_dimms_init(picl_nodehdl_t rooth, int slot, int module) 710 { 711 picl_nodehdl_t dimmsloth; 712 picl_nodehdl_t dimmmodh; 713 picl_nodehdl_t tmph; 714 int i, c, l, err; 715 716 for (i = 0; i < DIMMS_PER_MOD; i++) { 717 /* Create the node for the memory slot */ 718 err = ptree_create_node("dimm-slot", "location", 719 &dimmsloth); 720 if (err != PICL_SUCCESS) 721 return (err); 722 723 err = add_slot_prop(dimmsloth, i); 724 if (err != PICL_SUCCESS) 725 return (err); 726 727 c = ((slot * DIMMS_PER_SLOT) + 728 (module * DIMMS_PER_MOD) + i) + CPU0_DIMM0; 729 730 l = c - (DIMMS_PER_SLOT * slot); 731 732 err = add_label_prop(dimmsloth, location_label[l]); 733 if (err != PICL_SUCCESS) 734 return (err); 735 736 err = ptree_add_node(rooth, dimmsloth); 737 if (err != PICL_SUCCESS) 738 return (err); 739 740 /* If the memory module exists, create a node for it */ 741 if (ptree_get_node_by_path(platform_frupath[c], &tmph) == 742 PICL_SUCCESS) { 743 err = ptree_create_node("dimm-module", "fru", 744 &dimmmodh); 745 if (err != PICL_SUCCESS) 746 return (err); 747 748 err = add_ref_prop(dimmmodh, tmph, SEEPROM_SOURCE); 749 if (err != PICL_SUCCESS) 750 return (err); 751 752 err = add_void_fda_prop(dimmmodh); 753 if (err != PICL_SUCCESS) 754 return (err); 755 756 err = ptree_add_node(dimmsloth, dimmmodh); 757 if (err != PICL_SUCCESS) 758 return (err); 759 760 err = add_ref_prop(tmph, dimmmodh, FRU_PARENT); 761 if (err != PICL_SUCCESS) 762 return (err); 763 } 764 } 765 return (PICL_SUCCESS); 766 } 767 768 /* Creates a "reference" property between two PICL nodes */ 769 static int 770 add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str) 771 { 772 picl_prophdl_t proph; 773 ptree_propinfo_t propinfo; 774 int err; 775 776 if (str == NULL) 777 return (PICL_FAILURE); 778 779 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 780 PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t), 781 str, NULL, NULL); 782 if (err != PICL_SUCCESS) 783 return (err); 784 785 err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph); 786 if (err != PICL_SUCCESS) 787 return (err); 788 789 return (PICL_SUCCESS); 790 } 791 792 /* Creates a "slot" property for a given PICL node */ 793 static int 794 add_slot_prop(picl_nodehdl_t nodeh, int slotnum) 795 { 796 picl_prophdl_t proph; 797 ptree_propinfo_t propinfo; 798 int err; 799 800 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 801 PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL); 802 if (err != PICL_SUCCESS) 803 return (err); 804 805 err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph); 806 if (err != PICL_SUCCESS) 807 return (err); 808 809 return (PICL_SUCCESS); 810 } 811 812 /* Creates a "Label" property for a given PICL node */ 813 static int 814 add_label_prop(picl_nodehdl_t nodeh, char *label) 815 { 816 picl_prophdl_t proph; 817 ptree_propinfo_t propinfo; 818 int err; 819 820 if (label == NULL) 821 return (PICL_FAILURE); 822 823 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 824 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label", 825 NULL, NULL); 826 if (err != PICL_SUCCESS) 827 return (err); 828 829 err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph); 830 if (err != PICL_SUCCESS) 831 return (err); 832 833 return (PICL_SUCCESS); 834 } 835 836 /* Creates a "FRUDataAvailable" void property for the given PICL node */ 837 static int 838 add_void_fda_prop(picl_nodehdl_t nodeh) 839 { 840 picl_prophdl_t proph; 841 ptree_propinfo_t propinfo; 842 int err; 843 844 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 845 PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL); 846 if (err != PICL_SUCCESS) 847 return (err); 848 849 err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph); 850 if (err != PICL_SUCCESS) 851 return (err); 852 853 return (PICL_SUCCESS); 854 } 855 856 /* Creates a "ViewPoints" property -- used for chassis */ 857 static int 858 add_viewpoints_prop(picl_nodehdl_t nodeh, char *string) 859 { 860 picl_prophdl_t proph; 861 ptree_propinfo_t propinfo; 862 int err; 863 864 if (string == NULL) 865 return (PICL_FAILURE); 866 867 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 868 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints", 869 NULL, NULL); 870 if (err != PICL_SUCCESS) 871 return (err); 872 873 err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph); 874 if (err != PICL_SUCCESS) 875 return (err); 876 877 return (PICL_SUCCESS); 878 } 879 880 /* Creates and adds all of the frutree nodes */ 881 static int 882 add_all_nodes() 883 { 884 picl_nodehdl_t rooth; 885 picl_nodehdl_t chassish; 886 int err; 887 888 /* Get the root node of the PICL tree */ 889 err = ptree_get_root(&rooth); 890 if (err != PICL_SUCCESS) { 891 return (err); 892 } 893 894 /* Create and add the root node of the FRU subtree */ 895 err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh); 896 if (err != PICL_SUCCESS) { 897 syslog(LOG_ERR, CREATE_FRUTREE_FAIL); 898 return (err); 899 } 900 901 /* Create and add the chassis node */ 902 err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish); 903 if (err != PICL_SUCCESS) { 904 syslog(LOG_ERR, CREATE_CHASSIS_FAIL); 905 return (err); 906 } 907 908 /* Add ViewPoints prop to chassis node */ 909 err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS); 910 if (err != PICL_SUCCESS) 911 return (err); 912 913 /* Initialize the FRU nodes for the IO board */ 914 err = do_ioboard_init(chassish); 915 if (err != PICL_SUCCESS) { 916 syslog(LOG_ERR, IOBRD_INIT_FAIL); 917 return (err); 918 } 919 920 /* Initialize the FRU node for the RSC card */ 921 err = do_rscboard_init(chassish); 922 if (err != PICL_SUCCESS) { 923 syslog(LOG_ERR, RSCBRD_INIT_FAIL); 924 return (err); 925 } 926 927 /* Initialize the FRU nodes for the FCAL backplanes and GBIC board */ 928 err = do_fcal_init(chassish); 929 if (err != PICL_SUCCESS) { 930 syslog(LOG_ERR, FCAL_INIT_FAIL); 931 return (err); 932 } 933 934 /* Initialize the FRU nodes for the PDB and the power supplies */ 935 err = do_power_supplies_init(chassish); 936 if (err != PICL_SUCCESS) { 937 syslog(LOG_ERR, PS_INIT_FAIL); 938 return (err); 939 } 940 941 /* Initialize the FRU nodes for the CPU Memory modules */ 942 err = do_motherboard_init(chassish); 943 if (err != PICL_SUCCESS) { 944 syslog(LOG_ERR, SYSBOARD_INIT_FAIL); 945 return (err); 946 } 947 948 return (PICL_SUCCESS); 949 } 950 951 /* Deletes and destroys all PICL nodes for which rooth is a ancestor */ 952 static int 953 remove_all_nodes(picl_nodehdl_t rooth) 954 { 955 picl_nodehdl_t chdh; 956 int err, done = 0; 957 958 while (!done) { 959 err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 960 sizeof (picl_nodehdl_t)); 961 if (err != PICL_PROPNOTFOUND) { 962 (void) remove_all_nodes(chdh); 963 } else { 964 err = ptree_delete_node(rooth); 965 if (err != PICL_SUCCESS) { 966 return (err); 967 } else { 968 (void) ptree_destroy_node(rooth); 969 } 970 done = 1; 971 } 972 } 973 return (PICL_SUCCESS); 974 } 975 976 /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */ 977 static int 978 add_hotplug_fru_device() 979 { 980 int i, err, slotnum; 981 982 /* Check for hotplugged power supplies */ 983 for (i = PS0; i <= PS2; i++) { 984 /* Compare the /platform tree to the frutree */ 985 slotnum = i - PS0; 986 err = is_added_device(platform_frupath[i], 987 frutree_power_supply[slotnum]); 988 if (err != PICL_SUCCESS) 989 continue; 990 991 /* If they are different, then add a power supply */ 992 err = add_power_supply(slotnum); 993 if (err != PICL_SUCCESS) 994 continue; 995 } 996 997 /* Check for hotplugged CPU Memory modules */ 998 for (i = CPUMOD0; i <= CPUMOD3; i++) { 999 /* Compare the /platform tree to the frutree */ 1000 slotnum = i - CPUMOD0; 1001 err = is_added_device(platform_frupath[i], 1002 frutree_cpu_module[slotnum]); 1003 if (err != PICL_SUCCESS) 1004 continue; 1005 1006 /* If they are different, then add a CPU Mem module */ 1007 err = add_cpu_module(slotnum); 1008 if (err != PICL_SUCCESS) 1009 continue; 1010 } 1011 return (PICL_SUCCESS); 1012 } 1013 1014 /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */ 1015 static int 1016 rem_hotplug_fru_device() 1017 { 1018 int i, err, slotnum; 1019 1020 /* Check for hotplugged power supplies */ 1021 for (i = PS0; i <= PS2; i++) { 1022 /* Compare the /platform tree to the frutree */ 1023 slotnum = i - PS0; 1024 err = is_removed_device(platform_frupath[i], 1025 frutree_power_supply[slotnum]); 1026 if (err != PICL_SUCCESS) 1027 continue; 1028 1029 /* If they are different, then remove a power supply */ 1030 err = remove_power_supply(slotnum); 1031 if (err != PICL_SUCCESS) 1032 continue; 1033 } 1034 1035 /* Check for hotplugged CPU Memory modules */ 1036 for (i = CPUMOD0; i <= CPUMOD3; i++) { 1037 /* Compare the /platform tree to the frutree */ 1038 slotnum = i - CPUMOD0; 1039 err = is_removed_device(platform_frupath[i], 1040 frutree_cpu_module[slotnum]); 1041 if (err != PICL_SUCCESS) 1042 continue; 1043 1044 /* If they are different, then remove a CPU Mem module */ 1045 err = remove_cpu_module(slotnum); 1046 if (err != PICL_SUCCESS) 1047 continue; 1048 } 1049 return (PICL_SUCCESS); 1050 } 1051 1052 /* 1053 * Compare the /platform tree to the /frutree to determine if a 1054 * new device has been added 1055 */ 1056 static int 1057 is_added_device(char *plat, char *fru) 1058 { 1059 int err; 1060 picl_nodehdl_t plath, frusloth, frumodh; 1061 1062 /* Check for node in the /platform tree */ 1063 err = ptree_get_node_by_path(plat, &plath); 1064 if (err != PICL_SUCCESS) 1065 return (err); 1066 1067 /* 1068 * The node is in /platform, so find the corresponding slot in 1069 * the frutree 1070 */ 1071 err = ptree_get_node_by_path(fru, &frusloth); 1072 if (err != PICL_SUCCESS) 1073 return (err); 1074 1075 /* 1076 * If the slot in the frutree has a child, then return 1077 * PICL_FAILURE. This means that the /platform tree and 1078 * the frutree are consistent and no action is necessary. 1079 * Otherwise return PICL_SUCCESS to indicate that a node needs 1080 * to be added to the frutree 1081 */ 1082 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD, 1083 &frumodh, sizeof (picl_nodehdl_t)); 1084 if (err == PICL_SUCCESS) 1085 return (PICL_FAILURE); 1086 1087 return (PICL_SUCCESS); 1088 } 1089 1090 /* 1091 * Compare the /platform tree to the /frutree to determine if a 1092 * device has been removed 1093 */ 1094 static int 1095 is_removed_device(char *plat, char *fru) 1096 { 1097 int err; 1098 picl_nodehdl_t plath, frusloth, frumodh; 1099 1100 1101 /* Check for node in /platform tree */ 1102 err = ptree_get_node_by_path(plat, &plath); 1103 if (err == PICL_SUCCESS) 1104 return (PICL_FAILURE); 1105 1106 /* 1107 * The node is not in /platform, so find the corresponding slot in 1108 * the frutree 1109 */ 1110 err = ptree_get_node_by_path(fru, &frusloth); 1111 if (err != PICL_SUCCESS) 1112 return (err); 1113 1114 /* 1115 * If the slot in the frutree does not have a child, then return 1116 * PICL_FAILURE. This means that the /platform tree and 1117 * the frutree are consistent and no action is necessary. 1118 * Otherwise return PICL_SUCCESS to indicate that the needs 1119 * to be removed from the frutree 1120 */ 1121 err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD, 1122 &frumodh, sizeof (picl_nodehdl_t)); 1123 if (err != PICL_SUCCESS) 1124 return (err); 1125 1126 return (PICL_SUCCESS); 1127 } 1128 1129 static int 1130 remove_picl_node(picl_nodehdl_t nodeh) 1131 { 1132 int err; 1133 err = ptree_delete_node(nodeh); 1134 if (err != PICL_SUCCESS) 1135 return (err); 1136 (void) ptree_destroy_node(nodeh); 1137 return (PICL_SUCCESS); 1138 } 1139 1140 /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */ 1141 /*ARGSUSED2*/ 1142 static void 1143 frudr_completion_handler(char *ename, void *earg, size_t size) 1144 { 1145 picl_nodehdl_t fruh; 1146 1147 if (strcmp(ename, PICL_FRU_REMOVED) == 0) { 1148 /* 1149 * now frudata has been notified that the node is to be 1150 * removed, we can actually remove it 1151 */ 1152 fruh = NULL; 1153 (void) nvlist_lookup_uint64(earg, 1154 PICLEVENTARG_FRUHANDLE, &fruh); 1155 if (fruh != NULL) { 1156 (void) remove_picl_node(fruh); 1157 } 1158 } 1159 nvlist_free(earg); 1160 free(earg); 1161 free(ename); 1162 } 1163 1164 /* 1165 * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event 1166 */ 1167 static void 1168 post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh) 1169 { 1170 nvlist_t *nvl; 1171 char *ev_name; 1172 1173 ev_name = strdup(ename); 1174 if (ev_name == NULL) 1175 return; 1176 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) { 1177 free(ev_name); 1178 return; 1179 } 1180 if (parenth != 0L && 1181 nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) { 1182 free(ev_name); 1183 nvlist_free(nvl); 1184 return; 1185 } 1186 if (fruh != 0L && 1187 nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) { 1188 free(ev_name); 1189 nvlist_free(nvl); 1190 return; 1191 } 1192 if (ptree_post_event(ev_name, nvl, sizeof (nvl), 1193 frudr_completion_handler) != 0) { 1194 free(ev_name); 1195 nvlist_free(nvl); 1196 } 1197 } 1198 1199 /* Hotplug routine used to add a new power supply */ 1200 static int 1201 add_power_supply(int slotnum) 1202 { 1203 picl_nodehdl_t powersloth; 1204 picl_nodehdl_t powermodh; 1205 picl_nodehdl_t tmph; 1206 int i, err; 1207 1208 /* Find the node for the given power supply slot */ 1209 if (ptree_get_node_by_path(frutree_power_supply[slotnum], 1210 &powersloth) == PICL_SUCCESS) { 1211 1212 i = slotnum + PS0; 1213 1214 /* Make sure it's in /platform and create the frutree node */ 1215 if (ptree_get_node_by_path(platform_frupath[i], &tmph) == 1216 PICL_SUCCESS) { 1217 err = ptree_create_node("power-supply", "fru", 1218 &powermodh); 1219 if (err != PICL_SUCCESS) 1220 return (err); 1221 1222 err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE); 1223 if (err != PICL_SUCCESS) 1224 return (err); 1225 1226 err = add_void_fda_prop(powermodh); 1227 if (err != PICL_SUCCESS) 1228 return (err); 1229 1230 err = ptree_add_node(powersloth, powermodh); 1231 if (err != PICL_SUCCESS) 1232 return (err); 1233 1234 err = add_ref_prop(tmph, powermodh, FRU_PARENT); 1235 if (err != PICL_SUCCESS) 1236 return (err); 1237 1238 /* Post picl-fru-added event */ 1239 post_frudr_event(PICL_FRU_ADDED, NULL, powermodh); 1240 } 1241 } 1242 return (PICL_SUCCESS); 1243 } 1244 1245 /* Hotplug routine used to remove an existing power supply */ 1246 static int 1247 remove_power_supply(int slotnum) 1248 { 1249 picl_nodehdl_t powersloth; 1250 picl_nodehdl_t powermodh; 1251 int err; 1252 1253 /* Find the node for the given power supply slot */ 1254 if (ptree_get_node_by_path(frutree_power_supply[slotnum], 1255 &powersloth) == PICL_SUCCESS) { 1256 /* Make sure it's got a child, then delete it */ 1257 err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD, 1258 &powermodh, sizeof (picl_nodehdl_t)); 1259 if (err != PICL_SUCCESS) { 1260 return (err); 1261 } 1262 1263 err = ptree_delete_node(powermodh); 1264 if (err != PICL_SUCCESS) { 1265 return (err); 1266 } else { 1267 (void) ptree_destroy_node(powermodh); 1268 } 1269 1270 /* Post picl-fru-removed event */ 1271 post_frudr_event(PICL_FRU_REMOVED, NULL, powermodh); 1272 1273 } 1274 return (PICL_SUCCESS); 1275 } 1276 1277 /* Hotplug routine used to add a new CPU Mem Module (with associated DIMMs) */ 1278 static int 1279 add_cpu_module(int slotnum) 1280 { 1281 picl_nodehdl_t cpumemsloth; 1282 picl_nodehdl_t cpumemmodh; 1283 picl_nodehdl_t tmph; 1284 int i, err; 1285 1286 /* Find the node for the given CPU Memory module slot */ 1287 if (ptree_get_node_by_path(frutree_cpu_module[slotnum], 1288 &cpumemsloth) == PICL_SUCCESS) { 1289 1290 i = slotnum + CPUMOD0; 1291 1292 /* Make sure it's in /platform and create the frutree nodes */ 1293 if (ptree_get_node_by_path(platform_frupath[i], &tmph) == 1294 PICL_SUCCESS) { 1295 err = ptree_create_node("cpu-mem-module", "fru", 1296 &cpumemmodh); 1297 if (err != PICL_SUCCESS) 1298 return (err); 1299 1300 err = add_ref_prop(cpumemmodh, tmph, SEEPROM_SOURCE); 1301 if (err != PICL_SUCCESS) 1302 return (err); 1303 1304 err = add_void_fda_prop(cpumemmodh); 1305 if (err != PICL_SUCCESS) 1306 return (err); 1307 1308 err = ptree_add_node(cpumemsloth, cpumemmodh); 1309 if (err != PICL_SUCCESS) 1310 return (err); 1311 1312 err = add_ref_prop(tmph, cpumemmodh, FRU_PARENT); 1313 if (err != PICL_SUCCESS) 1314 return (err); 1315 } 1316 1317 err = do_cpu_module_init(cpumemmodh, slotnum); 1318 if (err != PICL_SUCCESS) 1319 return (err); 1320 } 1321 return (PICL_SUCCESS); 1322 } 1323 1324 /* Hotplug routine used to remove an existing CPU Mem Module */ 1325 static int 1326 remove_cpu_module(int slotnum) 1327 { 1328 picl_nodehdl_t cpumemsloth; 1329 picl_nodehdl_t cpumemmodh; 1330 int err; 1331 1332 /* Find the node for the given CPU Memory module slot */ 1333 if (ptree_get_node_by_path(frutree_cpu_module[slotnum], 1334 &cpumemsloth) == PICL_SUCCESS) { 1335 /* Make sure it's got a child, then delete it */ 1336 err = ptree_get_propval_by_name(cpumemsloth, PICL_PROP_CHILD, 1337 &cpumemmodh, sizeof (picl_nodehdl_t)); 1338 if (err != PICL_SUCCESS) { 1339 return (err); 1340 } 1341 1342 err = remove_all_nodes(cpumemmodh); 1343 if (err != PICL_SUCCESS) { 1344 return (err); 1345 } 1346 } 1347 return (PICL_SUCCESS); 1348 } 1349