xref: /titanic_41/usr/src/lib/libprtdiag_psr/sparc/snowbird/common/snowbird.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 
26 /*
27  * This program prints the diagnostics of Sanibel system. It
28  * also prints other miscellaneous information about watchdog, temperature
29  * of CPU sensor, firmware versions of SMC and, micro controller role
30  * etc. The basic sources of output is PICL, and  SMC.
31  */
32 
33 /* includes */
34 
35 #include <stdio.h>
36 #include <strings.h>
37 #include <ctype.h>
38 #include <string.h>
39 #include <time.h>
40 #include <dirent.h>
41 #include <sys/param.h>
42 #include <picl.h>
43 #include <libintl.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/systeminfo.h>
47 #include <sys/openpromio.h>
48 #include <fcntl.h>
49 #include <smc_if.h>
50 #include <stropts.h>
51 #include <alloca.h>
52 #include <errno.h>
53 #include <poll.h>
54 #include <stdlib.h>
55 #include <unistd.h>
56 #include <kstat.h>
57 #include <sys/utsname.h>
58 #include <stddef.h>
59 #include <pdevinfo.h>
60 #include <display_sun4u.h>
61 #include <libprtdiag.h>
62 #include <smclib.h>
63 #include <smc_commands.h>
64 #include <picldefs.h>
65 
66 /* #defines for the PICL library API usage and local static variables */
67 #define	PD_CPCI_SLOT_TYPE	"cpci"
68 #define	PD_PCI_SLOT_TYPE	"pci"
69 #define	PD_PRESENT		1
70 #define	PD_BLANK		" "
71 #define	PD_ENABLED		1
72 #define	PD_DISABLED		0
73 #define	SNOWBIRD		"SUNW,Netra-CP2300"
74 #define	CHASSIS_NODE_NAME	"chassis"
75 
76 /* #defines for the SMC and IPMI commands */
77 #define	POLL_TIMEOUT				10000
78 #define	DEFAULT_SEQN				0xff
79 
80 /* SMC driver */
81 #define	PD_SMC_DRV_PATH			"/dev/ctsmc"
82 
83 /* Constants */
84 #define	OBP_PROP_BANNER_NAME		"banner-name"
85 #define	OBP_PROP_CLOCK_FREQ		"clock-frequency"
86 
87 
88 
89 /* #defines for local usage */
90 #define	PD_SUCCESS	0
91 #define	PD_FAILURE	1
92 #define	PD_INTERNAL_FAILURE	2
93 #define	PD_ERROR	-1
94 
95 /*	static global variables	*/
96 static int pd_print_option;
97 static uint8_t pd_smc_glbl_enabl_rsp[2];
98 static boolean_t pd_hdr_prt		= B_TRUE;
99 static int pd_smc_fd			= 0;
100 
101 
102 /* function declarations used in this program */
103 static uint32_t pd_check_for_snowbird();
104 static uint32_t pd_prt_snowbird_diag();
105 static uint32_t pd_check_cpu_health();
106 static uint32_t pd_check_tty_debug_mode();
107 static uint32_t pd_query_SMC_firmware_version();
108 static uint32_t pd_check_slots();
109 int32_t pd_prt_slot_info(picl_nodehdl_t, void *);
110 int do_prominfo(int syserrlog, char *pname, int log_flag, int prt_flag);
111 static uint32_t pd_query_watchdog_state();
112 int pd_check_wd_state(picl_nodehdl_t, void *);
113 static uint32_t pd_print_fruinfo_hdr();
114 static uint32_t pd_print_device_info(int);
115 static uint32_t pd_get_role_information();
116 static uint32_t pd_get_message_flags();
117 static uint32_t pd_get_reset_mode();
118 static uint32_t pd_get_sensor_reading();
119 static uint32_t pd_get_sensor_threshold();
120 static uint32_t pd_prt_cpci_condition(picl_nodehdl_t nodeh);
121 static uint32_t pd_check_location_parent(picl_nodehdl_t nodeh);
122 static uint64_t
123 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret);
124 static int picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq);
125 static int display_system_clock(picl_nodehdl_t plafh);
126 
127 /*
128  * return the value of the uint prop
129  */
130 static uint64_t
picldiag_get_uint_propval(picl_nodehdl_t modh,char * prop_name,int * ret)131 picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
132 {
133 	int		err;
134 	picl_prophdl_t	proph;
135 	picl_propinfo_t	pinfo;
136 	uint8_t		uint8v;
137 	uint16_t	uint16v;
138 	uint32_t	uint32v;
139 	uint64_t	uint64v;
140 
141 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
142 	if (err != PICL_SUCCESS) {
143 		*ret = err;
144 		return (0);
145 	}
146 
147 	/*
148 	 * If it is not an int or uint prop, return failure
149 	 */
150 	if ((pinfo.type != PICL_PTYPE_INT) &&
151 	    (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
152 		*ret = PICL_FAILURE;
153 		return (0);
154 	}
155 
156 	/* uint prop */
157 
158 	switch (pinfo.size) {
159 	case sizeof (uint8_t):
160 		err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
161 		*ret = err;
162 		return (uint8v);
163 	case sizeof (uint16_t):
164 		err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
165 		*ret = err;
166 		return (uint16v);
167 	case sizeof (uint32_t):
168 		err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
169 		*ret = err;
170 		return (uint32v);
171 	case sizeof (uint64_t):
172 		err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
173 		*ret = err;
174 		return (uint64v);
175 	default:	/* not supported size */
176 		*ret = PICL_FAILURE;
177 		return (0);
178 	}
179 }
180 
181 
182 
183 /*
184  * get the clock frequency
185  */
186 static int
picldiag_get_clock_freq(picl_nodehdl_t modh,uint32_t * freq)187 picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq)
188 {
189 #define	ROUND_TO_MHZ(x)	(((x) + 500000)/ 1000000)
190 
191 	int		err;
192 	uint64_t	clk_freq;
193 
194 	clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
195 	if (err != PICL_SUCCESS)
196 		return (err);
197 
198 	*freq = ROUND_TO_MHZ(clk_freq);
199 
200 	return (PICL_SUCCESS);
201 }
202 
203 
204 /*
205  * display the clock frequency
206  */
207 static int
display_system_clock(picl_nodehdl_t plafh)208 display_system_clock(picl_nodehdl_t plafh)
209 {
210 	uint32_t	system_clk;
211 	int		err;
212 
213 	err = picldiag_get_clock_freq(plafh, &system_clk);
214 	if (err != PICL_SUCCESS)
215 		return (err);
216 
217 	log_printf(dgettext(TEXT_DOMAIN,
218 	    "System clock frequency: %d MHZ\n"), system_clk);
219 
220 	return (PICL_SUCCESS);
221 }
222 
223 
224 /*
225  * get the value by the property name of the string prop
226  * Caller must free the outbuf
227  */
228 static int
picldiag_get_string_propval(picl_nodehdl_t modh,char * prop_name,char ** outbuf)229 picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf)
230 {
231 	int		err;
232 	picl_prophdl_t	proph;
233 	picl_propinfo_t	pinfo;
234 	char		*prop_value;
235 
236 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
237 	if (err != PICL_SUCCESS)
238 		return (err);
239 
240 	/*
241 	 * If it is not a string prop, return NULL
242 	 */
243 	if (pinfo.type != PICL_PTYPE_CHARSTRING)
244 		return (PICL_FAILURE);
245 
246 	prop_value = malloc(pinfo.size);
247 	if (prop_value == NULL)
248 		return (PICL_FAILURE);
249 
250 	err = picl_get_propval(proph, prop_value, pinfo.size);
251 	if (err != PICL_SUCCESS) {
252 		free(prop_value);
253 		return (err);
254 	}
255 
256 	*outbuf = prop_value;
257 	return (PICL_SUCCESS);
258 }
259 
260 
261 
262 /*
263  * display platform banner
264  */
265 static int
display_platform_banner(picl_nodehdl_t plafh)266 display_platform_banner(picl_nodehdl_t plafh)
267 {
268 	char	*platform;
269 	char	*banner_name;
270 	int	err;
271 
272 	/*
273 	 * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME
274 	 */
275 	log_printf(dgettext(TEXT_DOMAIN,
276 	    "System Configuration: Oracle Corporation "), 0);
277 	err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE,
278 	    &platform);
279 	if (err != PICL_SUCCESS)
280 		return (err);
281 	log_printf(" %s", platform, 0);
282 	free(platform);
283 
284 	err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME,
285 	    &banner_name);
286 	if (err != PICL_SUCCESS)
287 		return (err);
288 	log_printf(" %s", banner_name, 0);
289 	free(banner_name);
290 
291 	log_printf("\n", 0);
292 	return (PICL_SUCCESS);
293 }
294 
295 /*
296  * search children to get the node by the nodename
297  */
298 static int
picldiag_get_node_by_name(picl_nodehdl_t rooth,char * name,picl_nodehdl_t * nodeh)299 picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name,
300     picl_nodehdl_t *nodeh)
301 {
302 	picl_nodehdl_t	childh;
303 	int		err;
304 	char		*nodename;
305 
306 	nodename = alloca(strlen(name) + 1);
307 	if (nodename == NULL)
308 		return (PICL_FAILURE);
309 
310 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
311 	    sizeof (picl_nodehdl_t));
312 
313 	while (err == PICL_SUCCESS) {
314 		err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
315 		    nodename, (strlen(name) + 1));
316 		if (err != PICL_SUCCESS) {
317 			err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
318 			    &childh, sizeof (picl_nodehdl_t));
319 			continue;
320 		}
321 
322 		if (strcmp(nodename, name) == 0) {
323 			*nodeh = childh;
324 			return (PICL_SUCCESS);
325 		}
326 
327 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
328 		    &childh, sizeof (picl_nodehdl_t));
329 	}
330 
331 	return (err);
332 }
333 
334 
335 /*
336  * This routine is invoked when prtdiag starts execution. It prints
337  * system configuration, memory size, initializes PICL and acts as
338  * a driver routine for prtdiag output for Snowbird.
339  */
340 /* ARGSUSED */
341 int
do_prominfo(int syserrlog,char * pname,int log_flag,int prt_flag)342 do_prominfo(int syserrlog, char *pname, int log_flag, int prt_flag)
343 {
344 
345 	struct mem_total memory_total;	/*	total memory in system	*/
346 	struct grp_info grps;
347 	uint8_t status = PD_SUCCESS;
348 	picl_nodehdl_t rooth;
349 	picl_nodehdl_t plafh;
350 	struct system_kstat_data *kstats = NULL;
351 	Sys_tree *tree = NULL;
352 
353 	sys_clk = -1;
354 	pd_print_option = syserrlog;
355 
356 	if ((status = picl_initialize()) != PICL_SUCCESS) {
357 		log_printf("prtdiag: failed to initialize the PICL\n", 0);
358 		exit(1);
359 	}
360 
361 	if ((status = picl_get_root(&rooth)) != PICL_SUCCESS) {
362 		log_printf("prtdiag: failed\n", 0);
363 		exit(1);
364 	}
365 
366 	status = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
367 	if (status != PICL_SUCCESS)
368 		return (status);
369 
370 	if (!log_flag) {
371 
372 		status = display_platform_banner(plafh);
373 		if (status != PICL_SUCCESS)
374 			return (status);
375 
376 		status = display_system_clock(plafh);
377 		if (status != PICL_SUCCESS)
378 			return (status);
379 
380 		/* display the memory Size */
381 		display_memorysize(tree, kstats, &grps, &memory_total);
382 	}
383 
384 	if ((pd_smc_fd = open(PD_SMC_DRV_PATH, O_RDWR)) == -1)
385 		return (PD_FAILURE);
386 
387 	if ((status = pd_check_for_snowbird()) != PD_SUCCESS)
388 		return (status);
389 
390 	if ((status = pd_prt_snowbird_diag()) != PD_SUCCESS)
391 		return (status);
392 
393 	(void) close(pd_smc_fd);
394 
395 	if (picl_shutdown() != PICL_SUCCESS)
396 		return (PD_INTERNAL_FAILURE);
397 
398 	return (PD_SUCCESS);
399 
400 }
401 
402 /*
403  * This routine prints out the platform name.
404  */
405 
406 static uint32_t
pd_check_for_snowbird()407 pd_check_for_snowbird()
408 {
409 
410 	char si_platform[30];
411 
412 	if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) {
413 		return (PD_FAILURE);
414 	}
415 	/* is it a Snowbird? */
416 	if (strcmp(si_platform, SNOWBIRD) != 0)
417 		return (PD_FAILURE);
418 
419 	log_printf("platform Type : %s\n", si_platform, 0);
420 	return (PD_SUCCESS);
421 
422 }
423 
424 
425 /*
426  * Driver routine for satellite specific output. This is also used by
427  * host driver routine as all satellite information is printed by host.
428  * It also prints some host specific information for formatting purposes
429  */
430 
431 static uint32_t
pd_prt_snowbird_diag()432 pd_prt_snowbird_diag()
433 {
434 	uint8_t status = PD_SUCCESS;
435 	if ((status = pd_check_cpu_health()) != PD_SUCCESS) {
436 		return (status);
437 	}
438 	if (pd_print_option) {
439 
440 		log_printf(
441 		    "\n %11s Other Miscellaneous Information \n",
442 		    PD_BLANK, 0);
443 		log_printf(
444 		    "%12s ------------------------------- \n",
445 		    PD_BLANK, 0);
446 
447 		if ((status = pd_get_role_information()) != PD_SUCCESS) {
448 			return (status);
449 		}
450 
451 		if (pd_smc_glbl_enabl_rsp[1] & 0x10) {
452 			log_printf(
453 			    "IPMI Response Notification\t\tEnabled\n", 0);
454 		} else {
455 			log_printf(
456 			    "IPMI Response Notification\t\tDisabled\n", 0);
457 		}
458 		if ((status = pd_query_SMC_firmware_version()) != PD_SUCCESS) {
459 			return (status);
460 		}
461 
462 		if ((status = pd_check_tty_debug_mode()) != PD_SUCCESS) {
463 			return (status);
464 		}
465 
466 		if ((status = pd_get_reset_mode()) != PD_SUCCESS) {
467 			return (status);
468 		}
469 
470 		if ((status = pd_get_message_flags()) != PD_SUCCESS) {
471 			return (status);
472 		}
473 
474 		if ((status = pd_query_watchdog_state()) != PD_SUCCESS) {
475 			return (status);
476 		}
477 
478 		if ((status = pd_get_sensor_reading()) != PD_SUCCESS) {
479 			return (status);
480 		}
481 
482 		if ((status = pd_get_sensor_threshold()) != PD_SUCCESS) {
483 			return (status);
484 		}
485 
486 	}
487 	return (status);
488 
489 }
490 
491 /*
492  * This routine prints the mode in which SMC is running. It uses the
493  * response from SMC global enables to determine the mode
494  */
495 static uint32_t
pd_check_tty_debug_mode()496 pd_check_tty_debug_mode()
497 {
498 
499 	if (pd_smc_glbl_enabl_rsp[1] & 0x20) {
500 		log_printf("SMC verbose mode\t\t\tON\n", 0);
501 	} else {
502 		log_printf("SMC verbose mode\t\t\tOFF\n", 0);
503 	}
504 
505 	return (PD_SUCCESS);
506 }
507 
508 /* This routine prints SMC f/w version */
509 static uint32_t
pd_query_SMC_firmware_version()510 pd_query_SMC_firmware_version()
511 {
512 
513 	sc_reqmsg_t req_pkt;
514 	sc_rspmsg_t rsp_pkt;
515 	uint8_t ver, rev, bldrev;
516 
517 
518 	smc_init_smc_msg(&req_pkt, SMC_QUERY_FIRMWARE_VERSION,
519 	    DEFAULT_SEQN, 0);
520 	smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
521 	ver = (rsp_pkt.data[0] & 0xf0) >> 4;
522 	rev = rsp_pkt.data[0] & 0x0f;
523 	bldrev = rsp_pkt.data[2] & 0x3f;
524 
525 	log_printf("SMC f/w version is\t\t\t%d.%d.%d\n", ver, rev, bldrev, 0);
526 
527 	return (PD_SUCCESS);
528 
529 }
530 
531 /*
532  * This routine checks CPU's health by using SMC self test results command
533  * It acts as driver routine for printing cPCI slot information
534  */
535 static uint32_t
pd_check_cpu_health()536 pd_check_cpu_health()
537 {
538 
539 	sc_reqmsg_t req_pkt;
540 	sc_rspmsg_t rsp_pkt;
541 	uint8_t	dev_id = 0x1f;
542 #ifdef DEBUG
543 	uint8_t i2c_chk = 0x40;
544 #endif
545 	uint8_t mem_test = 0x20;
546 
547 	smc_init_smc_msg(&req_pkt, SMC_GET_SMC_SELF_TEST_RESULT,
548 	    DEFAULT_SEQN, 0);
549 	smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
550 
551 	dev_id = rsp_pkt.data[0] & dev_id;
552 
553 #ifdef DEBUG
554 	if (rsp_pkt.data[0] & i2c_chk) {
555 		pd_print_device_info(dev_id);
556 	}
557 #endif
558 	if (rsp_pkt.data[0] & mem_test) {
559 		pd_print_device_info(dev_id);
560 	}
561 	return (pd_check_slots());
562 
563 }
564 
565 /*
566  * This routine decodes error message for CPU failures and prints details
567  * of the failure
568  */
569 static uint32_t
pd_print_device_info(int dev_id)570 pd_print_device_info(int dev_id)
571 {
572 
573 	switch (dev_id) {
574 		case 1:
575 			log_printf("Mux Philip 9540\n", 0);
576 			break;
577 		case 2:
578 			log_printf("cpu temp max1617\n", 0);
579 			break;
580 		case 3:
581 			log_printf("pmc temp max 1617\n", 0);
582 			break;
583 		case 4:
584 			log_printf("MB HS temp max 1617\n", 0);
585 			break;
586 		case 5:
587 			log_printf("MB mem temp max1617\n", 0);
588 			break;
589 		case 6:
590 			log_printf("MB gpio Philip8574\n", 0);
591 			break;
592 		case 7:
593 			log_printf("MB Fru ID ID i2c eep\n", 0);
594 			break;
595 		case 8:
596 			log_printf("MB enet ID ID i2d eep\n", 0);
597 			break;
598 		case 9:
599 			log_printf("MB gpio Philip8574A\n", 0);
600 			break;
601 		case 10:
602 			log_printf("SDRAM mod1 temp max1617\n", 0);
603 			break;
604 		case 11:
605 			log_printf("SDRAM mod ID  ID i2c eep\n", 0);
606 			break;
607 		case 12:
608 			log_printf("SDRAM mod2 temp max1617\n", 0);
609 			break;
610 		case 13:
611 			log_printf("SDRAM mod ID  ID i2c eep\n", 0);
612 			break;
613 		case 14:
614 			log_printf("Power mod temp ds1721\n", 0);
615 			break;
616 		case 15:
617 			log_printf("Power mod gpio Philip 8574\n", 0);
618 			break;
619 		case 16:
620 			log_printf("Power mod ID eep ST M24C01\n", 0);
621 			break;
622 		case 17:
623 			log_printf("SMC ID i2c eep\n", 0);
624 			break;
625 
626 		default:
627 			log_printf("device id unknown\n", 0);
628 			break;
629 
630 	}
631 
632 	return (PD_SUCCESS);
633 
634 }
635 
636 /*
637  * This routine walks PICL tree by "Location" class and calls prt_slot_info
638  * routine to print the slot information
639  */
640 
641 /*ARGSUSED*/
642 static uint32_t
pd_check_slots()643 pd_check_slots()
644 {
645 
646 	picl_nodehdl_t nodeh;
647 	char *c_args = NULL;
648 
649 	if (picl_get_root(&nodeh) != PICL_SUCCESS)
650 		return (PD_INTERNAL_FAILURE);
651 
652 
653 	if (picl_walk_tree_by_class(nodeh, PICL_CLASS_LOCATION,
654 	    (void *)c_args, pd_prt_slot_info) != PICL_SUCCESS) {
655 		return (PD_INTERNAL_FAILURE);
656 	}
657 
658 	return (PD_SUCCESS);
659 
660 }
661 
662 
663 /*ARGSUSED*/
664 int32_t
665 
pd_prt_slot_info(picl_nodehdl_t nodeh,void * c_args)666 pd_prt_slot_info(picl_nodehdl_t nodeh, void *c_args)
667 {
668 
669 	char *valbuf;
670 	char label_txt[30];
671 	int unit_no = -1, ctr = 0;
672 	picl_nodehdl_t childh;
673 	picl_propinfo_t propinfo;
674 	picl_prophdl_t proph;
675 
676 	/* if not immediate child of "chassis" node, ignore it */
677 	if (pd_check_location_parent(nodeh) != PD_SUCCESS)
678 		return (PD_INTERNAL_FAILURE);
679 
680 
681 	/* get the label on the location */
682 	if (picl_get_prop_by_name(nodeh, PICL_PROP_LABEL,
683 	    &proph) != PICL_SUCCESS)
684 		return (PD_INTERNAL_FAILURE);
685 
686 	if (picl_get_propinfo(proph, &propinfo) != PICL_SUCCESS)
687 		return (PD_INTERNAL_FAILURE);
688 
689 	valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
690 	if (valbuf == NULL)
691 		return (PD_INTERNAL_FAILURE);
692 
693 	if (picl_get_propval(proph, (void *)valbuf, propinfo.size)
694 	    != PICL_SUCCESS) {
695 		free(valbuf);
696 		return (PD_INTERNAL_FAILURE);
697 	}
698 
699 	while (valbuf[ctr] != ' ' && valbuf[ctr] != NULL) {
700 		label_txt[ctr] = valbuf[ctr];
701 		++ctr;
702 	}
703 
704 	label_txt[ctr++] = '\0';
705 
706 	if (valbuf[ctr] != NULL) {
707 		unit_no = atoi(valbuf+ctr);
708 	}
709 
710 	free(valbuf);
711 
712 	/* get the slot type for the location */
713 	if (picl_get_prop_by_name(nodeh, PICL_PROP_SLOT_TYPE,
714 	    &proph) != PICL_SUCCESS)
715 		return (PD_INTERNAL_FAILURE);
716 
717 	if (picl_get_propinfo(proph, & propinfo) != PICL_SUCCESS)
718 		return (PD_INTERNAL_FAILURE);
719 
720 	valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
721 	if (valbuf == NULL)
722 		return (PD_INTERNAL_FAILURE);
723 
724 	if (picl_get_propval(proph, (void *)valbuf,
725 	    propinfo.size) != PICL_SUCCESS) {
726 		free(valbuf);
727 		return (PD_INTERNAL_FAILURE);
728 	}
729 
730 	if ((strcmp(valbuf, PD_CPCI_SLOT_TYPE) == 0) ||
731 	    (strcmp(valbuf, PD_PCI_SLOT_TYPE) == 0)) {
732 		(void) pd_print_fruinfo_hdr();
733 		log_printf("\n%s         ", label_txt, 0);
734 
735 	/* For Snowbird no unit number is present on the label */
736 		unit_no = 1;
737 		log_printf(" %d       Yes      cPSB IO Slot\n", unit_no, 0);
738 
739 		if (picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
740 		    &childh, sizeof (childh)) == PICL_SUCCESS) {
741 			pd_prt_cpci_condition(childh);
742 		}
743 		/* For Snowbird auto configuration is always enabled */
744 		log_printf("%29s Properties:\n", PD_BLANK, 0);
745 		log_printf("%31s auto-config = enabled\n", PD_BLANK, 0);
746 	}
747 
748 
749 	free(valbuf);
750 	return (PD_SUCCESS);
751 
752 }
753 
754 
755 
756 static uint32_t
pd_print_fruinfo_hdr()757 pd_print_fruinfo_hdr()
758 {
759 
760 	log_printf(
761 	    "\n %19s FRU Information \n",
762 	    PD_BLANK, 0);
763 	log_printf(
764 	    "%11s ------------------------------------------------\n",
765 	    PD_BLANK, 0);
766 
767 	log_printf(dgettext(TEXT_DOMAIN,
768 	    "FRU         FRU    FRU      Miscellaneous\n"), 0);
769 	log_printf(dgettext(TEXT_DOMAIN,
770 	    "Type        Unit#  Present  Information\n"), 0);
771 	log_printf("----        -----  -------", 0);
772 	log_printf("  --------------------------------\n", 0);
773 	return (PD_SUCCESS);
774 
775 }
776 
777 static uint32_t
pd_check_location_parent(picl_nodehdl_t nodeh)778 pd_check_location_parent(picl_nodehdl_t nodeh)
779 {
780 
781 	picl_nodehdl_t parenth;
782 	char *prop_name;
783 
784 	if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
785 	    &parenth, sizeof (parenth)) != PICL_SUCCESS) {
786 		return (PD_FAILURE);
787 	}
788 
789 	prop_name = (char *) malloc(sizeof (char) * PICL_PROPNAMELEN_MAX);
790 	if (prop_name == NULL) {
791 		return (PD_FAILURE);
792 	}
793 
794 	if (picl_get_propval_by_name(parenth, PICL_PROP_NAME, (void *)prop_name,
795 	    PICL_PROPNAMELEN_MAX) != PICL_SUCCESS) {
796 		free(prop_name);
797 		return (PD_FAILURE);
798 	}
799 
800 	if (strcmp(prop_name, CHASSIS_NODE_NAME) == 0) {
801 		free(prop_name);
802 		return (PD_SUCCESS);
803 	} else {
804 		free(prop_name);
805 		return (PD_FAILURE);
806 	}
807 
808 }
809 
810 
811 /*ARGSUSED*/
812 static uint32_t
pd_query_watchdog_state()813 pd_query_watchdog_state()
814 {
815 
816 	picl_nodehdl_t nodehandle;
817 	char *c_args = NULL;
818 
819 	if (picl_get_root(&nodehandle) != PICL_SUCCESS) {
820 		return (PD_INTERNAL_FAILURE);
821 	}
822 
823 	if (picl_walk_tree_by_class(nodehandle, PICL_CLASS_WATCHDOG_TIMER,
824 	    (void *)c_args, pd_check_wd_state) != PICL_SUCCESS)
825 		return (PD_INTERNAL_FAILURE);
826 
827 	return (PD_SUCCESS);
828 
829 }
830 
831 /*ARGSUSED*/
832 int
pd_check_wd_state(picl_nodehdl_t nodeh,void * c_args)833 pd_check_wd_state(picl_nodehdl_t nodeh, void *c_args)
834 {
835 
836 	char *prop_name, *valbuf;
837 	picl_propinfo_t propinfo;
838 	picl_prophdl_t proph;
839 
840 	prop_name = (char *) malloc(sizeof (char) * PICL_PROPNAMELEN_MAX);
841 	if (prop_name == NULL) {
842 		return (PICL_WALK_TERMINATE);
843 	}
844 
845 	if (picl_get_propval_by_name(nodeh, PICL_PROP_NAME,
846 	    (void *)prop_name, PICL_PROPNAMELEN_MAX) != PICL_SUCCESS) {
847 		free(prop_name);
848 		return (PICL_WALK_TERMINATE);
849 	}
850 
851 	if ((picl_get_prop_by_name(nodeh, PICL_PROP_STATE,
852 	    &proph)) != PICL_SUCCESS) {
853 		free(prop_name);
854 		return (PICL_WALK_TERMINATE);
855 	}
856 
857 	if ((picl_get_propinfo(proph, &propinfo)) != PICL_SUCCESS) {
858 		free(prop_name);
859 		return (PICL_WALK_TERMINATE);
860 	}
861 
862 	valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
863 	if (valbuf == NULL) {
864 		free(prop_name);
865 		return (PICL_WALK_TERMINATE);
866 	}
867 
868 	if ((picl_get_propval(proph, (void *)valbuf,
869 	    propinfo.size)) != PICL_SUCCESS) {
870 		free(valbuf);
871 		free(prop_name);
872 		return (PICL_WALK_TERMINATE);
873 	}
874 
875 	if (pd_hdr_prt) {
876 		log_printf("\n       Watch Dog Status \n", 0);
877 		log_printf("       ---------------- \n", 0);
878 		log_printf("Node                      Status\n", 0);
879 		log_printf("----                      ------\n", 0);
880 		pd_hdr_prt = B_FALSE;
881 	}
882 
883 	log_printf("%s           ", prop_name, 0);
884 	log_printf("%s\n", valbuf, 0);
885 
886 	free(prop_name);
887 	free(valbuf);
888 	return (PICL_WALK_CONTINUE);
889 
890 }
891 
892 
893 static uint32_t
pd_get_role_information()894 pd_get_role_information()
895 {
896 
897 	sc_reqmsg_t req_pkt;
898 	sc_rspmsg_t rsp_pkt;
899 	uint8_t usparc_role;
900 
901 	smc_init_smc_msg(&req_pkt, SMC_GET_ROLE_INFO,
902 	    DEFAULT_SEQN, 0);
903 	smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
904 	usparc_role = rsp_pkt.data[1];
905 
906 	log_printf(dgettext(TEXT_DOMAIN,
907 	    "UltraSPARC Host Role\t\t\t"), 0);
908 	if (usparc_role & 0x80) {
909 		log_printf(
910 		    dgettext(TEXT_DOMAIN,
911 		    "System Board Computer (SBC)\n"), 0);
912 	}
913 	if (usparc_role & 0x40) {
914 		log_printf(dgettext(TEXT_DOMAIN,
915 		    "Standby System Board Computer (Standby SBC)\n"), 0);
916 	}
917 	if (usparc_role & 0x20) {
918 		log_printf(dgettext(TEXT_DOMAIN,
919 		"Alternate System Board Computer (Alternate SBC)\n"), 0);
920 	}
921 	if (usparc_role & 0x10) {
922 		log_printf(dgettext(TEXT_DOMAIN,
923 		    "Satellite Board Computer (SAT)\n"), 0);
924 	}
925 	return (PD_SUCCESS);
926 
927 }
928 
929 
930 static uint32_t
pd_get_message_flags()931 pd_get_message_flags()
932 {
933 
934 	sc_reqmsg_t req_pkt;
935 	sc_rspmsg_t rsp_pkt;
936 
937 	smc_init_smc_msg(&req_pkt, SMC_GET_MESSAGE_FLAGS,
938 	    DEFAULT_SEQN, 0);
939 	smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
940 
941 	if (rsp_pkt.data[0] & 0x01) {
942 		log_printf("Messages Available in queue Recieving\n", 0);
943 	} else {
944 		log_printf("No messages in queue for Recieving\n", 0);
945 	}
946 
947 	return (PD_SUCCESS);
948 
949 
950 }
951 
952 
953 
954 static uint32_t
pd_get_reset_mode()955 pd_get_reset_mode()
956 {
957 
958 	sc_reqmsg_t req_pkt;
959 	sc_rspmsg_t rsp_pkt;
960 
961 
962 	smc_init_smc_msg(&req_pkt, SMC_GET_CONFIG_BLOCK,
963 	    DEFAULT_SEQN,  0);
964 	smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
965 
966 	log_printf("Reset Mode\t\t\t\t%x \n", rsp_pkt.data[2], 0);
967 
968 	return (PD_SUCCESS);
969 
970 }
971 
972 
973 static uint32_t
pd_get_sensor_reading()974 pd_get_sensor_reading()
975 {
976 
977 
978 	sc_reqmsg_t req_pkt;
979 	sc_rspmsg_t rsp_pkt;
980 
981 	req_pkt.data[0] = 0x0e;
982 
983 	smc_init_smc_msg(&req_pkt, SMC_SENSOR_READING_GET,
984 	    DEFAULT_SEQN, 1);
985 	smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
986 	log_printf("\nCPU Node Temperature Information\n", PD_BLANK, 0);
987 	log_printf("--------------------------------\n", PD_BLANK, 0);
988 	log_printf("Temperature Reading: %d\n\n", rsp_pkt.data[0], 0);
989 
990 	return (PD_SUCCESS);
991 
992 }
993 
994 
995 static uint32_t
pd_get_sensor_threshold()996 pd_get_sensor_threshold()
997 {
998 
999 
1000 	sc_reqmsg_t req_pkt;
1001 	sc_rspmsg_t rsp_pkt;
1002 	uint8_t thres_mask;
1003 	req_pkt.data[0] = 0x0e;
1004 
1005 	smc_init_smc_msg(&req_pkt, SMC_SENSOR_THRESHOLD_GET,
1006 	    DEFAULT_SEQN,  1);
1007 	smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT);
1008 	log_printf("Critical Threshold Information\n", 0);
1009 	log_printf("------------------------------\n", 0);
1010 
1011 	thres_mask = rsp_pkt.data[0];
1012 
1013 	if (thres_mask & 0x20) {
1014 		log_printf("High Power-Off Threshold %9s", PD_BLANK, 0);
1015 		if (rsp_pkt.data[6] & 0x80) {
1016 			log_printf("-%d\n",
1017 			    (int)((uint8_t)~rsp_pkt.data[6] + 1), 0);
1018 		} else {
1019 			log_printf(" %d\n", rsp_pkt.data[6], 0);
1020 		}
1021 	}
1022 
1023 	if (thres_mask & 0x10) {
1024 		log_printf("High Shutdown Threshold %10s", PD_BLANK, 0);
1025 		if (rsp_pkt.data[5] & 0x80) {
1026 			log_printf("-%d\n",
1027 			    (int)((uint8_t)~rsp_pkt.data[5] + 1), 0);
1028 		} else {
1029 			log_printf(" %d\n", rsp_pkt.data[5], 0);
1030 		}
1031 	}
1032 
1033 
1034 	if (thres_mask & 0x08) {
1035 		log_printf("High Warning Threshold %11s", PD_BLANK, 0);
1036 		if (rsp_pkt.data[4] & 0x80) {
1037 			log_printf("-%d\n",
1038 			    (int)((uint8_t)~rsp_pkt.data[4] + 1), 0);
1039 		} else {
1040 			log_printf(" %d\n", rsp_pkt.data[4], 0);
1041 		}
1042 	}
1043 
1044 	if (thres_mask & 0x04) {
1045 		log_printf("Low Power Off Threshold %10s", PD_BLANK, 0);
1046 		if (rsp_pkt.data[3] & 0x80) {
1047 			log_printf("-%d\n",
1048 			    (int)((uint8_t)~rsp_pkt.data[3] + 1), 0);
1049 		} else {
1050 			log_printf(" %d\n", rsp_pkt.data[3], 0);
1051 		}
1052 	}
1053 
1054 	if (thres_mask & 0x02) {
1055 		log_printf("Low Shutdown Threshold %11s", PD_BLANK, 0);
1056 		if (rsp_pkt.data[2] & 0x80) {
1057 			log_printf("-%d\n",
1058 			    (int)((uint8_t)~rsp_pkt.data[2] + 1), 0);
1059 		} else {
1060 			log_printf(" %d\n", rsp_pkt.data[2], 0);
1061 		}
1062 	}
1063 
1064 	if (thres_mask & 0x01) {
1065 		log_printf("Low Warning Threshold %12s", PD_BLANK, 0);
1066 		if (rsp_pkt.data[1] & 0x80) {
1067 			log_printf("-%d\n",
1068 			    (int)((uint8_t)~rsp_pkt.data[1] + 1), 0);
1069 		} else {
1070 			log_printf(" %d\n", rsp_pkt.data[1], 0);
1071 		}
1072 	}
1073 
1074 	return (PD_SUCCESS);
1075 
1076 }
1077 
1078 
1079 
1080 static uint32_t
pd_prt_cpci_condition(picl_nodehdl_t nodeh)1081 pd_prt_cpci_condition(picl_nodehdl_t nodeh)
1082 {
1083 
1084 	picl_propinfo_t propinfo;
1085 	picl_prophdl_t proph;
1086 	char *valbuf;
1087 
1088 
1089 	if (picl_get_prop_by_name(nodeh, PICL_PROP_CONDITION,
1090 	    &proph) != PICL_SUCCESS) {
1091 		return (PD_FAILURE);
1092 	}
1093 
1094 	if (picl_get_propinfo(proph, &propinfo) != PICL_SUCCESS) {
1095 		return (PD_FAILURE);
1096 	}
1097 
1098 	valbuf = (char *) malloc(sizeof (char) * (propinfo.size));
1099 	if (valbuf == NULL) {
1100 		return (PD_FAILURE);
1101 	}
1102 
1103 	if (picl_get_propval(proph, (void *)valbuf,
1104 	    propinfo.size) != PICL_SUCCESS) {
1105 		free(valbuf);
1106 		return (PD_FAILURE);
1107 	}
1108 
1109 
1110 	log_printf("%29s Condition : %s\n", PD_BLANK, valbuf, 0);
1111 
1112 	free(valbuf);
1113 	return (PD_SUCCESS);
1114 
1115 
1116 }
1117