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