xref: /titanic_44/usr/src/lib/libprtdiag_psr/sparc/montecarlo/common/montecarlo.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
23  *
24  * Netract Platform specific functions.
25  *
26  * 	called when :
27  *	machine_type == MTYPE_MONTECARLO
28  */
29 
30 /* includes */
31 #include <assert.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <unistd.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <stropts.h>
40 #include <fcntl.h>
41 #include <kvm.h>
42 #include <kstat.h>
43 #include <sys/types.h>
44 #include <sys/utsname.h>
45 #include <sys/openpromio.h>
46 #include <sys/sunddi.h>
47 #include <sys/ddi_impldefs.h>
48 #include <sys/devinfo_impl.h>
49 #include <sys/ioccom.h>
50 #include <sys/systeminfo.h>
51 #include <libintl.h>
52 #include <config_admin.h>
53 #include "pdevinfo.h"
54 #include "display.h"
55 #include "pdevinfo_sun4u.h"
56 #include "display_sun4u.h"
57 #include "libprtdiag.h"
58 #include "libdevinfo.h"
59 
60 /* MC specific header, might just include from MC space */
61 #include "mct_topology.h"
62 #include "envctrl_gen.h"
63 #include "pcf8574_nct.h"
64 #include "netract_gen.h"
65 #include "hscimpl.h"
66 #include "scsbioctl.h"
67 
68 #if !defined(TEXT_DOMAIN)
69 #define	TEXT_DOMAIN			"SYS_TEST"
70 #endif
71 
72 /* globals */
73 #define	MAXNAMESZ			128
74 #define	MAX_NODE_NAME_SZ		32
75 
76 /* this values equates to Max Tree depth for now */
77 #define	MAXIMUM_DEVS			64
78 
79 typedef char device_info_t[MAX_NODE_NAME_SZ];
80 
81 typedef struct {
82 	cfga_list_data_t *ldatap;
83 	int req; /* If set, this list_data was requested by user */
84 } ap_out_t;
85 
86 
87 typedef struct {
88 	uint_t slot_addr;
89 	uint_t slot_stat;
90 	uint_t slot_cond;
91 	device_info_t devs_info[MAXIMUM_DEVS];
92 	uint_t number_devs;
93 } mc_slot_info_t;
94 
95 typedef struct {
96 	mc_slot_info_t mc_slot_info[MC_MAX_SLOTS];
97 } slot_data_t;
98 
99 
100 extern char *progname;
101 extern int print_flag;
102 
103 /* These are used to store all force loads of the drivers */
104 static int ps_fd[MC_MAX_PS];
105 static int oprom_fd;
106 static int slot_index			= 0;
107 static int idx_minuscpu			= 0;
108 static int num_devs			= 0;
109 static int sd_instances[MC_MAX_SLOTS*15];
110 static int gpio_instances[MC_MAX_PS+MC_MAX_FAN];
111 static int sd_count			= 0;
112 static int st_instance;
113 static int gpio_count			= 0;
114 static int slot_table_not_found		= 0;
115 
116 /* default not present */
117 static int alarm_card_present		= 0;
118 static int cpu_ftm_present		= 0;
119 
120 /*
121  * We will store all kstat in globals so that
122  * we can browse thru them later
123  */
124 static	int fail_syssoft_prop		= 0;
125 static  int fail_drv_prop		= 0;
126 di_node_t rootnode;	/* root nexus */
127 slot_data_t mc_slots_data;
128 
129 /* scsb driver kstats */
130 scsb_ks_leddata_t scsb_ks_leddata;
131 scsb_ks_state_t scsb_ks_state;
132 mct_topology_t scsb_ks_topo;
133 
134 /* pcf8574(gpio) driver kstats */
135 envctrl_cpuvoltage_t pcf8574_ks_cpuv;
136 envctrl_pwrsupp_t pcf8574_ks_ps1;
137 envctrl_fantray_t pcf8574_ks_fant1;
138 envctrl_pwrsupp_t pcf8574_ks_ps2;
139 envctrl_fantray_t pcf8574_ks_fant2;
140 
141 /* pcf8591(adc-dac) driver kstats */
142 envctrl_temp_t pcf8591_ks_temp;
143 
144 hsc_slot_table_t hotswap_slot_table[MC_MAX_SLOTS];
145 hsc_prom_slot_table_t prom_slot_table[MC_MAX_SLOTS];
146 
147 static char *hotswap_mode		= NULL;
148 static char *slot_auto_config[MC_MAX_SLOTS];
149 static	int slot_table_size;
150 
151 /*
152  * use this to ascertain what's the system,
153  * default is tonga, we can add more for future variations
154  * 0=tonga, 1=montecarlo
155  * we need also to figure out what the system version is
156  * 0 = 1.5, 1 = 1.0, 0.6 etc.
157  */
158 int montecarlo				= 0;
159 int version_p15_and_p20			= 0;
160 
161 #define	MAX_PRTDIAG_INFO_LENGTH		1024
162 #define	MAX_PRTDIAG_FRUS		22
163 #define	BIT_TEST(X, N)			((X) & (1 << (N)))
164 #define	SLOT1_OK_BIT			0
165 #define	SLOT2_OK_BIT			1
166 #define	SLOT3_OK_BIT			2
167 #define	SLOT4_OK_BIT			3
168 #define	SLOT5_OK_BIT			4
169 #define	SLOT6_OK_BIT			5
170 #define	SLOT7_OK_BIT			6
171 #define	SLOT8_OK_BIT			7
172 #define	PDU1_OK_BIT			SLOT2_OK_BIT
173 #define	PDU2_OK_BIT			SLOT4_OK_BIT
174 #define	FTM_OK_BIT			SLOT5_OK_BIT
175 #define	SCB_OK_BIT			SLOT6_OK_BIT
176 #define	FAN1_OK_BIT			SLOT1_OK_BIT
177 #define	FAN2_OK_BIT			SLOT2_OK_BIT
178 #define	DISK1_OK_BIT			SLOT4_OK_BIT
179 #define	DISK2_OK_BIT			SLOT5_OK_BIT
180 #define	DISK3_OK_BIT			SLOT6_OK_BIT
181 #define	PS1_OK_BIT			SLOT7_OK_BIT
182 #define	PS2_OK_BIT			SLOT8_OK_BIT
183 #define	S_FREE(x)	(((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
184 #define	ENVC_DEBUG_MODE			0x03
185 #define	OPENPROMDEV			"/dev/openprom"
186 #define	I2C_PCF8591_NAME 		"adc-dac"
187 #define	I2C_KSTAT_CPUTEMP 		"adc_temp"
188 #define	SCSB_DEV			"scsb"
189 #define	SDERR				"sderr"
190 #define	STERR				"sterr"
191 #define	OK				"ok"
192 #define	NOK				"Not ok"
193 #define	ON				"on"
194 #define	OFF				"off"
195 #define	BLINK				"blink"
196 #define	NA				"Not Available"
197 #define	UK				"Unknown "
198 #define	YES				"Yes"
199 #define	NO				"No "
200 #define	LO				"low"
201 #define	HI				"high"
202 #define	BLANK				" "
203 #define	SYSSOFT_PROP			"System software"
204 #define	DRV_PROP			"Driver"
205 #define	HSC_PROP_NAME			"hsc-slot-map"
206 #define	HSC_MODE			"hotswap-mode"
207 #define	PCI_ROOT_AP			"pci"
208 #define	PROPS				"Properties:"
209 #define	BOARDTYPE			"Board Type:"
210 #define	DEVS				"Devices:"
211 #define	CPCI_IO				"CompactPCI IO Slot"
212 #define	AC_CARD				"Alarm Card"
213 #define	CPU_FTM				"Front Transition Module"
214 #define	SCTRL_PROM_P06			0x00
215 #define	SCTRL_PROM_P10			0x01
216 #define	SCTRL_PROM_P15			0x02
217 #define	SCTRL_PROM_P20			0x03
218 
219 #define	RMM_NUMBER			3
220 
221 #define	MONTECARLO_PLATFORM		"SUNW,UltraSPARC-IIi-Netract"
222 #define	MAKAHA_PLATFORM			"SUNW,UltraSPARC-IIe-NetraCT-40"
223 
224 /*
225  * The follow table is indexed with the enum's defined by mct_slot_occupant_t
226  * OC_UNKN OC_CPU  OC_AC    OC_BHS OC_FHS OC_HAHS
227  * OC_QFE  OC_FRCH OC_COMBO OC_PMC OC_ATM
228  *
229  * But "scsb" can currently identify only CPU and Alarm Cards by known
230  * slot numbers.
231  */
232 char	*slot_occupants[] = {
233 		CPCI_IO,
234 		"CPU board ",
235 		CPCI_IO,
236 		"Basic HotSwap Board",
237 		"Full HotSwap Board",
238 		"HA Board",
239 		"QFE Board",
240 		"Fresh Choice Board",
241 		"SUN Combo Board",
242 		"PMC Board",
243 		"ATM Board"
244 	};
245 
246 static char	*prtdiag_fru_types[] = {
247 		"I/O        ",	/* 0 */
248 		"CPU        ",
249 		"PSU        ",
250 		"HDD        ",
251 		"FAN        ",
252 		"Alarm Card ",
253 		"SCB        ",
254 		"SSB        ",
255 		"CFTM       ",
256 		"CRTM       ",
257 		"PRTM       ",
258 		"Midplane   "	/* 11 */
259 	};
260 
261 char prtdiag_fru_info[MAX_PRTDIAG_FRUS][MAX_PRTDIAG_INFO_LENGTH];
262 
263 #define	SCB_REG_READ			1
264 #define	SCB_REG_WRITE			2
265 
266 /* Standard Device nodes - hardwired for now */
267 /* will include fan tray later, cpu voltage not impl */
268 static char	*scsb_node = NULL;
269 static char	**ps_node = NULL;
270 static char	*temp_node = NULL;
271 
272 static char	*mc_scsb_node =
273 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/sysctrl@0,80:scsb";
274 
275 static char	*ot_scsb_node =
276 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/sysctrl@0,80:scsb";
277 
278 static char	*mc_ps_node[] = {
279 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7c:pwrsuppply",
280 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7e:pwrsuppply"
281 };
282 
283 static char	*ot_ps_node[] = {
284 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7c:pwrsuppply",
285 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7e:pwrsuppply"
286 };
287 
288 static char	*mc_temp_node =
289 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/adc-dac@0,9e:cputemp";
290 
291 /*
292  * these functions will overlay the symbol table of libprtdiag
293  * at runtime (netract systems only)
294  * display functions
295  */
296 int	display(Sys_tree *, Prom_node *, struct system_kstat_data *, int);
297 /* local functions */
298 /*
299  * prom function
300  */
301 static void	gather_diaginfo(int flag);
302 static int	extract_slot_table_from_obp();
303 static int	mc_next(int id);
304 static void	mc_walk(int id);
305 static int	mc_child(int id);
306 static void	mc_dump_node(int id);
307 static int	mc_getpropval(struct openpromio *opp);
308 
309 #ifdef	REDUNDANT_INFO
310 static int	mc_get_cpu_freq(Prom_node *node);
311 static int	mc_get_ecache_size(Prom_node *node);
312 static void	mc_display_cpus(Board_node *board);
313 static void	mc_display_cpu_devices(Sys_tree *tree);
314 #endif	/* REDUNDANT_INFO */
315 
316 static void	netract_disp_prom_version();
317 
318 /*
319  * Since we do not have a system wide kstat for MC/Tg
320  * here we have to do specific kstats to drivers that
321  * post this information - MC/Tg specific drivers
322  * that post kstat here are : scsb, pcf8574(gpio) and pcf8591
323  */
324 static int	analyze_nodes(di_node_t, void*);
325 static void	analyze_pcipci_siblings(di_node_t);
326 static void	display_mc_prtdiag_info();
327 static int	dump_devs(di_node_t, void *);
328 static void	prtdiag_devinfo(void);
329 static void	force_load_drivers();
330 static int	dump_prop_list(char *name,
331 		    di_node_t node, di_prop_t (*nxtprop)());
332 static void	*config_calloc_check(size_t nelem, size_t elsize);
333 static void	explore_slot_occupants();
334 static void	do_scsb_kstat();
335 static void	do_pcf8574_kstat();
336 static void	do_pcf8591_kstat();
337 static void	do_promversion();
338 static int	mc_promopen(int oflag);
339 static int	scsi_disk_status(int disk_number);
340 static void	alarm_card_occupant();
341 static int	scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode);
342 static int	scsb_ioc_reg_read(int fd, uchar_t index,
343 		    scsb_ioc_rdwr_t *ioc_rd, int num);
344 
345 static int	check_platform();
346 
347 int
display(Sys_tree * tree,Prom_node * root,struct system_kstat_data * kstats,int syserrlog)348 display(Sys_tree *tree,
349 	    Prom_node *root,
350 	    struct system_kstat_data *kstats,
351 	    int syserrlog)
352 {
353 	int exit_code = 0;   /* init to all OK */
354 	void *value;  /* used for opaque PROM data */
355 	struct mem_total memory_total;  /* Total memory in system */
356 	struct grp_info grps;   /* Info on all groups in system */
357 #ifdef	lint
358 	syserrlog = syserrlog;
359 #endif
360 	sys_clk = -1;  /* System clock freq. (in MHz) */
361 	/*
362 	 * Now display the machine's configuration. We do this if we
363 	 * are not logging or exit_code is set (machine is broke).
364 	 */
365 	if (!logging || exit_code) {
366 		struct utsname uts_buf;
367 
368 		/*
369 		 * Display system banner
370 		 */
371 		(void) uname(&uts_buf);
372 
373 		log_printf(dgettext(TEXT_DOMAIN,
374 		    "System Configuration:  Oracle Corporation"
375 		    "  %s %s\n"), uts_buf.machine,
376 		    get_prop_val(find_prop(root, "banner-name")), 0);
377 
378 		/* display system clock frequency */
379 		value = get_prop_val(find_prop(root, "clock-frequency"));
380 		if (value != NULL) {
381 			sys_clk = ((*((int *)value)) + 500000) / 1000000;
382 			log_printf(dgettext(TEXT_DOMAIN,
383 			    "System clock frequency: "
384 			    "%d MHz\n"), sys_clk, 0);
385 		}
386 
387 		/* Display the Memory Size */
388 		display_memorysize(tree, kstats, &grps, &memory_total);
389 		/* Lets make sure we have all the needed drivers loaded */
390 		/* display Montecarlo/Tonga FRU information */
391 		if (!extract_slot_table_from_obp())
392 			log_printf(dgettext(TEXT_DOMAIN,
393 			    "\r\nslot-table not available\r\n"), 0);
394 		do_scsb_kstat();
395 		force_load_drivers();
396 		gather_diaginfo(print_flag && !logging);
397 		/* figure out if ac is present */
398 		alarm_card_occupant();
399 		/* platform specific display mod */
400 		display_mc_prtdiag_info();
401 		di_fini(rootnode);
402 		netract_disp_prom_version();
403 	}  /* if (!logging || exit_code) */
404 
405 	return (exit_code);
406 
407 }	/* display(....) */
408 
409 static int
check_platform()410 check_platform()
411 {
412 	char	si_platform[SYS_NMLN];
413 
414 	/*
415 	 * Check for the platform: Montecarlo or Makaha/CP2040 based
416 	 */
417 	if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) {
418 		return (-1);
419 	}
420 
421 	if ((strncmp(si_platform, MONTECARLO_PLATFORM,
422 	    strlen(MONTECARLO_PLATFORM))) == 0) {
423 		scsb_node = mc_scsb_node;
424 		ps_node = mc_ps_node;
425 		temp_node = mc_temp_node;
426 	} else if ((strncmp(si_platform, MAKAHA_PLATFORM,
427 	    strlen(MAKAHA_PLATFORM))) == 0) {
428 		scsb_node = ot_scsb_node;
429 		ps_node = ot_ps_node;
430 		temp_node = NULL;
431 	} else {
432 		return (-1);
433 	}
434 
435 	return (0);
436 }
437 
438 void
force_load_drivers()439 force_load_drivers()
440 {
441 	int	i;
442 
443 	if (NULL == scsb_node || NULL == ps_node) {
444 		if (check_platform() == -1) {
445 			return;
446 		}
447 	}
448 
449 	/* check scb/ssb presence */
450 	if (scsb_ks_state.scb_present || scsb_ks_state.ssb_present) {
451 		if (open(scsb_node, O_RDONLY) < 0)
452 			log_printf(dgettext(TEXT_DOMAIN,
453 			    "\nscsb open FAILED!"), 0);
454 	}
455 
456 	/* check the num of PS we have */
457 	for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
458 		if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
459 			if ((ps_fd[i] = open(ps_node[i], O_RDONLY)) < 0)
460 				log_printf(dgettext(TEXT_DOMAIN,
461 				    "\npowersupply%d open failed"),
462 				    i, 0);
463 		}
464 	} /* for */
465 
466 	/* open the cpu temp driver */
467 	if (temp_node) {
468 		if (open(temp_node, O_RDONLY) < 0)
469 			log_printf(dgettext(TEXT_DOMAIN,
470 			    "\ncputemp open FAILED!"), 0);
471 	}
472 }
473 
474 
475 void
explore_slot_occupants()476 explore_slot_occupants()
477 {
478 	char *cp = NULL;
479 	int index;
480 	int ret = CFGA_ERROR;
481 	char *estrp = NULL;
482 	cfga_list_data_t *list_array = NULL;
483 	ap_out_t *out_array = NULL;
484 	int nlist = 0;
485 	char  *prefilt_optp = NULL;
486 	int dyn_exp = 1;
487 	char *plat_opts = NULL;
488 
489 	ret = config_list_ext(0, NULL, &list_array,
490 	    &nlist, plat_opts, prefilt_optp, &estrp,
491 	    dyn_exp ? CFGA_FLAG_LIST_ALL : 0);
492 	if (ret != CFGA_OK) {
493 		log_printf(dgettext(TEXT_DOMAIN,
494 		    "\ncannot explore configuration"), 0);
495 		return;
496 	}
497 	assert(nlist != 0);
498 	out_array = config_calloc_check(nlist, sizeof (*out_array));
499 	if (out_array == NULL) {
500 		ret = CFGA_LIB_ERROR;
501 		goto bail;
502 	}
503 	/* create a list of output stat data */
504 	for (index = 0; index < nlist; index++) {
505 		out_array[index].ldatap = &list_array[index];
506 		out_array[index].req = 0;
507 	}
508 
509 	for (index = 0; index < nlist; index++) {
510 		if ((cp = strstr(out_array[index].ldatap->ap_phys_id,
511 		    "cpci_slot")) != NULL) {
512 			mc_slots_data.mc_slot_info[idx_minuscpu].slot_stat
513 			    = out_array[index].ldatap->ap_o_state;
514 			mc_slots_data.mc_slot_info[idx_minuscpu].slot_cond
515 			    = out_array[index].ldatap->ap_cond;
516 			idx_minuscpu++;
517 		}
518 	}
519 bail:
520 	S_FREE(list_array);
521 	S_FREE(out_array);
522 }
523 
524 
525 /*
526  * config_calloc_check - perform allocation, check result and
527  * set error indicator
528  */
529 void *
config_calloc_check(size_t nelem,size_t elsize)530 config_calloc_check(
531 	size_t nelem,
532 	size_t elsize)
533 {
534 	void *p;
535 	static char alloc_fail[] =
536 	    "%s: memory allocation failed (%d*%d bytes)\n";
537 
538 	p = calloc(nelem, elsize);
539 	if (p == NULL) {
540 		log_printf(dgettext(TEXT_DOMAIN, alloc_fail), nelem, elsize, 0);
541 	}
542 	return (p);
543 }
544 
545 
546 void
do_scsb_kstat()547 do_scsb_kstat()
548 {
549 	kstat_ctl_t	*kc;
550 	kstat_t		*ksp_leddata;
551 	kstat_t		*ksp_state;
552 	kstat_t		 *ksp_topo;
553 	scsb_ks_leddata_t *pks_leddata;
554 	scsb_ks_state_t *pks_state;
555 	mct_topology_t  *pks_topo;
556 	int i;
557 
558 #ifdef	DEBUG_TEMP1
559 		int index;
560 #endif
561 	if (!(kc = kstat_open())) {
562 #ifdef	DEBUG_TEMP
563 		log_printf("\nkstat_open failed", 0);
564 #endif
565 		return;
566 	}
567 #ifdef	lint
568 	kc = kc;
569 #endif
570 	/* get kstat on scsb led data */
571 	if ((ksp_leddata = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_LEDDATA))
572 	    == NULL) {
573 #ifdef	DEBUG_TEMP
574 		log_printf("\nkstat_lookup for scsb_leddata failed", 0);
575 #endif
576 		return;
577 	}
578 	if (kstat_read(kc, ksp_leddata, NULL) == -1) {
579 #ifdef	DEBUG_TEMP
580 		log_printf("\nkstat_read for scsb_leddata failed", 0);
581 #endif
582 		return;
583 	}
584 	pks_leddata = (scsb_ks_leddata_t *)ksp_leddata->ks_data;
585 	scsb_ks_leddata = *pks_leddata; /* set the globals for future */
586 #ifdef	DEBUG_LEDS
587 	/* dump the kstat leddata */
588 	printf("\nDumping LED regs: ");
589 	for (i = 0; i < SCSB_LEDDATA_REGISTERS; ++i) {
590 		log_printf("0x%x ", pks_leddata->scb_led_regs[i] & 0xff, 0);
591 	}
592 	log_printf("\n", 0);
593 #endif
594 	/* get kstat on scsb states */
595 	if ((ksp_state = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_STATE))
596 	    == NULL) {
597 #ifdef	DEBUG_TEMP
598 		log_printf("\nkstat_lookup for scsb_state failed", 0);
599 #endif
600 		return;
601 	}
602 	if (kstat_read(kc, ksp_state, NULL) == -1) {
603 #ifdef	DEBUG_TEMP
604 		log_printf("\nkstat_read for scsb_state failed", 0);
605 #endif
606 		return;
607 	}
608 	pks_state = (scsb_ks_state_t *)ksp_state->ks_data;
609 	scsb_ks_state = *pks_state; /* set the global for future */
610 #ifdef	DEBUG_TEMP1
611 	/* dump the kstat state */
612 	log_printf("\tSCB			is%spresent\n",
613 	    pks_state->scb_present ? " " : " not ", 0);
614 	log_printf("\tSSB			is%spresent\n",
615 	    pks_state->ssb_present ? " " : " not ", 0);
616 	log_printf("\tscsb			is%sfrozen\n",
617 	    pks_state->scsb_frozen ? " " : " not ", 0);
618 	log_printf("\tscsb mode:		", 0);
619 	switch (pks_state->scsb_mode) {
620 		case ENVC_DEBUG_MODE:
621 			log_printf("DEBUG MODE\n", 0);
622 			break;
623 		case ENVCTRL_DIAG_MODE:
624 			log_printf("DIAGNOSTIC MODE\n", 0);
625 			break;
626 		case ENVCTRL_NORMAL_MODE:
627 			log_printf("NORMAL MODE\n", 0);
628 			break;
629 	}
630 	log_printf("\tscsb event code:	0x%x\n", pks_state->event_code, 0);
631 #endif	/* DEBUG_TEMP1 */
632 
633 	if ((ksp_topo = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_TOPOLOGY))
634 	    == NULL) {
635 #ifdef	DEBUG_TEMP
636 		log_printf("\nkstat_lookup for scsb_topo failed", 0);
637 #endif
638 		return;
639 	}
640 	if (kstat_read(kc, ksp_topo, NULL) == -1) {
641 #ifdef	DEBUG_TEMP
642 		log_printf("\nkstat_read for scsb_topo failed", 0);
643 #endif
644 		return;
645 	}
646 	pks_topo = (mct_topology_t *)ksp_topo->ks_data;
647 	scsb_ks_topo = *pks_topo; /* set the global for future */
648 	/*
649 	 * we need to set this so that we can get status info
650 	 * for the 2 powersupplies in MC as we need to get
651 	 * kstat from both driver instances for environment
652 	 */
653 	if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
654 		montecarlo = 1; /* Monte Carlo */
655 	/*
656 	 * HW version 0.6 and 1.0 had different led maps
657 	 * its assumed that HW 2.0 would not change this
658 	 * need to modify if it does
659 	 */
660 	if ((pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P15) ||
661 	    (pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P20)) {
662 		version_p15_and_p20 = 1;
663 	}
664 
665 	/* set flag to note that CFTM is present */
666 	for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
667 		if (pks_topo->mct_cftm[i].fru_status == FRU_PRESENT)
668 			cpu_ftm_present = 1;
669 	}
670 
671 #ifdef	DEBUG_TEMP1
672 	/*
673 	 * Midplane
674 	 */
675 	log_printf("Midplane type:		", 0);
676 	if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
677 		log_printf("Netra ct800 server\n", 0);
678 	else
679 		log_printf("Netra ct400 server%s\n",
680 		    pks_topo->mid_plane.fru_id ==
681 		    SCTRL_MPID_QUARTER_NODSK ? ", no disk" : " with disk", 0);
682 	log_printf("Midplane version:	%d\n",
683 	    pks_topo->mid_plane.fru_version, 0);
684 	log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
685 	    pks_topo->mct_scb[0].fru_type,
686 	    pks_topo->mct_scb[0].fru_unit,
687 	    pks_topo->mct_scb[0].fru_id,
688 	    pks_topo->mct_scb[0].fru_version, 0);
689 	/*
690 	 * Slots
691 	 */
692 	log_printf("Slots present out of maximum %d\n",
693 	    pks_topo->max_units[SLOT], 0);
694 	for (i = 0; i < pks_topo->max_units[SLOT]; ++i) {
695 		if (pks_topo->mct_slots[i].fru_status != FRU_PRESENT)
696 			continue;
697 		index = (int)pks_topo->mct_slots[i].fru_type;
698 		log_printf("\tSlot %d occupant: %s;",
699 		    pks_topo->mct_slots[i].fru_unit, slot_occupants[index], 0);
700 		log_printf(" ID 0x%x; VER 0x%x ; ",
701 		    pks_topo->mct_slots[i].fru_id,
702 		    pks_topo->mct_slots[i].fru_version, 0);
703 		log_printf(" Slot health %d\n",
704 		    pks_topo->mct_slots[i].fru_health, 0);
705 		/* pks_topo->mct_slots[i].fru_health */
706 	}
707 
708 	/*
709 	 * PDU
710 	 */
711 	log_printf("PDUs present out of maximum %d\n",
712 	    pks_topo->max_units[PDU], 0);
713 	for (i = 0; i < pks_topo->max_units[PDU]; ++i) {
714 		if (pks_topo->mct_pdu[i].fru_status != FRU_PRESENT)
715 			continue;
716 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
717 		    pks_topo->mct_pdu[i].fru_type,
718 		    pks_topo->mct_pdu[i].fru_unit,
719 		    pks_topo->mct_pdu[i].fru_id,
720 		    pks_topo->mct_pdu[i].fru_version, 0);
721 		/* pks_topo->mct_pdu[i].fru_health */
722 	}
723 
724 	/*
725 	 * Power Supplies
726 	 */
727 	log_printf("Power Supplies present out of maximum %d\n",
728 	    pks_topo->max_units[PS], 0);
729 	for (i = 0; i < pks_topo->max_units[PS]; ++i) {
730 		if (pks_topo->mct_ps[i].fru_status != FRU_PRESENT)
731 			continue;
732 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
733 		    pks_topo->mct_ps[i].fru_type,
734 		    pks_topo->mct_ps[i].fru_unit,
735 		    pks_topo->mct_ps[i].fru_id,
736 		    pks_topo->mct_ps[i].fru_version, 0);
737 	}
738 
739 	/*
740 	 * Disks
741 	 */
742 	log_printf("Disks present out of maximum %d\n",
743 	    pks_topo->max_units[DISK], 0);
744 	for (i = 0; i < pks_topo->max_units[DISK]; ++i) {
745 		if (pks_topo->mct_disk[i].fru_status != FRU_PRESENT)
746 			continue;
747 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
748 		    pks_topo->mct_disk[i].fru_type,
749 		    pks_topo->mct_disk[i].fru_unit,
750 		    pks_topo->mct_disk[i].fru_id,
751 		    pks_topo->mct_disk[i].fru_version, 0);
752 	}
753 
754 	/*
755 	 * Fans
756 	 */
757 	log_printf("Fans present out of maximum %d\n",
758 	    pks_topo->max_units[FAN], 0);
759 	for (i = 0; i < pks_topo->max_units[FAN]; ++i) {
760 		if (pks_topo->mct_fan[i].fru_status != FRU_PRESENT)
761 			continue;
762 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
763 		    pks_topo->mct_fan[i].fru_type,
764 		    pks_topo->mct_fan[i].fru_unit,
765 		    pks_topo->mct_fan[i].fru_id,
766 		    pks_topo->mct_fan[i].fru_version, 0);
767 	}
768 
769 	/*
770 	 * SCBs
771 	 */
772 	log_printf("SCBs present out of maximum %d\n",
773 	    pks_topo->max_units[SCB], 0);
774 	for (i = 0; i < pks_topo->max_units[SCB]; ++i) {
775 		if (pks_topo->mct_scb[i].fru_status != FRU_PRESENT)
776 			continue;
777 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
778 		    pks_topo->mct_scb[i].fru_type,
779 		    pks_topo->mct_scb[i].fru_unit,
780 		    pks_topo->mct_scb[i].fru_id,
781 		    pks_topo->mct_scb[i].fru_version, 0);
782 	}
783 
784 	/*
785 	 * SSBs
786 	 */
787 	log_printf("SSBs present out of maximum %d\n",
788 	    pks_topo->max_units[SSB], 0);
789 	for (i = 0; i < pks_topo->max_units[SSB]; ++i) {
790 		if (pks_topo->mct_ssb[i].fru_status != FRU_PRESENT)
791 			continue;
792 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
793 		    pks_topo->mct_ssb[i].fru_type,
794 		    pks_topo->mct_ssb[i].fru_unit,
795 		    pks_topo->mct_ssb[i].fru_id,
796 		    pks_topo->mct_ssb[i].fru_version, 0);
797 	}
798 
799 	/*
800 	 * Alarms Cards
801 	 */
802 	log_printf("Alarm Cards present out of maximum %d\n",
803 	    pks_topo->max_units[ALARM], 0);
804 	for (i = 0; i < pks_topo->max_units[ALARM]; ++i) {
805 		if (pks_topo->mct_alarm[i].fru_status != FRU_PRESENT)
806 			continue;
807 		log_printf("\ttype %d; unit %d; id 0x%x; VER 0x%x\n",
808 		    pks_topo->mct_alarm[i].fru_type,
809 		    pks_topo->mct_alarm[i].fru_unit,
810 		    pks_topo->mct_alarm[i].fru_id,
811 		    pks_topo->mct_alarm[i].fru_version, 0);
812 	}
813 
814 	/*
815 	 * CFTMs
816 	 */
817 	log_printf("CFTMs present out of maximum %d\n",
818 	    pks_topo->max_units[CFTM], 0);
819 	for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
820 		if (pks_topo->mct_cftm[i].fru_status != FRU_PRESENT)
821 			continue;
822 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
823 		    pks_topo->mct_cftm[i].fru_type,
824 		    pks_topo->mct_cftm[i].fru_unit,
825 		    pks_topo->mct_cftm[i].fru_id,
826 		    pks_topo->mct_cftm[i].fru_version, 0);
827 	}
828 
829 	/*
830 	 * CRTMs
831 	 */
832 	log_printf("CRTMs present out of maximum %d\n",
833 	    pks_topo->max_units[CRTM], 0);
834 	for (i = 0; i < pks_topo->max_units[CRTM]; ++i) {
835 		if (pks_topo->mct_crtm[i].fru_status != FRU_PRESENT)
836 			continue;
837 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
838 		    pks_topo->mct_crtm[i].fru_type,
839 		    pks_topo->mct_crtm[i].fru_unit,
840 		    pks_topo->mct_crtm[i].fru_id,
841 		    pks_topo->mct_crtm[i].fru_version, 0);
842 	}
843 
844 	/*
845 	 * PRTMs
846 	 */
847 	log_printf("PRTMs present out of maximum %d\n",
848 	    pks_topo->max_units[PRTM], 0);
849 	for (i = 0; i < pks_topo->max_units[PRTM]; ++i) {
850 		if (pks_topo->mct_prtm[i].fru_status != FRU_PRESENT)
851 			continue;
852 		log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
853 		    pks_topo->mct_prtm[i].fru_type,
854 		    pks_topo->mct_prtm[i].fru_unit,
855 		    pks_topo->mct_prtm[i].fru_id,
856 		    pks_topo->mct_prtm[i].fru_version, 0);
857 	}
858 #endif	/* DEBUG_TEMP1 */
859 
860 }	/*  do_scsb_kstat(...) */
861 
862 
863 void
do_pcf8574_kstat()864 do_pcf8574_kstat()
865 {
866 	kstat_ctl_t	*kc;
867 	kstat_t		*ksp_ps;
868 	kstat_t		*ksp_fan;
869 	envctrl_pwrsupp_t *pks_ps;
870 	envctrl_fantray_t *pks_fan;
871 	int	i;
872 	char	*kstat_name = NULL;
873 
874 	if (!(kc = kstat_open())) {
875 #ifdef	DEBUG_TEMP
876 		log_printf("\nkstat_open for pcf8574 failed", 0);
877 #endif
878 		return;
879 	}
880 
881 #ifdef	lint
882 	kc = kc;
883 #endif
884 	/* get kstat on gpio powersupply and fan states */
885 	for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
886 		if (i == 1) {
887 			kstat_name = I2C_KSTAT_PWRSUPPLY;
888 			strncat(kstat_name, "1", 1);
889 		} else {
890 			kstat_name = I2C_KSTAT_PWRSUPPLY;
891 			strncat(kstat_name, "2", 1);
892 		}
893 		if ((ksp_ps = kstat_lookup(kc, I2C_PCF8574_NAME, 0, kstat_name))
894 		    == NULL) {
895 #ifdef	DEBUG_TEMP
896 			log_printf("\nks lookup for pwrsupply%d failed",
897 			    i+1, 0);
898 #endif
899 			return;
900 		}
901 		if (kstat_read(kc, ksp_ps, NULL) == -1) {
902 #ifdef	DEBUG_TEMP
903 			log_printf("\nks read for pwrsupply%d failed", i+1, 0);
904 #endif
905 			return;
906 		}
907 		pks_ps = (envctrl_pwrsupp_t *)ksp_ps->ks_data;
908 		if (i == 1)
909 			pcf8574_ks_ps1 = *pks_ps; /* ps 1 */
910 		else
911 			pcf8574_ks_ps2 = *pks_ps; /* ps 2 */
912 	} /* for */
913 	for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
914 		if (i == 1) {
915 			kstat_name = I2C_KSTAT_FANTRAY;
916 			strncat(kstat_name, "1", 1);
917 		} else {
918 			kstat_name = I2C_KSTAT_FANTRAY;
919 			strncat(kstat_name, "2", 1);
920 		}
921 		if ((ksp_fan = kstat_lookup(kc, I2C_PCF8574_NAME,
922 		    0, kstat_name)) == NULL) {
923 #ifdef	DEBUG_TEMP
924 			log_printf("\nks lookup for fantray%d failed",
925 			    i+1, 0);
926 #endif
927 			return;
928 		}
929 		if (kstat_read(kc, ksp_fan, NULL) == -1) {
930 #ifdef	DEBUG_TEMP
931 			log_printf("\nks read for fantray%d failed", i+1, 0);
932 #endif
933 			return;
934 		}
935 		pks_fan = (envctrl_fantray_t *)ksp_fan->ks_data;
936 		if (i == 1)
937 			pcf8574_ks_fant1 = *pks_fan; /* fan 1 */
938 		else
939 			pcf8574_ks_fant2 = *pks_fan; /* fan 2 */
940 	} /* for */
941 	kstat_close(kc);
942 
943 }	/*  do_pcf8574_kstat(...) */
944 
945 void
do_pcf8591_kstat()946 do_pcf8591_kstat()
947 {
948 	kstat_ctl_t	*kc;
949 	kstat_t		*ksp_temp;
950 
951 	envctrl_temp_t *pks_temp;
952 
953 	if (!(kc = kstat_open())) {
954 #ifdef	DEBUG_TEMP
955 		log_printf("ks open for pcf8591 failed", 0);
956 #endif
957 		return;
958 	}
959 #ifdef	lint
960 	kc = kc;
961 #endif
962 	/* get kstat on adc driver's CPU temperature data */
963 	if ((ksp_temp = kstat_lookup(kc, I2C_PCF8591_NAME,
964 	    -1, I2C_KSTAT_CPUTEMP))
965 	    == NULL) {
966 #ifdef	DEBUG_TEMP
967 		log_printf("ks lookup for adc_temp failed", 0);
968 #endif
969 		return;
970 	}
971 	if (kstat_read(kc, ksp_temp, NULL) == -1) {
972 #ifdef	DEBUG_TEMP
973 		log_printf("ks read for adc_temp failed", 0);
974 #endif
975 		return;
976 	}
977 	pks_temp = (envctrl_temp_t *)ksp_temp->ks_data;
978 	pcf8591_ks_temp = *pks_temp;
979 	kstat_close(kc);
980 }	/*  do_pcf8591_kstat(.) */
981 
982 
983 void
gather_diaginfo(int flag)984 gather_diaginfo(int flag)
985 {
986 	if (flag) {
987 		/* gather system environmental conditions. */
988 		/* obtain kstat info from gpio & temp. driver */
989 		do_pcf8574_kstat();
990 		do_pcf8591_kstat();
991 		explore_slot_occupants();	/* fill in some occupant info */
992 		prtdiag_devinfo();
993 		analyze_pcipci_siblings(rootnode);
994 	}
995 
996 }	/* display_diaginfo(...) */
997 
998 void
netract_disp_prom_version()999 netract_disp_prom_version()
1000 {
1001 	/* Display Prom revision header */
1002 	log_printf(dgettext(TEXT_DOMAIN, "System Board PROM revision:\n"), 0);
1003 	log_printf("---------------------------\n", 0);
1004 	do_promversion();
1005 
1006 }	/* netract_disp_prom_version(.) */
1007 
1008 
1009 /*
1010  * Get and print the PROM version.
1011  */
1012 void
do_promversion(void)1013 do_promversion(void)
1014 {
1015 	Oppbuf  oppbuf;
1016 	struct openpromio *opp = &(oppbuf.opp);
1017 
1018 	if (mc_promopen(O_RDONLY))  {
1019 		log_printf(dgettext(TEXT_DOMAIN,
1020 		    "\nCannot open openprom device"), 0);
1021 		return;
1022 	}
1023 
1024 	opp->oprom_size = MAXVALSIZE;
1025 	if (ioctl(oprom_fd, OPROMGETVERSION, opp) < 0) {
1026 		perror("\nOPROMGETVERSION ioctl failed");
1027 		return;
1028 	}
1029 	log_printf("%s\n", opp->oprom_array, 0);
1030 
1031 	if (close(oprom_fd) < 0) {
1032 		log_printf(dgettext(TEXT_DOMAIN,
1033 		    "\nclose error on %s"), OPENPROMDEV, 0);
1034 		return;
1035 	}
1036 }	/* do_promversion() */
1037 
1038 int
mc_promopen(int oflag)1039 mc_promopen(int oflag)
1040 {
1041 	for (;;) {
1042 		if ((oprom_fd = open(OPENPROMDEV, oflag)) < 0) {
1043 			if (errno == EAGAIN) {
1044 				(void) sleep(5);
1045 				continue;
1046 			}
1047 			if (errno == ENXIO)
1048 				return (-1);
1049 			log_printf(dgettext(TEXT_DOMAIN,
1050 			    "\ncannot open %s"), OPENPROMDEV, 0);
1051 			return (1);
1052 		} else
1053 			return (0);
1054 	}
1055 }
1056 
1057 
1058 /*
1059  * This will return -1 for status unknown, 0 for OK, and 1 for failed (scsi
1060  * hard errors)
1061  * swiped from envmon policies
1062  */
1063 int
scsi_disk_status(int disk_number)1064 scsi_disk_status(int disk_number)
1065 {
1066 	kstat_ctl_t    *kc;
1067 	kstat_t		*ksp_disk;
1068 	kstat_named_t  *disk_data;
1069 
1070 	int i;
1071 	int nlist = 0;
1072 	cfga_list_data_t *list_array = NULL;
1073 	char *ap_ids[] = {"c0"};
1074 
1075 	if ((kc = kstat_open()) == NULL) {
1076 		log_printf(dgettext(TEXT_DOMAIN, "\nks open failed"), 0);
1077 		return (-1);
1078 	}
1079 
1080 	if (disk_number == RMM_NUMBER) { /* RMM */
1081 		if (config_list_ext(1, ap_ids, &list_array, &nlist,
1082 		    NULL, NULL, NULL, CFGA_FLAG_LIST_ALL) != CFGA_OK) {
1083 			kstat_close(kc);
1084 			return (-1);
1085 		}
1086 		for (i = 0; i < nlist; i++) {
1087 			if (strstr(list_array[i].ap_phys_id, "rmt/0") != NULL) {
1088 				/* Tape drive */
1089 				if (list_array[i].ap_o_state ==
1090 				    CFGA_STAT_UNCONFIGURED) {
1091 					kstat_close(kc);
1092 					return (-1);
1093 				}
1094 				if ((ksp_disk = kstat_lookup(kc, STERR,
1095 				    st_instance, NULL)) == NULL) {
1096 					kstat_close(kc);
1097 					return (-1);
1098 				}
1099 				break;
1100 			} else if (strstr(list_array[i].ap_phys_id,
1101 			    "dsk/c0t6d0") != NULL) {
1102 				/* CD_ROM */
1103 				if (list_array[i].ap_o_state ==
1104 				    CFGA_STAT_UNCONFIGURED) {
1105 					kstat_close(kc);
1106 					return (-1);
1107 				}
1108 				if ((ksp_disk = kstat_lookup(kc, SDERR,
1109 				    sd_instances[disk_number-1], NULL)) ==
1110 				    NULL) {
1111 					kstat_close(kc);
1112 					return (-1);
1113 				}
1114 				break;
1115 			}
1116 		}
1117 	} else { /* Hard disk */
1118 		if ((ksp_disk = kstat_lookup(kc, SDERR,
1119 		    sd_instances[disk_number-1], NULL)) == NULL) {
1120 			kstat_close(kc);
1121 			return (-1);
1122 		}
1123 	}
1124 
1125 	if (kstat_read(kc, ksp_disk, NULL) == -1) {
1126 		log_printf(dgettext(TEXT_DOMAIN,
1127 		    "\nks read error for disk%d, drv inst%d"),
1128 		    disk_number, sd_instances[disk_number-1], 0);
1129 		kstat_close(kc);
1130 		return (-1);
1131 	}
1132 	disk_data = KSTAT_NAMED_PTR(ksp_disk);
1133 	/*
1134 	 * if disk_data[].value is >0, we have a problem
1135 	 */
1136 	if (disk_data[1].value.ui32 == 0) {
1137 		kstat_close(kc);
1138 		return (0);
1139 	} else {
1140 		kstat_close(kc);
1141 		return (1);
1142 	}
1143 }
1144 
1145 
1146 void
prtdiag_devinfo(void)1147 prtdiag_devinfo(void)
1148 {
1149 	uint_t flag;
1150 	/* lets get everything we can from kernel */
1151 	flag = DINFOSUBTREE|DINFOPROP;
1152 	rootnode = di_init("/", flag);
1153 	if (rootnode == DI_NODE_NIL) {
1154 		log_printf(dgettext(TEXT_DOMAIN,
1155 		    "\nprtdiag_devinfo: di_init() failed"), 0);
1156 		return;
1157 	}
1158 	(void) di_walk_node(rootnode, DI_WALK_CLDFIRST, NULL,
1159 	    dump_devs);
1160 }
1161 
1162 
1163 /*
1164  * gather information about this node, returns appropriate code.
1165  * specific information we seek are driver names, instances
1166  * we will initialize some globals depending on what we find
1167  * from the kernel device tree info and may be private data
1168  * if required
1169  */
1170 /*ARGSUSED1*/
1171 int
dump_devs(di_node_t node,void * arg)1172 dump_devs(di_node_t node, void *arg)
1173 {
1174 	char *driver_name;
1175 
1176 	driver_name = di_driver_name(node);
1177 	/* we will initialize our globals here */
1178 	if ((di_instance(node) >= 0) &&
1179 	    (driver_name != NULL) &&
1180 	    (!(di_state(node) & DI_DRIVER_DETACHED))) {
1181 		if (strcmp(driver_name, "pcf8574") == 0) {
1182 			gpio_instances[gpio_count] = di_instance(node);
1183 			gpio_count++;
1184 		} else if (strcmp(driver_name, "sd") == 0) {
1185 			sd_instances[sd_count] =  di_instance(node);
1186 			sd_count++;
1187 		} else if (strcmp(driver_name, "st") == 0) {
1188 			st_instance = di_instance(node);
1189 		}
1190 	}
1191 
1192 	if (strcmp(di_node_name(node), "pseudo") == 0)
1193 		return (DI_WALK_PRUNECHILD);
1194 	else
1195 		return (DI_WALK_CONTINUE);
1196 }
1197 
1198 
1199 
1200 /*
1201  * Returns 0 if error , 1 otherwise
1202  */
1203 int
dump_prop_list(char * name,di_node_t node,di_prop_t (* nxtprop)())1204 dump_prop_list(char *name, di_node_t node, di_prop_t (*nxtprop)())
1205 {
1206 	int prop_len, i, k, max_slots_minus_cpu, n;
1207 	uchar_t *prop_data;
1208 	char	*p;
1209 	char   *temp_s;
1210 	di_prop_t prop, next;
1211 	int ret_value = 0;
1212 
1213 	max_slots_minus_cpu = scsb_ks_topo.max_units[SLOT]-1;
1214 
1215 	if ((next = nxtprop(node, DI_PROP_NIL)) == DI_PROP_NIL)
1216 		return (0);
1217 	while (next != DI_PROP_NIL) {
1218 		int maybe_str = 1, npossible_strs = 0;
1219 		prop = next;
1220 		next = nxtprop(node, prop);
1221 		/*
1222 		 * get prop length and value:
1223 		 * private interface--always success
1224 		 */
1225 		prop_len = di_prop_rawdata(prop, &prop_data);
1226 		if (di_prop_type(prop) == DDI_PROP_UNDEF_IT) {
1227 			continue;
1228 		}
1229 
1230 		if (prop_len == 0)  {
1231 			continue;
1232 		}
1233 		if (prop_data[prop_len - 1] != '\0') {
1234 			maybe_str = 0;
1235 		} else {
1236 			/*
1237 			 * Every character must be a string character or a \0,
1238 			 * and there must not be two \0's in a row.
1239 			 */
1240 			for (i = 0; i < prop_len; i++) {
1241 				if (prop_data[i] == '\0') {
1242 					npossible_strs++;
1243 				} else if (!isascii(prop_data[i]) ||
1244 				    iscntrl(prop_data[i])) {
1245 					maybe_str = 0;
1246 					break;
1247 				}
1248 
1249 				if ((i > 0) && (prop_data[i] == '\0') &&
1250 				    (prop_data[i - 1] == '\0')) {
1251 					maybe_str = 0;
1252 					break;
1253 				}
1254 			}
1255 		}
1256 
1257 		if (maybe_str) {
1258 			p = (char *)prop_data;
1259 			for (i = 0; i < npossible_strs - 1; i++) {
1260 				if ((strcmp(name, SYSSOFT_PROP) == 0) &&
1261 				    (strcmp(di_prop_name(prop),
1262 				    HSC_PROP_NAME) == 0)) {
1263 					temp_s = p;
1264 					temp_s += strlen(temp_s) + 1;
1265 				}
1266 				p += strlen(p) + 1;
1267 			}
1268 
1269 			if ((strcmp(name, SYSSOFT_PROP) == 0) &&
1270 			    (strcmp(di_prop_name(prop), HSC_PROP_NAME) == 0)) {
1271 				temp_s = temp_s - prop_len+2;
1272 				for (k = 0, n = 0; k < prop_len; k++) {
1273 					if (temp_s[k] == 0) {
1274 						n++;
1275 					}
1276 				}
1277 				if (n % 4) {
1278 					log_printf(dgettext(TEXT_DOMAIN,
1279 					    "\nbad slot-table(%d)\n"), n);
1280 					slot_table_not_found = 0;
1281 					return (ret_value);
1282 				}
1283 				slot_table_size = n / 4;
1284 				/*
1285 				 * NOTE : We save slot table info in order
1286 				 */
1287 				for (k = 0; k < slot_table_size; k++) {
1288 					char *nexus, *pcidev, *phys_slotname;
1289 					char *ga;
1290 					/*
1291 					 * Pick off pointer to nexus
1292 					 * path or PROM handle
1293 					 */
1294 					nexus = temp_s;
1295 					while (*temp_s != NULL)
1296 						temp_s++;
1297 					temp_s++;
1298 
1299 					/*
1300 					 * Pick off pointer to the
1301 					 * pci device number
1302 					 */
1303 					pcidev = temp_s;
1304 					while (*temp_s != NULL)
1305 						temp_s++;
1306 					temp_s++;
1307 
1308 					/* Pick off physical slot no */
1309 					phys_slotname = temp_s;
1310 					while (*temp_s != NULL)
1311 						temp_s++;
1312 					temp_s++;
1313 
1314 					/*
1315 					 * Pick off GA bits which
1316 					 * we dont use for now.
1317 					 */
1318 					ga = temp_s;
1319 					while (*temp_s != NULL)
1320 						temp_s++;
1321 					temp_s++;
1322 
1323 					hotswap_slot_table[k].pslotnum
1324 					    = atoi(phys_slotname);
1325 					hotswap_slot_table[k].ga = atoi(ga);
1326 					hotswap_slot_table[k].pci_devno
1327 					    = atoi(pcidev);
1328 					strcpy(hotswap_slot_table[k].nexus,
1329 					    nexus);
1330 				} /* for (k = 0; k < slot_table_size; k++) */
1331 
1332 				ret_value = 1;
1333 			} else /* (strcmp(name, SYSSOFT_PROP) */
1334 				slot_table_not_found = 1;
1335 
1336 			/*
1337 			 * now we want to save off the info
1338 			 * we would use later
1339 			 */
1340 			if ((strcmp(name, DRV_PROP) == 0) &&
1341 			    (strcmp(di_prop_name(prop), HSC_MODE) == 0)) {
1342 				hotswap_mode = p;
1343 				ret_value = 1;
1344 			} else if ((strcmp(name, DRV_PROP) == 0) &&
1345 			    (strcmp(di_prop_name(prop), HSC_MODE) != 0)) {
1346 				/* save it in order in the right index */
1347 				slot_auto_config[max_slots_minus_cpu] = p;
1348 				max_slots_minus_cpu--;
1349 				ret_value = 1;
1350 			}
1351 
1352 		} else {
1353 			for (i = 0; i < prop_len; ++i)  {
1354 #if	0
1355 				unsigned char byte;
1356 				byte = (unsigned char)prop_data[i];
1357 				log_printf("%2.2x", byte, 0);
1358 #endif
1359 			}
1360 		}
1361 	}
1362 	return (ret_value);
1363 }
1364 
1365 
1366 void
display_mc_prtdiag_info()1367 display_mc_prtdiag_info()
1368 {
1369 	int i, index;
1370 	int s_index, i1;
1371 	int tg_cpu_index = 0;
1372 	char *mcfru_type, *status, *mc_ok_led, *mc_nok_led;
1373 	char *misc_info, *health, *board_type;
1374 
1375 	log_printf("===============================", 0);
1376 	log_printf(dgettext(TEXT_DOMAIN,
1377 	    " FRU Information ================================\n"), 0);
1378 	log_printf(dgettext(TEXT_DOMAIN,
1379 	    "FRU         FRU    FRU      Green    Amber"), 0);
1380 	log_printf(dgettext(TEXT_DOMAIN, "    Miscellaneous\n"), 0);
1381 	log_printf(dgettext(TEXT_DOMAIN,
1382 	    "Type        Unit#  Present  LED      LED"), 0);
1383 	log_printf(dgettext(TEXT_DOMAIN, "      Information\n"), 0);
1384 
1385 	log_printf("----------  -----  -------  -----    -----", 0);
1386 	log_printf("    ----------------------------------\n", 0);
1387 
1388 	if (scsb_ks_topo.mid_plane.fru_id == SCTRL_MPID_HALF)
1389 		misc_info = "Netra ct800";
1390 	else {
1391 		misc_info = "Netra ct400";
1392 	}
1393 	mcfru_type = prtdiag_fru_types[MIDPLANE];
1394 	switch (scsb_ks_topo.mid_plane.fru_status) {
1395 		case FRU_PRESENT:
1396 			status = YES;
1397 			break;
1398 		case FRU_NOT_PRESENT:
1399 			status = NO;
1400 			break;
1401 		case FRU_NOT_AVAILABLE:
1402 			status = NA; break;
1403 		default:
1404 			status = NA; break;
1405 		}
1406 	mc_ok_led = "   ";
1407 	mc_nok_led = "   ";
1408 
1409 	log_printf(dgettext(TEXT_DOMAIN,
1410 	    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1411 	    mcfru_type, scsb_ks_topo.mid_plane.fru_unit,
1412 	    status, mc_ok_led, mc_nok_led,
1413 	    misc_info, 0);
1414 	log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
1415 	log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
1416 	    scsb_ks_topo.mid_plane.fru_version, 0);
1417 	log_printf(dgettext(TEXT_DOMAIN, "%49sMaximum Slots=%d\n"), BLANK,
1418 	    scsb_ks_topo.max_units[SLOT], 0);
1419 
1420 	/* SCB & SSB */
1421 	mcfru_type = prtdiag_fru_types[SCB];
1422 	for (i = 0; i < scsb_ks_topo.max_units[SCB]; ++i) {
1423 		misc_info = "System Controller Board";
1424 		if (version_p15_and_p20) {
1425 			mc_ok_led =
1426 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
1427 			    & 0xff), SCB_OK_BIT) ? BLINK :
1428 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
1429 			    & 0xff), SCB_OK_BIT) ? ON:OFF);
1430 			mc_nok_led =
1431 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
1432 			    & 0xff), SCB_OK_BIT) ? ON:OFF;
1433 		} else {
1434 			/*
1435 			 * support for 1.0 systems -
1436 			 * Hack! - should use tables ?
1437 			 */
1438 			mc_ok_led =
1439 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
1440 			    & 0xff), 0) ? ON:OFF);
1441 			mc_nok_led =
1442 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
1443 			    & 0xff), 0) ? ON:OFF;
1444 		}
1445 		switch (scsb_ks_topo.mct_scb[i].fru_status) {
1446 			case FRU_PRESENT:
1447 				status = YES;
1448 				break;
1449 			case FRU_NOT_PRESENT:
1450 				status = NO;
1451 				break;
1452 			case FRU_NOT_AVAILABLE:
1453 				status = NA;
1454 				break;
1455 			default:
1456 				status = NA;
1457 				break;
1458 		}
1459 		log_printf(dgettext(TEXT_DOMAIN,
1460 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1461 		    mcfru_type, scsb_ks_topo.mct_scb[i].fru_unit,
1462 		    status, mc_ok_led, mc_nok_led, misc_info, 0);
1463 		log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
1464 		log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
1465 		    scsb_ks_topo.mct_scb[0].fru_version, 0);
1466 		if (fail_drv_prop == 1)
1467 			log_printf(dgettext(TEXT_DOMAIN,
1468 			    "%49s%s=%s\n"), BLANK, HSC_MODE,
1469 			    hotswap_mode, 0);
1470 	} /* for */
1471 
1472 	mcfru_type = prtdiag_fru_types[SSB];
1473 	for (i = 0; i < scsb_ks_topo.max_units[SSB]; ++i) {
1474 		misc_info = "System Status Panel";
1475 		switch (scsb_ks_topo.mct_ssb[i].fru_status) {
1476 			case FRU_PRESENT:
1477 				status = YES;
1478 				break;
1479 			case FRU_NOT_PRESENT:
1480 				status = NO;
1481 				break;
1482 			case FRU_NOT_AVAILABLE:
1483 				status = NA;
1484 				break;
1485 			default:
1486 				status = NA;
1487 				break;
1488 		}
1489 		log_printf(dgettext(TEXT_DOMAIN,
1490 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1491 		    mcfru_type, scsb_ks_topo.mct_ssb[i].fru_unit,
1492 		    status, BLANK, BLANK, misc_info, 0);
1493 	} /* for */
1494 
1495 	/* Slots */
1496 	for (i = 0; i < scsb_ks_topo.max_units[SLOT]; ++i) {
1497 		if (montecarlo) {
1498 			if (scsb_ks_topo.mct_slots[i].fru_unit == 1)
1499 				mcfru_type = prtdiag_fru_types[1];
1500 			else
1501 				mcfru_type = prtdiag_fru_types[SLOT];
1502 			/*
1503 			 * Another way this could have been done is,
1504 			 * to read the sub system id
1505 			 * it is 0x6722 for Alarm Card
1506 			 * but this id is only valid for the new ACs
1507 			 * older ACs still have the same susbsystem
1508 			 * id as most other Sun PCI cards
1509 			 * We cannot completely rely on this.
1510 			 * Also,it turns out that Sun OpenBoot does not
1511 			 * always follow IEEE 1275 std, hence in a few
1512 			 * systems, the "subsystem-id" published by the
1513 			 * PROM could not be found
1514 			 * We know the AC slot# if present on both MC&Tg
1515 			 * Hence we check on both - now we are sure
1516 			 * that we have found an AC
1517 			 */
1518 			if ((scsb_ks_topo.mct_slots[i].fru_unit == 8) &&
1519 			    (alarm_card_present == 1))
1520 				board_type = AC_CARD;
1521 			else
1522 				board_type = UK;
1523 		} else {
1524 			if (scsb_ks_topo.mct_slots[i].fru_unit == 3)
1525 				mcfru_type = prtdiag_fru_types[1];
1526 			else
1527 				mcfru_type = prtdiag_fru_types[SLOT];
1528 			/*
1529 			 * Another way this could have been done is,
1530 			 * to read the sub system id
1531 			 * it is 0x6722 for Alarm Card
1532 			 * but this id is only valid for the new ACs
1533 			 * older ACs still have the same susbsystem
1534 			 * id as most other Sun PCI cards
1535 			 * We cannot completely rely on this.
1536 			 * Also,it turns out that Sun OpenBoot does not
1537 			 * always follow IEEE 1275 std, hence in a few
1538 			 * systems, the "subsystem-id" published by the
1539 			 * PROM could not be found
1540 			 * We know the AC slot# if present on both MC&Tg
1541 			 * Hence we check on both - now we are sure
1542 			 * that we have found an AC
1543 			 */
1544 			if ((scsb_ks_topo.mct_slots[i].fru_unit == 1) &&
1545 			    (alarm_card_present == 1))
1546 				board_type = AC_CARD;
1547 			else
1548 				board_type = UK;
1549 		}
1550 		if (version_p15_and_p20) {
1551 			mc_ok_led =
1552 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[0]
1553 			    & 0xff), i) ? BLINK :
1554 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[0]
1555 			    & 0xff), i) ? ON:OFF);
1556 			mc_nok_led =
1557 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[0]
1558 			    & 0xff), i) ? ON:OFF;
1559 		} else {
1560 			/*
1561 			 * support for 1.0 systems -
1562 			 * Hack! - should use tables ?
1563 			 */
1564 			if (scsb_ks_topo.mct_slots[i].fru_unit == 7) {
1565 				mc_ok_led =
1566 				    BIT_TEST(
1567 				    (scsb_ks_leddata.leds.p10.blink_leds[1]
1568 				    & 0xff), 0) ? BLINK :
1569 				    (BIT_TEST(
1570 				    (scsb_ks_leddata.leds.p10.ok_leds[1]
1571 				    & 0xff), 0) ? ON:OFF);
1572 				mc_nok_led =
1573 				    BIT_TEST(
1574 				    (scsb_ks_leddata.leds.p10.nok_leds[1]
1575 				    & 0xff), 0) ? ON:OFF;
1576 			} else  if (scsb_ks_topo.mct_slots[i].fru_unit == 8) {
1577 				mc_ok_led =
1578 				    BIT_TEST(
1579 				    (scsb_ks_leddata.leds.p10.blink_leds[1]
1580 				    & 0xff), 1) ? BLINK :
1581 				    (BIT_TEST(
1582 				    (scsb_ks_leddata.leds.p10.ok_leds[1]
1583 				    & 0xff), 1) ? ON:OFF);
1584 				mc_nok_led =
1585 				    BIT_TEST(
1586 				    (scsb_ks_leddata.leds.p10.nok_leds[1]
1587 				    & 0xff), 1) ? ON:OFF;
1588 			} else {
1589 				/*
1590 				 * for all other slots offset,
1591 				 * index are the same
1592 				 */
1593 				mc_ok_led =
1594 				    BIT_TEST(
1595 				    (scsb_ks_leddata.leds.p10.blink_leds[0]
1596 				    & 0xff), i) ? BLINK :
1597 				    (BIT_TEST(
1598 				    (scsb_ks_leddata.leds.p10.ok_leds[0]
1599 				    & 0xff), i) ? ON:OFF);
1600 				mc_nok_led =
1601 				    BIT_TEST(
1602 				    (scsb_ks_leddata.leds.p10.nok_leds[0]
1603 				    & 0xff), i) ? ON:OFF;
1604 			}
1605 
1606 		} /* else if (!version_p15_and_p20) */
1607 
1608 		switch (scsb_ks_topo.mct_slots[i].fru_status) {
1609 			case FRU_PRESENT:
1610 				status = YES;
1611 				break;
1612 			case FRU_NOT_PRESENT:
1613 				status = NO;
1614 				break;
1615 			case FRU_NOT_AVAILABLE:
1616 				status = NA;
1617 				break;
1618 			default:
1619 				status = NA;
1620 				break;
1621 		}
1622 
1623 		index = (int)scsb_ks_topo.mct_slots[i].fru_type;
1624 		if (montecarlo) {
1625 			if (scsb_ks_topo.mct_slots[i].fru_unit == 1) {
1626 				/* cpu slot */
1627 				log_printf(dgettext(TEXT_DOMAIN,
1628 				    "%10s   %-5d  %-7s %-5s    "),
1629 				    mcfru_type,
1630 				    scsb_ks_topo.mct_slots[i].fru_unit,
1631 				    status, mc_ok_led, mc_nok_led, 0);
1632 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1633 				    mc_nok_led,
1634 				    slot_occupants[index], 0);
1635 				log_printf(dgettext(TEXT_DOMAIN,
1636 				    "%49stemperature(celsius):%d\n"),
1637 				    BLANK,
1638 				    pcf8591_ks_temp.value, 0);
1639 #ifdef	NEVER
1640 				log_printf(dgettext(TEXT_DOMAIN,
1641 				    "%49sminimum temperature:%d\n"),
1642 				    BLANK,
1643 				    pcf8591_ks_temp.min, 0);
1644 				log_printf(dgettext(TEXT_DOMAIN,
1645 				    "%49swarning temp. threshold:%d\n"),
1646 				    BLANK,
1647 				    pcf8591_ks_temp.warning_threshold, 0);
1648 				log_printf(dgettext(TEXT_DOMAIN,
1649 				    "%49sshutdown temp.threshold:%d\n"),
1650 				    BLANK,
1651 				    pcf8591_ks_temp.shutdown_threshold, 0);
1652 #endif	/* NEVER */
1653 			} else if ((scsb_ks_topo.mct_slots[i].fru_unit == 2) &&
1654 			    (cpu_ftm_present == 1)) {
1655 				/* CFTM slot */
1656 				/*
1657 				 * The CFTM can only be present in Slot 2
1658 				 * for Netract-800, for Netract-400 the FTM
1659 				 * is not sitted in a Slot. Hence, this is
1660 				 * another special case and we need to handle
1661 				 * this differently than other slots
1662 				 */
1663 				log_printf(dgettext(TEXT_DOMAIN,
1664 				    "%10s   %-5d  %-7s %-5s    "),
1665 				    mcfru_type,
1666 				    scsb_ks_topo.mct_slots[i].fru_unit,
1667 				    status, mc_ok_led, mc_nok_led, 0);
1668 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1669 				    mc_nok_led,
1670 				    CPU_FTM, 0);
1671 			} else {
1672 				if (fail_drv_prop == 1) {
1673 					log_printf(dgettext(TEXT_DOMAIN,
1674 					    "%10s   %-5d  %-7s %-5s    "),
1675 					    mcfru_type,
1676 					    scsb_ks_topo.mct_slots[i].fru_unit,
1677 					    status, mc_ok_led, 0);
1678 					log_printf(dgettext(TEXT_DOMAIN,
1679 					    "%-5s   %s\n"),
1680 					    mc_nok_led,
1681 					    slot_occupants[index], 0);
1682 					log_printf(dgettext(TEXT_DOMAIN,
1683 					    "%46s%s\n"), BLANK,
1684 					    PROPS, 0);
1685 					log_printf(dgettext(TEXT_DOMAIN,
1686 					    "%49sauto-config=%s\n"),
1687 					    BLANK,
1688 					    slot_auto_config[i], 0);
1689 				} else {
1690 				log_printf(dgettext(TEXT_DOMAIN,
1691 				    "%10s   %-5d  %-7s %-5s    "),
1692 				    mcfru_type,
1693 				    scsb_ks_topo.mct_slots[i].fru_unit,
1694 				    status, mc_ok_led, 0);
1695 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1696 				    mc_nok_led,
1697 				    slot_occupants[index], 0);
1698 				}
1699 			}
1700 		} else { /* tonga */
1701 			if (scsb_ks_topo.mct_slots[i].fru_unit == 3) {
1702 				/* cpu slot */
1703 				log_printf(dgettext(TEXT_DOMAIN,
1704 				    "%10s   %-5d  %-7s %-5s    "),
1705 				    mcfru_type,
1706 				    scsb_ks_topo.mct_slots[i].fru_unit,
1707 				    status, mc_ok_led, 0);
1708 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1709 				    mc_nok_led,
1710 				    slot_occupants[index], 0);
1711 				log_printf(dgettext(TEXT_DOMAIN,
1712 				    "%49stemperature(celsius):%d\n"),
1713 				    BLANK,
1714 				    pcf8591_ks_temp.value, 0);
1715 #ifdef	NEVER
1716 
1717 				log_printf(dgettext(TEXT_DOMAIN,
1718 				    "%49sminimum temperature:%d\n"),
1719 				    BLANK,
1720 				    pcf8591_ks_temp.min, 0);
1721 				log_printf(dgettext(TEXT_DOMAIN,
1722 				    "%49swarning temp. threshold:%d\n"),
1723 				    BLANK,
1724 				    pcf8591_ks_temp.warning_threshold, 0);
1725 				log_printf(dgettext(TEXT_DOMAIN,
1726 				    "%49sshutdown temp. threshold:%d\n"),
1727 				    BLANK,
1728 				    pcf8591_ks_temp.shutdown_threshold, 0);
1729 #endif	/* NEVER */
1730 			} else {
1731 				if (fail_drv_prop == 1) {
1732 					log_printf(dgettext(TEXT_DOMAIN,
1733 					    "%10s   %-5d  %-7s %-5s    "),
1734 					    mcfru_type,
1735 					    scsb_ks_topo.mct_slots[i].fru_unit,
1736 					    status, mc_ok_led, 0);
1737 					log_printf(dgettext(TEXT_DOMAIN,
1738 					    "%-5s   %s\n"),
1739 					    mc_nok_led,
1740 					    slot_occupants[index], 0);
1741 
1742 					log_printf(dgettext(TEXT_DOMAIN,
1743 					    "%46s%s\n"), BLANK, PROPS, 0);
1744 					log_printf(dgettext(TEXT_DOMAIN,
1745 					    "%49sauto-config=%s\n"),
1746 					    BLANK,
1747 					    slot_auto_config[tg_cpu_index+1],
1748 					    0);
1749 					if (scsb_ks_topo.mct_slots[i].fru_unit
1750 					    != 3)
1751 						tg_cpu_index++;
1752 				} else {
1753 				log_printf(dgettext(TEXT_DOMAIN,
1754 				    "%10s   %-5d  %-7s %-5s    "),
1755 				    mcfru_type,
1756 				    scsb_ks_topo.mct_slots[i].fru_unit,
1757 				    status, mc_ok_led, 0);
1758 				log_printf(dgettext(TEXT_DOMAIN, "%-5s   %s\n"),
1759 				    mc_nok_led,
1760 				    slot_occupants[index], 0);
1761 				}
1762 			}
1763 		}
1764 		/* we first match the correct slot numbers */
1765 		for (s_index = 0; s_index < slot_table_size; s_index++) {
1766 			if (slot_table_not_found == 1) {
1767 			/* use prom table */
1768 			if (scsb_ks_topo.mct_slots[i].fru_unit ==
1769 			    prom_slot_table[s_index].pslotnum) {
1770 				/*
1771 				 * search for the addr/pci num
1772 				 * in all slot info structs
1773 				 */
1774 				for (i1 = 0; i1 < slot_index;
1775 				    i1++) {
1776 			if (prom_slot_table[s_index].pci_devno ==
1777 			    mc_slots_data.mc_slot_info[i1].slot_addr) {
1778 					int nd;
1779 					log_printf(dgettext(TEXT_DOMAIN,
1780 					    "%46s%s%s\n"), BLANK,
1781 					    BOARDTYPE, board_type, 0);
1782 					log_printf(dgettext(TEXT_DOMAIN,
1783 					    "%46s%s\n"), BLANK, DEVS, 0);
1784 					log_printf(dgettext(TEXT_DOMAIN,
1785 					    "%49s%s\n"), BLANK,
1786 					    PCI_ROOT_AP, 0);
1787 			for (nd = 0;
1788 			    nd < mc_slots_data.mc_slot_info[i1].number_devs;
1789 			    nd++) {
1790 			log_printf(dgettext(TEXT_DOMAIN, "%52s%s\n"), BLANK,
1791 			    mc_slots_data.mc_slot_info[i1].devs_info[nd],
1792 			    0);
1793 						} /* for */
1794 
1795 					} /* if */
1796 
1797 				} /* for(i1) */
1798 
1799 			} /* if */
1800 
1801 		} else {
1802 			/* use solaris lot table */
1803 			if (fail_syssoft_prop == 1) {
1804 				if (scsb_ks_topo.mct_slots[i].fru_unit ==
1805 				    hotswap_slot_table[s_index].pslotnum) {
1806 					/*
1807 					 * search for the addr/pci
1808 					 * num in all slot info structs
1809 					 */
1810 					for (i1 = 0; i1 < slot_index; i1++) {
1811 				if (hotswap_slot_table[s_index].pci_devno ==
1812 				    mc_slots_data.mc_slot_info[i1].slot_addr) {
1813 					int nd;
1814 			for (nd = 0;
1815 			    nd < mc_slots_data.mc_slot_info[i1].number_devs;
1816 			    nd++) {
1817 			log_printf(dgettext(TEXT_DOMAIN, "%49s%s\n"), BLANK,
1818 			    mc_slots_data.mc_slot_info[i1].devs_info[nd],
1819 			    0);
1820 							}
1821 						} /* if */
1822 
1823 					} /* for(i1) */
1824 
1825 				} /* if */
1826 
1827 			} /* (fail_syssoft_prop == 1) */
1828 
1829 			}  /* (slot_table_not_found == 1) */
1830 
1831 		} /* for(s_index) */
1832 
1833 	}	/* for */
1834 	mcfru_type = "PDU";
1835 	misc_info = "Power Distribution Unit";
1836 	for (i = 0; i < scsb_ks_topo.max_units[PDU]; ++i) {
1837 		if (version_p15_and_p20) {
1838 			mc_ok_led =
1839 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
1840 			    & 0xff), PDU1_OK_BIT+i*2) ? BLINK :
1841 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
1842 			    & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF);
1843 			mc_nok_led =
1844 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
1845 			    & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF;
1846 		}
1847 		switch (scsb_ks_topo.mct_pdu[i].fru_status) {
1848 			case FRU_PRESENT:
1849 				status = YES;
1850 				break;
1851 			case FRU_NOT_PRESENT:
1852 				status = NO;
1853 				break;
1854 			case FRU_NOT_AVAILABLE:
1855 				status = NA;
1856 				break;
1857 			default:
1858 				status = NA;
1859 				break;
1860 		}
1861 		if (version_p15_and_p20) {
1862 			log_printf(dgettext(TEXT_DOMAIN,
1863 			    "%-10s    %-5d  %-7s %-5s    %-5s   %s\n"),
1864 			    mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
1865 			    status, mc_ok_led, mc_nok_led, misc_info, 0);
1866 		} else {
1867 			log_printf(dgettext(TEXT_DOMAIN,
1868 			    "%-10s    %-5d  %-7s%18s%s\n"),
1869 			    mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
1870 			    status, BLANK, misc_info, 0);
1871 		}
1872 	} /* for */
1873 
1874 	/* PS */
1875 	mcfru_type = prtdiag_fru_types[PS];
1876 	misc_info = "Power Supply Unit";
1877 	for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
1878 		if (version_p15_and_p20) {
1879 			mc_ok_led =
1880 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
1881 			    & 0xff), PS1_OK_BIT+i) ? BLINK :
1882 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
1883 			    & 0xff), PS1_OK_BIT+i) ? ON:OFF);
1884 			mc_nok_led =
1885 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
1886 			    & 0xff), PS1_OK_BIT+i) ? ON:OFF;
1887 		} else {
1888 			/*
1889 			 * support for 1.0 systems -
1890 			 * Hack! - should use tables ?
1891 			 */
1892 			mc_ok_led =
1893 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
1894 			    & 0xff), 1+i) ? ON:OFF);
1895 			mc_nok_led =
1896 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
1897 			    & 0xff), 1+i) ? ON:OFF;
1898 		}
1899 		switch (scsb_ks_topo.mct_ps[i].fru_status) {
1900 			case FRU_PRESENT:
1901 				status = YES;
1902 				break;
1903 			case FRU_NOT_PRESENT:
1904 				status = NO;
1905 				break;
1906 			case FRU_NOT_AVAILABLE:
1907 				status = NA;
1908 				break;
1909 			default:
1910 				status = NA;
1911 				break;
1912 		}
1913 		log_printf(dgettext(TEXT_DOMAIN,
1914 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1915 		    mcfru_type, scsb_ks_topo.mct_ps[i].fru_unit,
1916 		    status, mc_ok_led, mc_nok_led,
1917 		    misc_info, 0);
1918 		if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
1919 			if (scsb_ks_topo.mct_ps[i].fru_unit == 1) {
1920 				log_printf(dgettext(TEXT_DOMAIN,
1921 				    "%49scondition:%s\n"), BLANK,
1922 				    ((pcf8574_ks_ps1.ps_ok)? NOK:OK), 0);
1923 				log_printf(dgettext(TEXT_DOMAIN,
1924 				    "%49stemperature:%s\n"), BLANK,
1925 				    ((pcf8574_ks_ps1.temp_ok)? NOK:OK), 0);
1926 				log_printf(dgettext(TEXT_DOMAIN,
1927 				    "%49sps fan:%s\n"), BLANK,
1928 				    ((pcf8574_ks_ps1.psfan_ok)? NOK:OK), 0);
1929 				log_printf(dgettext(TEXT_DOMAIN,
1930 				    "%49ssupply:%s\n"), BLANK,
1931 				    ((pcf8574_ks_ps1.on_state)? OFF:ON), 0);
1932 			} else {
1933 				log_printf(dgettext(TEXT_DOMAIN,
1934 				    "%49scondition:%s\n"), BLANK,
1935 				    ((pcf8574_ks_ps2.ps_ok)? NOK:OK), 0);
1936 				log_printf(dgettext(TEXT_DOMAIN,
1937 				    "%49stemperature:%s\n"), BLANK,
1938 				    ((pcf8574_ks_ps2.temp_ok)? NOK:OK), 0);
1939 				log_printf(dgettext(TEXT_DOMAIN,
1940 				    "%49sps fan:%s\n"), BLANK,
1941 				    ((pcf8574_ks_ps2.psfan_ok)? NOK:OK), 0);
1942 				log_printf(dgettext(TEXT_DOMAIN,
1943 				    "%49ssupply:%s\n"), BLANK,
1944 				    ((pcf8574_ks_ps2.on_state)? OFF:ON), 0);
1945 			} /* if */
1946 		}
1947 
1948 	} /* for */
1949 
1950 	/* Fan tray */
1951 	mcfru_type = prtdiag_fru_types[FAN];
1952 	misc_info = "Fan Tray";
1953 	for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
1954 		if (version_p15_and_p20) {
1955 			mc_ok_led =
1956 			    BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
1957 			    & 0xff), FAN1_OK_BIT+i) ? BLINK :
1958 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
1959 			    & 0xff), FAN1_OK_BIT+i) ? ON:OFF);
1960 			mc_nok_led =
1961 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
1962 			    & 0xff), FAN1_OK_BIT+i) ? ON:OFF;
1963 		} else {
1964 			/*
1965 			 * support for 1.0 systems -
1966 			 * Hack! - should use tables ?
1967 			 */
1968 			mc_ok_led =
1969 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[3]
1970 			    & 0xff), 3+i) ? ON:OFF);
1971 			mc_nok_led =
1972 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[3]
1973 			    & 0xff), 3+i) ? ON:OFF;
1974 		}
1975 		switch (scsb_ks_topo.mct_fan[i].fru_status) {
1976 			case FRU_PRESENT:
1977 				status = YES;
1978 				break;
1979 			case FRU_NOT_PRESENT:
1980 				status = NO;
1981 				break;
1982 			case FRU_NOT_AVAILABLE:
1983 				status = NA;
1984 				break;
1985 			default:
1986 				status = NA;
1987 				break;
1988 		}
1989 		log_printf(dgettext(TEXT_DOMAIN,
1990 		    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
1991 		    mcfru_type, scsb_ks_topo.mct_fan[i].fru_unit,
1992 		    status, mc_ok_led, mc_nok_led,
1993 		    misc_info, 0);
1994 		if (scsb_ks_topo.mct_fan[i].fru_status == FRU_PRESENT) {
1995 			if (scsb_ks_topo.mct_fan[i].fru_unit == 1) {
1996 				log_printf(dgettext(TEXT_DOMAIN,
1997 				    "%49scondition:%s\n"), BLANK,
1998 				    ((pcf8574_ks_fant1.fan_ok)? OK:NOK), 0);
1999 				log_printf(dgettext(TEXT_DOMAIN,
2000 				    "%49sfan speed:%s\n"), BLANK,
2001 				    ((pcf8574_ks_fant1.fanspeed)? HI:LO), 0);
2002 			} else {
2003 				log_printf(dgettext(TEXT_DOMAIN,
2004 				    "%49scondition:%s\n"), BLANK,
2005 				    ((pcf8574_ks_fant2.fan_ok)? OK:NOK), 0);
2006 				log_printf(dgettext(TEXT_DOMAIN,
2007 				    "%49sfan speed:%s\n"), BLANK,
2008 				    ((pcf8574_ks_fant2.fanspeed)? HI:LO), 0);
2009 			}
2010 		}
2011 
2012 	} /* for */
2013 
2014 	/* DISKS */
2015 	for (i = 0; i < scsb_ks_topo.max_units[DISK]; ++i) {
2016 		if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER)
2017 			mcfru_type = prtdiag_fru_types[DISK];
2018 		else
2019 			mcfru_type = "RMM        ";
2020 		switch (scsb_ks_topo.mct_disk[i].fru_status) {
2021 			case FRU_PRESENT:
2022 				status = YES;
2023 				break;
2024 			case FRU_NOT_PRESENT:
2025 				status = NO;
2026 				break;
2027 			case FRU_NOT_AVAILABLE:
2028 				status = NA;
2029 				break;
2030 			default:
2031 				status = NA;
2032 				break;
2033 		}
2034 		if (version_p15_and_p20) {
2035 			mc_ok_led =
2036 			    BIT_TEST((scsb_ks_leddata.scb_led_regs[8]
2037 			    & 0xff), DISK1_OK_BIT+i) ? BLINK :
2038 			    (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
2039 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF);
2040 			mc_nok_led =
2041 			    BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
2042 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF;
2043 		} else {
2044 			/*
2045 			 * support for 1.0 systems -
2046 			 * Hack! - should use tables ?
2047 			 */
2048 			mc_ok_led =
2049 			    (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
2050 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF);
2051 			mc_nok_led =
2052 			    BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
2053 			    & 0xff), DISK1_OK_BIT+i) ? ON:OFF;
2054 		}
2055 		/* print everything except condition */
2056 		if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) {
2057 			misc_info = "Hard Disk Drive";
2058 			log_printf(dgettext(TEXT_DOMAIN,
2059 			    "%10s   %-5d  %-7s %-5s    %-5s   %s\n"),
2060 			    mcfru_type, scsb_ks_topo.mct_disk[i].fru_unit-1,
2061 			    status, mc_ok_led, mc_nok_led, misc_info, 0);
2062 		} else {
2063 			misc_info = "Removable Media Module";
2064 			log_printf(dgettext(TEXT_DOMAIN,
2065 			    "%10s   %5s  %-7s %-5s    %-5s   %s\n"),
2066 			    mcfru_type, BLANK,
2067 			    status, mc_ok_led, mc_nok_led, misc_info, 0);
2068 		}
2069 
2070 		/* find out fru health from the SCSI drivers */
2071 		if (scsb_ks_topo.mct_disk[i].fru_status == FRU_PRESENT) {
2072 			switch (
2073 			    scsi_disk_status(
2074 			    scsb_ks_topo.mct_disk[i].fru_unit)) {
2075 				case 0:
2076 					health = OK;
2077 					break;
2078 				case 1:
2079 					health = NOK;
2080 					break;
2081 				case -1:
2082 					health = UK;
2083 					break;
2084 				default:
2085 					health = NA;
2086 					break;
2087 			}
2088 			log_printf(dgettext(TEXT_DOMAIN,
2089 			    "%49scondition:%s\n"), BLANK, health, 0);
2090 		}
2091 
2092 	}	/* for */
2093 
2094 	log_printf(dgettext(TEXT_DOMAIN, "\n"), 0);
2095 
2096 }	/*  display_mc_prtdiag_info() */
2097 
2098 
2099 void
analyze_pcipci_siblings(di_node_t node)2100 analyze_pcipci_siblings(di_node_t node)
2101 {
2102 	di_node_t lc_node;
2103 	/* we will find all the dev info for slots first */
2104 	lc_node = di_drv_first_node("pci_pci", node);
2105 	lc_node = di_child_node(lc_node);
2106 	/* we are at "pci" node now */
2107 	do  {
2108 		if (di_walk_node(lc_node, DI_WALK_CLDFIRST,
2109 		    NULL, analyze_nodes) != 0) {
2110 			return;
2111 		}
2112 	} while ((lc_node = di_sibling_node(lc_node)) != DI_NODE_NIL);
2113 
2114 	/* now we wll gather info on sysctrl */
2115 	lc_node = di_drv_first_node(SCSB_DEV, node);
2116 	if (lc_node != DI_NODE_NIL)
2117 		analyze_nodes(lc_node, "sysctrl");
2118 }	/* analyze_pcipci_siblings(.) */
2119 
2120 
2121 int
analyze_nodes(di_node_t l_node,void * arg)2122 analyze_nodes(di_node_t l_node, void *arg)
2123 {
2124 	char *temp;
2125 	char *name, *pname;
2126 	di_node_t parent;
2127 	/*
2128 	 *  we will figure out whether the parent node is "pci" type
2129 	 *  we will save info only in this case as we only want to
2130 	 * print out the nodes under AP and not others
2131 	 */
2132 	parent = di_parent_node(l_node);
2133 	pname =  di_node_name(parent);
2134 	name = di_node_name(l_node);
2135 	/*
2136 	 * if this is PCI bridge, we know that this is the AP for slots
2137 	 * hence, we will save off the address(to convert to slot mapping)
2138 	 * later, and also we will start saving off slot info struct for
2139 	 * reporting later
2140 	 * we will save the immediate childs of this bridge only
2141 	 */
2142 	if (strcmp(name, "pci") == 0) {
2143 		num_devs = 0;
2144 		if ((temp = di_bus_addr(l_node)) != NULL) {
2145 			mc_slots_data.mc_slot_info[slot_index].slot_addr
2146 			    = (int)strtol(temp, (char **)NULL, 16);
2147 		}
2148 		slot_index++;
2149 	} else {
2150 		if (strcmp(pname, "pci") == 0) {
2151 	if ((mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs])
2152 	    != NULL) {
2153 	(void) strcat(
2154 	    mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
2155 	    name);
2156 			} else {
2157 	(void) strcpy(
2158 	    mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
2159 	    name);
2160 			} /* if ((mc_slots_data.mc_slot_inf */
2161 
2162 			num_devs++;
2163 			mc_slots_data.mc_slot_info[slot_index-1].number_devs
2164 			    = num_devs;
2165 		} /* if parent is pci */
2166 
2167 	} /* if node is pci */
2168 	if (arg != NULL) {
2169 		if (strcmp((char *)arg, "sysctrl") == 0) {
2170 			if (dump_prop_list("System", l_node,
2171 			    di_prop_sys_next)) {
2172 				(void) dump_prop_list(NULL, l_node,
2173 				    di_prop_global_next);
2174 			} else {
2175 				fail_syssoft_prop =
2176 				    dump_prop_list(SYSSOFT_PROP,
2177 				    l_node, di_prop_global_next);
2178 			}
2179 
2180 			fail_drv_prop =
2181 			    dump_prop_list(DRV_PROP, l_node,
2182 			    di_prop_drv_next);
2183 			/*
2184 			 * (void) dump_prop_list("Hardware",
2185 			 *   l_node, di_prop_hw_next);
2186 			 */
2187 			/*  dump_priv_data(l_node); */
2188 		}
2189 	}
2190 
2191 	return	(0);
2192 
2193 }	/* analyze_nodes(..) */
2194 
2195 
2196 
2197 /*
2198  * To get the slot information,
2199  * The OBP defines the 'slot-table' property. But the OS
2200  * can override it with 'hsc-slot-map' property
2201  * through the .conf file.
2202  * Since the formats are different, 2 different property names
2203  * are chosen.
2204  * The OBP property format is
2205  * <phandle>,<pci-devno>,<phys-slotno>,<ga-bits>
2206  * The OS property format is (ga-bits is not used however)
2207  * <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits>
2208  * returns 0 on error, 1 otherwise
2209  */
2210 int
extract_slot_table_from_obp()2211 extract_slot_table_from_obp()
2212 {
2213 	if (mc_promopen(O_RDONLY))  {
2214 		log_printf(dgettext(TEXT_DOMAIN,
2215 		    "\ncannot open openprom device"), 0);
2216 		return (0);
2217 	}
2218 
2219 	if (mc_next(0) == 0)
2220 		return (0);
2221 	mc_walk(mc_next(0));
2222 
2223 	if (close(oprom_fd) < 0) {
2224 		log_printf(dgettext(TEXT_DOMAIN,
2225 		    "\nclose error on %s"), OPENPROMDEV, 0);
2226 		return (0);
2227 	}
2228 
2229 	return (1);
2230 
2231 }	/* extract_slot_table_from_obp() */
2232 
2233 
2234 int
mc_next(int id)2235 mc_next(int id)
2236 {
2237 	Oppbuf  oppbuf;
2238 	struct openpromio *opp = &(oppbuf.opp);
2239 
2240 	bzero(oppbuf.buf, BUFSIZE);
2241 	opp->oprom_size = MAXVALSIZE;
2242 	opp->oprom_node = id;
2243 	if (ioctl(oprom_fd, OPROMNEXT, opp) < 0) {
2244 		log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMNEXT"), 0);
2245 		return (0);
2246 	}
2247 	return (opp->oprom_node);
2248 
2249 }	/* mc_next(.) */
2250 
2251 
2252 void
mc_walk(int id)2253 mc_walk(int id)
2254 {
2255 	int curnode;
2256 	mc_dump_node(id);
2257 	if (curnode = mc_child(id))
2258 		mc_walk(curnode);
2259 	if (curnode = mc_next(id))
2260 		mc_walk(curnode);
2261 }	/*  mc_walk(.) */
2262 
2263 int
mc_child(int id)2264 mc_child(int id)
2265 {
2266 	Oppbuf  oppbuf;
2267 	struct openpromio *opp = &(oppbuf.opp);
2268 
2269 	bzero(oppbuf.buf, BUFSIZE);
2270 	opp->oprom_size = MAXVALSIZE;
2271 	opp->oprom_node = id;
2272 	if (ioctl(oprom_fd, OPROMCHILD, opp) < 0) {
2273 		perror("\nOPROMCHILD");
2274 		exit(0);
2275 	}
2276 	return (opp->oprom_node);
2277 
2278 }	/* mc_child(.) */
2279 
2280 
2281 /*
2282  * Print all properties and values
2283  */
2284 void
mc_dump_node(int id)2285 mc_dump_node(int id)
2286 {
2287 	int k;
2288 	Oppbuf  oppbuf;
2289 	hsc_prom_slot_table_t	*hpstp;
2290 	struct openpromio *opp = &(oppbuf.opp);
2291 
2292 	/* get first prop by asking for null string */
2293 	bzero(oppbuf.buf, BUFSIZE);
2294 	for (;;) {
2295 		/*
2296 		 * get next property name
2297 		 */
2298 		opp->oprom_size = MAXNAMESZ;
2299 
2300 		if (ioctl(oprom_fd, OPROMNXTPROP, opp) < 0) {
2301 			perror("\nOPROMNXTPROP");
2302 			return;
2303 		}
2304 		if (opp->oprom_size == 0)
2305 			break;
2306 		if (strcmp(opp->oprom_array, "slot-table") == 0) {
2307 			if (mc_getpropval(opp) || opp->oprom_size
2308 			    == (uint_t)-1) {
2309 				log_printf(dgettext(TEXT_DOMAIN,
2310 				    "\ndata not available"), 0);
2311 				return;
2312 			} else {
2313 				slot_table_size =
2314 				    opp->oprom_size /
2315 				    sizeof (hsc_prom_slot_table_t);
2316 				hpstp =
2317 				    (hsc_prom_slot_table_t *)opp->oprom_array;
2318 				for (k = 0; k < slot_table_size; k++, hpstp++) {
2319 					prom_slot_table[k].pslotnum =
2320 					    hpstp->pslotnum;
2321 					prom_slot_table[k].ga =
2322 					    hpstp->ga;
2323 					prom_slot_table[k].pci_devno =
2324 					    hpstp->pci_devno;
2325 					prom_slot_table[k].phandle =
2326 					    hpstp->phandle;
2327 				} /* for (k = 0; k < slot_table_size; k++) */
2328 
2329 			}
2330 		}
2331 	}
2332 
2333 }	/* mc_dump_node(.) */
2334 
2335 
2336 int
mc_getpropval(struct openpromio * opp)2337 mc_getpropval(struct openpromio *opp)
2338 {
2339 	opp->oprom_size = MAXVALSIZE;
2340 	if (ioctl(oprom_fd, OPROMGETPROP, opp) < 0) {
2341 		log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMGETPROP"), 0);
2342 		return (1);
2343 	}
2344 	return (0);
2345 
2346 }	/* mc_getpropval(.) */
2347 
2348 
2349 
2350 /*
2351  * This function returns nothing.
2352  */
2353 void
alarm_card_occupant()2354 alarm_card_occupant()
2355 {
2356 	int		scsb_fd;
2357 	scsb_ioc_rdwr_t	ioc_read;
2358 	uint8_t		new_mode = 0;
2359 	uint8_t		old_mode = 0;
2360 	uchar_t		reg_index;
2361 
2362 	if (NULL == scsb_node) {
2363 		if (check_platform() == -1) {
2364 			return;
2365 		}
2366 	}
2367 
2368 	if (version_p15_and_p20 == 1)
2369 		reg_index = 0xe9;	/* config status reg offset on SCB */
2370 	else
2371 		reg_index = 0xd7;	/* config status reg offset on SCB */
2372 
2373 	if ((scsb_fd = open(scsb_node, O_RDONLY)) < 0)  {
2374 		log_printf(dgettext(TEXT_DOMAIN,
2375 		    "\n%s open failed"), scsb_node, 0);
2376 		return;
2377 	}
2378 
2379 	/* save off the old mode */
2380 	if (scsb_mode(scsb_fd, GET, &old_mode) == 0)
2381 		return;
2382 	/* we put scsb in diag mode to read this specific ioctl */
2383 	new_mode = ENVCTRL_DIAG_MODE;
2384 	if (scsb_mode(scsb_fd, SET, &new_mode) == 0)
2385 		return;
2386 	/* now lets read the config register */
2387 	if (scsb_ioc_reg_read(scsb_fd, reg_index, &ioc_read, 1) == 0)
2388 		return;
2389 	/* restore the original mode */
2390 	if (scsb_mode(scsb_fd, SET, &old_mode) == 0)
2391 		return;
2392 	alarm_card_present = (BIT_TEST(ioc_read.ioc_rbuf[0]&0xff, 0) ? 1:0);
2393 
2394 }	/* alarm_card_occupant() */
2395 
2396 
2397 /*
2398  * This function changes the SCSB mode to the desired one
2399  * 1 on sucess, 0 otherwise
2400  */
2401 int
scsb_mode(int fd,scsb_op_t sop,uint8_t * new_mode)2402 scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode)
2403 {
2404 	struct strioctl sioc;
2405 
2406 	if (sop == GET)
2407 		sioc.ic_cmd = ENVC_IOC_GETMODE;
2408 	else
2409 		sioc.ic_cmd = ENVC_IOC_SETMODE;
2410 
2411 	sioc.ic_timout = 0;
2412 	sioc.ic_len = sizeof (uint8_t);
2413 	sioc.ic_dp = (char *)new_mode;
2414 
2415 
2416 	if (ioctl(fd, I_STR, &sioc) == -1) {
2417 		log_printf(dgettext(TEXT_DOMAIN,
2418 		    "\nscsb_mode():scsb ioctl() failed"), 0);
2419 		return (0);
2420 	}
2421 	return (1);
2422 
2423 }	/* scsb_mode(...) */
2424 
2425 
2426 /*
2427  * 1 on success, 0 otherwise
2428  */
2429 int
scsb_ioc_reg_read(int fd,uchar_t index,scsb_ioc_rdwr_t * ioc_rd,int num)2430 scsb_ioc_reg_read(int fd, uchar_t index, scsb_ioc_rdwr_t *ioc_rd, int num)
2431 {
2432 	struct strioctl		sioc;
2433 	scsb_ioc_rdwr_t		*rdwrp;
2434 
2435 	rdwrp = ioc_rd;
2436 	sioc.ic_timout = 0;
2437 	sioc.ic_len = sizeof (scsb_ioc_rdwr_t);
2438 	sioc.ic_dp = (char *)rdwrp;
2439 	/* setup read command before ioctl */
2440 	sioc.ic_cmd = SCSBIOC_REG_READ;
2441 	rdwrp->ioc_wlen = 0;
2442 	rdwrp->ioc_rlen = num;
2443 	rdwrp->ioc_regindex = index;
2444 	if (ioctl(fd, I_STR, &sioc) == -1) {
2445 		log_printf(dgettext(TEXT_DOMAIN,
2446 		    "scsb_ioc_reg_read(): scsb ioctl() failed\n"), 0);
2447 		return (0);
2448 	}
2449 	return (1);
2450 
2451 }	/* scsb_ioc_reg_read(....) */
2452