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	*/
96static int pd_print_option;
97static uint8_t pd_smc_glbl_enabl_rsp[2];
98static boolean_t pd_hdr_prt		= B_TRUE;
99static int pd_smc_fd			= 0;
100
101
102/* function declarations used in this program */
103static uint32_t pd_check_for_snowbird();
104static uint32_t pd_prt_snowbird_diag();
105static uint32_t pd_check_cpu_health();
106static uint32_t pd_check_tty_debug_mode();
107static uint32_t pd_query_SMC_firmware_version();
108static uint32_t pd_check_slots();
109int32_t pd_prt_slot_info(picl_nodehdl_t, void *);
110int do_prominfo(int syserrlog, char *pname, int log_flag, int prt_flag);
111static uint32_t pd_query_watchdog_state();
112int pd_check_wd_state(picl_nodehdl_t, void *);
113static uint32_t pd_print_fruinfo_hdr();
114static uint32_t pd_print_device_info(int);
115static uint32_t pd_get_role_information();
116static uint32_t pd_get_message_flags();
117static uint32_t pd_get_reset_mode();
118static uint32_t pd_get_sensor_reading();
119static uint32_t pd_get_sensor_threshold();
120static uint32_t pd_prt_cpci_condition(picl_nodehdl_t nodeh);
121static uint32_t pd_check_location_parent(picl_nodehdl_t nodeh);
122static uint64_t
123picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret);
124static int picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq);
125static int display_system_clock(picl_nodehdl_t plafh);
126
127/*
128 * return the value of the uint prop
129 */
130static uint64_t
131picldiag_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 */
186static int
187picldiag_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 */
207static int
208display_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 */
228static int
229picldiag_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 */
265static int
266display_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 */
298static int
299picldiag_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 */
341int
342do_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
406static uint32_t
407pd_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
431static uint32_t
432pd_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 */
495static uint32_t
496pd_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 */
509static uint32_t
510pd_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 */
535static uint32_t
536pd_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 */
569static uint32_t
570pd_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*/
642static uint32_t
643pd_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*/
664int32_t
665
666pd_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
756static uint32_t
757pd_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
777static uint32_t
778pd_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*/
812static uint32_t
813pd_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*/
832int
833pd_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
893static uint32_t
894pd_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
930static uint32_t
931pd_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
954static uint32_t
955pd_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
973static uint32_t
974pd_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
995static uint32_t
996pd_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
1080static uint32_t
1081pd_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