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 * Opl Platform specific functions. 26 * 27 * called when : 28 * machine_type == MTYPE_OPL 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <ctype.h> 37 #include <string.h> 38 #include <varargs.h> 39 #include <fcntl.h> 40 #include <assert.h> 41 #include <sys/param.h> 42 #include <sys/stat.h> 43 #include <sys/types.h> 44 #include <sys/utsname.h> 45 #include <sys/systeminfo.h> 46 #include <sys/openpromio.h> 47 #include <libintl.h> 48 #include <syslog.h> 49 #include <sys/dkio.h> 50 #include <pdevinfo.h> 51 #include <libprtdiag.h> 52 #include <libdevinfo.h> 53 #include <kstat.h> 54 55 /* 56 * Globals and externs 57 */ 58 #define KBYTE 1024 59 #define MBYTE (KBYTE * KBYTE) 60 #define HZ_TO_MHZ(x) ((((uint64_t)(x)) + 500000) / 1000000) 61 #define SCF_SECURE_MODE_KSTAT_NAMED "secure_mode" 62 #define SCF_STAT_MODE_UNLOCK 0 63 #define SCF_STAT_MODE_LOCK 1 64 #define SCF_SYSTEM_KSTAT_NAME "scf" 65 #ifndef TEXT_DOMAIN 66 #define TEXT_DOMAIN "SYS_TEST" 67 #endif /* TEXT_DOMAIN */ 68 69 /* 70 * Global functions and variables 71 * these functions will overlay the symbol table of libprtdiag 72 * at runtime (Opl systems only) 73 */ 74 struct cs_status { 75 int cs_number; 76 int status; 77 uint_t avail_hi; 78 uint_t avail_lo; 79 uint_t dimm_hi; 80 uint_t dimm_lo; 81 int dimms; 82 }; 83 84 int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag); 85 void *get_prop_val(Prop *prop); 86 void display_ffb(Board_node *, int); 87 void display_sbus(Board_node *board); 88 void display_cpu_devices(Sys_tree *tree); 89 void display_cpus(Board_node *board); 90 void display_memoryconf(Sys_tree *tree, struct grp_info *grps); 91 void display_io_cards(struct io_card *list); 92 void display_io_devices(Sys_tree *tree); 93 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 94 struct system_kstat_data *kstats); 95 Prop *find_prop(Prom_node *pnode, char *name); 96 int do_piclinfo(int); 97 int get_proc_mode(void); 98 99 /* Local functions */ 100 static void opl_disp_environ(void); 101 static void opl_disp_hw_revisions(Sys_tree *tree, Prom_node *root); 102 static uint64_t print_opl_memory_line(int lsb, struct cs_status *cs_stat, 103 int ngrps, int mirror_mode); 104 static uint64_t get_opl_mem_regs(Board_node *bnode); 105 void add_node(Sys_tree *root, Prom_node *pnode); 106 static int get_prop_size(Prop *prop); 107 108 static int v_flag = 0; 109 110 /* 111 * Linked list of IO card info for display. 112 * Using file scope for use in a recursive function. 113 */ 114 static struct io_card *card_list = NULL; 115 116 /* 117 * Check prom node for a class-code. If it exists and it's not a bridge device 118 * then add an io_card to card_list. Then recursively call this function for 119 * its child and sibling nodes. 120 */ 121 static void 122 walk_tree_for_pci_devices(Prom_node *node, int board_number) 123 { 124 struct io_card card; 125 char *str; 126 void *val; 127 int ccode; 128 129 if (node == NULL) { 130 return; 131 } 132 133 /* Look for a class-code property. Skip, if it's a bridge */ 134 ccode = -1; 135 val = get_prop_val(find_prop(node, "class-code")); 136 if (val != NULL) { 137 ccode = *(int *)val; 138 } 139 if ((ccode != -1) && (ccode < 0x60000 || ccode > 0x6ffff)) { 140 (void) memset(&card, 0, sizeof (card)); 141 card.board = board_number; 142 143 str = (char *)get_prop_val(find_prop(node, "name")); 144 (void) strlcpy(card.name, (str == NULL ? "N/A":str), 145 sizeof (card.name)); 146 147 str = (char *)get_prop_val(find_prop(node, "model")); 148 (void) strlcpy(card.model, (str == NULL ? "N/A":str), 149 sizeof (card.model)); 150 151 /* insert card to the list */ 152 card_list = insert_io_card(card_list, &card); 153 } 154 /* Call this function for its child/sibling */ 155 walk_tree_for_pci_devices(node->child, board_number); 156 walk_tree_for_pci_devices(node->sibling, board_number); 157 } 158 159 /* 160 * For display of I/O devices for "prtdiag" 161 */ 162 void 163 display_io_devices(Sys_tree *tree) 164 { 165 Board_node *bnode; 166 167 if (v_flag) { 168 /* 169 * OPL's PICL interface for display of PCI I/O devices 170 * for "prtdiag -v" 171 */ 172 (void) do_piclinfo(v_flag); 173 } else { 174 log_printf("\n", 0); 175 log_printf("=========================", 0); 176 log_printf(dgettext(TEXT_DOMAIN, " IO Cards "), 0); 177 log_printf("=========================", 0); 178 log_printf("\n", 0); 179 log_printf("\n", 0); 180 bnode = tree->bd_list; 181 while (bnode != NULL) { 182 walk_tree_for_pci_devices(bnode->nodes, 183 bnode->board_num); 184 bnode = bnode->next; 185 } 186 display_io_cards(card_list); 187 free_io_cards(card_list); 188 } 189 } 190 191 /* 192 * There are no FFB's on OPL. 193 */ 194 /*ARGSUSED*/ 195 void 196 display_ffb(Board_node *board, int table) 197 { 198 } 199 200 /* 201 * There are no Sbus's on OPL. 202 */ 203 /*ARGSUSED*/ 204 void 205 display_sbus(Board_node *board) 206 { 207 } 208 209 /* 210 * Details of I/O information. Print out all the io cards. 211 */ 212 void 213 display_io_cards(struct io_card *list) 214 { 215 char *hdrfmt = "%-6.6s %-14.14s %-12.12s\n"; 216 217 struct io_card *p; 218 219 if (list == NULL) 220 return; 221 222 (void) textdomain(TEXT_DOMAIN); 223 224 log_printf(hdrfmt, gettext("LSB"), gettext("Name"), gettext("Model"), 225 0); 226 227 log_printf(hdrfmt, "---", "-----------------", "------------", 0); 228 229 for (p = list; p != NULL; p = p->next) { 230 231 /* Board number */ 232 log_printf(" %02d ", p->board, 0); 233 234 /* Card name */ 235 log_printf("%-15.15s", p->name, 0); 236 237 /* Card model */ 238 log_printf("%-12.12s", p->model, 0); 239 240 log_printf("\n", 0); 241 } 242 log_printf("\n", 0); 243 } 244 245 /* 246 * Details of CPU information. 247 */ 248 void 249 display_cpu_devices(Sys_tree *tree) 250 { 251 Board_node *bnode; 252 char *hdrfmt = 253 "%-4.4s %-4.4s %-40.40s %-5.5s %-5.5s %-5.5s %-4.4s\n"; 254 255 (void) textdomain(TEXT_DOMAIN); 256 257 /* 258 * Display the table header for CPUs . Then display the CPU 259 * frequency, cache size, and processor revision of all cpus. 260 */ 261 log_printf("\n", 0); 262 log_printf("====================================", 0); 263 log_printf(gettext(" CPUs "), 0); 264 log_printf("====================================", 0); 265 log_printf("\n\n", 0); 266 267 log_printf(hdrfmt, 268 "", 269 gettext("CPU"), 270 gettext(" CPU "), 271 gettext("Run"), 272 gettext("L2$"), 273 gettext("CPU"), 274 gettext("CPU"), 0); 275 276 log_printf(hdrfmt, 277 gettext("LSB"), 278 gettext("Chip"), 279 gettext(" ID "), 280 gettext("MHz"), 281 gettext(" MB"), 282 gettext("Impl."), 283 gettext("Mask"), 0); 284 285 log_printf(hdrfmt, 286 "---", "----", "----------------------------------------", "----", 287 "---", "-----", "----", 0); 288 289 /* Now display all of the cpus on each board */ 290 for (bnode = tree->bd_list; bnode != NULL; bnode = bnode->next) { 291 display_cpus(bnode); 292 } 293 294 log_printf("\n", 0); 295 } 296 297 /* 298 * Display the CPUs present on this board. 299 */ 300 void 301 display_cpus(Board_node *board) 302 { 303 int *impl, *mask, *cpuid, *portid, *l2cache_size; 304 uint_t freq; /* CPU clock frequency */ 305 Prom_node *pnode, *cpu; 306 char *name; 307 308 (void) textdomain(TEXT_DOMAIN); 309 310 /* 311 * Get the Cpus' properties for display 312 */ 313 for (pnode = board->nodes; pnode != NULL; pnode = pnode->sibling) { 314 char cpu_str[MAXSTRLEN], fcpu_str[MAXSTRLEN] = {0}; 315 316 name = get_node_name(pnode); 317 if ((name == NULL) || (strncmp(name, "cmp", 3) != 0)) { 318 continue; 319 } 320 321 portid = (int *)get_prop_val(find_prop(pnode, "portid")); 322 freq = (HZ_TO_MHZ(get_cpu_freq(pnode->child))); 323 l2cache_size = (int *)get_prop_val(find_prop(pnode->child, 324 "l2-cache-size")); 325 impl = (int *)get_prop_val(find_prop(pnode->child, 326 "implementation#")); 327 mask = (int *)get_prop_val(find_prop(pnode->child, "mask#")); 328 329 /* Lsb id */ 330 log_printf(" %02d ", board->board_num, 0); 331 332 if (portid != NULL) 333 log_printf("%3d ", (((*portid)>>3)&0x3), 0); 334 335 /* 336 * OPL 337 * Specific parsing of the CMP/CORE/CPU chain. 338 * The internal cpu tree built by walk_di_tree() 339 * in common code can be illustrated by the diagram 340 * below: 341 * 342 * Olympus: 343 * 344 * cmp->cpu->cpu->cpu->cpu->(next board nodes) 345 * / \ 346 * core core 347 * 348 * Jupiter: 349 * 350 * cmp->cpu->cpu->cpu->cpu->cpu->cpu->cpu->cpu->(board nodes) 351 * | 352 * _____________ 353 * / \ \ \ 354 * core core core core 355 * 356 * 357 * where "/" or "\" are children 358 * and "->" are siblings 359 * 360 */ 361 for (cpu = pnode->sibling; cpu != NULL; ) { 362 Prom_node *cpu_next = NULL; 363 364 name = get_node_name(cpu); 365 if ((name == NULL) || (strncmp(name, "cpu", 3) != 0)) { 366 break; 367 } 368 369 /* Id assigned to Virtual processor core */ 370 cpuid = (int *)get_prop_val(find_prop(cpu, "cpuid")); 371 cpu_next = cpu->sibling; 372 373 if (cpu_next != NULL) { 374 name = get_node_name(cpu_next); 375 376 if ((name == NULL) || 377 (strncmp(name, "cpu", 3) != 0)) { 378 cpu_next = NULL; 379 } 380 } 381 382 if (cpuid != NULL) { 383 /* Used for printing in comma format */ 384 (void) sprintf(cpu_str, "%4d", *cpuid); 385 (void) strlcat(fcpu_str, cpu_str, MAXSTRLEN); 386 387 if (cpu_next != NULL) { 388 (void) strlcat(fcpu_str, ",", 389 MAXSTRLEN); 390 } 391 } else { 392 (void) sprintf(cpu_str, "%4s", "N/A"); 393 (void) strlcat(fcpu_str, cpu_str, MAXSTRLEN); 394 395 if (cpu_next != NULL) { 396 (void) strlcat(fcpu_str, ",", 397 MAXSTRLEN); 398 } 399 } 400 cpu = cpu_next; 401 } 402 403 log_printf("%-40.40s", fcpu_str, 0); 404 405 /* Running frequency */ 406 if (freq != 0) 407 log_printf(" %4ld ", freq, 0); 408 else 409 log_printf(" %4s ", "N/A", 0); 410 411 /* L2 cache size */ 412 if (l2cache_size == NULL) 413 log_printf(" %3s ", "N/A", 0); 414 else { 415 log_printf("%4.1f ", 416 (float)(*l2cache_size) / (float)(1<<20), 0); 417 } 418 419 420 /* Implementation number of processor */ 421 if (impl != NULL) 422 log_printf(" %4d ", *impl, 0); 423 else 424 log_printf(" %4s ", "N/A", 0); 425 426 /* Mask Set version */ 427 /* Bits 31:24 of VER register is mask. */ 428 /* Mask value : Non MTP mode - 00-7f, MTP mode - 80-ff */ 429 if (mask == NULL) 430 log_printf("%3s", "N/A", 0); 431 else 432 log_printf("%-3d", (*mask)&0xff, 0); 433 434 log_printf("\n", 0); 435 436 } 437 } 438 439 /* 440 * Gather memory information: Details of memory information. 441 */ 442 static uint64_t 443 get_opl_mem_regs(Board_node *bnode) 444 { 445 Prom_node *pnode; 446 struct cs_status *cs_stat; 447 uint64_t total_mem = 0; 448 int cs_size, ngrps; 449 450 pnode = dev_find_node(bnode->nodes, "pseudo-mc"); 451 while (pnode != NULL) { 452 453 cs_size = get_prop_size(find_prop(pnode, "cs-status")); 454 455 if (cs_size > 0) { 456 int *mirror_mode = NULL; 457 int mode = 0; 458 459 /* OBP returns lists of 7 ints */ 460 cs_stat = (struct cs_status *)get_prop_val 461 (find_prop(pnode, "cs-status")); 462 463 mirror_mode = (int *)(get_prop_val 464 (find_prop(pnode, "mirror-mode"))); 465 466 if (mirror_mode != NULL) 467 mode = (*mirror_mode); 468 469 /* 470 * The units of cs_size will be either number of bytes 471 * or number of int array elements as this is derived 472 * from the libprtdiag Prop node size field which has 473 * inconsistent units. Until this is addressed in 474 * libprtdiag, we need a heuristic to determine the 475 * number of CS groups. Given that the maximum number 476 * of CS groups is 2, the maximum number of cs-status 477 * array elements will be 2*7=14. Since this is smaller 478 * than the byte size of a single struct status, we use 479 * this to decide if we are dealing with bytes or array 480 * elements in determining the number of CS groups. 481 */ 482 if (cs_size < sizeof (struct cs_status)) { 483 /* cs_size is number of total int [] elements */ 484 ngrps = cs_size / 7; 485 } else { 486 /* cs_size is total byte count */ 487 ngrps = cs_size/sizeof (struct cs_status); 488 } 489 490 if (cs_stat != NULL) { 491 total_mem += 492 print_opl_memory_line(bnode->board_num, 493 cs_stat, ngrps, mode); 494 } 495 } 496 497 pnode = dev_next_node(pnode, "pseudo-mc"); 498 } 499 return (total_mem); 500 } 501 502 /* 503 * Display memory information. 504 */ 505 /*ARGSUSED*/ 506 void 507 display_memoryconf(Sys_tree *tree, struct grp_info *grps) 508 { 509 Board_node *bnode = tree->bd_list; 510 uint64_t total_mem = 0, total_sys_mem = 0; 511 char *hdrfmt = "\n%-5.5s %-6.6s %-18.18s %-10.10s" 512 " %-6.6s %-5.5s %-7.7s %-10.10s"; 513 514 (void) textdomain(TEXT_DOMAIN); 515 516 log_printf("============================", 0); 517 log_printf(gettext(" Memory Configuration "), 0); 518 log_printf("============================", 0); 519 log_printf("\n", 0); 520 521 log_printf(hdrfmt, 522 "", 523 gettext("Memory"), 524 gettext("Available"), 525 gettext("Memory"), 526 gettext("DIMM"), 527 gettext("# of"), 528 gettext("Mirror"), 529 gettext("Interleave"), 530 0); 531 532 log_printf(hdrfmt, 533 gettext("LSB"), 534 gettext("Group"), 535 gettext("Size"), 536 gettext("Status"), 537 gettext("Size"), 538 gettext("DIMMs"), 539 gettext("Mode"), 540 gettext("Factor"), 0); 541 542 log_printf(hdrfmt, 543 "---", "-------", "------------------", "-------", "------", 544 "-----", "-------", "----------", 0); 545 546 log_printf("\n", 0); 547 548 for (bnode = tree->bd_list; bnode != NULL; bnode = bnode->next) { 549 total_mem += get_opl_mem_regs(bnode); 550 } 551 552 /* 553 * Sanity check to ensure that the total amount of system 554 * memory matches the total number of memory that 555 * we find here. Display error message if there is a mis-match. 556 */ 557 total_sys_mem = (((uint64_t)sysconf(_SC_PAGESIZE) * (uint64_t)sysconf 558 (_SC_PHYS_PAGES)) / MBYTE); 559 560 if (total_mem != total_sys_mem) { 561 log_printf(dgettext(TEXT_DOMAIN, "\nError:total available " 562 "size [%lldMB] does not match total system memory " 563 "[%lldMB]\n"), total_mem, total_sys_mem, 0); 564 } 565 566 } 567 568 /* 569 * This function provides Opl's formatting of the memory config 570 * information that get_opl_mem_regs() has gathered. 571 */ 572 static uint64_t 573 print_opl_memory_line(int lsb, struct cs_status *cs_stat, int ngrps, 574 int mirror_mode) 575 { 576 int i; 577 uint64_t total_board_mem = 0; 578 int i_factor = 2; /* default to non-mirror mode */ 579 int interleave; 580 581 (void) textdomain(TEXT_DOMAIN); 582 583 if (mirror_mode) 584 i_factor *= 2; 585 586 /* 587 * Interleave factor calculation: 588 * Obtain "mirror-mode" property from pseudo-mc. 589 * cs_stat[0].dimms/i_factor represents interleave factor per 590 * pseudo-mc node. Must use cs_stat[0].dimms since this will yield 591 * interleave factor even if some DIMMs are isolated. 592 * 593 * Mirror mode: 594 * interleave factor = (# of DIMMs on cs_stat[0]/4) 595 * 596 * Non-mirror mode: 597 * interleave factor = (# of DIMMs on cs_stat[0]/2) 598 */ 599 600 interleave = cs_stat[0].dimms/i_factor; 601 602 603 for (i = 0; i < ngrps; i++) { 604 uint64_t mem_size; 605 606 mem_size = ((((uint64_t)cs_stat[i].avail_hi)<<32) + 607 cs_stat[i].avail_lo); 608 609 if (mem_size == 0) 610 continue; 611 612 /* Lsb Id */ 613 log_printf(" %02d ", lsb, 0); 614 615 /* Memory Group Number */ 616 if ((cs_stat[i].cs_number) == 0) 617 log_printf("%-6.6s", "A", 0); 618 else 619 log_printf("%-6.6s", "B", 0); 620 621 /* Memory Group Size */ 622 log_printf("%8lldMB ", mem_size/MBYTE, 0); 623 624 total_board_mem += (mem_size/MBYTE); 625 626 /* Memory Group Status */ 627 log_printf("%-11.11s", 628 cs_stat[i].status ? "partial": "okay", 0); 629 630 /* DIMM Size */ 631 log_printf("%4lldMB ", 632 ((((uint64_t)cs_stat[i].dimm_hi)<<32) 633 + cs_stat[i].dimm_lo)/MBYTE, 0); 634 635 /* Number of DIMMs */ 636 log_printf(" %2d", cs_stat[i].dimms); 637 638 /* Mirror Mode */ 639 if (mirror_mode) { 640 log_printf("%-4.4s", " yes"); 641 } else 642 log_printf("%-4.4s", " no "); 643 644 /* Interleave Factor */ 645 if (interleave) 646 log_printf(" %d-way\n", interleave); 647 else 648 log_printf(" None\n"); 649 } 650 return (total_board_mem); 651 } 652 653 /* 654 * Details of hardware revision and environmental status. 655 */ 656 /*ARGSUSED*/ 657 void 658 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 659 struct system_kstat_data *kstats) 660 { 661 /* Print the PROM revisions */ 662 opl_disp_hw_revisions(tree, root); 663 } 664 665 /* 666 * Gather and display hardware revision and environmental status 667 */ 668 /*ARGSUSED*/ 669 static void 670 opl_disp_hw_revisions(Sys_tree *tree, Prom_node *root) 671 { 672 char *version; 673 Prom_node *pnode; 674 int value; 675 676 (void) textdomain(TEXT_DOMAIN); 677 678 /* Print the header */ 679 log_printf("\n", 0); 680 log_printf("====================", 0); 681 log_printf(gettext(" Hardware Revisions "), 0); 682 log_printf("====================", 0); 683 log_printf("\n\n", 0); 684 685 /* Display Prom revision header */ 686 log_printf(gettext("System PROM revisions:"), 0); 687 log_printf("\n----------------------\n", 0); 688 log_printf("\n", 0); 689 690 /* Display OBP version info */ 691 pnode = dev_find_node(root, "openprom"); 692 if (pnode != NULL) { 693 version = (char *)get_prop_val(find_prop(pnode, "version")); 694 if (version != NULL) 695 log_printf("%s\n\n", version, 0); 696 else 697 log_printf("%s\n\n", "N/A", 0); 698 } 699 700 /* Print the header */ 701 log_printf("\n", 0); 702 log_printf("===================", 0); 703 log_printf(gettext(" Environmental Status "), 0); 704 log_printf("===================", 0); 705 log_printf("\n\n", 0); 706 707 opl_disp_environ(); 708 709 /* 710 * PICL interface needs to be used for system processor mode display. 711 * Check existence of OBP property "SPARC64-VII-mode". 712 * No display if property does not exist. 713 * If property exists then system is in (Jupiter) SPARC64-VII-mode. 714 */ 715 value = get_proc_mode(); 716 717 if (value == 0) { 718 /* Print the header */ 719 log_printf("\n", 0); 720 log_printf("===================", 0); 721 log_printf(gettext(" System Processor Mode "), 0); 722 log_printf("===================", 0); 723 log_printf("\n\n", 0); 724 725 /* Jupiter mode */ 726 log_printf("%s\n\n", "SPARC64-VII mode"); 727 } 728 } 729 730 /* 731 * Gather environmental information 732 */ 733 static void 734 opl_disp_environ(void) 735 { 736 kstat_ctl_t *kc; 737 kstat_t *ksp; 738 kstat_named_t *k; 739 740 if ((kc = kstat_open()) == NULL) 741 return; 742 743 if ((ksp = kstat_lookup 744 (kc, "scfd", 0, SCF_SYSTEM_KSTAT_NAME)) == NULL) { 745 (void) kstat_close(kc); 746 return; 747 } 748 749 if (kstat_read(kc, ksp, NULL) == -1) { 750 (void) kstat_close(kc); 751 return; 752 } 753 754 if ((k = (kstat_named_t *)kstat_data_lookup 755 (ksp, SCF_SECURE_MODE_KSTAT_NAMED)) == NULL) { 756 (void) kstat_close(kc); 757 return; 758 } 759 760 if (k->value.c[0] == SCF_STAT_MODE_LOCK) 761 log_printf("Mode switch is in LOCK mode ", 0); 762 else if (k->value.c[0] == SCF_STAT_MODE_UNLOCK) 763 log_printf("Mode switch is in UNLOCK mode", 0); 764 else 765 log_printf("Mode switch is in UNKNOWN mode", 0); 766 767 log_printf("\n", 0); 768 769 (void) kstat_close(kc); 770 } 771 772 773 /* 774 * Calls do_devinfo() in order to use the libdevinfo device tree 775 * instead of OBP's device tree. 776 */ 777 int 778 do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag) 779 { 780 v_flag = syserrlog; 781 return (do_devinfo(syserrlog, pgname, log_flag, prt_flag)); 782 } 783 784 /* 785 * Return the property value for the Prop 786 * passed in. (When using libdevinfo) 787 */ 788 void * 789 get_prop_val(Prop *prop) 790 { 791 if (prop == NULL) 792 return (NULL); 793 794 return ((void *)(prop->value.val_ptr)); 795 } 796 797 /* 798 * Return the property size for the Prop 799 * passed in. (When using libdevinfo) 800 */ 801 static int 802 get_prop_size(Prop *prop) 803 { 804 805 if ((prop != NULL) && (prop->size > 0)) 806 return (prop->size); 807 else 808 return (0); 809 } 810 811 812 /* 813 * Search a Prom node and retrieve the property with the correct 814 * name. (When using libdevinfo) 815 */ 816 Prop * 817 find_prop(Prom_node *pnode, char *name) 818 { 819 Prop *prop; 820 821 if (pnode == NULL) 822 return (NULL); 823 824 for (prop = pnode->props; prop != NULL; prop = prop->next) { 825 if (prop->name.val_ptr != NULL && 826 strcmp((char *)(prop->name.val_ptr), name) == 0) 827 break; 828 } 829 830 return (prop); 831 } 832 833 /* 834 * This function adds a board node to the board structure where that 835 * that node's physical component lives. 836 */ 837 void 838 add_node(Sys_tree *root, Prom_node *pnode) 839 { 840 int board; 841 Board_node *bnode; 842 Prom_node *p; 843 char *type; 844 845 if ((board = get_board_num(pnode)) == -1) { 846 type = get_node_type(pnode); 847 if ((type != NULL) && (strcmp(type, "cpu") == 0)) 848 board = get_board_num((pnode->parent)->parent); 849 } 850 851 /* find the node with the same board number */ 852 if ((bnode = find_board(root, board)) == NULL) { 853 bnode = insert_board(root, board); 854 bnode->board_type = UNKNOWN_BOARD; 855 } 856 857 /* now attach this prom node to the board list */ 858 /* Insert this node at the end of the list */ 859 pnode->sibling = NULL; 860 if (bnode->nodes == NULL) 861 bnode->nodes = pnode; 862 else { 863 p = bnode->nodes; 864 while (p->sibling != NULL) 865 p = p->sibling; 866 p->sibling = pnode; 867 } 868 869 } 870