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 * 25 * Opl Platform specific functions. 26 * 27 * called when : 28 * machine_type == MTYPE_OPL 29 */ 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <ctype.h> 35 #include <string.h> 36 #include <varargs.h> 37 #include <fcntl.h> 38 #include <assert.h> 39 #include <sys/param.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #include <sys/utsname.h> 43 #include <sys/systeminfo.h> 44 #include <sys/openpromio.h> 45 #include <libintl.h> 46 #include <syslog.h> 47 #include <sys/dkio.h> 48 #include <pdevinfo.h> 49 #include <libprtdiag.h> 50 #include <libdevinfo.h> 51 #include <kstat.h> 52 53 /* 54 * Globals and externs 55 */ 56 #define KBYTE 1024 57 #define MBYTE (KBYTE * KBYTE) 58 #define HZ_TO_MHZ(x) ((((uint64_t)(x)) + 500000) / 1000000) 59 #define SCF_SECURE_MODE_KSTAT_NAMED "secure_mode" 60 #define SCF_STAT_MODE_UNLOCK 0 61 #define SCF_STAT_MODE_LOCK 1 62 #define SCF_SYSTEM_KSTAT_NAME "scf" 63 #ifndef TEXT_DOMAIN 64 #define TEXT_DOMAIN "SYS_TEST" 65 #endif /* TEXT_DOMAIN */ 66 67 /* 68 * Global functions and variables 69 * these functions will overlay the symbol table of libprtdiag 70 * at runtime (Opl systems only) 71 */ 72 struct cs_status { 73 int cs_number; 74 int status; 75 uint_t avail_hi; 76 uint_t avail_lo; 77 uint_t dimm_hi; 78 uint_t dimm_lo; 79 int dimms; 80 }; 81 82 int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag); 83 void *get_prop_val(Prop *prop); 84 void display_ffb(Board_node *, int); 85 void display_sbus(Board_node *board); 86 void display_cpu_devices(Sys_tree *tree); 87 void display_cpus(Board_node *board); 88 void display_memoryconf(Sys_tree *tree, struct grp_info *grps); 89 void display_io_cards(struct io_card *list); 90 void display_io_devices(Sys_tree *tree); 91 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, 92 struct system_kstat_data *kstats); 93 Prop *find_prop(Prom_node *pnode, char *name); 94 int do_piclinfo(int); 95 int get_proc_mode(void); 96 97 /* Local functions */ 98 static void opl_disp_environ(void); 99 static void opl_disp_hw_revisions(Sys_tree *tree, Prom_node *root); 100 static uint64_t print_opl_memory_line(int lsb, struct cs_status *cs_stat, 101 int ngrps, int mirror_mode); 102 static uint64_t get_opl_mem_regs(Board_node *bnode); 103 void add_node(Sys_tree *root, Prom_node *pnode); 104 static int get_prop_size(Prop *prop); 105 106 static int v_flag = 0; 107 108 /* 109 * Linked list of IO card info for display. 110 * Using file scope for use in a recursive function. 111 */ 112 static struct io_card *card_list = NULL; 113 114 /* 115 * Check prom node for a class-code. If it exists and it's not a bridge device 116 * then add an io_card to card_list. Then recursively call this function for 117 * its child and sibling nodes. 118 */ 119 static void 120 walk_tree_for_pci_devices(Prom_node *node, int board_number) 121 { 122 struct io_card card; 123 char *str; 124 void *val; 125 int ccode; 126 127 if (node == NULL) { 128 return; 129 } 130 131 /* Look for a class-code property. Skip, if it's a bridge */ 132 ccode = -1; 133 val = get_prop_val(find_prop(node, "class-code")); 134 if (val != NULL) { 135 ccode = *(int *)val; 136 } 137 if ((ccode != -1) && (ccode < 0x60000 || ccode > 0x6ffff)) { 138 (void) memset(&card, 0, sizeof (card)); 139 card.board = board_number; 140 141 str = (char *)get_prop_val(find_prop(node, "name")); 142 (void) strlcpy(card.name, (str == NULL ? "N/A":str), 143 sizeof (card.name)); 144 145 str = (char *)get_prop_val(find_prop(node, "model")); 146 (void) strlcpy(card.model, (str == NULL ? "N/A":str), 147 sizeof (card.model)); 148 149 /* insert card to the list */ 150 card_list = insert_io_card(card_list, &card); 151 } 152 /* Call this function for its child/sibling */ 153 walk_tree_for_pci_devices(node->child, board_number); 154 walk_tree_for_pci_devices(node->sibling, board_number); 155 } 156 157 /* 158 * For display of I/O devices for "prtdiag" 159 */ 160 void 161 display_io_devices(Sys_tree *tree) 162 { 163 Board_node *bnode; 164 165 if (v_flag) { 166 /* 167 * OPL's PICL interface for display of PCI I/O devices 168 * for "prtdiag -v" 169 */ 170 (void) do_piclinfo(v_flag); 171 } else { 172 log_printf("\n", 0); 173 log_printf("=========================", 0); 174 log_printf(dgettext(TEXT_DOMAIN, " IO Cards "), 0); 175 log_printf("=========================", 0); 176 log_printf("\n", 0); 177 log_printf("\n", 0); 178 bnode = tree->bd_list; 179 while (bnode != NULL) { 180 walk_tree_for_pci_devices(bnode->nodes, 181 bnode->board_num); 182 bnode = bnode->next; 183 } 184 display_io_cards(card_list); 185 free_io_cards(card_list); 186 } 187 } 188 189 /* 190 * There are no FFB's on OPL. 191 */ 192 /*ARGSUSED*/ 193 void 194 display_ffb(Board_node *board, int table) 195 { 196 } 197 198 /* 199 * There are no Sbus's on OPL. 200 */ 201 /*ARGSUSED*/ 202 void 203 display_sbus(Board_node *board) 204 { 205 } 206 207 /* 208 * Details of I/O information. Print out all the io cards. 209 */ 210 void 211 display_io_cards(struct io_card *list) 212 { 213 char *hdrfmt = "%-6.6s %-14.14s %-12.12s\n"; 214 215 struct io_card *p; 216 217 if (list == NULL) 218 return; 219 220 (void) textdomain(TEXT_DOMAIN); 221 222 log_printf(hdrfmt, gettext("LSB"), gettext("Name"), gettext("Model"), 223 0); 224 225 log_printf(hdrfmt, "---", "-----------------", "------------", 0); 226 227 for (p = list; p != NULL; p = p->next) { 228 229 /* Board number */ 230 log_printf(" %02d ", p->board, 0); 231 232 /* Card name */ 233 log_printf("%-15.15s", p->name, 0); 234 235 /* Card model */ 236 log_printf("%-12.12s", p->model, 0); 237 238 log_printf("\n", 0); 239 } 240 log_printf("\n", 0); 241 } 242 243 /* 244 * Details of CPU information. 245 */ 246 void 247 display_cpu_devices(Sys_tree *tree) 248 { 249 Board_node *bnode; 250 char *hdrfmt = 251 "%-4.4s %-4.4s %-40.40s %-5.5s %-5.5s %-5.5s %-4.4s\n"; 252 253 (void) textdomain(TEXT_DOMAIN); 254 255 /* 256 * Display the table header for CPUs . Then display the CPU 257 * frequency, cache size, and processor revision of all cpus. 258 */ 259 log_printf("\n", 0); 260 log_printf("====================================", 0); 261 log_printf(gettext(" CPUs "), 0); 262 log_printf("====================================", 0); 263 log_printf("\n\n", 0); 264 265 log_printf(hdrfmt, 266 "", 267 gettext("CPU"), 268 gettext(" CPU "), 269 gettext("Run"), 270 gettext("L2$"), 271 gettext("CPU"), 272 gettext("CPU"), 0); 273 274 log_printf(hdrfmt, 275 gettext("LSB"), 276 gettext("Chip"), 277 gettext(" ID "), 278 gettext("MHz"), 279 gettext(" MB"), 280 gettext("Impl."), 281 gettext("Mask"), 0); 282 283 log_printf(hdrfmt, 284 "---", "----", "----------------------------------------", "----", 285 "---", "-----", "----", 0); 286 287 /* Now display all of the cpus on each board */ 288 for (bnode = tree->bd_list; bnode != NULL; bnode = bnode->next) { 289 display_cpus(bnode); 290 } 291 292 log_printf("\n", 0); 293 } 294 295 /* 296 * Display the CPUs present on this board. 297 */ 298 void 299 display_cpus(Board_node *board) 300 { 301 int *impl, *mask, *cpuid, *portid, *l2cache_size; 302 uint_t freq; /* CPU clock frequency */ 303 Prom_node *pnode, *cpu; 304 char *name; 305 306 (void) textdomain(TEXT_DOMAIN); 307 308 /* 309 * Get the Cpus' properties for display 310 */ 311 for (pnode = board->nodes; pnode != NULL; pnode = pnode->sibling) { 312 char cpu_str[MAXSTRLEN], fcpu_str[MAXSTRLEN] = {0}; 313 314 name = get_node_name(pnode); 315 if ((name == NULL) || (strncmp(name, "cmp", 3) != 0)) { 316 continue; 317 } 318 319 portid = (int *)get_prop_val(find_prop(pnode, "portid")); 320 freq = (HZ_TO_MHZ(get_cpu_freq(pnode->child))); 321 l2cache_size = (int *)get_prop_val(find_prop(pnode->child, 322 "l2-cache-size")); 323 impl = (int *)get_prop_val(find_prop(pnode->child, 324 "implementation#")); 325 mask = (int *)get_prop_val(find_prop(pnode->child, "mask#")); 326 327 /* Lsb id */ 328 log_printf(" %02d ", board->board_num, 0); 329 330 if (portid != NULL) 331 log_printf("%3d ", (((*portid)>>3)&0x3), 0); 332 333 /* 334 * OPL 335 * Specific parsing of the CMP/CORE/CPU chain. 336 * The internal cpu tree built by walk_di_tree() 337 * in common code can be illustrated by the diagram 338 * below: 339 * 340 * Olympus: 341 * 342 * cmp->cpu->cpu->cpu->cpu->(next board nodes) 343 * / \ 344 * core core 345 * 346 * Jupiter: 347 * 348 * cmp->cpu->cpu->cpu->cpu->cpu->cpu->cpu->cpu->(board nodes) 349 * | 350 * _____________ 351 * / \ \ \ 352 * core core core core 353 * 354 * 355 * where "/" or "\" are children 356 * and "->" are siblings 357 * 358 */ 359 for (cpu = pnode->sibling; cpu != NULL; ) { 360 Prom_node *cpu_next = NULL; 361 362 name = get_node_name(cpu); 363 if ((name == NULL) || (strncmp(name, "cpu", 3) != 0)) { 364 break; 365 } 366 367 /* Id assigned to Virtual processor core */ 368 cpuid = (int *)get_prop_val(find_prop(cpu, "cpuid")); 369 cpu_next = cpu->sibling; 370 371 if (cpu_next != NULL) { 372 name = get_node_name(cpu_next); 373 374 if ((name == NULL) || 375 (strncmp(name, "cpu", 3) != 0)) { 376 cpu_next = NULL; 377 } 378 } 379 380 if (cpuid != NULL) { 381 /* Used for printing in comma format */ 382 (void) sprintf(cpu_str, "%4d", *cpuid); 383 (void) strlcat(fcpu_str, cpu_str, MAXSTRLEN); 384 385 if (cpu_next != NULL) { 386 (void) strlcat(fcpu_str, ",", 387 MAXSTRLEN); 388 } 389 } else { 390 (void) sprintf(cpu_str, "%4s", "N/A"); 391 (void) strlcat(fcpu_str, cpu_str, MAXSTRLEN); 392 393 if (cpu_next != NULL) { 394 (void) strlcat(fcpu_str, ",", 395 MAXSTRLEN); 396 } 397 } 398 cpu = cpu_next; 399 } 400 401 log_printf("%-40.40s", fcpu_str, 0); 402 403 /* Running frequency */ 404 if (freq != 0) 405 log_printf(" %4ld ", freq, 0); 406 else 407 log_printf(" %4s ", "N/A", 0); 408 409 /* L2 cache size */ 410 if (l2cache_size == NULL) 411 log_printf(" %3s ", "N/A", 0); 412 else { 413 log_printf("%4.1f ", 414 (float)(*l2cache_size) / (float)(1<<20), 0); 415 } 416 417 418 /* Implementation number of processor */ 419 if (impl != NULL) 420 log_printf(" %4d ", *impl, 0); 421 else 422 log_printf(" %4s ", "N/A", 0); 423 424 /* Mask Set version */ 425 /* Bits 31:24 of VER register is mask. */ 426 /* Mask value : Non MTP mode - 00-7f, MTP mode - 80-ff */ 427 if (mask == NULL) 428 log_printf("%3s", "N/A", 0); 429 else 430 log_printf("%-3d", (*mask)&0xff, 0); 431 432 log_printf("\n", 0); 433 434 } 435 } 436 437 /* 438 * Gather memory information: Details of memory information. 439 */ 440 static uint64_t 441 get_opl_mem_regs(Board_node *bnode) 442 { 443 Prom_node *pnode; 444 struct cs_status *cs_stat; 445 uint64_t total_mem = 0; 446 int cs_size, ngrps; 447 448 pnode = dev_find_node(bnode->nodes, "pseudo-mc"); 449 while (pnode != NULL) { 450 451 cs_size = get_prop_size(find_prop(pnode, "cs-status")); 452 453 if (cs_size > 0) { 454 int *mirror_mode = NULL; 455 int mode = 0; 456 457 /* OBP returns lists of 7 ints */ 458 cs_stat = (struct cs_status *)get_prop_val 459 (find_prop(pnode, "cs-status")); 460 461 mirror_mode = (int *)(get_prop_val 462 (find_prop(pnode, "mirror-mode"))); 463 464 if (mirror_mode != NULL) 465 mode = (*mirror_mode); 466 467 /* 468 * The units of cs_size will be either number of bytes 469 * or number of int array elements as this is derived 470 * from the libprtdiag Prop node size field which has 471 * inconsistent units. Until this is addressed in 472 * libprtdiag, we need a heuristic to determine the 473 * number of CS groups. Given that the maximum number 474 * of CS groups is 2, the maximum number of cs-status 475 * array elements will be 2*7=14. Since this is smaller 476 * than the byte size of a single struct status, we use 477 * this to decide if we are dealing with bytes or array 478 * elements in determining the number of CS groups. 479 */ 480 if (cs_size < sizeof (struct cs_status)) { 481 /* cs_size is number of total int [] elements */ 482 ngrps = cs_size / 7; 483 } else { 484 /* cs_size is total byte count */ 485 ngrps = cs_size/sizeof (struct cs_status); 486 } 487 488 if (cs_stat != NULL) { 489 total_mem += 490 print_opl_memory_line(bnode->board_num, 491 cs_stat, ngrps, mode); 492 } 493 } 494 495 pnode = dev_next_node(pnode, "pseudo-mc"); 496 } 497 return (total_mem); 498 } 499 500 /* 501 * Display memory information. 502 */ 503 /*ARGSUSED*/ 504 void 505 display_memoryconf(Sys_tree *tree, struct grp_info *grps) 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