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