11708Sstevel /*
21708Sstevel  * CDDL HEADER START
31708Sstevel  *
41708Sstevel  * The contents of this file are subject to the terms of the
5*13019SMichael.Bergknoff@Oracle.COM  * Common Development and Distribution License (the "License").
6*13019SMichael.Bergknoff@Oracle.COM  * You may not use this file except in compliance with the License.
71708Sstevel  *
81708Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel  * or http://www.opensolaris.org/os/licensing.
101708Sstevel  * See the License for the specific language governing permissions
111708Sstevel  * and limitations under the License.
121708Sstevel  *
131708Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel  * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel  *
191708Sstevel  * CDDL HEADER END
201708Sstevel  */
211708Sstevel /*
22*13019SMichael.Bergknoff@Oracle.COM  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
231708Sstevel  *
241708Sstevel  * Netract Platform specific functions.
251708Sstevel  *
261708Sstevel  * 	called when :
271708Sstevel  *	machine_type == MTYPE_MONTECARLO
281708Sstevel  */
291708Sstevel 
301708Sstevel /* includes */
311708Sstevel #include <assert.h>
321708Sstevel #include <stdio.h>
331708Sstevel #include <stdlib.h>
341708Sstevel #include <stddef.h>
351708Sstevel #include <unistd.h>
361708Sstevel #include <ctype.h>
371708Sstevel #include <string.h>
381708Sstevel #include <strings.h>
391708Sstevel #include <stropts.h>
401708Sstevel #include <fcntl.h>
411708Sstevel #include <kvm.h>
421708Sstevel #include <kstat.h>
431708Sstevel #include <sys/types.h>
441708Sstevel #include <sys/utsname.h>
451708Sstevel #include <sys/openpromio.h>
461708Sstevel #include <sys/sunddi.h>
471708Sstevel #include <sys/ddi_impldefs.h>
481708Sstevel #include <sys/devinfo_impl.h>
491708Sstevel #include <sys/ioccom.h>
501708Sstevel #include <sys/systeminfo.h>
511708Sstevel #include <libintl.h>
521708Sstevel #include <config_admin.h>
531708Sstevel #include "pdevinfo.h"
541708Sstevel #include "display.h"
551708Sstevel #include "pdevinfo_sun4u.h"
561708Sstevel #include "display_sun4u.h"
571708Sstevel #include "libprtdiag.h"
581708Sstevel #include "libdevinfo.h"
591708Sstevel 
601708Sstevel /* MC specific header, might just include from MC space */
611708Sstevel #include "mct_topology.h"
621708Sstevel #include "envctrl_gen.h"
631708Sstevel #include "pcf8574_nct.h"
641708Sstevel #include "netract_gen.h"
651708Sstevel #include "hscimpl.h"
661708Sstevel #include "scsbioctl.h"
671708Sstevel 
681708Sstevel #if !defined(TEXT_DOMAIN)
691708Sstevel #define	TEXT_DOMAIN			"SYS_TEST"
701708Sstevel #endif
711708Sstevel 
721708Sstevel /* globals */
731708Sstevel #define	MAXNAMESZ			128
741708Sstevel #define	MAX_NODE_NAME_SZ		32
751708Sstevel 
761708Sstevel /* this values equates to Max Tree depth for now */
771708Sstevel #define	MAXIMUM_DEVS			64
781708Sstevel 
791708Sstevel typedef char device_info_t[MAX_NODE_NAME_SZ];
801708Sstevel 
811708Sstevel typedef struct {
821708Sstevel 	cfga_list_data_t *ldatap;
831708Sstevel 	int req; /* If set, this list_data was requested by user */
841708Sstevel } ap_out_t;
851708Sstevel 
861708Sstevel 
871708Sstevel typedef struct {
881708Sstevel 	uint_t slot_addr;
891708Sstevel 	uint_t slot_stat;
901708Sstevel 	uint_t slot_cond;
911708Sstevel 	device_info_t devs_info[MAXIMUM_DEVS];
921708Sstevel 	uint_t number_devs;
931708Sstevel } mc_slot_info_t;
941708Sstevel 
951708Sstevel typedef struct {
961708Sstevel 	mc_slot_info_t mc_slot_info[MC_MAX_SLOTS];
971708Sstevel } slot_data_t;
981708Sstevel 
991708Sstevel 
1001708Sstevel extern char *progname;
1011708Sstevel extern int print_flag;
1021708Sstevel 
1031708Sstevel /* These are used to store all force loads of the drivers */
1041708Sstevel static int ps_fd[MC_MAX_PS];
1051708Sstevel static int oprom_fd;
1061708Sstevel static int slot_index			= 0;
1071708Sstevel static int idx_minuscpu			= 0;
1081708Sstevel static int num_devs			= 0;
1091708Sstevel static int sd_instances[MC_MAX_SLOTS*15];
1101708Sstevel static int gpio_instances[MC_MAX_PS+MC_MAX_FAN];
1111708Sstevel static int sd_count			= 0;
1121708Sstevel static int st_instance;
1131708Sstevel static int gpio_count			= 0;
1141708Sstevel static int slot_table_not_found		= 0;
1151708Sstevel 
1161708Sstevel /* default not present */
1171708Sstevel static int alarm_card_present		= 0;
1181708Sstevel static int cpu_ftm_present		= 0;
1191708Sstevel 
1201708Sstevel /*
1211708Sstevel  * We will store all kstat in globals so that
1221708Sstevel  * we can browse thru them later
1231708Sstevel  */
1241708Sstevel static	int fail_syssoft_prop		= 0;
1251708Sstevel static  int fail_drv_prop		= 0;
1261708Sstevel di_node_t rootnode;	/* root nexus */
1271708Sstevel slot_data_t mc_slots_data;
1281708Sstevel 
1291708Sstevel /* scsb driver kstats */
1301708Sstevel scsb_ks_leddata_t scsb_ks_leddata;
1311708Sstevel scsb_ks_state_t scsb_ks_state;
1321708Sstevel mct_topology_t scsb_ks_topo;
1331708Sstevel 
1341708Sstevel /* pcf8574(gpio) driver kstats */
1351708Sstevel envctrl_cpuvoltage_t pcf8574_ks_cpuv;
1361708Sstevel envctrl_pwrsupp_t pcf8574_ks_ps1;
1371708Sstevel envctrl_fantray_t pcf8574_ks_fant1;
1381708Sstevel envctrl_pwrsupp_t pcf8574_ks_ps2;
1391708Sstevel envctrl_fantray_t pcf8574_ks_fant2;
1401708Sstevel 
1411708Sstevel /* pcf8591(adc-dac) driver kstats */
1421708Sstevel envctrl_temp_t pcf8591_ks_temp;
1431708Sstevel 
1441708Sstevel hsc_slot_table_t hotswap_slot_table[MC_MAX_SLOTS];
1451708Sstevel hsc_prom_slot_table_t prom_slot_table[MC_MAX_SLOTS];
1461708Sstevel 
1471708Sstevel static char *hotswap_mode		= NULL;
1481708Sstevel static char *slot_auto_config[MC_MAX_SLOTS];
1491708Sstevel static	int slot_table_size;
1501708Sstevel 
1511708Sstevel /*
1521708Sstevel  * use this to ascertain what's the system,
1531708Sstevel  * default is tonga, we can add more for future variations
1541708Sstevel  * 0=tonga, 1=montecarlo
1551708Sstevel  * we need also to figure out what the system version is
1561708Sstevel  * 0 = 1.5, 1 = 1.0, 0.6 etc.
1571708Sstevel  */
1581708Sstevel int montecarlo				= 0;
1591708Sstevel int version_p15_and_p20			= 0;
1601708Sstevel 
1611708Sstevel #define	MAX_PRTDIAG_INFO_LENGTH		1024
1621708Sstevel #define	MAX_PRTDIAG_FRUS		22
1631708Sstevel #define	BIT_TEST(X, N)			((X) & (1 << (N)))
1641708Sstevel #define	SLOT1_OK_BIT			0
1651708Sstevel #define	SLOT2_OK_BIT			1
1661708Sstevel #define	SLOT3_OK_BIT			2
1671708Sstevel #define	SLOT4_OK_BIT			3
1681708Sstevel #define	SLOT5_OK_BIT			4
1691708Sstevel #define	SLOT6_OK_BIT			5
1701708Sstevel #define	SLOT7_OK_BIT			6
1711708Sstevel #define	SLOT8_OK_BIT			7
1721708Sstevel #define	PDU1_OK_BIT			SLOT2_OK_BIT
1731708Sstevel #define	PDU2_OK_BIT			SLOT4_OK_BIT
1741708Sstevel #define	FTM_OK_BIT			SLOT5_OK_BIT
1751708Sstevel #define	SCB_OK_BIT			SLOT6_OK_BIT
1761708Sstevel #define	FAN1_OK_BIT			SLOT1_OK_BIT
1771708Sstevel #define	FAN2_OK_BIT			SLOT2_OK_BIT
1781708Sstevel #define	DISK1_OK_BIT			SLOT4_OK_BIT
1791708Sstevel #define	DISK2_OK_BIT			SLOT5_OK_BIT
1801708Sstevel #define	DISK3_OK_BIT			SLOT6_OK_BIT
1811708Sstevel #define	PS1_OK_BIT			SLOT7_OK_BIT
1821708Sstevel #define	PS2_OK_BIT			SLOT8_OK_BIT
1831708Sstevel #define	S_FREE(x)	(((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
1841708Sstevel #define	ENVC_DEBUG_MODE			0x03
1851708Sstevel #define	OPENPROMDEV			"/dev/openprom"
1861708Sstevel #define	I2C_PCF8591_NAME 		"adc-dac"
1871708Sstevel #define	I2C_KSTAT_CPUTEMP 		"adc_temp"
1881708Sstevel #define	SCSB_DEV			"scsb"
1891708Sstevel #define	SDERR				"sderr"
1901708Sstevel #define	STERR				"sterr"
1911708Sstevel #define	OK				"ok"
1921708Sstevel #define	NOK				"Not ok"
1931708Sstevel #define	ON				"on"
1941708Sstevel #define	OFF				"off"
1951708Sstevel #define	BLINK				"blink"
1961708Sstevel #define	NA				"Not Available"
1971708Sstevel #define	UK				"Unknown "
1981708Sstevel #define	YES				"Yes"
1991708Sstevel #define	NO				"No "
2001708Sstevel #define	LO				"low"
2011708Sstevel #define	HI				"high"
2021708Sstevel #define	BLANK				" "
2031708Sstevel #define	SYSSOFT_PROP			"System software"
2041708Sstevel #define	DRV_PROP			"Driver"
2051708Sstevel #define	HSC_PROP_NAME			"hsc-slot-map"
2061708Sstevel #define	HSC_MODE			"hotswap-mode"
2071708Sstevel #define	PCI_ROOT_AP			"pci"
2081708Sstevel #define	PROPS				"Properties:"
2091708Sstevel #define	BOARDTYPE			"Board Type:"
2101708Sstevel #define	DEVS				"Devices:"
2111708Sstevel #define	CPCI_IO				"CompactPCI IO Slot"
2121708Sstevel #define	AC_CARD				"Alarm Card"
2131708Sstevel #define	CPU_FTM				"Front Transition Module"
2141708Sstevel #define	SCTRL_PROM_P06			0x00
2151708Sstevel #define	SCTRL_PROM_P10			0x01
2161708Sstevel #define	SCTRL_PROM_P15			0x02
2171708Sstevel #define	SCTRL_PROM_P20			0x03
2181708Sstevel 
2191708Sstevel #define	RMM_NUMBER			3
2201708Sstevel 
2211708Sstevel #define	MONTECARLO_PLATFORM		"SUNW,UltraSPARC-IIi-Netract"
2221708Sstevel #define	MAKAHA_PLATFORM			"SUNW,UltraSPARC-IIe-NetraCT-40"
2231708Sstevel 
2241708Sstevel /*
2251708Sstevel  * The follow table is indexed with the enum's defined by mct_slot_occupant_t
2261708Sstevel  * OC_UNKN OC_CPU  OC_AC    OC_BHS OC_FHS OC_HAHS
2271708Sstevel  * OC_QFE  OC_FRCH OC_COMBO OC_PMC OC_ATM
2281708Sstevel  *
2291708Sstevel  * But "scsb" can currently identify only CPU and Alarm Cards by known
2301708Sstevel  * slot numbers.
2311708Sstevel  */
2321708Sstevel char	*slot_occupants[] = {
2331708Sstevel 		CPCI_IO,
2341708Sstevel 		"CPU board ",
2351708Sstevel 		CPCI_IO,
2361708Sstevel 		"Basic HotSwap Board",
2371708Sstevel 		"Full HotSwap Board",
2381708Sstevel 		"HA Board",
2391708Sstevel 		"QFE Board",
2401708Sstevel 		"Fresh Choice Board",
2411708Sstevel 		"SUN Combo Board",
2421708Sstevel 		"PMC Board",
2431708Sstevel 		"ATM Board"
2441708Sstevel 	};
2451708Sstevel 
2461708Sstevel static char	*prtdiag_fru_types[] = {
2471708Sstevel 		"I/O        ",	/* 0 */
2481708Sstevel 		"CPU        ",
2491708Sstevel 		"PSU        ",
2501708Sstevel 		"HDD        ",
2511708Sstevel 		"FAN        ",
2521708Sstevel 		"Alarm Card ",
2531708Sstevel 		"SCB        ",
2541708Sstevel 		"SSB        ",
2551708Sstevel 		"CFTM       ",
2561708Sstevel 		"CRTM       ",
2571708Sstevel 		"PRTM       ",
2581708Sstevel 		"Midplane   "	/* 11 */
2591708Sstevel 	};
2601708Sstevel 
2611708Sstevel char prtdiag_fru_info[MAX_PRTDIAG_FRUS][MAX_PRTDIAG_INFO_LENGTH];
2621708Sstevel 
2631708Sstevel #define	SCB_REG_READ			1
2641708Sstevel #define	SCB_REG_WRITE			2
2651708Sstevel 
2661708Sstevel /* Standard Device nodes - hardwired for now */
2671708Sstevel /* will include fan tray later, cpu voltage not impl */
2681708Sstevel static char	*scsb_node = NULL;
2691708Sstevel static char	**ps_node = NULL;
2701708Sstevel static char	*temp_node = NULL;
2711708Sstevel 
2721708Sstevel static char	*mc_scsb_node =
2731708Sstevel "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/sysctrl@0,80:scsb";
2741708Sstevel 
2751708Sstevel static char	*ot_scsb_node =
2761708Sstevel "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/sysctrl@0,80:scsb";
2771708Sstevel 
2781708Sstevel static char	*mc_ps_node[] = {
2791708Sstevel "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7c:pwrsuppply",
2801708Sstevel "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7e:pwrsuppply"
2811708Sstevel };
2821708Sstevel 
2831708Sstevel static char	*ot_ps_node[] = {
2841708Sstevel "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7c:pwrsuppply",
2851708Sstevel "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7e:pwrsuppply"
2861708Sstevel };
2871708Sstevel 
2881708Sstevel static char	*mc_temp_node =
2891708Sstevel "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/adc-dac@0,9e:cputemp";
2901708Sstevel 
2911708Sstevel /*
2921708Sstevel  * these functions will overlay the symbol table of libprtdiag
2931708Sstevel  * at runtime (netract systems only)
2941708Sstevel  * display functions
2951708Sstevel  */
2961708Sstevel int	display(Sys_tree *, Prom_node *, struct system_kstat_data *, int);
2971708Sstevel /* local functions */
2981708Sstevel /*
2991708Sstevel  * prom function
3001708Sstevel  */
3011708Sstevel static void	gather_diaginfo(int flag);
3021708Sstevel static int	extract_slot_table_from_obp();
3031708Sstevel static int	mc_next(int id);
3041708Sstevel static void	mc_walk(int id);
3051708Sstevel static int	mc_child(int id);
3061708Sstevel static void	mc_dump_node(int id);
3071708Sstevel static int	mc_getpropval(struct openpromio *opp);
3081708Sstevel 
3091708Sstevel #ifdef	REDUNDANT_INFO
3101708Sstevel static int	mc_get_cpu_freq(Prom_node *node);
3111708Sstevel static int	mc_get_ecache_size(Prom_node *node);
3121708Sstevel static void	mc_display_cpus(Board_node *board);
3131708Sstevel static void	mc_display_cpu_devices(Sys_tree *tree);
3141708Sstevel #endif	/* REDUNDANT_INFO */
3151708Sstevel 
3161708Sstevel static void	netract_disp_prom_version();
3171708Sstevel 
3181708Sstevel /*
3191708Sstevel  * Since we do not have a system wide kstat for MC/Tg
3201708Sstevel  * here we have to do specific kstats to drivers that
3211708Sstevel  * post this information - MC/Tg specific drivers
3221708Sstevel  * that post kstat here are : scsb, pcf8574(gpio) and pcf8591
3231708Sstevel  */
3241708Sstevel static int	analyze_nodes(di_node_t, void*);
3251708Sstevel static void	analyze_pcipci_siblings(di_node_t);
3261708Sstevel static void	display_mc_prtdiag_info();
3271708Sstevel static int	dump_devs(di_node_t, void *);
3281708Sstevel static void	prtdiag_devinfo(void);
3291708Sstevel static void	force_load_drivers();
3301708Sstevel static int	dump_prop_list(char *name,
3311708Sstevel 		    di_node_t node, di_prop_t (*nxtprop)());
3321708Sstevel static void	*config_calloc_check(size_t nelem, size_t elsize);
3331708Sstevel static void	explore_slot_occupants();
3341708Sstevel static void	do_scsb_kstat();
3351708Sstevel static void	do_pcf8574_kstat();
3361708Sstevel static void	do_pcf8591_kstat();
3371708Sstevel static void	do_promversion();
3381708Sstevel static int	mc_promopen(int oflag);
3391708Sstevel static int	scsi_disk_status(int disk_number);
3401708Sstevel static void	alarm_card_occupant();
3411708Sstevel static int	scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode);
3421708Sstevel static int	scsb_ioc_reg_read(int fd, uchar_t index,
3431708Sstevel 		    scsb_ioc_rdwr_t *ioc_rd, int num);
3441708Sstevel 
3451708Sstevel static int	check_platform();
3461708Sstevel 
3471708Sstevel int
display(Sys_tree * tree,Prom_node * root,struct system_kstat_data * kstats,int syserrlog)3481708Sstevel display(Sys_tree *tree,
3491708Sstevel 	    Prom_node *root,
3501708Sstevel 	    struct system_kstat_data *kstats,
3511708Sstevel 	    int syserrlog)
3521708Sstevel {
3531708Sstevel 	int exit_code = 0;   /* init to all OK */
3541708Sstevel 	void *value;  /* used for opaque PROM data */
3551708Sstevel 	struct mem_total memory_total;  /* Total memory in system */
3561708Sstevel 	struct grp_info grps;   /* Info on all groups in system */
3571708Sstevel #ifdef	lint
3581708Sstevel 	syserrlog = syserrlog;
3591708Sstevel #endif
3601708Sstevel 	sys_clk = -1;  /* System clock freq. (in MHz) */
3611708Sstevel 	/*
3621708Sstevel 	 * Now display the machine's configuration. We do this if we
3631708Sstevel 	 * are not logging or exit_code is set (machine is broke).
3641708Sstevel 	 */
3651708Sstevel 	if (!logging || exit_code) {
3661708Sstevel 		struct utsname uts_buf;
3671708Sstevel 
3681708Sstevel 		/*
3691708Sstevel 		 * Display system banner
3701708Sstevel 		 */
3711708Sstevel 		(void) uname(&uts_buf);
3721708Sstevel 
3731708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
374*13019SMichael.Bergknoff@Oracle.COM 		    "System Configuration:  Oracle Corporation"
375*13019SMichael.Bergknoff@Oracle.COM 		    "  %s %s\n"), uts_buf.machine,
376*13019SMichael.Bergknoff@Oracle.COM 		    get_prop_val(find_prop(root, "banner-name")), 0);
3771708Sstevel 
3781708Sstevel 		/* display system clock frequency */
3791708Sstevel 		value = get_prop_val(find_prop(root, "clock-frequency"));
3801708Sstevel 		if (value != NULL) {
3811708Sstevel 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
3821708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
3831708Sstevel 			    "System clock frequency: "
3841708Sstevel 			    "%d MHz\n"), sys_clk, 0);
3851708Sstevel 		}
3861708Sstevel 
3871708Sstevel 		/* Display the Memory Size */
3881708Sstevel 		display_memorysize(tree, kstats, &grps, &memory_total);
3891708Sstevel 		/* Lets make sure we have all the needed drivers loaded */
3901708Sstevel 		/* display Montecarlo/Tonga FRU information */
3911708Sstevel 		if (!extract_slot_table_from_obp())
3921708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
3931708Sstevel 			    "\r\nslot-table not available\r\n"), 0);
3941708Sstevel 		do_scsb_kstat();
3951708Sstevel 		force_load_drivers();
3961708Sstevel 		gather_diaginfo(print_flag && !logging);
3971708Sstevel 		/* figure out if ac is present */
3981708Sstevel 		alarm_card_occupant();
3991708Sstevel 		/* platform specific display mod */
4001708Sstevel 		display_mc_prtdiag_info();
4011708Sstevel 		di_fini(rootnode);
4021708Sstevel 		netract_disp_prom_version();
4031708Sstevel 	}  /* if (!logging || exit_code) */
4041708Sstevel 
4051708Sstevel 	return (exit_code);
4061708Sstevel 
4071708Sstevel }	/* display(....) */
4081708Sstevel 
4091708Sstevel static int
check_platform()4101708Sstevel check_platform()
4111708Sstevel {
4121708Sstevel 	char	si_platform[SYS_NMLN];
4131708Sstevel 
4141708Sstevel 	/*
4151708Sstevel 	 * Check for the platform: Montecarlo or Makaha/CP2040 based
4161708Sstevel 	 */
4171708Sstevel 	if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) {
4181708Sstevel 		return (-1);
4191708Sstevel 	}
4201708Sstevel 
4211708Sstevel 	if ((strncmp(si_platform, MONTECARLO_PLATFORM,
422*13019SMichael.Bergknoff@Oracle.COM 	    strlen(MONTECARLO_PLATFORM))) == 0) {
4231708Sstevel 		scsb_node = mc_scsb_node;
4241708Sstevel 		ps_node = mc_ps_node;
4251708Sstevel 		temp_node = mc_temp_node;
4261708Sstevel 	} else if ((strncmp(si_platform, MAKAHA_PLATFORM,
427*13019SMichael.Bergknoff@Oracle.COM 	    strlen(MAKAHA_PLATFORM))) == 0) {
4281708Sstevel 		scsb_node = ot_scsb_node;
4291708Sstevel 		ps_node = ot_ps_node;
4301708Sstevel 		temp_node = NULL;
4311708Sstevel 	} else {
4321708Sstevel 		return (-1);
4331708Sstevel 	}
4341708Sstevel 
4351708Sstevel 	return (0);
4361708Sstevel }
4371708Sstevel 
4381708Sstevel void
force_load_drivers()4391708Sstevel force_load_drivers()
4401708Sstevel {
4411708Sstevel 	int	i;
4421708Sstevel 
4431708Sstevel 	if (NULL == scsb_node || NULL == ps_node) {
4441708Sstevel 		if (check_platform() == -1) {
4451708Sstevel 			return;
4461708Sstevel 		}
4471708Sstevel 	}
4481708Sstevel 
4491708Sstevel 	/* check scb/ssb presence */
4501708Sstevel 	if (scsb_ks_state.scb_present || scsb_ks_state.ssb_present) {
4511708Sstevel 		if (open(scsb_node, O_RDONLY) < 0)
4521708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
4531708Sstevel 			    "\nscsb open FAILED!"), 0);
4541708Sstevel 	}
4551708Sstevel 
4561708Sstevel 	/* check the num of PS we have */
4571708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
4581708Sstevel 		if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
4591708Sstevel 			if ((ps_fd[i] = open(ps_node[i], O_RDONLY)) < 0)
4601708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
4611708Sstevel 				    "\npowersupply%d open failed"),
4621708Sstevel 				    i, 0);
4631708Sstevel 		}
4641708Sstevel 	} /* for */
4651708Sstevel 
4661708Sstevel 	/* open the cpu temp driver */
4671708Sstevel 	if (temp_node) {
4681708Sstevel 		if (open(temp_node, O_RDONLY) < 0)
4691708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
470*13019SMichael.Bergknoff@Oracle.COM 			    "\ncputemp open FAILED!"), 0);
4711708Sstevel 	}
4721708Sstevel }
4731708Sstevel 
4741708Sstevel 
4751708Sstevel void
explore_slot_occupants()4761708Sstevel explore_slot_occupants()
4771708Sstevel {
4781708Sstevel 	char *cp = NULL;
4791708Sstevel 	int index;
4801708Sstevel 	int ret = CFGA_ERROR;
4811708Sstevel 	char *estrp = NULL;
4821708Sstevel 	cfga_list_data_t *list_array = NULL;
4831708Sstevel 	ap_out_t *out_array = NULL;
4841708Sstevel 	int nlist = 0;
4851708Sstevel 	char  *prefilt_optp = NULL;
4861708Sstevel 	int dyn_exp = 1;
4871708Sstevel 	char *plat_opts = NULL;
4881708Sstevel 
4891708Sstevel 	ret = config_list_ext(0, NULL, &list_array,
4901708Sstevel 	    &nlist, plat_opts, prefilt_optp, &estrp,
4911708Sstevel 	    dyn_exp ? CFGA_FLAG_LIST_ALL : 0);
4921708Sstevel 	if (ret != CFGA_OK) {
4931708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
4941708Sstevel 		    "\ncannot explore configuration"), 0);
4951708Sstevel 		return;
4961708Sstevel 	}
4971708Sstevel 	assert(nlist != 0);
4981708Sstevel 	out_array = config_calloc_check(nlist, sizeof (*out_array));
4991708Sstevel 	if (out_array == NULL) {
5001708Sstevel 		ret = CFGA_LIB_ERROR;
5011708Sstevel 		goto bail;
5021708Sstevel 	}
5031708Sstevel 	/* create a list of output stat data */
5041708Sstevel 	for (index = 0; index < nlist; index++) {
5051708Sstevel 		out_array[index].ldatap = &list_array[index];
5061708Sstevel 		out_array[index].req = 0;
5071708Sstevel 	}
5081708Sstevel 
5091708Sstevel 	for (index = 0; index < nlist; index++) {
5101708Sstevel 		if ((cp = strstr(out_array[index].ldatap->ap_phys_id,
5111708Sstevel 		    "cpci_slot")) != NULL) {
5121708Sstevel 			mc_slots_data.mc_slot_info[idx_minuscpu].slot_stat
5131708Sstevel 			    = out_array[index].ldatap->ap_o_state;
5141708Sstevel 			mc_slots_data.mc_slot_info[idx_minuscpu].slot_cond
5151708Sstevel 			    = out_array[index].ldatap->ap_cond;
5161708Sstevel 			idx_minuscpu++;
5171708Sstevel 		}
5181708Sstevel 	}
5191708Sstevel bail:
5201708Sstevel 	S_FREE(list_array);
5211708Sstevel 	S_FREE(out_array);
5221708Sstevel }
5231708Sstevel 
5241708Sstevel 
5251708Sstevel /*
5261708Sstevel  * config_calloc_check - perform allocation, check result and
5271708Sstevel  * set error indicator
5281708Sstevel  */
5291708Sstevel void *
config_calloc_check(size_t nelem,size_t elsize)5301708Sstevel config_calloc_check(
5311708Sstevel 	size_t nelem,
5321708Sstevel 	size_t elsize)
5331708Sstevel {
5341708Sstevel 	void *p;
5351708Sstevel 	static char alloc_fail[] =
536*13019SMichael.Bergknoff@Oracle.COM 	    "%s: memory allocation failed (%d*%d bytes)\n";
5371708Sstevel 
5381708Sstevel 	p = calloc(nelem, elsize);
5391708Sstevel 	if (p == NULL) {
5401708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, alloc_fail), nelem, elsize, 0);
5411708Sstevel 	}
5421708Sstevel 	return (p);
5431708Sstevel }
5441708Sstevel 
5451708Sstevel 
5461708Sstevel void
do_scsb_kstat()5471708Sstevel do_scsb_kstat()
5481708Sstevel {
5491708Sstevel 	kstat_ctl_t	*kc;
5501708Sstevel 	kstat_t		*ksp_leddata;
5511708Sstevel 	kstat_t		*ksp_state;
5521708Sstevel 	kstat_t		 *ksp_topo;
5531708Sstevel 	scsb_ks_leddata_t *pks_leddata;
5541708Sstevel 	scsb_ks_state_t *pks_state;
5551708Sstevel 	mct_topology_t  *pks_topo;
5561708Sstevel 	int i;
5571708Sstevel 
5581708Sstevel #ifdef	DEBUG_TEMP1
5591708Sstevel 		int index;
5601708Sstevel #endif
5611708Sstevel 	if (!(kc = kstat_open())) {
5621708Sstevel #ifdef	DEBUG_TEMP
5631708Sstevel 		log_printf("\nkstat_open failed", 0);
5641708Sstevel #endif
5651708Sstevel 		return;
5661708Sstevel 	}
5671708Sstevel #ifdef	lint
5681708Sstevel 	kc = kc;
5691708Sstevel #endif
5701708Sstevel 	/* get kstat on scsb led data */
5711708Sstevel 	if ((ksp_leddata = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_LEDDATA))
5721708Sstevel 	    == NULL) {
5731708Sstevel #ifdef	DEBUG_TEMP
5741708Sstevel 		log_printf("\nkstat_lookup for scsb_leddata failed", 0);
5751708Sstevel #endif
5761708Sstevel 		return;
5771708Sstevel 	}
5781708Sstevel 	if (kstat_read(kc, ksp_leddata, NULL) == -1) {
5791708Sstevel #ifdef	DEBUG_TEMP
5801708Sstevel 		log_printf("\nkstat_read for scsb_leddata failed", 0);
5811708Sstevel #endif
5821708Sstevel 		return;
5831708Sstevel 	}
5841708Sstevel 	pks_leddata = (scsb_ks_leddata_t *)ksp_leddata->ks_data;
5851708Sstevel 	scsb_ks_leddata = *pks_leddata; /* set the globals for future */
5861708Sstevel #ifdef	DEBUG_LEDS
5871708Sstevel 	/* dump the kstat leddata */
5881708Sstevel 	printf("\nDumping LED regs: ");
5891708Sstevel 	for (i = 0; i < SCSB_LEDDATA_REGISTERS; ++i) {
5901708Sstevel 		log_printf("0x%x ", pks_leddata->scb_led_regs[i] & 0xff, 0);
5911708Sstevel 	}
5921708Sstevel 	log_printf("\n", 0);
5931708Sstevel #endif
5941708Sstevel 	/* get kstat on scsb states */
5951708Sstevel 	if ((ksp_state = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_STATE))
5961708Sstevel 	    == NULL) {
5971708Sstevel #ifdef	DEBUG_TEMP
5981708Sstevel 		log_printf("\nkstat_lookup for scsb_state failed", 0);
5991708Sstevel #endif
6001708Sstevel 		return;
6011708Sstevel 	}
6021708Sstevel 	if (kstat_read(kc, ksp_state, NULL) == -1) {
6031708Sstevel #ifdef	DEBUG_TEMP
6041708Sstevel 		log_printf("\nkstat_read for scsb_state failed", 0);
6051708Sstevel #endif
6061708Sstevel 		return;
6071708Sstevel 	}
6081708Sstevel 	pks_state = (scsb_ks_state_t *)ksp_state->ks_data;
6091708Sstevel 	scsb_ks_state = *pks_state; /* set the global for future */
6101708Sstevel #ifdef	DEBUG_TEMP1
6111708Sstevel 	/* dump the kstat state */
6121708Sstevel 	log_printf("\tSCB			is%spresent\n",
6131708Sstevel 	    pks_state->scb_present ? " " : " not ", 0);
6141708Sstevel 	log_printf("\tSSB			is%spresent\n",
6151708Sstevel 	    pks_state->ssb_present ? " " : " not ", 0);
6161708Sstevel 	log_printf("\tscsb			is%sfrozen\n",
6171708Sstevel 	    pks_state->scsb_frozen ? " " : " not ", 0);
6181708Sstevel 	log_printf("\tscsb mode:		", 0);
6191708Sstevel 	switch (pks_state->scsb_mode) {
6201708Sstevel 		case ENVC_DEBUG_MODE:
6211708Sstevel 			log_printf("DEBUG MODE\n", 0);
6221708Sstevel 			break;
6231708Sstevel 		case ENVCTRL_DIAG_MODE:
6241708Sstevel 			log_printf("DIAGNOSTIC MODE\n", 0);
6251708Sstevel 			break;
6261708Sstevel 		case ENVCTRL_NORMAL_MODE:
6271708Sstevel 			log_printf("NORMAL MODE\n", 0);
6281708Sstevel 			break;
6291708Sstevel 	}
6301708Sstevel 	log_printf("\tscsb event code:	0x%x\n", pks_state->event_code, 0);
6311708Sstevel #endif	/* DEBUG_TEMP1 */
6321708Sstevel 
6331708Sstevel 	if ((ksp_topo = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_TOPOLOGY))
6341708Sstevel 	    == NULL) {
6351708Sstevel #ifdef	DEBUG_TEMP
6361708Sstevel 		log_printf("\nkstat_lookup for scsb_topo failed", 0);
6371708Sstevel #endif
6381708Sstevel 		return;
6391708Sstevel 	}
6401708Sstevel 	if (kstat_read(kc, ksp_topo, NULL) == -1) {
6411708Sstevel #ifdef	DEBUG_TEMP
6421708Sstevel 		log_printf("\nkstat_read for scsb_topo failed", 0);
6431708Sstevel #endif
6441708Sstevel 		return;
6451708Sstevel 	}
6461708Sstevel 	pks_topo = (mct_topology_t *)ksp_topo->ks_data;
6471708Sstevel 	scsb_ks_topo = *pks_topo; /* set the global for future */
6481708Sstevel 	/*
6491708Sstevel 	 * we need to set this so that we can get status info
6501708Sstevel 	 * for the 2 powersupplies in MC as we need to get
6511708Sstevel 	 * kstat from both driver instances for environment
6521708Sstevel 	 */
6531708Sstevel 	if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
6541708Sstevel 		montecarlo = 1; /* Monte Carlo */
6551708Sstevel 	/*
6561708Sstevel 	 * HW version 0.6 and 1.0 had different led maps
6571708Sstevel 	 * its assumed that HW 2.0 would not change this
6581708Sstevel 	 * need to modify if it does
6591708Sstevel 	 */
6601708Sstevel 	if ((pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P15) ||
6611708Sstevel 	    (pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P20)) {
6621708Sstevel 		version_p15_and_p20 = 1;
6631708Sstevel 	}
6641708Sstevel 
6651708Sstevel 	/* set flag to note that CFTM is present */
6661708Sstevel 	for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
6671708Sstevel 		if (pks_topo->mct_cftm[i].fru_status == FRU_PRESENT)
6681708Sstevel 			cpu_ftm_present = 1;
6691708Sstevel 	}
6701708Sstevel 
6711708Sstevel #ifdef	DEBUG_TEMP1
6721708Sstevel 	/*
6731708Sstevel 	 * Midplane
6741708Sstevel 	 */
6751708Sstevel 	log_printf("Midplane type:		", 0);
6761708Sstevel 	if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
6771708Sstevel 		log_printf("Netra ct800 server\n", 0);
6781708Sstevel 	else
6791708Sstevel 		log_printf("Netra ct400 server%s\n",
6801708Sstevel 		    pks_topo->mid_plane.fru_id ==
6811708Sstevel 		    SCTRL_MPID_QUARTER_NODSK ? ", no disk" : " with disk", 0);
6821708Sstevel 	log_printf("Midplane version:	%d\n",
6831708Sstevel 	    pks_topo->mid_plane.fru_version, 0);
6841708Sstevel 	log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
685*13019SMichael.Bergknoff@Oracle.COM 	    pks_topo->mct_scb[0].fru_type,
686*13019SMichael.Bergknoff@Oracle.COM 	    pks_topo->mct_scb[0].fru_unit,
687*13019SMichael.Bergknoff@Oracle.COM 	    pks_topo->mct_scb[0].fru_id,
688*13019SMichael.Bergknoff@Oracle.COM 	    pks_topo->mct_scb[0].fru_version, 0);
6891708Sstevel 	/*
6901708Sstevel 	 * Slots
6911708Sstevel 	 */
6921708Sstevel 	log_printf("Slots present out of maximum %d\n",
6931708Sstevel 	    pks_topo->max_units[SLOT], 0);
6941708Sstevel 	for (i = 0; i < pks_topo->max_units[SLOT]; ++i) {
6951708Sstevel 		if (pks_topo->mct_slots[i].fru_status != FRU_PRESENT)
6961708Sstevel 			continue;
6971708Sstevel 		index = (int)pks_topo->mct_slots[i].fru_type;
6981708Sstevel 		log_printf("\tSlot %d occupant: %s;",
6991708Sstevel 		    pks_topo->mct_slots[i].fru_unit, slot_occupants[index], 0);
7001708Sstevel 		log_printf(" ID 0x%x; VER 0x%x ; ",
7011708Sstevel 		    pks_topo->mct_slots[i].fru_id,
7021708Sstevel 		    pks_topo->mct_slots[i].fru_version, 0);
7031708Sstevel 		log_printf(" Slot health %d\n",
7041708Sstevel 		    pks_topo->mct_slots[i].fru_health, 0);
7051708Sstevel 		/* pks_topo->mct_slots[i].fru_health */
7061708Sstevel 	}
7071708Sstevel 
7081708Sstevel 	/*
7091708Sstevel 	 * PDU
7101708Sstevel 	 */
7111708Sstevel 	log_printf("PDUs present out of maximum %d\n",
7121708Sstevel 	    pks_topo->max_units[PDU], 0);
7131708Sstevel 	for (i = 0; i < pks_topo->max_units[PDU]; ++i) {
7141708Sstevel 		if (pks_topo->mct_pdu[i].fru_status != FRU_PRESENT)
7151708Sstevel 			continue;
7161708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
7171708Sstevel 		    pks_topo->mct_pdu[i].fru_type,
7181708Sstevel 		    pks_topo->mct_pdu[i].fru_unit,
7191708Sstevel 		    pks_topo->mct_pdu[i].fru_id,
7201708Sstevel 		    pks_topo->mct_pdu[i].fru_version, 0);
7211708Sstevel 		/* pks_topo->mct_pdu[i].fru_health */
7221708Sstevel 	}
7231708Sstevel 
7241708Sstevel 	/*
7251708Sstevel 	 * Power Supplies
7261708Sstevel 	 */
7271708Sstevel 	log_printf("Power Supplies present out of maximum %d\n",
7281708Sstevel 	    pks_topo->max_units[PS], 0);
7291708Sstevel 	for (i = 0; i < pks_topo->max_units[PS]; ++i) {
7301708Sstevel 		if (pks_topo->mct_ps[i].fru_status != FRU_PRESENT)
7311708Sstevel 			continue;
7321708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
7331708Sstevel 		    pks_topo->mct_ps[i].fru_type,
7341708Sstevel 		    pks_topo->mct_ps[i].fru_unit,
7351708Sstevel 		    pks_topo->mct_ps[i].fru_id,
7361708Sstevel 		    pks_topo->mct_ps[i].fru_version, 0);
7371708Sstevel 	}
7381708Sstevel 
7391708Sstevel 	/*
7401708Sstevel 	 * Disks
7411708Sstevel 	 */
7421708Sstevel 	log_printf("Disks present out of maximum %d\n",
7431708Sstevel 	    pks_topo->max_units[DISK], 0);
7441708Sstevel 	for (i = 0; i < pks_topo->max_units[DISK]; ++i) {
7451708Sstevel 		if (pks_topo->mct_disk[i].fru_status != FRU_PRESENT)
7461708Sstevel 			continue;
7471708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
7481708Sstevel 		    pks_topo->mct_disk[i].fru_type,
7491708Sstevel 		    pks_topo->mct_disk[i].fru_unit,
7501708Sstevel 		    pks_topo->mct_disk[i].fru_id,
7511708Sstevel 		    pks_topo->mct_disk[i].fru_version, 0);
7521708Sstevel 	}
7531708Sstevel 
7541708Sstevel 	/*
7551708Sstevel 	 * Fans
7561708Sstevel 	 */
7571708Sstevel 	log_printf("Fans present out of maximum %d\n",
7581708Sstevel 	    pks_topo->max_units[FAN], 0);
7591708Sstevel 	for (i = 0; i < pks_topo->max_units[FAN]; ++i) {
7601708Sstevel 		if (pks_topo->mct_fan[i].fru_status != FRU_PRESENT)
7611708Sstevel 			continue;
7621708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
7631708Sstevel 		    pks_topo->mct_fan[i].fru_type,
7641708Sstevel 		    pks_topo->mct_fan[i].fru_unit,
7651708Sstevel 		    pks_topo->mct_fan[i].fru_id,
7661708Sstevel 		    pks_topo->mct_fan[i].fru_version, 0);
7671708Sstevel 	}
7681708Sstevel 
7691708Sstevel 	/*
7701708Sstevel 	 * SCBs
7711708Sstevel 	 */
7721708Sstevel 	log_printf("SCBs present out of maximum %d\n",
7731708Sstevel 	    pks_topo->max_units[SCB], 0);
7741708Sstevel 	for (i = 0; i < pks_topo->max_units[SCB]; ++i) {
7751708Sstevel 		if (pks_topo->mct_scb[i].fru_status != FRU_PRESENT)
7761708Sstevel 			continue;
7771708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
7781708Sstevel 		    pks_topo->mct_scb[i].fru_type,
7791708Sstevel 		    pks_topo->mct_scb[i].fru_unit,
7801708Sstevel 		    pks_topo->mct_scb[i].fru_id,
7811708Sstevel 		    pks_topo->mct_scb[i].fru_version, 0);
7821708Sstevel 	}
7831708Sstevel 
7841708Sstevel 	/*
7851708Sstevel 	 * SSBs
7861708Sstevel 	 */
7871708Sstevel 	log_printf("SSBs present out of maximum %d\n",
7881708Sstevel 	    pks_topo->max_units[SSB], 0);
7891708Sstevel 	for (i = 0; i < pks_topo->max_units[SSB]; ++i) {
7901708Sstevel 		if (pks_topo->mct_ssb[i].fru_status != FRU_PRESENT)
7911708Sstevel 			continue;
7921708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
7931708Sstevel 		    pks_topo->mct_ssb[i].fru_type,
7941708Sstevel 		    pks_topo->mct_ssb[i].fru_unit,
7951708Sstevel 		    pks_topo->mct_ssb[i].fru_id,
7961708Sstevel 		    pks_topo->mct_ssb[i].fru_version, 0);
7971708Sstevel 	}
7981708Sstevel 
7991708Sstevel 	/*
8001708Sstevel 	 * Alarms Cards
8011708Sstevel 	 */
8021708Sstevel 	log_printf("Alarm Cards present out of maximum %d\n",
8031708Sstevel 	    pks_topo->max_units[ALARM], 0);
8041708Sstevel 	for (i = 0; i < pks_topo->max_units[ALARM]; ++i) {
8051708Sstevel 		if (pks_topo->mct_alarm[i].fru_status != FRU_PRESENT)
8061708Sstevel 			continue;
8071708Sstevel 		log_printf("\ttype %d; unit %d; id 0x%x; VER 0x%x\n",
8081708Sstevel 		    pks_topo->mct_alarm[i].fru_type,
8091708Sstevel 		    pks_topo->mct_alarm[i].fru_unit,
8101708Sstevel 		    pks_topo->mct_alarm[i].fru_id,
8111708Sstevel 		    pks_topo->mct_alarm[i].fru_version, 0);
8121708Sstevel 	}
8131708Sstevel 
8141708Sstevel 	/*
8151708Sstevel 	 * CFTMs
8161708Sstevel 	 */
8171708Sstevel 	log_printf("CFTMs present out of maximum %d\n",
8181708Sstevel 	    pks_topo->max_units[CFTM], 0);
8191708Sstevel 	for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
8201708Sstevel 		if (pks_topo->mct_cftm[i].fru_status != FRU_PRESENT)
8211708Sstevel 			continue;
8221708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
8231708Sstevel 		    pks_topo->mct_cftm[i].fru_type,
8241708Sstevel 		    pks_topo->mct_cftm[i].fru_unit,
8251708Sstevel 		    pks_topo->mct_cftm[i].fru_id,
8261708Sstevel 		    pks_topo->mct_cftm[i].fru_version, 0);
8271708Sstevel 	}
8281708Sstevel 
8291708Sstevel 	/*
8301708Sstevel 	 * CRTMs
8311708Sstevel 	 */
8321708Sstevel 	log_printf("CRTMs present out of maximum %d\n",
8331708Sstevel 	    pks_topo->max_units[CRTM], 0);
8341708Sstevel 	for (i = 0; i < pks_topo->max_units[CRTM]; ++i) {
8351708Sstevel 		if (pks_topo->mct_crtm[i].fru_status != FRU_PRESENT)
8361708Sstevel 			continue;
8371708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
8381708Sstevel 		    pks_topo->mct_crtm[i].fru_type,
8391708Sstevel 		    pks_topo->mct_crtm[i].fru_unit,
8401708Sstevel 		    pks_topo->mct_crtm[i].fru_id,
8411708Sstevel 		    pks_topo->mct_crtm[i].fru_version, 0);
8421708Sstevel 	}
8431708Sstevel 
8441708Sstevel 	/*
8451708Sstevel 	 * PRTMs
8461708Sstevel 	 */
8471708Sstevel 	log_printf("PRTMs present out of maximum %d\n",
8481708Sstevel 	    pks_topo->max_units[PRTM], 0);
8491708Sstevel 	for (i = 0; i < pks_topo->max_units[PRTM]; ++i) {
8501708Sstevel 		if (pks_topo->mct_prtm[i].fru_status != FRU_PRESENT)
8511708Sstevel 			continue;
8521708Sstevel 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
8531708Sstevel 		    pks_topo->mct_prtm[i].fru_type,
8541708Sstevel 		    pks_topo->mct_prtm[i].fru_unit,
8551708Sstevel 		    pks_topo->mct_prtm[i].fru_id,
8561708Sstevel 		    pks_topo->mct_prtm[i].fru_version, 0);
8571708Sstevel 	}
8581708Sstevel #endif	/* DEBUG_TEMP1 */
8591708Sstevel 
8601708Sstevel }	/*  do_scsb_kstat(...) */
8611708Sstevel 
8621708Sstevel 
8631708Sstevel void
do_pcf8574_kstat()8641708Sstevel do_pcf8574_kstat()
8651708Sstevel {
8661708Sstevel 	kstat_ctl_t	*kc;
8671708Sstevel 	kstat_t		*ksp_ps;
8681708Sstevel 	kstat_t		*ksp_fan;
8691708Sstevel 	envctrl_pwrsupp_t *pks_ps;
8701708Sstevel 	envctrl_fantray_t *pks_fan;
8711708Sstevel 	int	i;
8721708Sstevel 	char	*kstat_name = NULL;
8731708Sstevel 
8741708Sstevel 	if (!(kc = kstat_open())) {
8751708Sstevel #ifdef	DEBUG_TEMP
8761708Sstevel 		log_printf("\nkstat_open for pcf8574 failed", 0);
8771708Sstevel #endif
8781708Sstevel 		return;
8791708Sstevel 	}
8801708Sstevel 
8811708Sstevel #ifdef	lint
8821708Sstevel 	kc = kc;
8831708Sstevel #endif
8841708Sstevel 	/* get kstat on gpio powersupply and fan states */
8851708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
8861708Sstevel 		if (i == 1) {
8871708Sstevel 			kstat_name = I2C_KSTAT_PWRSUPPLY;
8881708Sstevel 			strncat(kstat_name, "1", 1);
8891708Sstevel 		} else {
8901708Sstevel 			kstat_name = I2C_KSTAT_PWRSUPPLY;
8911708Sstevel 			strncat(kstat_name, "2", 1);
8921708Sstevel 		}
8931708Sstevel 		if ((ksp_ps = kstat_lookup(kc, I2C_PCF8574_NAME, 0, kstat_name))
894*13019SMichael.Bergknoff@Oracle.COM 		    == NULL) {
8951708Sstevel #ifdef	DEBUG_TEMP
8961708Sstevel 			log_printf("\nks lookup for pwrsupply%d failed",
8971708Sstevel 			    i+1, 0);
8981708Sstevel #endif
8991708Sstevel 			return;
9001708Sstevel 		}
9011708Sstevel 		if (kstat_read(kc, ksp_ps, NULL) == -1) {
9021708Sstevel #ifdef	DEBUG_TEMP
9031708Sstevel 			log_printf("\nks read for pwrsupply%d failed", i+1, 0);
9041708Sstevel #endif
9051708Sstevel 			return;
9061708Sstevel 		}
9071708Sstevel 		pks_ps = (envctrl_pwrsupp_t *)ksp_ps->ks_data;
9081708Sstevel 		if (i == 1)
9091708Sstevel 			pcf8574_ks_ps1 = *pks_ps; /* ps 1 */
9101708Sstevel 		else
9111708Sstevel 			pcf8574_ks_ps2 = *pks_ps; /* ps 2 */
9121708Sstevel 	} /* for */
9131708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
9141708Sstevel 		if (i == 1) {
9151708Sstevel 			kstat_name = I2C_KSTAT_FANTRAY;
9161708Sstevel 			strncat(kstat_name, "1", 1);
9171708Sstevel 		} else {
9181708Sstevel 			kstat_name = I2C_KSTAT_FANTRAY;
9191708Sstevel 			strncat(kstat_name, "2", 1);
9201708Sstevel 		}
9211708Sstevel 		if ((ksp_fan = kstat_lookup(kc, I2C_PCF8574_NAME,
9221708Sstevel 		    0, kstat_name)) == NULL) {
9231708Sstevel #ifdef	DEBUG_TEMP
9241708Sstevel 			log_printf("\nks lookup for fantray%d failed",
9251708Sstevel 			    i+1, 0);
9261708Sstevel #endif
9271708Sstevel 			return;
9281708Sstevel 		}
9291708Sstevel 		if (kstat_read(kc, ksp_fan, NULL) == -1) {
9301708Sstevel #ifdef	DEBUG_TEMP
9311708Sstevel 			log_printf("\nks read for fantray%d failed", i+1, 0);
9321708Sstevel #endif
9331708Sstevel 			return;
9341708Sstevel 		}
9351708Sstevel 		pks_fan = (envctrl_fantray_t *)ksp_fan->ks_data;
9361708Sstevel 		if (i == 1)
9371708Sstevel 			pcf8574_ks_fant1 = *pks_fan; /* fan 1 */
9381708Sstevel 		else
9391708Sstevel 			pcf8574_ks_fant2 = *pks_fan; /* fan 2 */
9401708Sstevel 	} /* for */
9411708Sstevel 	kstat_close(kc);
9421708Sstevel 
9431708Sstevel }	/*  do_pcf8574_kstat(...) */
9441708Sstevel 
9451708Sstevel void
do_pcf8591_kstat()9461708Sstevel do_pcf8591_kstat()
9471708Sstevel {
9481708Sstevel 	kstat_ctl_t	*kc;
9491708Sstevel 	kstat_t		*ksp_temp;
9501708Sstevel 
9511708Sstevel 	envctrl_temp_t *pks_temp;
9521708Sstevel 
9531708Sstevel 	if (!(kc = kstat_open())) {
9541708Sstevel #ifdef	DEBUG_TEMP
9551708Sstevel 		log_printf("ks open for pcf8591 failed", 0);
9561708Sstevel #endif
9571708Sstevel 		return;
9581708Sstevel 	}
9591708Sstevel #ifdef	lint
9601708Sstevel 	kc = kc;
9611708Sstevel #endif
9621708Sstevel 	/* get kstat on adc driver's CPU temperature data */
9631708Sstevel 	if ((ksp_temp = kstat_lookup(kc, I2C_PCF8591_NAME,
9641708Sstevel 	    -1, I2C_KSTAT_CPUTEMP))
9651708Sstevel 	    == NULL) {
9661708Sstevel #ifdef	DEBUG_TEMP
9671708Sstevel 		log_printf("ks lookup for adc_temp failed", 0);
9681708Sstevel #endif
9691708Sstevel 		return;
9701708Sstevel 	}
9711708Sstevel 	if (kstat_read(kc, ksp_temp, NULL) == -1) {
9721708Sstevel #ifdef	DEBUG_TEMP
9731708Sstevel 		log_printf("ks read for adc_temp failed", 0);
9741708Sstevel #endif
9751708Sstevel 		return;
9761708Sstevel 	}
9771708Sstevel 	pks_temp = (envctrl_temp_t *)ksp_temp->ks_data;
9781708Sstevel 	pcf8591_ks_temp = *pks_temp;
9791708Sstevel 	kstat_close(kc);
9801708Sstevel }	/*  do_pcf8591_kstat(.) */
9811708Sstevel 
9821708Sstevel 
9831708Sstevel void
gather_diaginfo(int flag)9841708Sstevel gather_diaginfo(int flag)
9851708Sstevel {
9861708Sstevel 	if (flag) {
9871708Sstevel 		/* gather system environmental conditions. */
9881708Sstevel 		/* obtain kstat info from gpio & temp. driver */
9891708Sstevel 		do_pcf8574_kstat();
9901708Sstevel 		do_pcf8591_kstat();
9911708Sstevel 		explore_slot_occupants();	/* fill in some occupant info */
9921708Sstevel 		prtdiag_devinfo();
9931708Sstevel 		analyze_pcipci_siblings(rootnode);
9941708Sstevel 	}
9951708Sstevel 
9961708Sstevel }	/* display_diaginfo(...) */
9971708Sstevel 
9981708Sstevel void
netract_disp_prom_version()9991708Sstevel netract_disp_prom_version()
10001708Sstevel {
10011708Sstevel 	/* Display Prom revision header */
10021708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "System Board PROM revision:\n"), 0);
10031708Sstevel 	log_printf("---------------------------\n", 0);
10041708Sstevel 	do_promversion();
10051708Sstevel 
10061708Sstevel }	/* netract_disp_prom_version(.) */
10071708Sstevel 
10081708Sstevel 
10091708Sstevel /*
10101708Sstevel  * Get and print the PROM version.
10111708Sstevel  */
10121708Sstevel void
do_promversion(void)10131708Sstevel do_promversion(void)
10141708Sstevel {
10151708Sstevel 	Oppbuf  oppbuf;
10161708Sstevel 	struct openpromio *opp = &(oppbuf.opp);
10171708Sstevel 
10181708Sstevel 	if (mc_promopen(O_RDONLY))  {
10191708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
10201708Sstevel 		    "\nCannot open openprom device"), 0);
10211708Sstevel 		return;
10221708Sstevel 	}
10231708Sstevel 
10241708Sstevel 	opp->oprom_size = MAXVALSIZE;
10251708Sstevel 	if (ioctl(oprom_fd, OPROMGETVERSION, opp) < 0) {
10261708Sstevel 		perror("\nOPROMGETVERSION ioctl failed");
10271708Sstevel 		return;
10281708Sstevel 	}
10291708Sstevel 	log_printf("%s\n", opp->oprom_array, 0);
10301708Sstevel 
10311708Sstevel 	if (close(oprom_fd) < 0) {
10321708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
10331708Sstevel 		    "\nclose error on %s"), OPENPROMDEV, 0);
10341708Sstevel 		return;
10351708Sstevel 	}
10361708Sstevel }	/* do_promversion() */
10371708Sstevel 
10381708Sstevel int
mc_promopen(int oflag)10391708Sstevel mc_promopen(int oflag)
10401708Sstevel {
10411708Sstevel 	for (;;) {
10421708Sstevel 		if ((oprom_fd = open(OPENPROMDEV, oflag)) < 0) {
10431708Sstevel 			if (errno == EAGAIN) {
10441708Sstevel 				(void) sleep(5);
10451708Sstevel 				continue;
10461708Sstevel 			}
10471708Sstevel 			if (errno == ENXIO)
10481708Sstevel 				return (-1);
10491708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
10501708Sstevel 			    "\ncannot open %s"), OPENPROMDEV, 0);
10511708Sstevel 			return (1);
10521708Sstevel 		} else
10531708Sstevel 			return (0);
10541708Sstevel 	}
10551708Sstevel }
10561708Sstevel 
10571708Sstevel 
10581708Sstevel /*
10591708Sstevel  * This will return -1 for status unknown, 0 for OK, and 1 for failed (scsi
10601708Sstevel  * hard errors)
10611708Sstevel  * swiped from envmon policies
10621708Sstevel  */
10631708Sstevel int
scsi_disk_status(int disk_number)10641708Sstevel scsi_disk_status(int disk_number)
10651708Sstevel {
10661708Sstevel 	kstat_ctl_t    *kc;
10671708Sstevel 	kstat_t		*ksp_disk;
10681708Sstevel 	kstat_named_t  *disk_data;
10691708Sstevel 
10701708Sstevel 	int i;
10711708Sstevel 	int nlist = 0;
10721708Sstevel 	cfga_list_data_t *list_array = NULL;
10731708Sstevel 	char *ap_ids[] = {"c0"};
10741708Sstevel 
10751708Sstevel 	if ((kc = kstat_open()) == NULL) {
10761708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "\nks open failed"), 0);
10771708Sstevel 		return (-1);
10781708Sstevel 	}
10791708Sstevel 
10801708Sstevel 	if (disk_number == RMM_NUMBER) { /* RMM */
10811708Sstevel 		if (config_list_ext(1, ap_ids, &list_array, &nlist,
1082*13019SMichael.Bergknoff@Oracle.COM 		    NULL, NULL, NULL, CFGA_FLAG_LIST_ALL) != CFGA_OK) {
10831708Sstevel 			kstat_close(kc);
10841708Sstevel 			return (-1);
10851708Sstevel 		}
10861708Sstevel 		for (i = 0; i < nlist; i++) {
10871708Sstevel 			if (strstr(list_array[i].ap_phys_id, "rmt/0") != NULL) {
10881708Sstevel 				/* Tape drive */
10891708Sstevel 				if (list_array[i].ap_o_state ==
1090*13019SMichael.Bergknoff@Oracle.COM 				    CFGA_STAT_UNCONFIGURED) {
10911708Sstevel 					kstat_close(kc);
10921708Sstevel 					return (-1);
10931708Sstevel 				}
10941708Sstevel 				if ((ksp_disk = kstat_lookup(kc, STERR,
1095*13019SMichael.Bergknoff@Oracle.COM 				    st_instance, NULL)) == NULL) {
10961708Sstevel 					kstat_close(kc);
10971708Sstevel 					return (-1);
10981708Sstevel 				}
10991708Sstevel 				break;
11001708Sstevel 			} else if (strstr(list_array[i].ap_phys_id,
1101*13019SMichael.Bergknoff@Oracle.COM 			    "dsk/c0t6d0") != NULL) {
11021708Sstevel 				/* CD_ROM */
11031708Sstevel 				if (list_array[i].ap_o_state ==
1104*13019SMichael.Bergknoff@Oracle.COM 				    CFGA_STAT_UNCONFIGURED) {
11051708Sstevel 					kstat_close(kc);
11061708Sstevel 					return (-1);
11071708Sstevel 				}
11081708Sstevel 				if ((ksp_disk = kstat_lookup(kc, SDERR,
1109*13019SMichael.Bergknoff@Oracle.COM 				    sd_instances[disk_number-1], NULL)) ==
1110*13019SMichael.Bergknoff@Oracle.COM 				    NULL) {
11111708Sstevel 					kstat_close(kc);
11121708Sstevel 					return (-1);
11131708Sstevel 				}
11141708Sstevel 				break;
11151708Sstevel 			}
11161708Sstevel 		}
11171708Sstevel 	} else { /* Hard disk */
11181708Sstevel 		if ((ksp_disk = kstat_lookup(kc, SDERR,
1119*13019SMichael.Bergknoff@Oracle.COM 		    sd_instances[disk_number-1], NULL)) == NULL) {
11201708Sstevel 			kstat_close(kc);
11211708Sstevel 			return (-1);
11221708Sstevel 		}
11231708Sstevel 	}
11241708Sstevel 
11251708Sstevel 	if (kstat_read(kc, ksp_disk, NULL) == -1) {
11261708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
11271708Sstevel 		    "\nks read error for disk%d, drv inst%d"),
11281708Sstevel 		    disk_number, sd_instances[disk_number-1], 0);
11291708Sstevel 		kstat_close(kc);
11301708Sstevel 		return (-1);
11311708Sstevel 	}
11321708Sstevel 	disk_data = KSTAT_NAMED_PTR(ksp_disk);
11331708Sstevel 	/*
11341708Sstevel 	 * if disk_data[].value is >0, we have a problem
11351708Sstevel 	 */
11361708Sstevel 	if (disk_data[1].value.ui32 == 0) {
11371708Sstevel 		kstat_close(kc);
11381708Sstevel 		return (0);
11391708Sstevel 	} else {
11401708Sstevel 		kstat_close(kc);
11411708Sstevel 		return (1);
11421708Sstevel 	}
11431708Sstevel }
11441708Sstevel 
11451708Sstevel 
11461708Sstevel void
prtdiag_devinfo(void)11471708Sstevel prtdiag_devinfo(void)
11481708Sstevel {
11491708Sstevel 	uint_t flag;
11501708Sstevel 	/* lets get everything we can from kernel */
11511708Sstevel 	flag = DINFOSUBTREE|DINFOPROP;
11521708Sstevel 	rootnode = di_init("/", flag);
11531708Sstevel 	if (rootnode == DI_NODE_NIL) {
11541708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
11551708Sstevel 		    "\nprtdiag_devinfo: di_init() failed"), 0);
11561708Sstevel 		return;
11571708Sstevel 	}
11581708Sstevel 	(void) di_walk_node(rootnode, DI_WALK_CLDFIRST, NULL,
11591708Sstevel 	    dump_devs);
11601708Sstevel }
11611708Sstevel 
11621708Sstevel 
11631708Sstevel /*
11641708Sstevel  * gather information about this node, returns appropriate code.
11651708Sstevel  * specific information we seek are driver names, instances
11661708Sstevel  * we will initialize some globals depending on what we find
11671708Sstevel  * from the kernel device tree info and may be private data
11681708Sstevel  * if required
11691708Sstevel  */
11701708Sstevel /*ARGSUSED1*/
11711708Sstevel int
dump_devs(di_node_t node,void * arg)11721708Sstevel dump_devs(di_node_t node, void *arg)
11731708Sstevel {
11741708Sstevel 	char *driver_name;
11751708Sstevel 
11761708Sstevel 	driver_name = di_driver_name(node);
11771708Sstevel 	/* we will initialize our globals here */
11781708Sstevel 	if ((di_instance(node) >= 0) &&
11791708Sstevel 	    (driver_name != NULL) &&
11801708Sstevel 	    (!(di_state(node) & DI_DRIVER_DETACHED))) {
11811708Sstevel 		if (strcmp(driver_name, "pcf8574") == 0) {
11821708Sstevel 			gpio_instances[gpio_count] = di_instance(node);
11831708Sstevel 			gpio_count++;
11841708Sstevel 		} else if (strcmp(driver_name, "sd") == 0) {
11851708Sstevel 			sd_instances[sd_count] =  di_instance(node);
11861708Sstevel 			sd_count++;
11871708Sstevel 		} else if (strcmp(driver_name, "st") == 0) {
11881708Sstevel 			st_instance = di_instance(node);
11891708Sstevel 		}
11901708Sstevel 	}
11911708Sstevel 
11921708Sstevel 	if (strcmp(di_node_name(node), "pseudo") == 0)
11931708Sstevel 		return (DI_WALK_PRUNECHILD);
11941708Sstevel 	else
11951708Sstevel 		return (DI_WALK_CONTINUE);
11961708Sstevel }
11971708Sstevel 
11981708Sstevel 
11991708Sstevel 
12001708Sstevel /*
12011708Sstevel  * Returns 0 if error , 1 otherwise
12021708Sstevel  */
12031708Sstevel int
dump_prop_list(char * name,di_node_t node,di_prop_t (* nxtprop)())12041708Sstevel dump_prop_list(char *name, di_node_t node, di_prop_t (*nxtprop)())
12051708Sstevel {
12061708Sstevel 	int prop_len, i, k, max_slots_minus_cpu, n;
12071708Sstevel 	uchar_t *prop_data;
12081708Sstevel 	char	*p;
12091708Sstevel 	char   *temp_s;
12101708Sstevel 	di_prop_t prop, next;
12111708Sstevel 	int ret_value = 0;
12121708Sstevel 
12131708Sstevel 	max_slots_minus_cpu = scsb_ks_topo.max_units[SLOT]-1;
12141708Sstevel 
12151708Sstevel 	if ((next = nxtprop(node, DI_PROP_NIL)) == DI_PROP_NIL)
12161708Sstevel 		return (0);
12171708Sstevel 	while (next != DI_PROP_NIL) {
12181708Sstevel 		int maybe_str = 1, npossible_strs = 0;
12191708Sstevel 		prop = next;
12201708Sstevel 		next = nxtprop(node, prop);
12211708Sstevel 		/*
12221708Sstevel 		 * get prop length and value:
12231708Sstevel 		 * private interface--always success
12241708Sstevel 		 */
12251708Sstevel 		prop_len = di_prop_rawdata(prop, &prop_data);
12261708Sstevel 		if (di_prop_type(prop) == DDI_PROP_UNDEF_IT) {
12271708Sstevel 			continue;
12281708Sstevel 		}
12291708Sstevel 
12301708Sstevel 		if (prop_len == 0)  {
12311708Sstevel 			continue;
12321708Sstevel 		}
12331708Sstevel 		if (prop_data[prop_len - 1] != '\0') {
12341708Sstevel 			maybe_str = 0;
12351708Sstevel 		} else {
12361708Sstevel 			/*
12371708Sstevel 			 * Every character must be a string character or a \0,
12381708Sstevel 			 * and there must not be two \0's in a row.
12391708Sstevel 			 */
12401708Sstevel 			for (i = 0; i < prop_len; i++) {
12411708Sstevel 				if (prop_data[i] == '\0') {
12421708Sstevel 					npossible_strs++;
12431708Sstevel 				} else if (!isascii(prop_data[i]) ||
12441708Sstevel 				    iscntrl(prop_data[i])) {
12451708Sstevel 					maybe_str = 0;
12461708Sstevel 					break;
12471708Sstevel 				}
12481708Sstevel 
12491708Sstevel 				if ((i > 0) && (prop_data[i] == '\0') &&
12501708Sstevel 				    (prop_data[i - 1] == '\0')) {
12511708Sstevel 					maybe_str = 0;
12521708Sstevel 					break;
12531708Sstevel 				}
12541708Sstevel 			}
12551708Sstevel 		}
12561708Sstevel 
12571708Sstevel 		if (maybe_str) {
12581708Sstevel 			p = (char *)prop_data;
12591708Sstevel 			for (i = 0; i < npossible_strs - 1; i++) {
12601708Sstevel 				if ((strcmp(name, SYSSOFT_PROP) == 0) &&
12611708Sstevel 				    (strcmp(di_prop_name(prop),
12621708Sstevel 				    HSC_PROP_NAME) == 0)) {
12631708Sstevel 					temp_s = p;
12641708Sstevel 					temp_s += strlen(temp_s) + 1;
12651708Sstevel 				}
12661708Sstevel 				p += strlen(p) + 1;
12671708Sstevel 			}
12681708Sstevel 
12691708Sstevel 			if ((strcmp(name, SYSSOFT_PROP) == 0) &&
12701708Sstevel 			    (strcmp(di_prop_name(prop), HSC_PROP_NAME) == 0)) {
12711708Sstevel 				temp_s = temp_s - prop_len+2;
12721708Sstevel 				for (k = 0, n = 0; k < prop_len; k++) {
12731708Sstevel 					if (temp_s[k] == 0) {
12741708Sstevel 						n++;
12751708Sstevel 					}
12761708Sstevel 				}
12771708Sstevel 				if (n % 4) {
12781708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
12791708Sstevel 					    "\nbad slot-table(%d)\n"), n);
12801708Sstevel 					slot_table_not_found = 0;
12811708Sstevel 					return (ret_value);
12821708Sstevel 				}
12831708Sstevel 				slot_table_size = n / 4;
12841708Sstevel 				/*
12851708Sstevel 				 * NOTE : We save slot table info in order
12861708Sstevel 				 */
12871708Sstevel 				for (k = 0; k < slot_table_size; k++) {
12881708Sstevel 					char *nexus, *pcidev, *phys_slotname;
12891708Sstevel 					char *ga;
12901708Sstevel 					/*
12911708Sstevel 					 * Pick off pointer to nexus
12921708Sstevel 					 * path or PROM handle
12931708Sstevel 					 */
12941708Sstevel 					nexus = temp_s;
12951708Sstevel 					while (*temp_s != NULL)
12961708Sstevel 						temp_s++;
12971708Sstevel 					temp_s++;
12981708Sstevel 
12991708Sstevel 					/*
13001708Sstevel 					 * Pick off pointer to the
13011708Sstevel 					 * pci device number
13021708Sstevel 					 */
13031708Sstevel 					pcidev = temp_s;
13041708Sstevel 					while (*temp_s != NULL)
13051708Sstevel 						temp_s++;
13061708Sstevel 					temp_s++;
13071708Sstevel 
13081708Sstevel 					/* Pick off physical slot no */
13091708Sstevel 					phys_slotname = temp_s;
13101708Sstevel 					while (*temp_s != NULL)
13111708Sstevel 						temp_s++;
13121708Sstevel 					temp_s++;
13131708Sstevel 
13141708Sstevel 					/*
13151708Sstevel 					 * Pick off GA bits which
13161708Sstevel 					 * we dont use for now.
13171708Sstevel 					 */
13181708Sstevel 					ga = temp_s;
13191708Sstevel 					while (*temp_s != NULL)
13201708Sstevel 						temp_s++;
13211708Sstevel 					temp_s++;
13221708Sstevel 
13231708Sstevel 					hotswap_slot_table[k].pslotnum
13241708Sstevel 					    = atoi(phys_slotname);
13251708Sstevel 					hotswap_slot_table[k].ga = atoi(ga);
13261708Sstevel 					hotswap_slot_table[k].pci_devno
13271708Sstevel 					    = atoi(pcidev);
13281708Sstevel 					strcpy(hotswap_slot_table[k].nexus,
13291708Sstevel 					    nexus);
13301708Sstevel 				} /* for (k = 0; k < slot_table_size; k++) */
13311708Sstevel 
13321708Sstevel 				ret_value = 1;
13331708Sstevel 			} else /* (strcmp(name, SYSSOFT_PROP) */
13341708Sstevel 				slot_table_not_found = 1;
13351708Sstevel 
13361708Sstevel 			/*
13371708Sstevel 			 * now we want to save off the info
13381708Sstevel 			 * we would use later
13391708Sstevel 			 */
13401708Sstevel 			if ((strcmp(name, DRV_PROP) == 0) &&
13411708Sstevel 			    (strcmp(di_prop_name(prop), HSC_MODE) == 0)) {
13421708Sstevel 				hotswap_mode = p;
13431708Sstevel 				ret_value = 1;
13441708Sstevel 			} else if ((strcmp(name, DRV_PROP) == 0) &&
13451708Sstevel 			    (strcmp(di_prop_name(prop), HSC_MODE) != 0)) {
13461708Sstevel 				/* save it in order in the right index */
13471708Sstevel 				slot_auto_config[max_slots_minus_cpu] = p;
13481708Sstevel 				max_slots_minus_cpu--;
13491708Sstevel 				ret_value = 1;
13501708Sstevel 			}
13511708Sstevel 
13521708Sstevel 		} else {
13531708Sstevel 			for (i = 0; i < prop_len; ++i)  {
13541708Sstevel #if	0
13551708Sstevel 				unsigned char byte;
13561708Sstevel 				byte = (unsigned char)prop_data[i];
13571708Sstevel 				log_printf("%2.2x", byte, 0);
13581708Sstevel #endif
13591708Sstevel 			}
13601708Sstevel 		}
13611708Sstevel 	}
13621708Sstevel 	return (ret_value);
13631708Sstevel }
13641708Sstevel 
13651708Sstevel 
13661708Sstevel void
display_mc_prtdiag_info()13671708Sstevel display_mc_prtdiag_info()
13681708Sstevel {
13691708Sstevel 	int i, index;
13701708Sstevel 	int s_index, i1;
13711708Sstevel 	int tg_cpu_index = 0;
13721708Sstevel 	char *mcfru_type, *status, *mc_ok_led, *mc_nok_led;
13731708Sstevel 	char *misc_info, *health, *board_type;
13741708Sstevel 
13751708Sstevel 	log_printf("===============================", 0);
13761708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
13771708Sstevel 	    " FRU Information ================================\n"), 0);
13781708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
13791708Sstevel 	    "FRU         FRU    FRU      Green    Amber"), 0);
13801708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "    Miscellaneous\n"), 0);
13811708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
13821708Sstevel 	    "Type        Unit#  Present  LED      LED"), 0);
13831708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "      Information\n"), 0);
13841708Sstevel 
13851708Sstevel 	log_printf("----------  -----  -------  -----    -----", 0);
13861708Sstevel 	log_printf("    ----------------------------------\n", 0);
13871708Sstevel 
13881708Sstevel 	if (scsb_ks_topo.mid_plane.fru_id == SCTRL_MPID_HALF)
13891708Sstevel 		misc_info = "Netra ct800";
13901708Sstevel 	else {
13911708Sstevel 		misc_info = "Netra ct400";
13921708Sstevel 	}
13931708Sstevel 	mcfru_type = prtdiag_fru_types[MIDPLANE];
13941708Sstevel 	switch (scsb_ks_topo.mid_plane.fru_status) {
13951708Sstevel 		case FRU_PRESENT:
13961708Sstevel 			status = YES;
13971708Sstevel 			break;
13981708Sstevel 		case FRU_NOT_PRESENT:
13991708Sstevel 			status = NO;
14001708Sstevel 			break;
14011708Sstevel 		case FRU_NOT_AVAILABLE:
14021708Sstevel 			status = NA; break;
14031708Sstevel 		default:
14041708Sstevel 			status = NA; break;
14051708Sstevel 		}
14061708Sstevel 	mc_ok_led = "   ";
14071708Sstevel 	mc_nok_led = "   ";
14081708Sstevel 
14091708Sstevel 	log_printf(dgettext(TEXT_DOMAIN,
14101708Sstevel 	    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
14111708Sstevel 	    mcfru_type, scsb_ks_topo.mid_plane.fru_unit,
14121708Sstevel 	    status, mc_ok_led, mc_nok_led,
14131708Sstevel 	    misc_info, 0);
14141708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
14151708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
14161708Sstevel 	    scsb_ks_topo.mid_plane.fru_version, 0);
14171708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "%49sMaximum Slots=%d\n"), BLANK,
14181708Sstevel 	    scsb_ks_topo.max_units[SLOT], 0);
14191708Sstevel 
14201708Sstevel 	/* SCB & SSB */
14211708Sstevel 	mcfru_type = prtdiag_fru_types[SCB];
14221708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[SCB]; ++i) {
14231708Sstevel 		misc_info = "System Controller Board";
14241708Sstevel 		if (version_p15_and_p20) {
14251708Sstevel 			mc_ok_led =
14261708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
14271708Sstevel 			    & 0xff), SCB_OK_BIT) ? BLINK :
14281708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
14291708Sstevel 			    & 0xff), SCB_OK_BIT) ? ON:OFF);
14301708Sstevel 			mc_nok_led =
14311708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
14321708Sstevel 			    & 0xff), SCB_OK_BIT) ? ON:OFF;
14331708Sstevel 		} else {
14341708Sstevel 			/*
14351708Sstevel 			 * support for 1.0 systems -
14361708Sstevel 			 * Hack! - should use tables ?
14371708Sstevel 			 */
14381708Sstevel 			mc_ok_led =
14391708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
14401708Sstevel 			    & 0xff), 0) ? ON:OFF);
14411708Sstevel 			mc_nok_led =
14421708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
14431708Sstevel 			    & 0xff), 0) ? ON:OFF;
14441708Sstevel 		}
14451708Sstevel 		switch (scsb_ks_topo.mct_scb[i].fru_status) {
14461708Sstevel 			case FRU_PRESENT:
14471708Sstevel 				status = YES;
14481708Sstevel 				break;
14491708Sstevel 			case FRU_NOT_PRESENT:
14501708Sstevel 				status = NO;
14511708Sstevel 				break;
14521708Sstevel 			case FRU_NOT_AVAILABLE:
14531708Sstevel 				status = NA;
14541708Sstevel 				break;
14551708Sstevel 			default:
14561708Sstevel 				status = NA;
14571708Sstevel 				break;
14581708Sstevel 		}
14591708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
14601708Sstevel 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
14611708Sstevel 		    mcfru_type, scsb_ks_topo.mct_scb[i].fru_unit,
14621708Sstevel 		    status, mc_ok_led, mc_nok_led, misc_info, 0);
14631708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
14641708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
14651708Sstevel 		    scsb_ks_topo.mct_scb[0].fru_version, 0);
14661708Sstevel 		if (fail_drv_prop == 1)
14671708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
14681708Sstevel 			    "%49s%s=%s\n"), BLANK, HSC_MODE,
14691708Sstevel 			    hotswap_mode, 0);
14701708Sstevel 	} /* for */
14711708Sstevel 
14721708Sstevel 	mcfru_type = prtdiag_fru_types[SSB];
14731708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[SSB]; ++i) {
14741708Sstevel 		misc_info = "System Status Panel";
14751708Sstevel 		switch (scsb_ks_topo.mct_ssb[i].fru_status) {
14761708Sstevel 			case FRU_PRESENT:
14771708Sstevel 				status = YES;
14781708Sstevel 				break;
14791708Sstevel 			case FRU_NOT_PRESENT:
14801708Sstevel 				status = NO;
14811708Sstevel 				break;
14821708Sstevel 			case FRU_NOT_AVAILABLE:
14831708Sstevel 				status = NA;
14841708Sstevel 				break;
14851708Sstevel 			default:
14861708Sstevel 				status = NA;
14871708Sstevel 				break;
14881708Sstevel 		}
14891708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
14901708Sstevel 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
14911708Sstevel 		    mcfru_type, scsb_ks_topo.mct_ssb[i].fru_unit,
14921708Sstevel 		    status, BLANK, BLANK, misc_info, 0);
14931708Sstevel 	} /* for */
14941708Sstevel 
14951708Sstevel 	/* Slots */
14961708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[SLOT]; ++i) {
14971708Sstevel 		if (montecarlo) {
14981708Sstevel 			if (scsb_ks_topo.mct_slots[i].fru_unit == 1)
14991708Sstevel 				mcfru_type = prtdiag_fru_types[1];
15001708Sstevel 			else
15011708Sstevel 				mcfru_type = prtdiag_fru_types[SLOT];
15021708Sstevel 			/*
15031708Sstevel 			 * Another way this could have been done is,
15041708Sstevel 			 * to read the sub system id
15051708Sstevel 			 * it is 0x6722 for Alarm Card
15061708Sstevel 			 * but this id is only valid for the new ACs
15071708Sstevel 			 * older ACs still have the same susbsystem
15081708Sstevel 			 * id as most other Sun PCI cards
15091708Sstevel 			 * We cannot completely rely on this.
15101708Sstevel 			 * Also,it turns out that Sun OpenBoot does not
15111708Sstevel 			 * always follow IEEE 1275 std, hence in a few
15121708Sstevel 			 * systems, the "subsystem-id" published by the
15131708Sstevel 			 * PROM could not be found
15141708Sstevel 			 * We know the AC slot# if present on both MC&Tg
15151708Sstevel 			 * Hence we check on both - now we are sure
15161708Sstevel 			 * that we have found an AC
15171708Sstevel 			 */
15181708Sstevel 			if ((scsb_ks_topo.mct_slots[i].fru_unit == 8) &&
15191708Sstevel 			    (alarm_card_present == 1))
15201708Sstevel 				board_type = AC_CARD;
15211708Sstevel 			else
15221708Sstevel 				board_type = UK;
15231708Sstevel 		} else {
15241708Sstevel 			if (scsb_ks_topo.mct_slots[i].fru_unit == 3)
15251708Sstevel 				mcfru_type = prtdiag_fru_types[1];
15261708Sstevel 			else
15271708Sstevel 				mcfru_type = prtdiag_fru_types[SLOT];
15281708Sstevel 			/*
15291708Sstevel 			 * Another way this could have been done is,
15301708Sstevel 			 * to read the sub system id
15311708Sstevel 			 * it is 0x6722 for Alarm Card
15321708Sstevel 			 * but this id is only valid for the new ACs
15331708Sstevel 			 * older ACs still have the same susbsystem
15341708Sstevel 			 * id as most other Sun PCI cards
15351708Sstevel 			 * We cannot completely rely on this.
15361708Sstevel 			 * Also,it turns out that Sun OpenBoot does not
15371708Sstevel 			 * always follow IEEE 1275 std, hence in a few
15381708Sstevel 			 * systems, the "subsystem-id" published by the
15391708Sstevel 			 * PROM could not be found
15401708Sstevel 			 * We know the AC slot# if present on both MC&Tg
15411708Sstevel 			 * Hence we check on both - now we are sure
15421708Sstevel 			 * that we have found an AC
15431708Sstevel 			 */
15441708Sstevel 			if ((scsb_ks_topo.mct_slots[i].fru_unit == 1) &&
15451708Sstevel 			    (alarm_card_present == 1))
15461708Sstevel 				board_type = AC_CARD;
15471708Sstevel 			else
15481708Sstevel 				board_type = UK;
15491708Sstevel 		}
15501708Sstevel 		if (version_p15_and_p20) {
15511708Sstevel 			mc_ok_led =
15521708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[0]
15531708Sstevel 			    & 0xff), i) ? BLINK :
15541708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[0]
15551708Sstevel 			    & 0xff), i) ? ON:OFF);
15561708Sstevel 			mc_nok_led =
15571708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[0]
15581708Sstevel 			    & 0xff), i) ? ON:OFF;
15591708Sstevel 		} else {
15601708Sstevel 			/*
15611708Sstevel 			 * support for 1.0 systems -
15621708Sstevel 			 * Hack! - should use tables ?
15631708Sstevel 			 */
15641708Sstevel 			if (scsb_ks_topo.mct_slots[i].fru_unit == 7) {
15651708Sstevel 				mc_ok_led =
15661708Sstevel 				    BIT_TEST(
15671708Sstevel 				    (scsb_ks_leddata.leds.p10.blink_leds[1]
15681708Sstevel 				    & 0xff), 0) ? BLINK :
15691708Sstevel 				    (BIT_TEST(
15701708Sstevel 				    (scsb_ks_leddata.leds.p10.ok_leds[1]
15711708Sstevel 				    & 0xff), 0) ? ON:OFF);
15721708Sstevel 				mc_nok_led =
15731708Sstevel 				    BIT_TEST(
15741708Sstevel 				    (scsb_ks_leddata.leds.p10.nok_leds[1]
15751708Sstevel 				    & 0xff), 0) ? ON:OFF;
15761708Sstevel 			} else  if (scsb_ks_topo.mct_slots[i].fru_unit == 8) {
15771708Sstevel 				mc_ok_led =
15781708Sstevel 				    BIT_TEST(
15791708Sstevel 				    (scsb_ks_leddata.leds.p10.blink_leds[1]
15801708Sstevel 				    & 0xff), 1) ? BLINK :
15811708Sstevel 				    (BIT_TEST(
15821708Sstevel 				    (scsb_ks_leddata.leds.p10.ok_leds[1]
15831708Sstevel 				    & 0xff), 1) ? ON:OFF);
15841708Sstevel 				mc_nok_led =
15851708Sstevel 				    BIT_TEST(
15861708Sstevel 				    (scsb_ks_leddata.leds.p10.nok_leds[1]
15871708Sstevel 				    & 0xff), 1) ? ON:OFF;
15881708Sstevel 			} else {
15891708Sstevel 				/*
15901708Sstevel 				 * for all other slots offset,
15911708Sstevel 				 * index are the same
15921708Sstevel 				 */
15931708Sstevel 				mc_ok_led =
15941708Sstevel 				    BIT_TEST(
15951708Sstevel 				    (scsb_ks_leddata.leds.p10.blink_leds[0]
15961708Sstevel 				    & 0xff), i) ? BLINK :
15971708Sstevel 				    (BIT_TEST(
15981708Sstevel 				    (scsb_ks_leddata.leds.p10.ok_leds[0]
15991708Sstevel 				    & 0xff), i) ? ON:OFF);
16001708Sstevel 				mc_nok_led =
16011708Sstevel 				    BIT_TEST(
16021708Sstevel 				    (scsb_ks_leddata.leds.p10.nok_leds[0]
16031708Sstevel 				    & 0xff), i) ? ON:OFF;
16041708Sstevel 			}
16051708Sstevel 
16061708Sstevel 		} /* else if (!version_p15_and_p20) */
16071708Sstevel 
16081708Sstevel 		switch (scsb_ks_topo.mct_slots[i].fru_status) {
16091708Sstevel 			case FRU_PRESENT:
16101708Sstevel 				status = YES;
16111708Sstevel 				break;
16121708Sstevel 			case FRU_NOT_PRESENT:
16131708Sstevel 				status = NO;
16141708Sstevel 				break;
16151708Sstevel 			case FRU_NOT_AVAILABLE:
16161708Sstevel 				status = NA;
16171708Sstevel 				break;
16181708Sstevel 			default:
16191708Sstevel 				status = NA;
16201708Sstevel 				break;
16211708Sstevel 		}
16221708Sstevel 
16231708Sstevel 		index = (int)scsb_ks_topo.mct_slots[i].fru_type;
16241708Sstevel 		if (montecarlo) {
16251708Sstevel 			if (scsb_ks_topo.mct_slots[i].fru_unit == 1) {
16261708Sstevel 				/* cpu slot */
16271708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
16281708Sstevel 				    "%10s   %-5d  %-7s %-5s    "),
16291708Sstevel 				    mcfru_type,
16301708Sstevel 				    scsb_ks_topo.mct_slots[i].fru_unit,
16311708Sstevel 				    status, mc_ok_led, mc_nok_led, 0);
16321708Sstevel 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
16331708Sstevel 				    mc_nok_led,
16341708Sstevel 				    slot_occupants[index], 0);
16351708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
16361708Sstevel 				    "%49stemperature(celsius):%d\n"),
16371708Sstevel 				    BLANK,
16381708Sstevel 				    pcf8591_ks_temp.value, 0);
16391708Sstevel #ifdef	NEVER
16401708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
16411708Sstevel 				    "%49sminimum temperature:%d\n"),
16421708Sstevel 				    BLANK,
16431708Sstevel 				    pcf8591_ks_temp.min, 0);
16441708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
16451708Sstevel 				    "%49swarning temp. threshold:%d\n"),
16461708Sstevel 				    BLANK,
16471708Sstevel 				    pcf8591_ks_temp.warning_threshold, 0);
16481708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
16491708Sstevel 				    "%49sshutdown temp.threshold:%d\n"),
16501708Sstevel 				    BLANK,
16511708Sstevel 				    pcf8591_ks_temp.shutdown_threshold, 0);
16521708Sstevel #endif	/* NEVER */
16531708Sstevel 			} else if ((scsb_ks_topo.mct_slots[i].fru_unit == 2) &&
16541708Sstevel 			    (cpu_ftm_present == 1)) {
16551708Sstevel 				/* CFTM slot */
16561708Sstevel 				/*
16571708Sstevel 				 * The CFTM can only be present in Slot 2
16581708Sstevel 				 * for Netract-800, for Netract-400 the FTM
16591708Sstevel 				 * is not sitted in a Slot. Hence, this is
16601708Sstevel 				 * another special case and we need to handle
16611708Sstevel 				 * this differently than other slots
16621708Sstevel 				 */
16631708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
16641708Sstevel 				    "%10s   %-5d  %-7s %-5s    "),
16651708Sstevel 				    mcfru_type,
16661708Sstevel 				    scsb_ks_topo.mct_slots[i].fru_unit,
16671708Sstevel 				    status, mc_ok_led, mc_nok_led, 0);
16681708Sstevel 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
16691708Sstevel 				    mc_nok_led,
16701708Sstevel 				    CPU_FTM, 0);
16711708Sstevel 			} else {
16721708Sstevel 				if (fail_drv_prop == 1) {
16731708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
16741708Sstevel 					    "%10s   %-5d  %-7s %-5s    "),
16751708Sstevel 					    mcfru_type,
16761708Sstevel 					    scsb_ks_topo.mct_slots[i].fru_unit,
16771708Sstevel 					    status, mc_ok_led, 0);
16781708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
16791708Sstevel 					    "%-5s   %s\n"),
16801708Sstevel 					    mc_nok_led,
16811708Sstevel 					    slot_occupants[index], 0);
16821708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
16831708Sstevel 					    "%46s%s\n"), BLANK,
16841708Sstevel 					    PROPS, 0);
16851708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
16861708Sstevel 					    "%49sauto-config=%s\n"),
16871708Sstevel 					    BLANK,
16881708Sstevel 					    slot_auto_config[i], 0);
16891708Sstevel 				} else {
16901708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
16911708Sstevel 				    "%10s   %-5d  %-7s %-5s    "),
16921708Sstevel 				    mcfru_type,
16931708Sstevel 				    scsb_ks_topo.mct_slots[i].fru_unit,
16941708Sstevel 				    status, mc_ok_led, 0);
16951708Sstevel 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
16961708Sstevel 				    mc_nok_led,
16971708Sstevel 				    slot_occupants[index], 0);
16981708Sstevel 				}
16991708Sstevel 			}
17001708Sstevel 		} else { /* tonga */
17011708Sstevel 			if (scsb_ks_topo.mct_slots[i].fru_unit == 3) {
17021708Sstevel 				/* cpu slot */
17031708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17041708Sstevel 				    "%10s   %-5d  %-7s %-5s    "),
17051708Sstevel 				    mcfru_type,
17061708Sstevel 				    scsb_ks_topo.mct_slots[i].fru_unit,
17071708Sstevel 				    status, mc_ok_led, 0);
17081708Sstevel 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
17091708Sstevel 				    mc_nok_led,
17101708Sstevel 				    slot_occupants[index], 0);
17111708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17121708Sstevel 				    "%49stemperature(celsius):%d\n"),
17131708Sstevel 				    BLANK,
17141708Sstevel 				    pcf8591_ks_temp.value, 0);
17151708Sstevel #ifdef	NEVER
17161708Sstevel 
17171708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17181708Sstevel 				    "%49sminimum temperature:%d\n"),
17191708Sstevel 				    BLANK,
17201708Sstevel 				    pcf8591_ks_temp.min, 0);
17211708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17221708Sstevel 				    "%49swarning temp. threshold:%d\n"),
17231708Sstevel 				    BLANK,
17241708Sstevel 				    pcf8591_ks_temp.warning_threshold, 0);
17251708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17261708Sstevel 				    "%49sshutdown temp. threshold:%d\n"),
17271708Sstevel 				    BLANK,
17281708Sstevel 				    pcf8591_ks_temp.shutdown_threshold, 0);
17291708Sstevel #endif	/* NEVER */
17301708Sstevel 			} else {
17311708Sstevel 				if (fail_drv_prop == 1) {
17321708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
17331708Sstevel 					    "%10s   %-5d  %-7s %-5s    "),
17341708Sstevel 					    mcfru_type,
17351708Sstevel 					    scsb_ks_topo.mct_slots[i].fru_unit,
17361708Sstevel 					    status, mc_ok_led, 0);
17371708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
17381708Sstevel 					    "%-5s   %s\n"),
17391708Sstevel 					    mc_nok_led,
17401708Sstevel 					    slot_occupants[index], 0);
17411708Sstevel 
17421708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
17431708Sstevel 					    "%46s%s\n"), BLANK, PROPS, 0);
17441708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
17451708Sstevel 					    "%49sauto-config=%s\n"),
17461708Sstevel 					    BLANK,
17471708Sstevel 					    slot_auto_config[tg_cpu_index+1],
17481708Sstevel 					    0);
17491708Sstevel 					if (scsb_ks_topo.mct_slots[i].fru_unit
17501708Sstevel 					    != 3)
17511708Sstevel 						tg_cpu_index++;
17521708Sstevel 				} else {
17531708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
17541708Sstevel 				    "%10s   %-5d  %-7s %-5s    "),
17551708Sstevel 				    mcfru_type,
17561708Sstevel 				    scsb_ks_topo.mct_slots[i].fru_unit,
17571708Sstevel 				    status, mc_ok_led, 0);
17581708Sstevel 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
17591708Sstevel 				    mc_nok_led,
17601708Sstevel 				    slot_occupants[index], 0);
17611708Sstevel 				}
17621708Sstevel 			}
17631708Sstevel 		}
17641708Sstevel 		/* we first match the correct slot numbers */
17651708Sstevel 		for (s_index = 0; s_index < slot_table_size; s_index++) {
17661708Sstevel 			if (slot_table_not_found == 1) {
17671708Sstevel 			/* use prom table */
17681708Sstevel 			if (scsb_ks_topo.mct_slots[i].fru_unit ==
17691708Sstevel 			    prom_slot_table[s_index].pslotnum) {
17701708Sstevel 				/*
17711708Sstevel 				 * search for the addr/pci num
17721708Sstevel 				 * in all slot info structs
17731708Sstevel 				 */
17741708Sstevel 				for (i1 = 0; i1 < slot_index;
17751708Sstevel 				    i1++) {
17761708Sstevel 			if (prom_slot_table[s_index].pci_devno ==
17771708Sstevel 			    mc_slots_data.mc_slot_info[i1].slot_addr) {
17781708Sstevel 					int nd;
17791708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
17801708Sstevel 					    "%46s%s%s\n"), BLANK,
17811708Sstevel 					    BOARDTYPE, board_type, 0);
17821708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
17831708Sstevel 					    "%46s%s\n"), BLANK, DEVS, 0);
17841708Sstevel 					log_printf(dgettext(TEXT_DOMAIN,
17851708Sstevel 					    "%49s%s\n"), BLANK,
17861708Sstevel 					    PCI_ROOT_AP, 0);
17871708Sstevel 			for (nd = 0;
17881708Sstevel 			    nd < mc_slots_data.mc_slot_info[i1].number_devs;
1789*13019SMichael.Bergknoff@Oracle.COM 			    nd++) {
17901708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "%52s%s\n"), BLANK,
17911708Sstevel 			    mc_slots_data.mc_slot_info[i1].devs_info[nd],
17921708Sstevel 			    0);
17931708Sstevel 						} /* for */
17941708Sstevel 
17951708Sstevel 					} /* if */
17961708Sstevel 
17971708Sstevel 				} /* for(i1) */
17981708Sstevel 
17991708Sstevel 			} /* if */
18001708Sstevel 
18011708Sstevel 		} else {
18021708Sstevel 			/* use solaris lot table */
18031708Sstevel 			if (fail_syssoft_prop == 1) {
18041708Sstevel 				if (scsb_ks_topo.mct_slots[i].fru_unit ==
1805*13019SMichael.Bergknoff@Oracle.COM 				    hotswap_slot_table[s_index].pslotnum) {
18061708Sstevel 					/*
18071708Sstevel 					 * search for the addr/pci
18081708Sstevel 					 * num in all slot info structs
18091708Sstevel 					 */
18101708Sstevel 					for (i1 = 0; i1 < slot_index; i1++) {
18111708Sstevel 				if (hotswap_slot_table[s_index].pci_devno ==
18121708Sstevel 				    mc_slots_data.mc_slot_info[i1].slot_addr) {
18131708Sstevel 					int nd;
18141708Sstevel 			for (nd = 0;
18151708Sstevel 			    nd < mc_slots_data.mc_slot_info[i1].number_devs;
18161708Sstevel 			    nd++) {
18171708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "%49s%s\n"), BLANK,
18181708Sstevel 			    mc_slots_data.mc_slot_info[i1].devs_info[nd],
18191708Sstevel 			    0);
18201708Sstevel 							}
18211708Sstevel 						} /* if */
18221708Sstevel 
18231708Sstevel 					} /* for(i1) */
18241708Sstevel 
18251708Sstevel 				} /* if */
18261708Sstevel 
18271708Sstevel 			} /* (fail_syssoft_prop == 1) */
18281708Sstevel 
18291708Sstevel 			}  /* (slot_table_not_found == 1) */
18301708Sstevel 
18311708Sstevel 		} /* for(s_index) */
18321708Sstevel 
18331708Sstevel 	}	/* for */
18341708Sstevel 	mcfru_type = "PDU";
18351708Sstevel 	misc_info = "Power Distribution Unit";
18361708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[PDU]; ++i) {
18371708Sstevel 		if (version_p15_and_p20) {
18381708Sstevel 			mc_ok_led =
18391708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
18401708Sstevel 			    & 0xff), PDU1_OK_BIT+i*2) ? BLINK :
18411708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
18421708Sstevel 			    & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF);
18431708Sstevel 			mc_nok_led =
18441708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
18451708Sstevel 			    & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF;
18461708Sstevel 		}
18471708Sstevel 		switch (scsb_ks_topo.mct_pdu[i].fru_status) {
18481708Sstevel 			case FRU_PRESENT:
18491708Sstevel 				status = YES;
18501708Sstevel 				break;
18511708Sstevel 			case FRU_NOT_PRESENT:
18521708Sstevel 				status = NO;
18531708Sstevel 				break;
18541708Sstevel 			case FRU_NOT_AVAILABLE:
18551708Sstevel 				status = NA;
18561708Sstevel 				break;
18571708Sstevel 			default:
18581708Sstevel 				status = NA;
18591708Sstevel 				break;
18601708Sstevel 		}
18611708Sstevel 		if (version_p15_and_p20) {
18621708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
18631708Sstevel 			    "%-10s    %-5d  %-7s %-5s    %-5s   %s\n"),
18641708Sstevel 			    mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
18651708Sstevel 			    status, mc_ok_led, mc_nok_led, misc_info, 0);
18661708Sstevel 		} else {
18671708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
18681708Sstevel 			    "%-10s    %-5d  %-7s%18s%s\n"),
18691708Sstevel 			    mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
18701708Sstevel 			    status, BLANK, misc_info, 0);
18711708Sstevel 		}
18721708Sstevel 	} /* for */
18731708Sstevel 
18741708Sstevel 	/* PS */
18751708Sstevel 	mcfru_type = prtdiag_fru_types[PS];
18761708Sstevel 	misc_info = "Power Supply Unit";
18771708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
18781708Sstevel 		if (version_p15_and_p20) {
18791708Sstevel 			mc_ok_led =
18801708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
18811708Sstevel 			    & 0xff), PS1_OK_BIT+i) ? BLINK :
18821708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
18831708Sstevel 			    & 0xff), PS1_OK_BIT+i) ? ON:OFF);
18841708Sstevel 			mc_nok_led =
18851708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
18861708Sstevel 			    & 0xff), PS1_OK_BIT+i) ? ON:OFF;
18871708Sstevel 		} else {
18881708Sstevel 			/*
18891708Sstevel 			 * support for 1.0 systems -
18901708Sstevel 			 * Hack! - should use tables ?
18911708Sstevel 			 */
18921708Sstevel 			mc_ok_led =
18931708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
18941708Sstevel 			    & 0xff), 1+i) ? ON:OFF);
18951708Sstevel 			mc_nok_led =
18961708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
18971708Sstevel 			    & 0xff), 1+i) ? ON:OFF;
18981708Sstevel 		}
18991708Sstevel 		switch (scsb_ks_topo.mct_ps[i].fru_status) {
19001708Sstevel 			case FRU_PRESENT:
19011708Sstevel 				status = YES;
19021708Sstevel 				break;
19031708Sstevel 			case FRU_NOT_PRESENT:
19041708Sstevel 				status = NO;
19051708Sstevel 				break;
19061708Sstevel 			case FRU_NOT_AVAILABLE:
19071708Sstevel 				status = NA;
19081708Sstevel 				break;
19091708Sstevel 			default:
19101708Sstevel 				status = NA;
19111708Sstevel 				break;
19121708Sstevel 		}
19131708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
19141708Sstevel 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
19151708Sstevel 		    mcfru_type, scsb_ks_topo.mct_ps[i].fru_unit,
19161708Sstevel 		    status, mc_ok_led, mc_nok_led,
19171708Sstevel 		    misc_info, 0);
19181708Sstevel 		if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
19191708Sstevel 			if (scsb_ks_topo.mct_ps[i].fru_unit == 1) {
19201708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19211708Sstevel 				    "%49scondition:%s\n"), BLANK,
19221708Sstevel 				    ((pcf8574_ks_ps1.ps_ok)? NOK:OK), 0);
19231708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19241708Sstevel 				    "%49stemperature:%s\n"), BLANK,
19251708Sstevel 				    ((pcf8574_ks_ps1.temp_ok)? NOK:OK), 0);
19261708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19271708Sstevel 				    "%49sps fan:%s\n"), BLANK,
19281708Sstevel 				    ((pcf8574_ks_ps1.psfan_ok)? NOK:OK), 0);
19291708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19301708Sstevel 				    "%49ssupply:%s\n"), BLANK,
19311708Sstevel 				    ((pcf8574_ks_ps1.on_state)? OFF:ON), 0);
19321708Sstevel 			} else {
19331708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19341708Sstevel 				    "%49scondition:%s\n"), BLANK,
19351708Sstevel 				    ((pcf8574_ks_ps2.ps_ok)? NOK:OK), 0);
19361708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19371708Sstevel 				    "%49stemperature:%s\n"), BLANK,
19381708Sstevel 				    ((pcf8574_ks_ps2.temp_ok)? NOK:OK), 0);
19391708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19401708Sstevel 				    "%49sps fan:%s\n"), BLANK,
19411708Sstevel 				    ((pcf8574_ks_ps2.psfan_ok)? NOK:OK), 0);
19421708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19431708Sstevel 				    "%49ssupply:%s\n"), BLANK,
19441708Sstevel 				    ((pcf8574_ks_ps2.on_state)? OFF:ON), 0);
19451708Sstevel 			} /* if */
19461708Sstevel 		}
19471708Sstevel 
19481708Sstevel 	} /* for */
19491708Sstevel 
19501708Sstevel 	/* Fan tray */
19511708Sstevel 	mcfru_type = prtdiag_fru_types[FAN];
19521708Sstevel 	misc_info = "Fan Tray";
19531708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
19541708Sstevel 		if (version_p15_and_p20) {
19551708Sstevel 			mc_ok_led =
19561708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
19571708Sstevel 			    & 0xff), FAN1_OK_BIT+i) ? BLINK :
19581708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
19591708Sstevel 			    & 0xff), FAN1_OK_BIT+i) ? ON:OFF);
19601708Sstevel 			mc_nok_led =
19611708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
19621708Sstevel 			    & 0xff), FAN1_OK_BIT+i) ? ON:OFF;
19631708Sstevel 		} else {
19641708Sstevel 			/*
19651708Sstevel 			 * support for 1.0 systems -
19661708Sstevel 			 * Hack! - should use tables ?
19671708Sstevel 			 */
19681708Sstevel 			mc_ok_led =
19691708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[3]
19701708Sstevel 			    & 0xff), 3+i) ? ON:OFF);
19711708Sstevel 			mc_nok_led =
19721708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[3]
19731708Sstevel 			    & 0xff), 3+i) ? ON:OFF;
19741708Sstevel 		}
19751708Sstevel 		switch (scsb_ks_topo.mct_fan[i].fru_status) {
19761708Sstevel 			case FRU_PRESENT:
19771708Sstevel 				status = YES;
19781708Sstevel 				break;
19791708Sstevel 			case FRU_NOT_PRESENT:
19801708Sstevel 				status = NO;
19811708Sstevel 				break;
19821708Sstevel 			case FRU_NOT_AVAILABLE:
19831708Sstevel 				status = NA;
19841708Sstevel 				break;
19851708Sstevel 			default:
19861708Sstevel 				status = NA;
19871708Sstevel 				break;
19881708Sstevel 		}
19891708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
19901708Sstevel 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
19911708Sstevel 		    mcfru_type, scsb_ks_topo.mct_fan[i].fru_unit,
19921708Sstevel 		    status, mc_ok_led, mc_nok_led,
19931708Sstevel 		    misc_info, 0);
19941708Sstevel 		if (scsb_ks_topo.mct_fan[i].fru_status == FRU_PRESENT) {
19951708Sstevel 			if (scsb_ks_topo.mct_fan[i].fru_unit == 1) {
19961708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
19971708Sstevel 				    "%49scondition:%s\n"), BLANK,
19981708Sstevel 				    ((pcf8574_ks_fant1.fan_ok)? OK:NOK), 0);
19991708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
20001708Sstevel 				    "%49sfan speed:%s\n"), BLANK,
20011708Sstevel 				    ((pcf8574_ks_fant1.fanspeed)? HI:LO), 0);
20021708Sstevel 			} else {
20031708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
20041708Sstevel 				    "%49scondition:%s\n"), BLANK,
20051708Sstevel 				    ((pcf8574_ks_fant2.fan_ok)? OK:NOK), 0);
20061708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
20071708Sstevel 				    "%49sfan speed:%s\n"), BLANK,
20081708Sstevel 				    ((pcf8574_ks_fant2.fanspeed)? HI:LO), 0);
20091708Sstevel 			}
20101708Sstevel 		}
20111708Sstevel 
20121708Sstevel 	} /* for */
20131708Sstevel 
20141708Sstevel 	/* DISKS */
20151708Sstevel 	for (i = 0; i < scsb_ks_topo.max_units[DISK]; ++i) {
20161708Sstevel 		if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER)
20171708Sstevel 			mcfru_type = prtdiag_fru_types[DISK];
20181708Sstevel 		else
20191708Sstevel 			mcfru_type = "RMM        ";
20201708Sstevel 		switch (scsb_ks_topo.mct_disk[i].fru_status) {
20211708Sstevel 			case FRU_PRESENT:
20221708Sstevel 				status = YES;
20231708Sstevel 				break;
20241708Sstevel 			case FRU_NOT_PRESENT:
20251708Sstevel 				status = NO;
20261708Sstevel 				break;
20271708Sstevel 			case FRU_NOT_AVAILABLE:
20281708Sstevel 				status = NA;
20291708Sstevel 				break;
20301708Sstevel 			default:
20311708Sstevel 				status = NA;
20321708Sstevel 				break;
20331708Sstevel 		}
20341708Sstevel 		if (version_p15_and_p20) {
20351708Sstevel 			mc_ok_led =
20361708Sstevel 			    BIT_TEST((scsb_ks_leddata.scb_led_regs[8]
20371708Sstevel 			    & 0xff), DISK1_OK_BIT+i) ? BLINK :
20381708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
20391708Sstevel 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF);
20401708Sstevel 			mc_nok_led =
20411708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
20421708Sstevel 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF;
20431708Sstevel 		} else {
20441708Sstevel 			/*
20451708Sstevel 			 * support for 1.0 systems -
20461708Sstevel 			 * Hack! - should use tables ?
20471708Sstevel 			 */
20481708Sstevel 			mc_ok_led =
20491708Sstevel 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
20501708Sstevel 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF);
20511708Sstevel 			mc_nok_led =
20521708Sstevel 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
20531708Sstevel 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF;
20541708Sstevel 		}
20551708Sstevel 		/* print everything except condition */
20561708Sstevel 		if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) {
20571708Sstevel 			misc_info = "Hard Disk Drive";
20581708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
20591708Sstevel 			    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
20601708Sstevel 			    mcfru_type, scsb_ks_topo.mct_disk[i].fru_unit-1,
20611708Sstevel 			    status, mc_ok_led, mc_nok_led, misc_info, 0);
20621708Sstevel 		} else {
20631708Sstevel 			misc_info = "Removable Media Module";
20641708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
20651708Sstevel 			    "%10s   %5s  %-7s %-5s    %-5s   %s\n"),
20661708Sstevel 			    mcfru_type, BLANK,
20671708Sstevel 			    status, mc_ok_led, mc_nok_led, misc_info, 0);
20681708Sstevel 		}
20691708Sstevel 
20701708Sstevel 		/* find out fru health from the SCSI drivers */
20711708Sstevel 		if (scsb_ks_topo.mct_disk[i].fru_status == FRU_PRESENT) {
20721708Sstevel 			switch (
20731708Sstevel 			    scsi_disk_status(
20741708Sstevel 			    scsb_ks_topo.mct_disk[i].fru_unit)) {
20751708Sstevel 				case 0:
20761708Sstevel 					health = OK;
20771708Sstevel 					break;
20781708Sstevel 				case 1:
20791708Sstevel 					health = NOK;
20801708Sstevel 					break;
20811708Sstevel 				case -1:
20821708Sstevel 					health = UK;
20831708Sstevel 					break;
20841708Sstevel 				default:
20851708Sstevel 					health = NA;
20861708Sstevel 					break;
20871708Sstevel 			}
20881708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
20891708Sstevel 			    "%49scondition:%s\n"), BLANK, health, 0);
20901708Sstevel 		}
20911708Sstevel 
20921708Sstevel 	}	/* for */
20931708Sstevel 
20941708Sstevel 	log_printf(dgettext(TEXT_DOMAIN, "\n"), 0);
20951708Sstevel 
20961708Sstevel }	/*  display_mc_prtdiag_info() */
20971708Sstevel 
20981708Sstevel 
20991708Sstevel void
analyze_pcipci_siblings(di_node_t node)21001708Sstevel analyze_pcipci_siblings(di_node_t node)
21011708Sstevel {
21021708Sstevel 	di_node_t lc_node;
21031708Sstevel 	/* we will find all the dev info for slots first */
21041708Sstevel 	lc_node = di_drv_first_node("pci_pci", node);
21051708Sstevel 	lc_node = di_child_node(lc_node);
21061708Sstevel 	/* we are at "pci" node now */
21071708Sstevel 	do  {
21081708Sstevel 		if (di_walk_node(lc_node, DI_WALK_CLDFIRST,
21091708Sstevel 		    NULL, analyze_nodes) != 0) {
21101708Sstevel 			return;
21111708Sstevel 		}
21121708Sstevel 	} while ((lc_node = di_sibling_node(lc_node)) != DI_NODE_NIL);
21131708Sstevel 
21141708Sstevel 	/* now we wll gather info on sysctrl */
21151708Sstevel 	lc_node = di_drv_first_node(SCSB_DEV, node);
21161708Sstevel 	if (lc_node != DI_NODE_NIL)
21171708Sstevel 		analyze_nodes(lc_node, "sysctrl");
21181708Sstevel }	/* analyze_pcipci_siblings(.) */
21191708Sstevel 
21201708Sstevel 
21211708Sstevel int
analyze_nodes(di_node_t l_node,void * arg)21221708Sstevel analyze_nodes(di_node_t l_node, void *arg)
21231708Sstevel {
21241708Sstevel 	char *temp;
21251708Sstevel 	char *name, *pname;
21261708Sstevel 	di_node_t parent;
21271708Sstevel 	/*
21281708Sstevel 	 *  we will figure out whether the parent node is "pci" type
21291708Sstevel 	 *  we will save info only in this case as we only want to
21301708Sstevel 	 * print out the nodes under AP and not others
21311708Sstevel 	 */
21321708Sstevel 	parent = di_parent_node(l_node);
21331708Sstevel 	pname =  di_node_name(parent);
21341708Sstevel 	name = di_node_name(l_node);
21351708Sstevel 	/*
21361708Sstevel 	 * if this is PCI bridge, we know that this is the AP for slots
21371708Sstevel 	 * hence, we will save off the address(to convert to slot mapping)
21381708Sstevel 	 * later, and also we will start saving off slot info struct for
21391708Sstevel 	 * reporting later
21401708Sstevel 	 * we will save the immediate childs of this bridge only
21411708Sstevel 	 */
21421708Sstevel 	if (strcmp(name, "pci") == 0) {
21431708Sstevel 		num_devs = 0;
21441708Sstevel 		if ((temp = di_bus_addr(l_node)) != NULL) {
21451708Sstevel 			mc_slots_data.mc_slot_info[slot_index].slot_addr
21461708Sstevel 			    = (int)strtol(temp, (char **)NULL, 16);
21471708Sstevel 		}
21481708Sstevel 		slot_index++;
21491708Sstevel 	} else {
21501708Sstevel 		if (strcmp(pname, "pci") == 0) {
21511708Sstevel 	if ((mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs])
21521708Sstevel 	    != NULL) {
21531708Sstevel 	(void) strcat(
21541708Sstevel 	    mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
21551708Sstevel 	    name);
21561708Sstevel 			} else {
21571708Sstevel 	(void) strcpy(
21581708Sstevel 	    mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
21591708Sstevel 	    name);
21601708Sstevel 			} /* if ((mc_slots_data.mc_slot_inf */
21611708Sstevel 
21621708Sstevel 			num_devs++;
21631708Sstevel 			mc_slots_data.mc_slot_info[slot_index-1].number_devs
21641708Sstevel 			    = num_devs;
21651708Sstevel 		} /* if parent is pci */
21661708Sstevel 
21671708Sstevel 	} /* if node is pci */
21681708Sstevel 	if (arg != NULL) {
21691708Sstevel 		if (strcmp((char *)arg, "sysctrl") == 0) {
21701708Sstevel 			if (dump_prop_list("System", l_node,
21711708Sstevel 			    di_prop_sys_next)) {
21721708Sstevel 				(void) dump_prop_list(NULL, l_node,
21731708Sstevel 				    di_prop_global_next);
21741708Sstevel 			} else {
21751708Sstevel 				fail_syssoft_prop =
21761708Sstevel 				    dump_prop_list(SYSSOFT_PROP,
21771708Sstevel 				    l_node, di_prop_global_next);
21781708Sstevel 			}
21791708Sstevel 
21801708Sstevel 			fail_drv_prop =
21811708Sstevel 			    dump_prop_list(DRV_PROP, l_node,
21821708Sstevel 			    di_prop_drv_next);
21831708Sstevel 			/*
21841708Sstevel 			 * (void) dump_prop_list("Hardware",
21851708Sstevel 			 *   l_node, di_prop_hw_next);
21861708Sstevel 			 */
21871708Sstevel 			/*  dump_priv_data(l_node); */
21881708Sstevel 		}
21891708Sstevel 	}
21901708Sstevel 
21911708Sstevel 	return	(0);
21921708Sstevel 
21931708Sstevel }	/* analyze_nodes(..) */
21941708Sstevel 
21951708Sstevel 
21961708Sstevel 
21971708Sstevel /*
21981708Sstevel  * To get the slot information,
21991708Sstevel  * The OBP defines the 'slot-table' property. But the OS
22001708Sstevel  * can override it with 'hsc-slot-map' property
22011708Sstevel  * through the .conf file.
22021708Sstevel  * Since the formats are different, 2 different property names
22031708Sstevel  * are chosen.
22041708Sstevel  * The OBP property format is
22051708Sstevel  * <phandle>,<pci-devno>,<phys-slotno>,<ga-bits>
22061708Sstevel  * The OS property format is (ga-bits is not used however)
22071708Sstevel  * <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits>
22081708Sstevel  * returns 0 on error, 1 otherwise
22091708Sstevel  */
22101708Sstevel int
extract_slot_table_from_obp()22111708Sstevel extract_slot_table_from_obp()
22121708Sstevel {
22131708Sstevel 	if (mc_promopen(O_RDONLY))  {
22141708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
22151708Sstevel 		    "\ncannot open openprom device"), 0);
22161708Sstevel 		return (0);
22171708Sstevel 	}
22181708Sstevel 
22191708Sstevel 	if (mc_next(0) == 0)
22201708Sstevel 		return (0);
22211708Sstevel 	mc_walk(mc_next(0));
22221708Sstevel 
22231708Sstevel 	if (close(oprom_fd) < 0) {
22241708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
22251708Sstevel 		    "\nclose error on %s"), OPENPROMDEV, 0);
22261708Sstevel 		return (0);
22271708Sstevel 	}
22281708Sstevel 
22291708Sstevel 	return (1);
22301708Sstevel 
22311708Sstevel }	/* extract_slot_table_from_obp() */
22321708Sstevel 
22331708Sstevel 
22341708Sstevel int
mc_next(int id)22351708Sstevel mc_next(int id)
22361708Sstevel {
22371708Sstevel 	Oppbuf  oppbuf;
22381708Sstevel 	struct openpromio *opp = &(oppbuf.opp);
22391708Sstevel 
22401708Sstevel 	bzero(oppbuf.buf, BUFSIZE);
22411708Sstevel 	opp->oprom_size = MAXVALSIZE;
22421708Sstevel 	opp->oprom_node = id;
22431708Sstevel 	if (ioctl(oprom_fd, OPROMNEXT, opp) < 0) {
22441708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMNEXT"), 0);
22451708Sstevel 		return (0);
22461708Sstevel 	}
22471708Sstevel 	return (opp->oprom_node);
22481708Sstevel 
22491708Sstevel }	/* mc_next(.) */
22501708Sstevel 
22511708Sstevel 
22521708Sstevel void
mc_walk(int id)22531708Sstevel mc_walk(int id)
22541708Sstevel {
22551708Sstevel 	int curnode;
22561708Sstevel 	mc_dump_node(id);
22571708Sstevel 	if (curnode = mc_child(id))
22581708Sstevel 		mc_walk(curnode);
22591708Sstevel 	if (curnode = mc_next(id))
22601708Sstevel 		mc_walk(curnode);
22611708Sstevel }	/*  mc_walk(.) */
22621708Sstevel 
22631708Sstevel int
mc_child(int id)22641708Sstevel mc_child(int id)
22651708Sstevel {
22661708Sstevel 	Oppbuf  oppbuf;
22671708Sstevel 	struct openpromio *opp = &(oppbuf.opp);
22681708Sstevel 
22691708Sstevel 	bzero(oppbuf.buf, BUFSIZE);
22701708Sstevel 	opp->oprom_size = MAXVALSIZE;
22711708Sstevel 	opp->oprom_node = id;
22721708Sstevel 	if (ioctl(oprom_fd, OPROMCHILD, opp) < 0) {
22731708Sstevel 		perror("\nOPROMCHILD");
22741708Sstevel 		exit(0);
22751708Sstevel 	}
22761708Sstevel 	return (opp->oprom_node);
22771708Sstevel 
22781708Sstevel }	/* mc_child(.) */
22791708Sstevel 
22801708Sstevel 
22811708Sstevel /*
22821708Sstevel  * Print all properties and values
22831708Sstevel  */
22841708Sstevel void
mc_dump_node(int id)22851708Sstevel mc_dump_node(int id)
22861708Sstevel {
22871708Sstevel 	int k;
22881708Sstevel 	Oppbuf  oppbuf;
22891708Sstevel 	hsc_prom_slot_table_t	*hpstp;
22901708Sstevel 	struct openpromio *opp = &(oppbuf.opp);
22911708Sstevel 
22921708Sstevel 	/* get first prop by asking for null string */
22931708Sstevel 	bzero(oppbuf.buf, BUFSIZE);
22941708Sstevel 	for (;;) {
22951708Sstevel 		/*
22961708Sstevel 		 * get next property name
22971708Sstevel 		 */
22981708Sstevel 		opp->oprom_size = MAXNAMESZ;
22991708Sstevel 
23001708Sstevel 		if (ioctl(oprom_fd, OPROMNXTPROP, opp) < 0) {
23011708Sstevel 			perror("\nOPROMNXTPROP");
23021708Sstevel 			return;
23031708Sstevel 		}
23041708Sstevel 		if (opp->oprom_size == 0)
23051708Sstevel 			break;
23061708Sstevel 		if (strcmp(opp->oprom_array, "slot-table") == 0) {
23071708Sstevel 			if (mc_getpropval(opp) || opp->oprom_size
23081708Sstevel 			    == (uint_t)-1) {
23091708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
23101708Sstevel 				    "\ndata not available"), 0);
23111708Sstevel 				return;
23121708Sstevel 			} else {
23131708Sstevel 				slot_table_size =
23141708Sstevel 				    opp->oprom_size /
23151708Sstevel 				    sizeof (hsc_prom_slot_table_t);
23161708Sstevel 				hpstp =
23171708Sstevel 				    (hsc_prom_slot_table_t *)opp->oprom_array;
23181708Sstevel 				for (k = 0; k < slot_table_size; k++, hpstp++) {
23191708Sstevel 					prom_slot_table[k].pslotnum =
23201708Sstevel 					    hpstp->pslotnum;
23211708Sstevel 					prom_slot_table[k].ga =
23221708Sstevel 					    hpstp->ga;
23231708Sstevel 					prom_slot_table[k].pci_devno =
23241708Sstevel 					    hpstp->pci_devno;
23251708Sstevel 					prom_slot_table[k].phandle =
23261708Sstevel 					    hpstp->phandle;
23271708Sstevel 				} /* for (k = 0; k < slot_table_size; k++) */
23281708Sstevel 
23291708Sstevel 			}
23301708Sstevel 		}
23311708Sstevel 	}
23321708Sstevel 
23331708Sstevel }	/* mc_dump_node(.) */
23341708Sstevel 
23351708Sstevel 
23361708Sstevel int
mc_getpropval(struct openpromio * opp)23371708Sstevel mc_getpropval(struct openpromio *opp)
23381708Sstevel {
23391708Sstevel 	opp->oprom_size = MAXVALSIZE;
23401708Sstevel 	if (ioctl(oprom_fd, OPROMGETPROP, opp) < 0) {
23411708Sstevel 		log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMGETPROP"), 0);
23421708Sstevel 		return (1);
23431708Sstevel 	}
23441708Sstevel 	return (0);
23451708Sstevel 
23461708Sstevel }	/* mc_getpropval(.) */
23471708Sstevel 
23481708Sstevel 
23491708Sstevel 
23501708Sstevel /*
23511708Sstevel  * This function returns nothing.
23521708Sstevel  */
23531708Sstevel void
alarm_card_occupant()23541708Sstevel alarm_card_occupant()
23551708Sstevel {
23561708Sstevel 	int		scsb_fd;
23571708Sstevel 	scsb_ioc_rdwr_t	ioc_read;
23581708Sstevel 	uint8_t		new_mode = 0;
23591708Sstevel 	uint8_t		old_mode = 0;
23601708Sstevel 	uchar_t		reg_index;
23611708Sstevel 
23621708Sstevel 	if (NULL == scsb_node) {
23631708Sstevel 		if (check_platform() == -1) {
23641708Sstevel 			return;
23651708Sstevel 		}
23661708Sstevel 	}
23671708Sstevel 
23681708Sstevel 	if (version_p15_and_p20 == 1)
23691708Sstevel 		reg_index = 0xe9;	/* config status reg offset on SCB */
23701708Sstevel 	else
23711708Sstevel 		reg_index = 0xd7;	/* config status reg offset on SCB */
23721708Sstevel 
23731708Sstevel 	if ((scsb_fd = open(scsb_node, O_RDONLY)) < 0)  {
23741708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
23751708Sstevel 		    "\n%s open failed"), scsb_node, 0);
23761708Sstevel 		return;
23771708Sstevel 	}
23781708Sstevel 
23791708Sstevel 	/* save off the old mode */
23801708Sstevel 	if (scsb_mode(scsb_fd, GET, &old_mode) == 0)
23811708Sstevel 		return;
23821708Sstevel 	/* we put scsb in diag mode to read this specific ioctl */
23831708Sstevel 	new_mode = ENVCTRL_DIAG_MODE;
23841708Sstevel 	if (scsb_mode(scsb_fd, SET, &new_mode) == 0)
23851708Sstevel 		return;
23861708Sstevel 	/* now lets read the config register */
23871708Sstevel 	if (scsb_ioc_reg_read(scsb_fd, reg_index, &ioc_read, 1) == 0)
23881708Sstevel 		return;
23891708Sstevel 	/* restore the original mode */
23901708Sstevel 	if (scsb_mode(scsb_fd, SET, &old_mode) == 0)
23911708Sstevel 		return;
23921708Sstevel 	alarm_card_present = (BIT_TEST(ioc_read.ioc_rbuf[0]&0xff, 0) ? 1:0);
23931708Sstevel 
23941708Sstevel }	/* alarm_card_occupant() */
23951708Sstevel 
23961708Sstevel 
23971708Sstevel /*
23981708Sstevel  * This function changes the SCSB mode to the desired one
23991708Sstevel  * 1 on sucess, 0 otherwise
24001708Sstevel  */
24011708Sstevel int
scsb_mode(int fd,scsb_op_t sop,uint8_t * new_mode)24021708Sstevel scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode)
24031708Sstevel {
24041708Sstevel 	struct strioctl sioc;
24051708Sstevel 
24061708Sstevel 	if (sop == GET)
24071708Sstevel 		sioc.ic_cmd = ENVC_IOC_GETMODE;
24081708Sstevel 	else
24091708Sstevel 		sioc.ic_cmd = ENVC_IOC_SETMODE;
24101708Sstevel 
24111708Sstevel 	sioc.ic_timout = 0;
24121708Sstevel 	sioc.ic_len = sizeof (uint8_t);
24131708Sstevel 	sioc.ic_dp = (char *)new_mode;
24141708Sstevel 
24151708Sstevel 
24161708Sstevel 	if (ioctl(fd, I_STR, &sioc) == -1) {
24171708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
24181708Sstevel 		    "\nscsb_mode():scsb ioctl() failed"), 0);
24191708Sstevel 		return (0);
24201708Sstevel 	}
24211708Sstevel 	return (1);
24221708Sstevel 
24231708Sstevel }	/* scsb_mode(...) */
24241708Sstevel 
24251708Sstevel 
24261708Sstevel /*
24271708Sstevel  * 1 on success, 0 otherwise
24281708Sstevel  */
24291708Sstevel int
scsb_ioc_reg_read(int fd,uchar_t index,scsb_ioc_rdwr_t * ioc_rd,int num)24301708Sstevel scsb_ioc_reg_read(int fd, uchar_t index, scsb_ioc_rdwr_t *ioc_rd, int num)
24311708Sstevel {
24321708Sstevel 	struct strioctl		sioc;
24331708Sstevel 	scsb_ioc_rdwr_t		*rdwrp;
24341708Sstevel 
24351708Sstevel 	rdwrp = ioc_rd;
24361708Sstevel 	sioc.ic_timout = 0;
24371708Sstevel 	sioc.ic_len = sizeof (scsb_ioc_rdwr_t);
24381708Sstevel 	sioc.ic_dp = (char *)rdwrp;
24391708Sstevel 	/* setup read command before ioctl */
24401708Sstevel 	sioc.ic_cmd = SCSBIOC_REG_READ;
24411708Sstevel 	rdwrp->ioc_wlen = 0;
24421708Sstevel 	rdwrp->ioc_rlen = num;
24431708Sstevel 	rdwrp->ioc_regindex = index;
24441708Sstevel 	if (ioctl(fd, I_STR, &sioc) == -1) {
24451708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
24461708Sstevel 		    "scsb_ioc_reg_read(): scsb ioctl() failed\n"), 0);
24471708Sstevel 		return (0);
24481708Sstevel 	}
24491708Sstevel 	return (1);
24501708Sstevel 
24511708Sstevel }	/* scsb_ioc_reg_read(....) */
2452