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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <ctype.h>
33 #include <string.h>
34 #include <kvm.h>
35 #include <varargs.h>
36 #include <time.h>
37 #include <dirent.h>
38 #include <fcntl.h>
39 #include <sys/param.h>
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #include <sys/utsname.h>
43 #include <sys/openpromio.h>
44 #include <libintl.h>
45 #include <syslog.h>
46 #include <sys/dkio.h>
47 #include "pdevinfo.h"
48 #include "display.h"
49 #include "display_sun4v.h"
50 #include "libprtdiag.h"
51 
52 
53 #if !defined(TEXT_DOMAIN)
54 #define	TEXT_DOMAIN	"SYS_TEST"
55 #endif
56 
57 extern	int sys_clk;
58 
59 int
60 sun4v_display(Sys_tree *tree, Prom_node *root, int syserrlog,
61     picl_nodehdl_t plafh)
62 {
63 	int exit_code = 0;	/* init to all OK */
64 	void *value;		/* used for opaque PROM data */
65 	struct mem_total memory_total;	/* Total memory in system */
66 	struct grp_info grps;	/* Info on all groups in system */
67 
68 	sys_clk = -1;  /* System clock freq. (in MHz) */
69 
70 	/*
71 	 * Now display the machine's configuration. We do this if we
72 	 * are not logging.
73 	 */
74 	if (!logging) {
75 		struct utsname uts_buf;
76 
77 		/*
78 		 * Display system banner
79 		 */
80 		(void) uname(&uts_buf);
81 
82 		log_printf(
83 			dgettext(TEXT_DOMAIN, "System Configuration:  "
84 				"Sun Microsystems  %s %s\n"), uts_buf.machine,
85 					get_prop_val(find_prop(root,
86 					"banner-name")), 0);
87 
88 		/* display system clock frequency */
89 		value = get_prop_val(find_prop(root, "clock-frequency"));
90 		if (value != NULL) {
91 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
92 			log_printf(dgettext(TEXT_DOMAIN, "System clock "
93 				"frequency: %d MHz\n"), sys_clk, 0);
94 		}
95 
96 		/* Display the Memory Size */
97 		display_memorysize(tree, NULL, &grps, &memory_total);
98 
99 		/* Display the CPU devices */
100 		sun4v_display_cpu_devices(plafh);
101 
102 		/* Display the Memory configuration */
103 		sun4v_display_memoryconf(plafh);
104 
105 		/* Display all the IO cards. */
106 		(void) sun4v_display_pci(plafh);
107 
108 		sun4v_display_diaginfo((syserrlog || (logging)), root, plafh);
109 	}
110 
111 	return (exit_code);
112 }
113 
114 /*
115  * display_pci
116  * Display all the PCI IO cards on this board.
117  */
118 void
119 sun4v_display_pci(picl_nodehdl_t plafh)
120 {
121 #ifdef	lint
122 	plafh = plafh;
123 #endif
124 	/*
125 	 * This function is intentionally empty
126 	 */
127 }
128 
129 void
130 sun4v_display_memoryconf(picl_nodehdl_t plafh)
131 {
132 #ifdef	lint
133 	plafh = plafh;
134 #endif
135 	/*
136 	 * This function is intentionally empty
137 	 */
138 }
139 
140 void
141 sun4v_display_cpu_devices(picl_nodehdl_t plafh)
142 {
143 	char	*fmt = "%-12s %-5s %-8s %-19s %-5s";
144 
145 	/*
146 	 * Display the table header for CPUs . Then display the CPU
147 	 * frequency, cache size, and processor revision of all cpus.
148 	 */
149 	log_printf(dgettext(TEXT_DOMAIN,
150 		"\n"
151 		"========================="
152 		" CPUs "
153 		"==============================================="
154 		"\n"
155 		"\n"));
156 	log_printf(fmt, "", "", "", "CPU", "CPU", 0);
157 	log_printf("\n");
158 	log_printf(fmt, "Location", "CPU", "Freq",
159 	    "Implementation", "Mask", 0);
160 	log_printf("\n");
161 	log_printf(fmt, "------------", "-----", "--------",
162 	    "-------------------", "-----", 0);
163 	log_printf("\n");
164 
165 	(void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus);
166 
167 	log_printf("\n");
168 }
169 
170 /*
171  * Display the CPUs present on this board.
172  */
173 /*ARGSUSED*/
174 int
175 sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
176 {
177 	int status;
178 	picl_prophdl_t	proph;
179 	picl_prophdl_t	tblh;
180 	picl_prophdl_t	rowproph;
181 	picl_propinfo_t propinfo;
182 	int		*int_value;
183 	uint64_t	cpuid, mask_no;
184 	char		*comp_value;
185 	char		*no_prop_value = "   ";
186 	char		freq_str[MAXSTRLEN];
187 	char		fru_name[MAXSTRLEN];
188 
189 	/*
190 	 * Get cpuid property and print it and the NAC name
191 	 */
192 	status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph);
193 	if (status == PICL_SUCCESS) {
194 		status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
195 		if (status != PICL_SUCCESS) {
196 			log_printf("%-12s", no_prop_value);
197 			log_printf("%6s", no_prop_value);
198 		} else {
199 			(void) snprintf(fru_name, sizeof (fru_name), "%s%d",
200 			    CPU_STRAND_NAC, (int)cpuid);
201 			log_printf("%-12s", fru_name);
202 			log_printf("%6d", (int)cpuid);
203 		}
204 	} else {
205 		log_printf("%-12s", no_prop_value);
206 		log_printf("%6s", no_prop_value);
207 	}
208 
209 clock_freq:
210 	status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
211 	    &proph);
212 	if (status == PICL_SUCCESS) {
213 		int_value = malloc(propinfo.size);
214 		if (int_value == NULL) {
215 			log_printf("%9s", no_prop_value);
216 			goto compatible;
217 		}
218 		status = picl_get_propval(proph, int_value, propinfo.size);
219 		if (status != PICL_SUCCESS) {
220 			log_printf("%9s", no_prop_value);
221 		} else {
222 			/* Running frequency */
223 			(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
224 			    CLK_FREQ_TO_MHZ(*int_value));
225 			log_printf("%9s", freq_str);
226 		}
227 		free(int_value);
228 	} else
229 		log_printf("%9s", no_prop_value);
230 
231 compatible:
232 	status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
233 	    &proph);
234 	if (status == PICL_SUCCESS) {
235 		if (propinfo.type == PICL_PTYPE_CHARSTRING) {
236 			/*
237 			 * Compatible Property only has 1 value
238 			 */
239 			comp_value = malloc(propinfo.size);
240 			if (comp_value == NULL) {
241 				log_printf("%20s", no_prop_value, 0);
242 				goto mask;
243 			}
244 			status = picl_get_propval(proph, comp_value,
245 			    propinfo.size);
246 			if (status == PICL_SUCCESS) {
247 				log_printf("%20s", no_prop_value, 0);
248 				free(comp_value);
249 			}
250 		} else if (propinfo.type == PICL_PTYPE_TABLE) {
251 			/*
252 			 * Compatible Property has multiple values
253 			 */
254 			status = picl_get_propval(proph, &tblh, propinfo.size);
255 			if (status != PICL_SUCCESS) {
256 				printf("Failed getting tblh\n");
257 				log_printf("%20s", no_prop_value, 0);
258 				goto mask;
259 			}
260 			status = picl_get_next_by_row(tblh, &rowproph);
261 			if (status != PICL_SUCCESS) {
262 				printf("Failed getting next by row\n");
263 				log_printf("%20s", no_prop_value, 0);
264 				goto mask;
265 			}
266 
267 			status = picl_get_propinfo(rowproph, &propinfo);
268 			if (status != PICL_SUCCESS) {
269 				printf("Failed getting prop for rowproph\n");
270 				log_printf("%20s", no_prop_value, 0);
271 				goto mask;
272 			}
273 
274 			comp_value = malloc(propinfo.size);
275 			if (comp_value == NULL) {
276 				printf("Failed to get malloc value?\n");
277 				log_printf("%20s", no_prop_value, 0);
278 				goto mask;
279 			}
280 
281 			status = picl_get_propval(rowproph, comp_value,
282 			    propinfo.size);
283 			if (status != PICL_SUCCESS) {
284 				printf("Failed geting rowproph\n");
285 				log_printf("%20s", no_prop_value, 0);
286 				free(comp_value);
287 				goto mask;
288 			} else
289 				log_printf("%20s", comp_value, 0);
290 			free(comp_value);
291 		}
292 	} else
293 		log_printf("%20s", no_prop_value, 0);
294 
295 mask:
296 	status = picl_get_propinfo_by_name(cpuh, "mask#", &propinfo, &proph);
297 	if (status == PICL_SUCCESS) {
298 		status = picl_get_propval(proph, &mask_no, sizeof (mask_no));
299 		if (status != PICL_SUCCESS) {
300 			log_printf("%9s", no_prop_value);
301 		} else {
302 			log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
303 			    (mask_no>> 4) & 0xf, mask_no & 0xf);
304 		}
305 	} else
306 		log_printf("%9s", no_prop_value);
307 
308 done:
309 	log_printf("\n");
310 	return (PICL_WALK_CONTINUE);
311 }
312 
313 void
314 sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
315 {
316 #ifdef	lint
317 	flag = flag;
318 	root = root;
319 	plafh = plafh;
320 #endif
321 	/*
322 	 * This function is intentionally empty
323 	 */
324 }
325 
326 void
327 display_boardnum(int num)
328 {
329 	log_printf("%2d   ", num, 0);
330 }
331