xref: /illumos-gate/usr/src/lib/libprtdiag_psr/sparc/opl/common/opl.c (revision fb2a9bae0030340ad72b9c26ba1ffee2ee3cafec)
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