xref: /illumos-gate/usr/src/lib/libprtdiag_psr/sparc/daktari/common/daktari.c (revision 004388ebfdfe2ed7dfd2d153a876dfcc22d2c006)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Daktari Platform specific functions.
29  *
30  * 	called when :
31  *      machine_type ==  MTYPE_DAKTARI
32  *
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <kstat.h>
41 #include <string.h>
42 #include <assert.h>
43 #include <libintl.h>
44 #include <note.h>
45 
46 #include <sys/openpromio.h>
47 #include <sys/sysmacros.h>
48 #include <sys/daktari.h>
49 
50 #include <pdevinfo.h>
51 #include <display.h>
52 #include <pdevinfo_sun4u.h>
53 #include <display_sun4u.h>
54 #include <libprtdiag.h>
55 
56 #include <picl.h>
57 #include "workfile.c"
58 
59 #if !defined(TEXT_DOMAIN)
60 #define	TEXT_DOMAIN	"SYS_TEST"
61 #endif
62 
63 #define	DAK_MAX_SLOTS_PER_IO_BD		9
64 #define	DAK_MAX_DISKS			12
65 #define	DAK_MAX_FSP_LEDS		2
66 #define	DAK_MAX_PS			3
67 #define	DAK_MAX_PS_VOLTAGE_SENSORS	4
68 #define	DAK_MAX_PS_FAULT_SENSORS	3
69 #define	DAK_MAX_FANS			10
70 #ifndef SCHIZO_COMPAT_PROP
71 #define	SCHIZO_COMPAT_PROP		"pci108e,8001"
72 #endif
73 
74 #define	MULTIPLE_BITS_SET(x)		((x)&((x)-1))
75 
76 extern	int	print_flag;
77 
78 /*
79  * these functions will overlay the symbol table of libprtdiag
80  * at runtime (workgroup server systems only)
81  */
82 void	display_cpu_devices(Sys_tree *tree);
83 void	display_cpus(Board_node *board);
84 void	display_pci(Board_node *board);
85 void	display_io_cards(struct io_card *list);
86 void	display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
87 				struct system_kstat_data *kstats);
88 void	display_ffb(Board_node *board, int table);
89 void	display_memoryconf(Sys_tree *tree, struct grp_info *grps);
90 
91 /* local functions */
92 static	int disp_envc_status(void);
93 static	int dak_env_print_temps(picl_nodehdl_t);
94 static	int dak_env_print_keyswitch(picl_nodehdl_t);
95 static	int dak_env_print_FSP_LEDS(picl_nodehdl_t);
96 static	int dak_env_print_disk(picl_nodehdl_t);
97 static	int dak_env_print_fans(picl_nodehdl_t);
98 static	int dak_env_print_ps(picl_nodehdl_t);
99 
100 static void dak_display_hw_revisions(Prom_node *root,
101 					Board_node *bnode);
102 static void display_schizo_revisions(Board_node *bdlist);
103 
104 
105 /*
106  * Defining the error_check function in order to return the
107  * appropriate error code.
108  */
109 /*ARGSUSED0*/
110 int
111 error_check(Sys_tree *tree, struct system_kstat_data *kstats)
112 {
113 	int exit_code = 0;	/* init to all OK */
114 	/*
115 	 * silently check for any types of machine errors
116 	 */
117 	print_flag = 0;
118 	if (disp_fail_parts(tree)) {
119 		/* set exit_code to show failures */
120 		exit_code = 1;
121 	}
122 	print_flag = 1;
123 
124 	return (exit_code);
125 }
126 
127 /*
128  * disp_fail_parts
129  *
130  * Display the failed parts in the system. This function looks for
131  * the status property in all PROM nodes. On systems where
132  * the PROM does not support passing diagnostic information
133  * through the device tree, this routine will be silent.
134  */
135 int
136 disp_fail_parts(Sys_tree *tree)
137 {
138 	int exit_code = 0;
139 	int system_failed = 0;
140 	Board_node *bnode = tree->bd_list;
141 	Prom_node *pnode;
142 
143 	/* go through all of the boards looking for failed units. */
144 	while (bnode != NULL) {
145 		/* find failed chips */
146 		pnode = find_failed_node(bnode->nodes);
147 		if ((pnode != NULL) && !system_failed) {
148 			system_failed = 1;
149 			exit_code = 1;
150 			if (print_flag == 0) {
151 				return (exit_code);
152 			}
153 			log_printf("\n");
154 			log_printf(dgettext(TEXT_DOMAIN, "Failed Field "
155 				"Replaceable Units (FRU) in System:\n"));
156 			log_printf("=========================="
157 				"====================\n");
158 		}
159 		while (pnode != NULL) {
160 			void *value;
161 			char *name;		/* node name string */
162 			char *type;		/* node type string */
163 			char *board_type = NULL;
164 
165 			value = get_prop_val(find_prop(pnode, "status"));
166 			name = get_node_name(pnode);
167 
168 			/* sanity check of data retrieved from PROM */
169 			if ((value == NULL) || (name == NULL)) {
170 				pnode = next_failed_node(pnode);
171 				continue;
172 			}
173 
174 			/* Find the board type of this board */
175 			if (bnode->board_type == CPU_BOARD) {
176 				board_type = "CPU";
177 			} else {
178 				board_type = "IO";
179 			}
180 
181 			log_printf(dgettext(TEXT_DOMAIN, "%s unavailable "
182 				"on %s Board #%d\n"), name, board_type,
183 					bnode->board_num);
184 
185 			log_printf(dgettext(TEXT_DOMAIN,
186 				"\tPROM fault string: %s\n"), value);
187 
188 			log_printf(dgettext(TEXT_DOMAIN,
189 				"\tFailed Field Replaceable Unit is "));
190 
191 			/*
192 			 * Determine whether FRU is CPU module, system
193 			 * board, or SBus card.
194 			 */
195 			if ((name != NULL) && (strstr(name, "sbus"))) {
196 
197 				log_printf(dgettext(TEXT_DOMAIN,
198 					"SBus Card %d\n"),
199 					get_sbus_slot(pnode));
200 
201 			} else if (((name = get_node_name(pnode->parent)) !=
202 			    NULL) && (strstr(name, "pci"))) {
203 
204 				log_printf(dgettext(TEXT_DOMAIN,
205 					"PCI Card %d"),
206 					get_pci_device(pnode));
207 
208 			} else if (((type = get_node_type(pnode)) != NULL) &&
209 			    (strstr(type, "cpu"))) {
210 
211 				log_printf(dgettext(TEXT_DOMAIN, "UltraSPARC "
212 					"module Board %d Module %d\n"), 0,
213 						get_id(pnode));
214 
215 			} else {
216 				log_printf(dgettext(TEXT_DOMAIN,
217 					"%s board %d\n"), board_type,
218 					bnode->board_num);
219 			}
220 			pnode = next_failed_node(pnode);
221 		}
222 		bnode = bnode->next;
223 	}
224 
225 	if (!system_failed) {
226 		log_printf(dgettext(TEXT_DOMAIN,
227 			"No failures found in System\n"));
228 		log_printf("===========================\n\n");
229 	}
230 
231 	if (system_failed)
232 		return (1);
233 	else
234 		return (0);
235 }
236 
237 /*ARGSUSED*/
238 void
239 display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats)
240 {
241 	/* Display failed units */
242 	(void) disp_fail_parts(tree);
243 }
244 
245 /*ARGSUSED*/
246 void
247 display_memoryconf(Sys_tree *tree, struct grp_info *grps)
248 {
249 	Board_node	*bnode = tree->bd_list;
250 
251 	log_printf(dgettext(TEXT_DOMAIN,
252 		"========================= Memory Configuration"
253 		" ===============================\n"
254 		"\n           Logical  Logical"
255 		"  Logical "
256 		"\n      MC   Bank     Bank     Bank"
257 		"         DIMM    Interleave  Interleaved"
258 		"\n Brd  ID   num      size     "
259 		"Status       Size    "
260 		"Factor      with"
261 		"\n----  ---  ----     ------   "
262 		"-----------  ------  "
263 		"----------  -----------"));
264 
265 	while (bnode != NULL) {
266 		if (get_us3_mem_regs(bnode)) {
267 			log_printf(dgettext(TEXT_DOMAIN,
268 				"\nFailed to get memory information.\n"));
269 			return;
270 		}
271 		bnode = bnode->next;
272 	}
273 
274 	/* Display what we have found */
275 	display_us3_banks();
276 }
277 
278 void
279 display_cpu_devices(Sys_tree *tree)
280 {
281 	Board_node *bnode;
282 
283 	/*
284 	 * Display the table header for CPUs . Then display the CPU
285 	 * frequency, cache size, and processor revision of all cpus.
286 	 */
287 	log_printf(dgettext(TEXT_DOMAIN,
288 		"\n"
289 		"========================="
290 		" CPUs "
291 		"==============================================="
292 		"\n"
293 		"\n"
294 		"           Run   E$  CPU    CPU  \n"
295 		"Brd  CPU   MHz   MB Impl.   Mask \n"
296 		"--- ----- ---- ---- ------- ---- \n"));
297 
298 	/* Now display all of the cpus on each board */
299 	bnode = tree->bd_list;
300 	if (bnode == NULL) {
301 		log_printf(dgettext(TEXT_DOMAIN,
302 			"CPU Board list was NULL\n"));
303 	}
304 	while (bnode != NULL) {
305 		display_cpus(bnode);
306 		bnode = bnode->next;
307 	}
308 
309 	log_printf("\n");
310 }
311 
312 /*
313  * Display the CPUs present on this board.
314  */
315 void
316 display_cpus(Board_node *board)
317 {
318 	Prom_node 	*cpu;
319 	int freq;	 /* CPU clock frequency */
320 	int ecache_size; /* External cache size */
321 	int *l3_shares;
322 	int *mid;
323 	int *impl;
324 	int *mask;
325 	int *coreid;
326 	char fru_prev = 'X'; /* Valid frus are 'A','B','C','D' */
327 	int mid_prev;
328 	int ecache_size_prev = 0;
329 	char fru_name;
330 
331 	/*
332 	 * display the CPUs' operating frequency, cache size, impl. field
333 	 * and mask revision.
334 	 */
335 	for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
336 	    cpu = dev_next_type(cpu, "cpu")) {
337 
338 		mid = (int *)get_prop_val(find_prop(cpu, "portid"));
339 		if (mid == NULL)
340 			mid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
341 		freq = DAK_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu));
342 		ecache_size = get_ecache_size(cpu);
343 		impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
344 		mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
345 		l3_shares =
346 			(int *)get_prop_val(find_prop(cpu, "l3-cache-sharing"));
347 
348 		/* Do not display a failed CPU node */
349 		if ((impl == NULL) || (freq == 0) || (node_failed(cpu)))
350 			continue;
351 
352 		/* Board number */
353 		fru_name = (char)('A' + DAK_GETSLOT(*mid));
354 
355 		if (CPU_IMPL_IS_CMP(*impl)) {
356 			coreid = (int *)get_prop_val(find_prop(cpu, "reg"));
357 			if (coreid == NULL) {
358 				continue;
359 			}
360 			if ((fru_prev == 'X') ||
361 				((fru_prev != 'X') &&
362 				(fru_name != fru_prev))) {
363 				fru_prev = fru_name;
364 				mid_prev = *mid;
365 				ecache_size_prev = ecache_size;
366 				continue;
367 			} else {
368 				/*
369 				 * Some CMP chips have a split E$,
370 				 * so the size for both cores is added
371 				 * together to get the total size for
372 				 * the chip.
373 				 *
374 				 * Still, other CMP chips have E$ (L3)
375 				 * which is logically shared, so the
376 				 * total size is equal to the core size.
377 				 */
378 				if ((l3_shares == NULL) ||
379 					((l3_shares != NULL) &&
380 					MULTIPLE_BITS_SET(*l3_shares))) {
381 					ecache_size += ecache_size_prev;
382 				}
383 				ecache_size_prev = 0;
384 				fru_prev = 'X';
385 			}
386 		}
387 
388 		log_printf("%2c", fru_name);
389 
390 		/* CPU Module ID */
391 		if (CPU_IMPL_IS_CMP(*impl)) {
392 			log_printf("%3d,%3d", mid_prev, *mid, 0);
393 		} else
394 			log_printf("    %d  ", *mid);
395 
396 		/* Running frequency */
397 		log_printf(" %4d ", freq);
398 
399 		/* Ecache size */
400 		if (ecache_size == 0)
401 			log_printf(dgettext(TEXT_DOMAIN, "%3s  "),
402 			    "N/A");
403 		else
404 			log_printf("%4.1f ",
405 				(float)ecache_size / (float)(1<<20));
406 
407 		/* Implementation */
408 		if (impl == NULL) {
409 			log_printf(dgettext(TEXT_DOMAIN, "%s    "),
410 			"N/A");
411 		} else {
412 			if (IS_CHEETAH(*impl))
413 				log_printf("%7s", "US-III ", 0);
414 			else if (IS_CHEETAH_PLUS(*impl))
415 				log_printf("%7s", "US-III+", 0);
416 			else if (IS_JAGUAR(*impl))
417 				log_printf("%7s", "US-IV  ", 0);
418 			else if (IS_PANTHER(*impl))
419 				log_printf("%7s", "US-IV+ ", 0);
420 			else
421 				log_printf("%-7x", *impl, 0);
422 		}
423 
424 		/* CPU Mask */
425 		if (mask == NULL) {
426 			log_printf(dgettext(TEXT_DOMAIN, " %3s   "),
427 			"N/A");
428 		} else {
429 			log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
430 			    (*mask >> 4) & 0xf, *mask & 0xf);
431 		}
432 
433 		log_printf("\n");
434 	}
435 }
436 
437 /*
438  * display_pci
439  * Display all the PCI IO cards on this board.
440  */
441 void
442 display_pci(Board_node *board)
443 {
444 	struct io_card	*card_list = NULL;
445 	struct io_card	card;
446 	void		*value;
447 	Prom_node	*pci;
448 	Prom_node	*card_node;
449 	char		*slot_name_arr[DAK_MAX_SLOTS_PER_IO_BD] = {NULL};
450 	int		i;
451 #ifdef DEBUG
452 	int		slot_name_bits;
453 #endif
454 
455 	if (board == NULL)
456 		return;
457 
458 	memset(&card, 0, sizeof (struct io_card));
459 	/* Initialize all the common information */
460 	card.display = TRUE;
461 	card.board = board->board_num;
462 
463 	/*
464 	 * Search for each pci instance, then find/display all nodes under
465 	 * each instance node found.
466 	 */
467 	for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP);
468 		pci != NULL;
469 		pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) {
470 		(void) snprintf(card.bus_type, MAXSTRLEN,
471 			dgettext(TEXT_DOMAIN, "PCI"));
472 		/*
473 		 * Get slot-name properties from parent node and
474 		 * store them in an array.
475 		 */
476 		value = (char *)get_prop_val(
477 			find_prop(pci, "slot-names"));
478 
479 		if (value != NULL) {
480 #ifdef DEBUG
481 			/* save the 4 byte bitmask */
482 			slot_name_bits = *(int *)value;
483 #endif
484 
485 			/* array starts after first int */
486 			slot_name_arr[0] = (char *)value + sizeof (int);
487 			for (i = 1; i < DAK_MAX_SLOTS_PER_IO_BD; i++) {
488 				slot_name_arr[i] = (char *)slot_name_arr[i - 1]
489 					+ strlen(slot_name_arr[i - 1]) +1;
490 			}
491 		}
492 		/*
493 		 * Search for Children of this node ie. Cards.
494 		 * Note: any of these cards can be a pci-bridge
495 		 *	that itself has children. If we find a
496 		 *	pci-bridge we need to handle it specially.
497 		 */
498 		card_node = pci->child;
499 		/* Generate the list of pci cards on pci instance: pci */
500 		fill_pci_card_list(pci, card_node, &card, &card_list,
501 			slot_name_arr);
502 	} /* end-for */
503 
504 	display_io_cards(card_list);
505 	free_io_cards(card_list);
506 	log_printf("\n");
507 }
508 
509 /*
510  * Print out all the io cards in the list.  Also print the column
511  * headers if told to do so.
512  */
513 void
514 display_io_cards(struct io_card *list)
515 {
516 	static int banner = 0; /* Have we printed the column headings? */
517 	struct io_card *p;
518 
519 	if (list == NULL)
520 		return;
521 
522 	if (banner == FALSE) {
523 		log_printf(dgettext(TEXT_DOMAIN,
524 			"                         Bus  Max\n"
525 			"     IO   Port Bus       Freq Bus  Dev,"
526 			"\n"
527 			"Brd  Type  ID  Side Slot MHz  Freq "
528 			"Func State Name                              "
529 			"Model\n"
530 		/* ---------Brd  IO   Port Bus  Slot Bus  Max  Dev  Stat */
531 			"---- ---- ---- ---- ---- ---- ---- ----"
532 			" ----- "
533 			"--------------------------------  "
534 			"----------------------\n"));
535 		banner = TRUE;
536 	}
537 
538 	for (p = list; p != NULL; p = p -> next) {
539 		log_printf(dgettext(TEXT_DOMAIN, "I/O  "));
540 		log_printf("%-4s  ", p->bus_type);
541 		log_printf("%-3d  ", p->schizo_portid);
542 		log_printf("%c    ", p->pci_bus);
543 		log_printf("%-1s    ", p->slot_str);
544 		log_printf("%-3d ", p->freq);
545 		switch (p->pci_bus) {
546 		case 'A':
547 			log_printf(dgettext(TEXT_DOMAIN, " 66  "));
548 			break;
549 		case 'B':
550 			log_printf(dgettext(TEXT_DOMAIN, " 33  "));
551 			break;
552 		default:
553 			log_printf(dgettext(TEXT_DOMAIN, "  -  "));
554 			break;
555 		}
556 
557 		log_printf("%-1d,%-1d  ", p->dev_no, p->func_no);
558 		log_printf("%-5s ", p->status);
559 		log_printf("%-32.32s", p->name);
560 		if (strlen(p->name) > 32)
561 			log_printf(dgettext(TEXT_DOMAIN, "+ "));
562 		else
563 			log_printf(dgettext(TEXT_DOMAIN, "  "));
564 		log_printf("%-22.22s", p->model);
565 		if (strlen(p->model) > 22)
566 			log_printf(dgettext(TEXT_DOMAIN, "+"));
567 
568 #ifdef DEBUG
569 		log_printf(dgettext(TEXT_DOMAIN, "%s  "), p->notes);
570 #endif
571 		log_printf("\n");
572 	}
573 }
574 
575 /*
576  * display_ffb
577  *
578  * There are no FFB's on a Daktari, however in the generic library,
579  * the display_ffb() function is implemented so we have to define an
580  * empty function here.
581  */
582 /* ARGSUSED */
583 void
584 display_ffb(Board_node *board, int table)
585 {}
586 
587 
588 /*
589  * ----------------------------------------------------------------------------
590  */
591 
592 /* ARGSUSED */
593 void
594 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
595 	struct system_kstat_data *kstats)
596 {
597 	/* NOTE(ARGUNUSED(kstats)) */
598 	/*
599 	 * Now display the last powerfail time and the fatal hardware
600 	 * reset information. We do this under a couple of conditions.
601 	 * First if the user asks for it. The second is if the user
602 	 * told us to do logging, and we found a system failure.
603 	 */
604 	if (flag) {
605 		/*
606 		 * display time of latest powerfail. Not all systems
607 		 * have this capability. For those that do not, this
608 		 * is just a no-op.
609 		 */
610 		disp_powerfail(root);
611 
612 		(void) disp_envc_status();
613 
614 		/* platform_disp_prom_version(tree); */
615 		dak_display_hw_revisions(root, tree->bd_list);
616 	}
617 }
618 
619 /*
620  * local functions
621  */
622 
623 /*
624  * disp_envc_status
625  *
626  * This routine displays the environmental status passed up from
627  * device drivers via the envlibobj.so library.
628  * This is a Daktari specific environmental information display routine.
629  */
630 int
631 disp_envc_status()
632 {
633 	int err;
634 	char *system = "SYSTEM";
635 	picl_nodehdl_t system_node, root;
636 
637 	err = picl_initialize();
638 	if (err != PICL_SUCCESS) {
639 		log_printf(dgettext(TEXT_DOMAIN,
640 			"picl_initialize failed\n"
641 			"%s\nCannot display environmental status\n"),
642 			    picl_strerror(err));
643 		return (err);
644 	}
645 	err = picl_get_root(&root);
646 	err = find_child_device(root, system, &system_node);
647 	if (err != PICL_SUCCESS) {
648 		log_printf(dgettext(TEXT_DOMAIN,
649 			"picl_get_node_by_path for the SYSTEM node "
650 			"failed\n"
651 			"%s\nCannot display environmental status\n"),
652 			    picl_strerror(err));
653 		return (err);
654 	}
655 
656 	log_printf(dgettext(TEXT_DOMAIN,
657 		"\n"
658 		"========================= "
659 		"Environmental Status "
660 		"========================="
661 		"\n"
662 		"\n"));
663 
664 	dak_env_print_temps(system_node);
665 	dak_env_print_keyswitch(system_node);
666 	dak_env_print_FSP_LEDS(system_node);
667 	dak_env_print_disk(system_node);
668 	dak_env_print_fans(system_node);
669 	dak_env_print_ps(system_node);
670 
671 	(void) picl_shutdown();
672 	return (0);
673 }
674 
675 int
676 dak_env_print_ps(picl_nodehdl_t system_node)
677 {
678 	int		i, r, fail, err = 0;
679 	int32_t		number;
680 	char		name[PICL_PROPNAMELEN_MAX];
681 	picl_nodehdl_t	*ps;
682 	picl_nodehdl_t	*ps_fail[DAK_MAX_PS_FAULT_SENSORS];
683 	picl_nodehdl_t	*ps_I_sensor[DAK_MAX_PS_VOLTAGE_SENSORS];
684 	int32_t		volts[DAK_MAX_PS_VOLTAGE_SENSORS];
685 	char		fault_state
686 			    [DAK_MAX_PS_FAULT_SENSORS][PICL_PROPNAMELEN_MAX];
687 	char		ps_state[PICL_PROPNAMELEN_MAX];
688 	/* Printing out the Power Supply Heading information */
689 	log_printf(dgettext(TEXT_DOMAIN,
690 		"Power Supplies:\n"
691 		"---------------\n"
692 		"                                                    "
693 		"Current Drain:\n"
694 		"Supply     Status     Fan Fail  Temp Fail  CS Fail  "
695 		"3.3V   5V   12V   48V\n"
696 		"------  ------------  --------  ---------  "
697 		"-------  ----   --   ---   ---\n"));
698 
699 	err = fill_device_array_from_id(system_node, "PSVC_PS", &number,
700 	    &ps);
701 	if (err != PICL_SUCCESS) {
702 		log_printf(dgettext(TEXT_DOMAIN,
703 			"failed in fill_device_array_from_id for PS\n"
704 			"%s\n"), picl_strerror(err));
705 		return (err);
706 	}
707 	/* Printing out the Power Supply Status information */
708 	for (i = 0; i < DAK_MAX_PS; i++) {
709 		/*
710 		 * Re initialize the fail variable so that if
711 		 * one power supply fails, they don't all do also.
712 		 */
713 		fail = 0;
714 
715 		err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name,
716 		    PICL_PROPNAMELEN_MAX);
717 		if (err != PICL_SUCCESS) {
718 			continue;
719 		}
720 		err = picl_get_propval_by_name(ps[i], "State", ps_state,
721 			PICL_PROPNAMELEN_MAX);
722 		if (err != PICL_SUCCESS) {
723 			log_printf(dgettext(TEXT_DOMAIN,
724 				"Error getting ps[%d]'s state: %s"),
725 				i, picl_strerror(err));
726 		}
727 
728 		err = fill_device_array_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR",
729 			&number, &ps_fail[i]);
730 
731 		if (err != PICL_SUCCESS) {
732 			log_printf(dgettext(TEXT_DOMAIN,
733 				"failed to get present PS fault sensors\n"
734 				"%s\n"), picl_strerror(err));
735 			return (err);
736 		}
737 
738 		err = fill_device_array_from_id(ps[i], "PSVC_PS_I_SENSOR",
739 		    &number, &ps_I_sensor[i]);
740 
741 		if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) {
742 			log_printf(dgettext(TEXT_DOMAIN,
743 				"failed to get present PS I sensors\n"
744 				"%s\n"), picl_strerror(err));
745 		}
746 
747 		log_printf("%s", name);
748 
749 		/*
750 		 * If the AC cord is unplugged, then the power supply
751 		 * sensors will have unreliable values.  In this case,
752 		 * skip to the next power supply.
753 		 */
754 		if (strcmp(ps_state, "HOTPLUGGED") == 0) {
755 			log_printf(dgettext(TEXT_DOMAIN,
756 			    "      UNPLUGGED\n"));
757 			continue;
758 		}
759 
760 		for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) {
761 			err = picl_get_propval_by_name(ps_fail[i][r], "State",
762 				fault_state[r], PICL_PROPNAMELEN_MAX);
763 			if (err == PICL_SUCCESS) {
764 				fail =
765 				    strcmp(fault_state[r], "OFF")
766 				    + fail;
767 			} else {
768 				log_printf(dgettext(TEXT_DOMAIN,
769 					"picl_get_propval_by_name for ps "
770 					"fault state failed\n"
771 					"%s\n"), picl_strerror(err));
772 				return (err);
773 			}
774 		}
775 		for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) {
776 			err = picl_get_propval_by_name(ps_I_sensor[i][r],
777 				"AtoDSensorValue", &volts[r],
778 				sizeof (int32_t));
779 		}
780 
781 		if (fail != 0) {
782 			log_printf(dgettext(TEXT_DOMAIN,
783 			    "      FAIL      "));
784 			for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) {
785 				log_printf(dgettext(TEXT_DOMAIN, "      %-4s"),
786 					fault_state[r]);
787 			}
788 		} else {
789 			log_printf(dgettext(TEXT_DOMAIN, "      GOOD      "));
790 			for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) {
791 				log_printf(dgettext(TEXT_DOMAIN, "          "));
792 			}
793 		}
794 		for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) {
795 			log_printf(dgettext(TEXT_DOMAIN, "    %2d"), volts[r]);
796 		}
797 		log_printf("\n");
798 	}
799 	log_printf("\n");
800 	return (err);
801 }
802 
803 int
804 dak_env_print_fans(picl_nodehdl_t system_node)
805 {
806 	int		i, err = 0;
807 	int32_t		number, fan_speed;
808 	picl_nodehdl_t	*fans;
809 	char		name[PICL_PROPNAMELEN_MAX];
810 	char		enabled[PICL_PROPNAMELEN_MAX];
811 
812 	err = fill_device_array_from_id(system_node, "PSVC_FAN", &number,
813 	    &fans);
814 	if (err != PICL_SUCCESS) {
815 		log_printf(dgettext(TEXT_DOMAIN,
816 			"failed in fill_device_array_from_id "
817 			"for FAN\n"
818 			"%s\n"), picl_strerror(err));
819 		return (err);
820 	}
821 
822 	log_printf("\n");
823 	log_printf(dgettext(TEXT_DOMAIN,
824 		"=================================\n"));
825 	log_printf("\n");
826 	log_printf(dgettext(TEXT_DOMAIN, "Fan Bank :\n"));
827 	log_printf(dgettext(TEXT_DOMAIN, "----------\n"));
828 	log_printf("\n");
829 	log_printf(dgettext(TEXT_DOMAIN, "Bank                        Speed "
830 				"        Status        Fan State\n"));
831 	log_printf(dgettext(TEXT_DOMAIN, "                           ( RPMS )"
832 				"	\n"));
833 	log_printf(dgettext(TEXT_DOMAIN, "----                       --------"
834 				"      ---------      ---------\n"));
835 
836 
837 	for (i = 0; i < DAK_MAX_FANS; i++) {
838 		char fan_state[PICL_PROPNAMELEN_MAX];
839 		fan_speed = 0;
840 		err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, name,
841 		    PICL_PROPNAMELEN_MAX);
842 		if (err == PICL_SUCCESS) {
843 			log_printf(dgettext(TEXT_DOMAIN, "%16-s"), name);
844 		} else {
845 			continue;
846 		}
847 
848 		err = picl_get_propval_by_name(fans[i], "Fan-speed",
849 			&fan_speed, sizeof (int32_t));
850 		if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) {
851 			log_printf(dgettext(TEXT_DOMAIN,
852 				"failed in picl_get_propval_by_name for "
853 				"fan speed\n"
854 				"%s\n"), picl_strerror(err));
855 			return (err);
856 		}
857 
858 		if ((strcmp(name, "CPU0_PRIM_FAN") != 0) &&
859 			(strcmp(name, "CPU1_PRIM_FAN") != 0)) {
860 			err = picl_get_propval_by_name(fans[i], "Fan-switch",
861 				enabled, PICL_PROPNAMELEN_MAX);
862 			if ((err != PICL_SUCCESS) &&
863 			    (err != PICL_INVALIDHANDLE)) {
864 				log_printf(dgettext(TEXT_DOMAIN,
865 					"failed in picl_get_propval_by_name for"
866 					" fan enabled/disabled\n"
867 					"%s\n"), picl_strerror(err));
868 				return (err);
869 			}
870 			/*
871 			 * Display the fan's speed and whether or not
872 			 * it's enabled.
873 			 */
874 			if (strcmp(enabled, "ON") == 0) {
875 				log_printf(dgettext(TEXT_DOMAIN,
876 					"\t     %4d        [ENABLED]"),
877 					fan_speed);
878 			} else {
879 				log_printf(dgettext(TEXT_DOMAIN,
880 					"\t        0        [DISABLED]"));
881 			}
882 
883 		} else {
884 			/* Display the fan's speed */
885 			log_printf(dgettext(TEXT_DOMAIN, "\t     %4d"),
886 				fan_speed);
887 			log_printf(dgettext(TEXT_DOMAIN,
888 				"        [ENABLED]"));
889 		}
890 
891 		err = picl_get_propval_by_name(fans[i], "State", fan_state,
892 			PICL_PROPNAMELEN_MAX);
893 		if (err != PICL_SUCCESS) {
894 			log_printf(dgettext(TEXT_DOMAIN,
895 				"picl_get_propval_by_name failed: %s"),
896 				picl_strerror(err));
897 			return (err);
898 		}
899 		log_printf(dgettext(TEXT_DOMAIN, "\t    %s\n"), fan_state);
900 	}
901 	log_printf("\n");
902 	log_printf(dgettext(TEXT_DOMAIN,
903 		"=================================\n"));
904 	log_printf("\n");
905 
906 	return (err);
907 }
908 
909 int
910 dak_env_print_disk(picl_nodehdl_t system_node)
911 {
912 	int		i, err;
913 	int32_t		number;
914 	picl_nodehdl_t	*disks;
915 	picl_nodehdl_t	disk_slots[DAK_MAX_DISKS];
916 	picl_nodehdl_t	disk_fault_leds[DAK_MAX_DISKS];
917 	picl_nodehdl_t	disk_remove_leds[DAK_MAX_DISKS];
918 	char		led_state[PICL_PROPNAMELEN_MAX];
919 	char		name[PICL_PROPNAMELEN_MAX];
920 
921 	err = fill_device_array_from_id(system_node, "PSVC_DISK", &number,
922 		&disks);
923 	if (err != PICL_SUCCESS) {
924 		log_printf(dgettext(TEXT_DOMAIN,
925 			"failed in fill_device_array_from_id for "
926 			"DISK\n"
927 			"%s\n"), picl_strerror(err));
928 		return (err);
929 	}
930 
931 	log_printf(dgettext(TEXT_DOMAIN,
932 		"Disk Status:\n"
933 		"	  Presence	Fault LED	Remove LED\n"));
934 
935 	for (i = 0; i < DAK_MAX_DISKS; i++) {
936 		err = picl_get_propval_by_name(disks[i], PICL_PROP_NAME, name,
937 		    PICL_PROPNAMELEN_MAX);
938 		switch (err) {
939 		case PICL_SUCCESS:
940 			log_printf(dgettext(TEXT_DOMAIN, "DISK  %2d: [%7s]"),
941 				i, "PRESENT");
942 			break;
943 		case PICL_INVALIDHANDLE:
944 			log_printf(dgettext(TEXT_DOMAIN, "DISK  %2d: [%7s]"),
945 				i, "EMPTY");
946 			log_printf("\n");
947 			continue;
948 		default:
949 			log_printf(dgettext(TEXT_DOMAIN,
950 				"Failed picl_get_propval_by_name for "
951 				"disk %d with %s\n"), i, picl_strerror(err));
952 			return (err);
953 		}
954 
955 		err = fill_device_from_id(disks[i], "PSVC_PARENT",
956 			&(disk_slots[i]));
957 		switch (err) {
958 		case PICL_SUCCESS:
959 			break;
960 		case PICL_INVALIDHANDLE:
961 			continue;
962 		default:
963 			log_printf(dgettext(TEXT_DOMAIN,
964 				"failed in fill_device_from_id for disk "
965 				"slot\n"
966 				"%s\n"), picl_strerror(err));
967 			return (err);
968 		}
969 
970 		err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_FAULT_LED",
971 		    &disk_fault_leds[i]);
972 		if (err != PICL_SUCCESS) {
973 			log_printf(dgettext(TEXT_DOMAIN,
974 				"failed in fill_device_from_id for disk slot "
975 				"fault led\n"
976 				"%s\n"), picl_strerror(err));
977 			return (err);
978 		}
979 		err = picl_get_propval_by_name(disk_fault_leds[i],
980 			"State", led_state, PICL_PROPNAMELEN_MAX);
981 		if (err == PICL_SUCCESS) {
982 			log_printf(dgettext(TEXT_DOMAIN, "	   [%3s]"),
983 				led_state);
984 		} else {
985 			log_printf(dgettext(TEXT_DOMAIN,
986 				"picl_get_propval_by_name for fault led_state"
987 				" failed\n"
988 				"%s\n"), picl_strerror(err));
989 			return (err);
990 		}
991 		err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_REMOVE_LED",
992 		    &disk_remove_leds[i]);
993 		if (err != PICL_SUCCESS) {
994 			log_printf(dgettext(TEXT_DOMAIN,
995 				"failed in fill_device_from_id for disk slot "
996 				"remove led\n"
997 				"%s\n"), picl_strerror(err));
998 			return (err);
999 		}
1000 
1001 		err = picl_get_propval_by_name(disk_remove_leds[i],
1002 			"State", led_state, PICL_PROPNAMELEN_MAX);
1003 		if (err == PICL_SUCCESS) {
1004 			log_printf(dgettext(TEXT_DOMAIN,
1005 				"	   [%3s]"), led_state);
1006 		} else {
1007 			log_printf(dgettext(TEXT_DOMAIN,
1008 				"picl_get_propval_by_name for remove"
1009 				" led_state failed\n"
1010 				"%s\n"), picl_strerror(err));
1011 			return (err);
1012 		}
1013 		log_printf("\n");
1014 	}
1015 	return (err);
1016 }
1017 
1018 int
1019 dak_env_print_FSP_LEDS(picl_nodehdl_t system_node)
1020 {
1021 	int		i, err = 0;
1022 	int32_t		number;
1023 	picl_nodehdl_t	*fsp_leds;
1024 	char		led_state[PICL_PROPNAMELEN_MAX];
1025 
1026 	err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number,
1027 	    &fsp_leds);
1028 	if (err != PICL_SUCCESS) {
1029 		log_printf(dgettext(TEXT_DOMAIN,
1030 			"failed in fill_device_array_from_id for "
1031 			"FSP_LED\n"
1032 			"%s\n"), picl_strerror(err));
1033 		return (err);
1034 	}
1035 
1036 	log_printf(dgettext(TEXT_DOMAIN,
1037 		"System LED Status:\n"
1038 		"                   GEN FAULT                REMOVE\n"));
1039 	for (i = 0; i < DAK_MAX_FSP_LEDS; i++) {
1040 		err = picl_get_propval_by_name(fsp_leds[i], "State",
1041 			led_state, PICL_PROPNAMELEN_MAX);
1042 		if (err != PICL_SUCCESS) {
1043 			log_printf(dgettext(TEXT_DOMAIN,
1044 				"picl_get_propval_by_name for led_state"
1045 				" failed\n"
1046 				"%s\n"), picl_strerror(err));
1047 			return (err);
1048 		}
1049 
1050 		log_printf(dgettext(TEXT_DOMAIN,
1051 			"                    [%3s]"), led_state);
1052 	}
1053 	log_printf("\n\n");
1054 	log_printf(dgettext(TEXT_DOMAIN,
1055 		"                   DISK FAULT               "));
1056 	log_printf(dgettext(TEXT_DOMAIN, "POWER FAULT\n"));
1057 	for (i = 2; i < 4; i++) {
1058 		err = picl_get_propval_by_name(fsp_leds[i], "State",
1059 			led_state, PICL_PROPNAMELEN_MAX);
1060 		if (err != PICL_SUCCESS) {
1061 			log_printf(dgettext(TEXT_DOMAIN,
1062 				"picl_get_propval_by_name for led_state"
1063 				" failed\n"
1064 				"%s\n"), picl_strerror(err));
1065 			return (err);
1066 		}
1067 		log_printf(dgettext(TEXT_DOMAIN, "                    [%3s]"),
1068 		    led_state);
1069 	}
1070 	log_printf("\n\n");
1071 	log_printf(dgettext(TEXT_DOMAIN,
1072 		"                   LEFT THERMAL FAULT       "
1073 		"RIGHT THERMAL FAULT\n"));
1074 	for (i = 4; i < 6; i++) {
1075 		err = picl_get_propval_by_name(fsp_leds[i], "State",
1076 		    led_state, PICL_PROPNAMELEN_MAX);
1077 		if (err != PICL_SUCCESS) {
1078 			log_printf(dgettext(TEXT_DOMAIN,
1079 				"picl_get_propval_by_name for led_state "
1080 				"failed\n"
1081 				"%s\n"), picl_strerror(err));
1082 			return (err);
1083 		}
1084 		log_printf(dgettext(TEXT_DOMAIN, "                    [%3s]"),
1085 			led_state);
1086 	}
1087 	log_printf("\n\n");
1088 	log_printf(dgettext(TEXT_DOMAIN,
1089 		"                   LEFT DOOR                "
1090 		"RIGHT DOOR\n"));
1091 	for (i = 6; i < 8; i++) {
1092 		err = picl_get_propval_by_name(fsp_leds[i], "State",
1093 		    led_state, PICL_PROPNAMELEN_MAX);
1094 		if (err != PICL_SUCCESS) {
1095 			log_printf(dgettext(TEXT_DOMAIN,
1096 				"picl_get_propval_by_name for led_state"
1097 				" failed\n"
1098 				"%s\n"), picl_strerror(err));
1099 			return (err);
1100 		}
1101 		log_printf(dgettext(TEXT_DOMAIN, "                    [%3s]"),
1102 			led_state);
1103 	}
1104 	log_printf("\n\n");
1105 	log_printf(dgettext(TEXT_DOMAIN,
1106 		"=================================\n"));
1107 	log_printf("\n");
1108 
1109 	return (err);
1110 }
1111 
1112 int
1113 dak_env_print_keyswitch(picl_nodehdl_t system_node)
1114 {
1115 	int 		err = 0;
1116 	picl_nodehdl_t *keyswitch;
1117 	int32_t		number;
1118 	char		ks_pos[PICL_PROPNAMELEN_MAX];
1119 
1120 	err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number,
1121 	    &keyswitch);
1122 	if (err != PICL_SUCCESS) {
1123 		log_printf(dgettext(TEXT_DOMAIN,
1124 			"failed in fill_device_array_from_id for "
1125 			"	PSVC_KEYSWITCH\n"
1126 			"%s\n"), picl_strerror(err));
1127 		return (err);
1128 	}
1129 
1130 	err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos,
1131 		PICL_PROPNAMELEN_MAX);
1132 	if (err != PICL_SUCCESS) {
1133 		log_printf(dgettext(TEXT_DOMAIN,
1134 			"picl_get_propval_by_name for keyswitch state "
1135 			"failed\n"
1136 			"%s\n"), picl_strerror(err));
1137 		return (err);
1138 	}
1139 
1140 	log_printf(dgettext(TEXT_DOMAIN,
1141 		"Front Status Panel:\n"
1142 		"-------------------\n"
1143 		"Keyswitch position: "
1144 		"%s\n"), ks_pos);
1145 	log_printf("\n");
1146 
1147 	return (err);
1148 }
1149 
1150 int
1151 dak_env_print_temps(picl_nodehdl_t system_node)
1152 {
1153 	int		i;
1154 	int		err;
1155 	picl_nodehdl_t	*system_ts_nodes;
1156 	int32_t		temp;
1157 	int32_t		number;
1158 	char		label[PICL_PROPNAMELEN_MAX];
1159 	char		state[PICL_PROPNAMELEN_MAX];
1160 	char		*p;
1161 
1162 	err = fill_device_array_from_id(system_node, "PSVC_TS", &number,
1163 	    &system_ts_nodes);
1164 	if (err != PICL_SUCCESS) {
1165 		return (err);
1166 	}
1167 
1168 	log_printf(dgettext(TEXT_DOMAIN,
1169 		"System Temperatures (Celsius):\n"
1170 		"-------------------------------\n"
1171 		"Device\t\tTemperature\tStatus\n"
1172 		"---------------------------------------\n"));
1173 
1174 	for (i = 0; i < number; i++) {
1175 		err = picl_get_propval_by_name(system_ts_nodes[i],
1176 		    "State", state, sizeof (state));
1177 		if (err != PICL_SUCCESS) {
1178 			if (err == PICL_INVALIDHANDLE) {
1179 				strcpy(state, "n/a");
1180 			} else {
1181 				log_printf("%s\n", picl_strerror(err));
1182 				return (err);
1183 			}
1184 		}
1185 		err = picl_get_propval_by_name(system_ts_nodes[i],
1186 		    PICL_PROP_NAME, label, PICL_PROPNAMELEN_MAX);
1187 		if (err != PICL_SUCCESS) {
1188 			if (err == PICL_INVALIDHANDLE)
1189 				/* This FRU isn't present. Skip it. */
1190 				continue;
1191 			log_printf("%s\n", picl_strerror(err));
1192 			return (err);
1193 		}
1194 
1195 		/*
1196 		 * The names in the tree are like "CPU0_DIE_TEMPERATURE_SENSOR".
1197 		 * All we want to print is up to the first underscore.
1198 		 */
1199 		p = strchr(label, '_');
1200 		if (p != NULL)
1201 			*p = '\0';
1202 
1203 		err = picl_get_propval_by_name(system_ts_nodes[i],
1204 				"Temperature", &temp, sizeof (temp));
1205 		if (err != PICL_SUCCESS) {
1206 			log_printf("%s\n", picl_strerror(err));
1207 			return (err);
1208 		}
1209 		log_printf("%s\t\t%3d\t\t%s\n", label, temp, state);
1210 	}
1211 
1212 	log_printf(dgettext(TEXT_DOMAIN,
1213 		"\n=================================\n\n"));
1214 
1215 	return (PICL_SUCCESS);
1216 }
1217 
1218 static void
1219 dak_display_hw_revisions(Prom_node *root, Board_node *bdlist)
1220 {
1221 	Prom_node	*pnode;
1222 	char		*value;
1223 
1224 	log_printf(dgettext(TEXT_DOMAIN, "\n"
1225 		"========================= HW Revisions "
1226 		"=======================================\n\n"));
1227 
1228 	log_printf(dgettext(TEXT_DOMAIN,
1229 		"System PROM revisions:\n"
1230 		"----------------------\n"));
1231 
1232 	pnode = dev_find_node(root, "openprom");
1233 	if (pnode != NULL) {
1234 	    value = (char *)get_prop_val(find_prop(pnode, "version"));
1235 	    log_printf(value);
1236 	}
1237 
1238 	log_printf(dgettext(TEXT_DOMAIN, "\n\n"
1239 		"IO ASIC revisions:\n"
1240 		"------------------\n"
1241 		"         Port\n"
1242 		"Model     ID  Status Version\n"
1243 		"-------- ---- ------ -------\n"));
1244 
1245 	display_schizo_revisions(bdlist);
1246 }
1247 
1248 static void
1249 display_schizo_revisions(Board_node *bdlist)
1250 {
1251 	Prom_node	*pnode;
1252 	int		*int_val;
1253 	int		portid;
1254 	int		prev_portid = -1;
1255 	char		*status_a = NULL;
1256 	char		*status_b = NULL;
1257 	int		revision;
1258 #ifdef DEBUG
1259 	uint32_t	a_notes, b_notes;
1260 #endif
1261 	int		pci_bus;
1262 	Board_node	*bnode;
1263 	bnode = bdlist;
1264 
1265 	while (bnode != NULL) {
1266 		/*
1267 		 * search this board node for all Schizos
1268 		 */
1269 		for (pnode = dev_find_node_by_compat(bnode->nodes,
1270 			SCHIZO_COMPAT_PROP); pnode != NULL;
1271 			pnode = dev_next_node_by_compat(pnode,
1272 			    SCHIZO_COMPAT_PROP)) {
1273 
1274 			/*
1275 			 * get the reg property to determine
1276 			 * whether we are looking at side A or B
1277 			 */
1278 			int_val = (int *)get_prop_val
1279 				(find_prop(pnode, "reg"));
1280 			if (int_val != NULL) {
1281 				int_val ++; /* second integer in array */
1282 				pci_bus = ((*int_val) & 0x7f0000);
1283 			}
1284 
1285 			/* get portid */
1286 			int_val = (int *)get_prop_val
1287 				(find_prop(pnode, "portid"));
1288 			if (int_val == NULL)
1289 				continue;
1290 
1291 			portid = *int_val;
1292 
1293 			/*
1294 			 * If this is a new portid and it is PCI bus B,
1295 			 * we skip onto the PCI bus A.
1296 			 */
1297 			if ((portid != prev_portid) && (pci_bus == 0x700000)) {
1298 				prev_portid = portid;
1299 				/* status */
1300 				status_b = (char *)get_prop_val
1301 				    (find_prop(pnode, "status"));
1302 #ifdef DEBUG
1303 				b_notes = pci_bus;
1304 #endif
1305 				continue; /* skip to the next schizo */
1306 			}
1307 
1308 			/*
1309 			 * This must be side A of the same Schizo.
1310 			 * Gather all its props and display them.
1311 			 */
1312 #ifdef DEBUG
1313 			a_notes = pci_bus;
1314 #endif
1315 
1316 			prev_portid = portid;
1317 
1318 			int_val = (int *)get_prop_val
1319 				(find_prop(pnode, "version#"));
1320 			if (int_val != NULL)
1321 				revision = *int_val;
1322 			else
1323 				revision = -1;
1324 
1325 			status_a = (char *)get_prop_val(find_prop
1326 				(pnode, "status"));
1327 
1328 			log_printf(dgettext(TEXT_DOMAIN, "Schizo    "));
1329 
1330 			log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0);
1331 
1332 
1333 			log_printf((status_a == NULL && status_b == NULL) ?
1334 				dgettext(TEXT_DOMAIN, "  ok  ") :
1335 				dgettext(TEXT_DOMAIN, " fail "));
1336 
1337 			log_printf(dgettext(TEXT_DOMAIN, " %4d   "),
1338 			    revision);
1339 #ifdef DEBUG
1340 			log_printf(" 0x%x 0x%x", a_notes, b_notes);
1341 #endif
1342 			log_printf("\n");
1343 		}
1344 		bnode = bnode->next;
1345 	}
1346 }
1347