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