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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Sun4v Platform specific functions. 28 * 29 * called when : 30 * machine_type == ontario 31 * 32 */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <kstat.h> 40 #include <fcntl.h> 41 #include <string.h> 42 #include <assert.h> 43 #include <libintl.h> 44 #include <note.h> 45 #include <sys/systeminfo.h> 46 #include <sys/openpromio.h> 47 #include <sys/sysmacros.h> 48 #include <picl.h> 49 #include "picldefs.h" 50 #include <pdevinfo.h> 51 #include <display.h> 52 #include <display_sun4v.h> 53 #include <libprtdiag.h> 54 #include "ontario.h" 55 #include "erie.h" 56 #include "pelton.h" 57 #include "stpaul.h" 58 #include "huron.h" 59 #include "glendale_common.h" 60 61 #if !defined(TEXT_DOMAIN) 62 #define TEXT_DOMAIN "SYS_TEST" 63 #endif 64 65 /* 66 * these functions will overlay the symbol table of libprtdiag 67 * at runtime 68 */ 69 void sun4v_display_pci(picl_nodehdl_t plafh); 70 void sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh); 71 72 73 /* local functions */ 74 static void sun4v_display_hw_revisions(Prom_node *root, picl_nodehdl_t plafh); 75 static int ontario_pci_callback(picl_nodehdl_t pcih, void *args); 76 static int ontario_get_first_compatible_value(picl_nodehdl_t nodeh, 77 char **outbuf); 78 static int64_t ontario_get_int_propval(picl_nodehdl_t modh, char *prop_name, 79 int *ret); 80 81 static void 82 get_bus_type(char *path, struct io_card *card) 83 { 84 if (strncmp(path, PCIX_SLOT0, PCIX_COMP_NUM) == 0) { 85 (void) strcpy(card->bus_type, "PCIX"); 86 } else { 87 (void) strcpy(card->bus_type, "PCIE"); 88 } 89 } 90 91 static void 92 get_slot_number(picl_nodehdl_t nodeh, char *path, struct io_card *card) 93 { 94 if (strncmp(path, PCIE_SLOT0, PCIE_COMP_NUM) == 0) { 95 (void) strcpy(card->slot_str, "0"); 96 card->slot = 0; 97 } else if (strncmp(path, PCIE_SLOT1, PCIE_COMP_NUM) == 0) { 98 (void) strcpy(card->slot_str, "1"); 99 card->slot = 1; 100 } else if (strncmp(path, PCIE_SLOT2, PCIE_COMP_NUM) == 0) { 101 (void) strcpy(card->slot_str, "2"); 102 card->slot = 2; 103 } else if ((strncmp(path, PCIX_SLOT1, strlen(PCIX_SLOT1)) == 0) || 104 (strncmp(path, PCIX_SLOT0, strlen(PCIX_SLOT0)) == 0)) { 105 char ua[MAXSTRLEN]; 106 int err; 107 108 (void) strcpy(card->slot_str, "PCIX"); 109 card->slot = -1; 110 111 /* 112 * PCIX_SLOT0 and PCIX_SLOT1 are actually the same path so 113 * use the unit address to distinguish the slot number. 114 */ 115 err = picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, 116 ua, sizeof (ua)); 117 if (err == PICL_SUCCESS) { 118 if (ua[0] == '2') { 119 card->slot = 0; 120 (void) strcpy(card->slot_str, "0"); 121 } else if (ua[0] == '1') { 122 card->slot = 1; 123 (void) strcpy(card->slot_str, "1"); 124 } 125 } 126 } else { 127 (void) strcpy(card->slot_str, IOBOARD); 128 card->slot = -1; 129 } 130 } 131 132 static int 133 ontario_get_network_instance(char *path) 134 { 135 if (strncmp(path, NETWORK_1_PATH, strlen(NETWORK_1_PATH)) == 0) { 136 return (1); 137 } else if (strncmp(path, NETWORK_3_PATH, strlen(NETWORK_3_PATH)) == 0) { 138 return (3); 139 } else if (strncmp(path, NETWORK_0_PATH, strlen(NETWORK_0_PATH)) == 0) { 140 return (0); 141 } else if (strncmp(path, NETWORK_2_PATH, strlen(NETWORK_2_PATH)) == 0) { 142 return (2); 143 } else { 144 return (-1); 145 } 146 } 147 /* 148 * add all io devices under pci in io list 149 */ 150 /* ARGSUSED */ 151 static int 152 ontario_pci_callback(picl_nodehdl_t pcih, void *args) 153 { 154 int err = PICL_SUCCESS; 155 picl_nodehdl_t nodeh; 156 char path[MAXSTRLEN]; 157 char parent_path[MAXSTRLEN]; 158 char piclclass[PICL_CLASSNAMELEN_MAX]; 159 char name[MAXSTRLEN]; 160 char model[MAXSTRLEN]; 161 char *compatible; 162 char binding_name[MAXSTRLEN]; 163 struct io_card pci_card; 164 int32_t instance; 165 166 err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, parent_path, 167 sizeof (parent_path)); 168 if (err != PICL_SUCCESS) { 169 return (err); 170 } 171 172 /* Walk through the children */ 173 174 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 175 sizeof (picl_nodehdl_t)); 176 177 while (err == PICL_SUCCESS) { 178 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 179 piclclass, sizeof (piclclass)); 180 if (err != PICL_SUCCESS) 181 return (err); 182 183 /* 184 * Skip PCI and PCIEX devices because they will be processed 185 * later in the picl tree walk. 186 */ 187 if ((strcmp(piclclass, "pci") == 0) || 188 (strcmp(piclclass, "pciex") == 0)) { 189 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 190 &nodeh, sizeof (picl_nodehdl_t)); 191 continue; 192 } 193 194 err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, 195 path, sizeof (path)); 196 if (err != PICL_SUCCESS) { 197 return (err); 198 } 199 200 (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes)); 201 202 get_bus_type(parent_path, &pci_card); 203 204 get_slot_number(nodeh, parent_path, &pci_card); 205 206 err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, &name, 207 sizeof (name)); 208 if (err == PICL_PROPNOTFOUND) 209 (void) strcpy(name, ""); 210 else if (err != PICL_SUCCESS) 211 return (err); 212 213 /* Figure NAC name */ 214 if ((strcmp(name, NETWORK) == 0) && 215 (strcmp(pci_card.slot_str, IOBOARD) == 0)) { 216 instance = ontario_get_network_instance(path); 217 218 (void) snprintf(pci_card.status, 219 sizeof (pci_card.status), "%s/%s%d", IOBOARD, 220 "NET", instance); 221 } else { 222 if (pci_card.slot != -1) { 223 (void) snprintf(pci_card.status, 224 sizeof (pci_card.status), "%s/%s%d", 225 IOBOARD, pci_card.bus_type, pci_card.slot); 226 } else { 227 (void) snprintf(pci_card.status, 228 sizeof (pci_card.status), "%s/%s", IOBOARD, 229 pci_card.bus_type); 230 } 231 } 232 233 /* 234 * Get the name of this card. If binding_name is found, 235 * name will be <nodename>-<binding_name> 236 */ 237 238 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 239 &binding_name, sizeof (binding_name)); 240 if (err == PICL_PROPNOTFOUND) { 241 /* 242 * if compatible prop is found, name will be 243 * <nodename>-<compatible> 244 */ 245 err = ontario_get_first_compatible_value(nodeh, 246 &compatible); 247 if (err == PICL_SUCCESS) { 248 (void) strlcat(name, "-", MAXSTRLEN); 249 (void) strlcat(name, compatible, MAXSTRLEN); 250 free(compatible); 251 } else if (err != PICL_PROPNOTFOUND) { 252 return (err); 253 } 254 } else if (err != PICL_SUCCESS) { 255 return (err); 256 } else if (strcmp(name, binding_name) != 0) { 257 (void) strlcat(name, "-", MAXSTRLEN); 258 (void) strlcat(name, binding_name, MAXSTRLEN); 259 } 260 261 (void) strlcpy(pci_card.name, name, sizeof (pci_card.name)); 262 263 /* Get the model of this card */ 264 265 err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL, 266 &model, sizeof (model)); 267 if (err == PICL_PROPNOTFOUND) 268 (void) strcpy(model, ""); 269 else if (err != PICL_SUCCESS) 270 return (err); 271 (void) strlcpy(pci_card.model, model, sizeof (pci_card.model)); 272 273 /* Print NAC name */ 274 log_printf("%-11s", pci_card.status); 275 /* Print IO Type */ 276 log_printf("%6s", pci_card.bus_type); 277 /* Print Slot # */ 278 log_printf("%5s", pci_card.slot_str); 279 /* Print Parent Path */ 280 log_printf("%46.45s", pci_card.notes); 281 /* Printf Card Name */ 282 if (strlen(pci_card.name) > 25) 283 log_printf("%25.24s+", pci_card.name); 284 else 285 log_printf("%26s", pci_card.name); 286 /* Print Card Model */ 287 if (strlen(pci_card.model) > 10) 288 log_printf("%10.9s+", pci_card.model); 289 else 290 log_printf("%11s", pci_card.model); 291 log_printf("\n"); 292 293 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 294 sizeof (picl_nodehdl_t)); 295 296 } 297 298 return (PICL_WALK_CONTINUE); 299 } 300 /* 301 * display_pci 302 * Display all the PCI IO cards on this board. 303 */ 304 void 305 sun4v_display_pci(picl_nodehdl_t plafh) 306 { 307 char platbuf[MAXSTRLEN]; 308 char *fmt = "%-11s %-5s %-4s %-45s %-25s %-10s"; 309 static int banner = FALSE; /* Have we printed the column headings? */ 310 311 if (banner == FALSE) { 312 log_printf("\n", 0); 313 log_printf("=========================", 0); 314 log_printf(dgettext(TEXT_DOMAIN, " IO Configuration "), 0); 315 log_printf("=========================", 0); 316 log_printf("\n", 0); 317 log_printf("\n", 0); 318 log_printf(fmt, "", "IO", "", "", "", "", 0); 319 log_printf("\n", 0); 320 log_printf(fmt, "Location", "Type", "Slot", "Path", 321 "Name", "Model", 0); 322 log_printf("\n"); 323 log_printf(fmt, "-----------", "-----", "----", 324 "---------------------------------------------", 325 "-------------------------", "----------", 0); 326 log_printf("\n"); 327 banner = TRUE; 328 } 329 330 /* Get platform name, if that fails, use ontario name by default */ 331 if (sysinfo(SI_PLATFORM, platbuf, sizeof (platbuf)) == -1) { 332 (void) strcpy(platbuf, ONTARIO_PLATFORM); 333 } 334 335 /* 336 * Call functions based on appropriate platform 337 */ 338 if ((strncmp(platbuf, ONTARIO_PLATFORM, 339 strlen(ONTARIO_PLATFORM)) == 0) || 340 (strncmp(platbuf, ONTARIO_PLATFORM2, 341 strlen(ONTARIO_PLATFORM2)) == 0)) { 342 (void) picl_walk_tree_by_class(plafh, "pciex", 343 "pciex", ontario_pci_callback); 344 (void) picl_walk_tree_by_class(plafh, "pci", 345 "pci", ontario_pci_callback); 346 } else if ((strncmp(platbuf, PELTON_PLATFORM, 347 strlen(PELTON_PLATFORM))) == 0) { 348 (void) picl_walk_tree_by_class(plafh, "pciex", 349 "pciex", pelton_pci_callback); 350 (void) picl_walk_tree_by_class(plafh, "pci", 351 "pci", pelton_pci_callback); 352 } else if ((strncmp(platbuf, STPAUL_PLATFORM, 353 strlen(STPAUL_PLATFORM))) == 0) { 354 (void) picl_walk_tree_by_class(plafh, "pciex", 355 "pciex", stpaul_pci_callback); 356 } else if ((strncmp(platbuf, HURON_1U_PLATFORM, 357 strlen(HURON_1U_PLATFORM)) == 0) || (strncmp(platbuf, 358 HURON_2U_PLATFORM, strlen(HURON_2U_PLATFORM)) == 0)) { 359 (void) picl_walk_tree_by_class(plafh, "sun4v", 360 "niu", huron_pci_callback); 361 (void) picl_walk_tree_by_class(plafh, "pciex", 362 "pciex", huron_pci_callback); 363 } else if ((strncmp(platbuf, GLENDALE_PLATFORM, 364 strlen(GLENDALE_PLATFORM))) == 0) { 365 (void) picl_walk_tree_by_class(plafh, "sun4v", 366 "niu", glendale_pci_callback); 367 (void) picl_walk_tree_by_class(plafh, "pciex", 368 "pciex", glendale_pci_callback); 369 } else { 370 (void) picl_walk_tree_by_class(plafh, "pciex", "pciex", 371 erie_pci_callback); 372 (void) picl_walk_tree_by_class(plafh, "pci", "pci", 373 erie_pci_callback); 374 } 375 } 376 377 /* 378 * ---------------------------------------------------------------------------- 379 */ 380 381 /* ARGSUSED */ 382 void 383 sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh) 384 { 385 /* NOTE(ARGUNUSED(kstats)) */ 386 /* 387 * Now display the last powerfail time and the fatal hardware 388 * reset information. We do this under a couple of conditions. 389 * First if the user asks for it. The second is if the user 390 * told us to do logging, and we found a system failure. 391 */ 392 if (flag) { 393 /* 394 * display time of latest powerfail. Not all systems 395 * have this capability. For those that do not, this 396 * is just a no-op. 397 */ 398 disp_powerfail(root); 399 400 /* platform_disp_prom_version(tree); */ 401 sun4v_display_hw_revisions(root, plafh); 402 } 403 } 404 405 /* 406 * local functions 407 */ 408 /* 409 * add all io devices under pci in io list 410 */ 411 /* ARGSUSED */ 412 static int 413 ontario_hw_rev_callback(picl_nodehdl_t pcih, void *args) 414 { 415 int err = PICL_SUCCESS; 416 char path[MAXSTRLEN] = ""; 417 char device_path[MAXSTRLEN]; 418 char NAC[MAXSTRLEN]; 419 char *compatible; 420 int32_t revision; 421 int device_found; 422 423 device_found = 0; 424 425 err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, path, 426 sizeof (path)); 427 if (err != PICL_SUCCESS) { 428 return (err); 429 } 430 431 if ((strcmp(path, NETWORK_0_PATH) == 0) || 432 (strcmp(path, NETWORK_1_PATH) == 0)) { 433 device_found = 1; 434 (void) snprintf(NAC, sizeof (NAC), "%s/%s%d", IOBOARD, OPHIR, 435 0); 436 revision = ontario_get_int_propval(pcih, OBP_PROP_REVISION_ID, 437 &err); 438 } 439 440 if ((strcmp(path, NETWORK_2_PATH) == 0) || 441 (strcmp(path, NETWORK_3_PATH) == 0)) { 442 device_found = 1; 443 (void) snprintf(NAC, sizeof (NAC), "%s/%s%d", IOBOARD, OPHIR, 444 1); 445 revision = ontario_get_int_propval(pcih, OBP_PROP_REVISION_ID, 446 &err); 447 } 448 449 if ((strcmp(path, FIRE_PATH0) == 0) || 450 (strcmp(path, FIRE_PATH1) == 0)) { 451 device_found = 1; 452 (void) snprintf(NAC, sizeof (NAC), "%s/%s", IOBOARD, 453 "IO-BRIDGE"); 454 revision = ontario_get_int_propval(pcih, OBP_PROP_VERSION_NUM, 455 &err); 456 } 457 458 if ((strcmp(path, PCIX_SLOT0) == 0) || 459 (strcmp(path, PCIX_SLOT1) == 0)) { 460 device_found = 1; 461 (void) snprintf(NAC, sizeof (NAC), "%s/%s", IOBOARD, 462 PCI_BRIDGE); 463 revision = ontario_get_int_propval(pcih, OBP_PROP_REVISION_ID, 464 &err); 465 } 466 467 if (strcmp(path, SWITCH_A_PATH) == 0) { 468 device_found = 1; 469 (void) snprintf(NAC, sizeof (NAC), "%s/%s", IOBOARD, SWITCH_A); 470 revision = ontario_get_int_propval(pcih, OBP_PROP_REVISION_ID, 471 &err); 472 } 473 474 if (strcmp(path, SWITCH_B_PATH) == 0) { 475 device_found = 1; 476 (void) snprintf(NAC, sizeof (NAC), "%s/%s", IOBOARD, SWITCH_B); 477 revision = ontario_get_int_propval(pcih, OBP_PROP_REVISION_ID, 478 &err); 479 } 480 481 if (strcmp(path, ONT_LSI_PATH) == 0) { 482 device_found = 1; 483 (void) snprintf(NAC, sizeof (NAC), "%s/%s", IOBOARD, 484 SAS_SATA_HBA); 485 revision = ontario_get_int_propval(pcih, OBP_PROP_REVISION_ID, 486 &err); 487 } 488 if (device_found == 1) { 489 (void) strcpy(device_path, path); 490 err = ontario_get_first_compatible_value(pcih, &compatible); 491 492 /* Print NAC name */ 493 log_printf("%-20s", NAC); 494 /* Print Device Path */ 495 if (strlen(device_path) > 38) 496 log_printf("%38.37s+", device_path); 497 else 498 log_printf("%39s", device_path); 499 /* Print Compatible # */ 500 log_printf("%31s", compatible); 501 free(compatible); 502 /* Print Revision */ 503 log_printf("%6d", revision); 504 log_printf("\n"); 505 } 506 507 return (PICL_WALK_CONTINUE); 508 } 509 510 /*ARGSUSED*/ 511 static void 512 sun4v_display_hw_revisions(Prom_node *root, picl_nodehdl_t plafh) 513 { 514 Prom_node *pnode; 515 char *value; 516 char platbuf[MAXSTRLEN]; 517 char *fmt = "%-20s %-45s %-30s %-9s"; 518 519 log_printf(dgettext(TEXT_DOMAIN, "\n" 520 "========================= HW Revisions " 521 "=======================================\n\n")); 522 523 log_printf(dgettext(TEXT_DOMAIN, 524 "System PROM revisions:\n" 525 "----------------------\n")); 526 527 pnode = dev_find_node(root, "openprom"); 528 if (pnode != NULL) { 529 value = (char *)get_prop_val(find_prop(pnode, "version")); 530 log_printf(value); 531 } 532 533 log_printf(dgettext(TEXT_DOMAIN, "\n\n" 534 "IO ASIC revisions:\n" 535 "------------------\n")); 536 log_printf(fmt, "Location", "Path", "Device", "Revision\n", 0); 537 log_printf(fmt, "--------------------", 538 "---------------------------------------------", 539 "------------------------------", 540 "---------\n", 0); 541 542 /* Get platform name, if that fails, use ontario name by default */ 543 if (sysinfo(SI_PLATFORM, platbuf, sizeof (platbuf)) == -1) { 544 (void) strcpy(platbuf, ONTARIO_PLATFORM); 545 } 546 547 /* 548 * Walk tree based on platform 549 */ 550 if ((strncmp(platbuf, ONTARIO_PLATFORM, 551 strlen(ONTARIO_PLATFORM))) == 0) { 552 (void) picl_walk_tree_by_class(plafh, "pciex", 553 "pciex", ontario_hw_rev_callback); 554 (void) picl_walk_tree_by_class(plafh, "pci", 555 "pci", ontario_hw_rev_callback); 556 (void) picl_walk_tree_by_class(plafh, "network", 557 "network", ontario_hw_rev_callback); 558 (void) picl_walk_tree_by_class(plafh, "scsi-2", "scsi-2", 559 ontario_hw_rev_callback); 560 } else if ((strncmp(platbuf, PELTON_PLATFORM, 561 strlen(PELTON_PLATFORM))) == 0) { 562 (void) picl_walk_tree_by_class(plafh, "pciex", 563 "pciex", pelton_hw_rev_callback); 564 (void) picl_walk_tree_by_class(plafh, "pci", 565 "pci", pelton_hw_rev_callback); 566 (void) picl_walk_tree_by_class(plafh, "network", 567 "network", pelton_hw_rev_callback); 568 (void) picl_walk_tree_by_class(plafh, "scsi-2", "scsi-2", 569 pelton_hw_rev_callback); 570 } else if ((strncmp(platbuf, STPAUL_PLATFORM, 571 strlen(STPAUL_PLATFORM))) == 0) { 572 (void) picl_walk_tree_by_class(plafh, "pciex", 573 "pciex", stpaul_hw_rev_callback); 574 (void) picl_walk_tree_by_class(plafh, "pci", 575 "pci", stpaul_hw_rev_callback); 576 (void) picl_walk_tree_by_class(plafh, "network", 577 "network", stpaul_hw_rev_callback); 578 (void) picl_walk_tree_by_class(plafh, "scsi-2", "scsi-2", 579 stpaul_hw_rev_callback); 580 } else if ((strncmp(platbuf, HURON_1U_PLATFORM, 581 strlen(HURON_1U_PLATFORM)) == 0) || (strncmp(platbuf, 582 HURON_2U_PLATFORM, strlen(HURON_2U_PLATFORM)) == 0)) { 583 (void) picl_walk_tree_by_class(plafh, "pciex", 584 "pciex", huron_hw_rev_callback); 585 (void) picl_walk_tree_by_class(plafh, "sun4v", 586 "niu", huron_hw_rev_callback); 587 (void) picl_walk_tree_by_class(plafh, "network", 588 "network", huron_hw_rev_callback); 589 (void) picl_walk_tree_by_class(plafh, "scsi-2", "scsi-2", 590 huron_hw_rev_callback); 591 } else if ((strncmp(platbuf, GLENDALE_PLATFORM, 592 strlen(GLENDALE_PLATFORM))) == 0) { 593 (void) picl_walk_tree_by_class(plafh, "pciex", 594 "pciex", glendale_hw_rev_callback); 595 (void) picl_walk_tree_by_class(plafh, "sun4v", 596 "niu", glendale_hw_rev_callback); 597 (void) picl_walk_tree_by_class(plafh, "pci", 598 "pci", glendale_hw_rev_callback); 599 (void) picl_walk_tree_by_class(plafh, "sun4v", 600 "pci", glendale_hw_rev_callback); 601 (void) picl_walk_tree_by_class(plafh, "network", 602 "network", glendale_hw_rev_callback); 603 (void) picl_walk_tree_by_class(plafh, "scsi-2", 604 "scsi-2", glendale_hw_rev_callback); 605 } else { 606 (void) picl_walk_tree_by_class(plafh, "pciex", "pciex", 607 erie_hw_rev_callback); 608 (void) picl_walk_tree_by_class(plafh, "pci", "pci", 609 erie_hw_rev_callback); 610 (void) picl_walk_tree_by_class(plafh, "network", "network", 611 erie_hw_rev_callback); 612 (void) picl_walk_tree_by_class(plafh, "scsi-2", "scsi-2", 613 erie_hw_rev_callback); 614 } 615 } 616 617 /* 618 * return the first compatible value 619 */ 620 static int 621 ontario_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 622 { 623 int err; 624 picl_prophdl_t proph; 625 picl_propinfo_t pinfo; 626 picl_prophdl_t tblh; 627 picl_prophdl_t rowproph; 628 char *pval; 629 630 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 631 &pinfo, &proph); 632 if (err != PICL_SUCCESS) 633 return (err); 634 635 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 636 pval = malloc(pinfo.size); 637 if (pval == NULL) 638 return (PICL_FAILURE); 639 err = picl_get_propval(proph, pval, pinfo.size); 640 if (err != PICL_SUCCESS) { 641 free(pval); 642 return (err); 643 } 644 *outbuf = pval; 645 return (PICL_SUCCESS); 646 } 647 648 if (pinfo.type != PICL_PTYPE_TABLE) 649 return (PICL_FAILURE); 650 651 /* get first string from table */ 652 err = picl_get_propval(proph, &tblh, pinfo.size); 653 if (err != PICL_SUCCESS) 654 return (err); 655 656 err = picl_get_next_by_row(tblh, &rowproph); 657 if (err != PICL_SUCCESS) 658 return (err); 659 660 err = picl_get_propinfo(rowproph, &pinfo); 661 if (err != PICL_SUCCESS) 662 return (err); 663 664 pval = malloc(pinfo.size); 665 if (pval == NULL) 666 return (PICL_FAILURE); 667 668 err = picl_get_propval(rowproph, pval, pinfo.size); 669 if (err != PICL_SUCCESS) { 670 free(pval); 671 return (err); 672 } 673 674 *outbuf = pval; 675 return (PICL_SUCCESS); 676 } 677 678 static int64_t 679 ontario_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 680 { 681 int err; 682 picl_prophdl_t proph; 683 picl_propinfo_t pinfo; 684 int8_t int8v; 685 int16_t int16v; 686 int32_t int32v; 687 int64_t int64v; 688 689 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 690 if (err != PICL_SUCCESS) { 691 *ret = err; 692 return (0); 693 } 694 695 /* 696 * If it is not an int, uint or byte array prop, return failure 697 */ 698 if ((pinfo.type != PICL_PTYPE_INT) && 699 (pinfo.type != PICL_PTYPE_UNSIGNED_INT) && 700 (pinfo.type != PICL_PTYPE_BYTEARRAY)) { 701 *ret = PICL_FAILURE; 702 return (0); 703 } 704 705 switch (pinfo.size) { 706 case sizeof (int8_t): 707 err = picl_get_propval(proph, &int8v, sizeof (int8v)); 708 *ret = err; 709 return (int8v); 710 case sizeof (int16_t): 711 err = picl_get_propval(proph, &int16v, sizeof (int16v)); 712 *ret = err; 713 return (int16v); 714 case sizeof (int32_t): 715 err = picl_get_propval(proph, &int32v, sizeof (int32v)); 716 *ret = err; 717 return (int32v); 718 case sizeof (int64_t): 719 err = picl_get_propval(proph, &int64v, sizeof (int64v)); 720 *ret = err; 721 return (int64v); 722 default: /* not supported size */ 723 *ret = PICL_FAILURE; 724 return (0); 725 } 726 } 727