xref: /onnv-gate/usr/src/lib/libprtdiag_psr/sparc/desktop/common/desktop.c (revision 1708:ea74d8598a3a)
1*1708Sstevel /*
2*1708Sstevel  * CDDL HEADER START
3*1708Sstevel  *
4*1708Sstevel  * The contents of this file are subject to the terms of the
5*1708Sstevel  * Common Development and Distribution License, Version 1.0 only
6*1708Sstevel  * (the "License").  You may not use this file except in compliance
7*1708Sstevel  * with the License.
8*1708Sstevel  *
9*1708Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*1708Sstevel  * or http://www.opensolaris.org/os/licensing.
11*1708Sstevel  * See the License for the specific language governing permissions
12*1708Sstevel  * and limitations under the License.
13*1708Sstevel  *
14*1708Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
15*1708Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*1708Sstevel  * If applicable, add the following below this CDDL HEADER, with the
17*1708Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
18*1708Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
19*1708Sstevel  *
20*1708Sstevel  * CDDL HEADER END
21*1708Sstevel  */
22*1708Sstevel /*
23*1708Sstevel  * Copyright 1999-2002 Sun Microsystems, Inc.  All rights reserved.
24*1708Sstevel  * Use is subject to license terms.
25*1708Sstevel  *
26*1708Sstevel  * Desktop Platform specific functions.
27*1708Sstevel  *
28*1708Sstevel  *	Called when:
29*1708Sstevel  *	machine_type == MTYPE_DARWIN &&
30*1708Sstevel  *	machine_type == MTYPE_DEFAULT
31*1708Sstevel  *
32*1708Sstevel  */
33*1708Sstevel 
34*1708Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
35*1708Sstevel 
36*1708Sstevel #include <stdio.h>
37*1708Sstevel #include <stdlib.h>
38*1708Sstevel #include <unistd.h>
39*1708Sstevel #include <ctype.h>
40*1708Sstevel #include <string.h>
41*1708Sstevel #include <kvm.h>
42*1708Sstevel #include <varargs.h>
43*1708Sstevel #include <errno.h>
44*1708Sstevel #include <time.h>
45*1708Sstevel #include <dirent.h>
46*1708Sstevel #include <fcntl.h>
47*1708Sstevel #include <sys/param.h>
48*1708Sstevel #include <sys/stat.h>
49*1708Sstevel #include <sys/types.h>
50*1708Sstevel #include <sys/systeminfo.h>
51*1708Sstevel #include <sys/utsname.h>
52*1708Sstevel #include <sys/openpromio.h>
53*1708Sstevel #include <kstat.h>
54*1708Sstevel #include <libintl.h>
55*1708Sstevel #include <syslog.h>
56*1708Sstevel #include <sys/dkio.h>
57*1708Sstevel #include "pdevinfo.h"
58*1708Sstevel #include "display.h"
59*1708Sstevel #include "pdevinfo_sun4u.h"
60*1708Sstevel #include "display_sun4u.h"
61*1708Sstevel #include "libprtdiag.h"
62*1708Sstevel 
63*1708Sstevel #if !defined(TEXT_DOMAIN)
64*1708Sstevel #define	TEXT_DOMAIN	"SYS_TEST"
65*1708Sstevel #endif
66*1708Sstevel 
67*1708Sstevel 
68*1708Sstevel #define	PCI_BUS(x)		((x  >> 16) & 0xff)
69*1708Sstevel 
70*1708Sstevel /*
71*1708Sstevel  * State variable to signify the type of machine we're currently
72*1708Sstevel  * running on.  Since prtdiag has come to be the dumping ground
73*1708Sstevel  * for lots of platform-specific routines, and machine architecture
74*1708Sstevel  * alone is not enough to determine our course of action, we need
75*1708Sstevel  * to enumerate the different machine types that we should worry
76*1708Sstevel  * about.
77*1708Sstevel  */
78*1708Sstevel enum machine_type {
79*1708Sstevel 	MTYPE_DEFAULT = 0,  /* Desktop-class machine */
80*1708Sstevel 	MTYPE_DARWIN = 1
81*1708Sstevel };
82*1708Sstevel 
83*1708Sstevel enum machine_type machine_type = MTYPE_DEFAULT;
84*1708Sstevel 
85*1708Sstevel extern	int	print_flag;
86*1708Sstevel 
87*1708Sstevel /*
88*1708Sstevel  * these functions will overlay the symbol table of libprtdiag
89*1708Sstevel  * at runtime (desktop systems only)
90*1708Sstevel  */
91*1708Sstevel int	error_check(Sys_tree *tree, struct system_kstat_data *kstats);
92*1708Sstevel void 	display_memoryconf(Sys_tree *tree, struct grp_info *grps);
93*1708Sstevel int	disp_fail_parts(Sys_tree *tree);
94*1708Sstevel void	display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats);
95*1708Sstevel void	display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
96*1708Sstevel 		struct system_kstat_data *kstats);
97*1708Sstevel void	display_pci(Board_node *bnode);
98*1708Sstevel void	read_platform_kstats(Sys_tree *tree,
99*1708Sstevel 		struct system_kstat_data *sys_kstat,
100*1708Sstevel 		struct bd_kstat_data *bdp, struct envctrl_kstat_data *ep);
101*1708Sstevel void	display_sbus(Board_node *);
102*1708Sstevel 
103*1708Sstevel 
104*1708Sstevel /* local functions */
105*1708Sstevel static	void dt_disp_asic_revs(Sys_tree *);
106*1708Sstevel static	void display_sabre_pci(Board_node *);
107*1708Sstevel static	void display_dev_node(Prom_node *np, int depth);
108*1708Sstevel static	void get_machine_type(void);
109*1708Sstevel 
110*1708Sstevel int
error_check(Sys_tree * tree,struct system_kstat_data * kstats)111*1708Sstevel error_check(Sys_tree *tree, struct system_kstat_data *kstats)
112*1708Sstevel {
113*1708Sstevel 	int exit_code = 0;	/* init to all OK */
114*1708Sstevel 
115*1708Sstevel #ifdef lint
116*1708Sstevel 	kstats = kstats;
117*1708Sstevel #endif
118*1708Sstevel 
119*1708Sstevel 	/*
120*1708Sstevel 	 * silently check for any types of machine errors
121*1708Sstevel 	 */
122*1708Sstevel 	print_flag = 0;
123*1708Sstevel 	if (disp_fail_parts(tree)) {
124*1708Sstevel 		/* set exit_code to show failures */
125*1708Sstevel 		exit_code = 1;
126*1708Sstevel 	}
127*1708Sstevel 	print_flag = 1;
128*1708Sstevel 
129*1708Sstevel 	return (exit_code);
130*1708Sstevel }
131*1708Sstevel 
132*1708Sstevel 
133*1708Sstevel void
display_memoryconf(Sys_tree * tree,struct grp_info * grps)134*1708Sstevel display_memoryconf(Sys_tree *tree, struct grp_info *grps)
135*1708Sstevel {
136*1708Sstevel #ifdef lint
137*1708Sstevel 	tree = tree;
138*1708Sstevel 	grps = grps;
139*1708Sstevel #endif
140*1708Sstevel }
141*1708Sstevel 
142*1708Sstevel /*
143*1708Sstevel  * disp_fail_parts
144*1708Sstevel  *
145*1708Sstevel  * Display the failed parts in the system. This function looks for
146*1708Sstevel  * the status property in all PROM nodes. On systems where
147*1708Sstevel  * the PROM does not supports passing diagnostic information
148*1708Sstevel  * thruogh the device tree, this routine will be silent.
149*1708Sstevel  */
150*1708Sstevel int
disp_fail_parts(Sys_tree * tree)151*1708Sstevel disp_fail_parts(Sys_tree *tree)
152*1708Sstevel {
153*1708Sstevel 	int exit_code;
154*1708Sstevel 	int system_failed = 0;
155*1708Sstevel 	Board_node *bnode = tree->bd_list;
156*1708Sstevel 	Prom_node *pnode;
157*1708Sstevel 
158*1708Sstevel 	exit_code = 0;
159*1708Sstevel 
160*1708Sstevel 	/* go through all of the boards looking for failed units. */
161*1708Sstevel 	while (bnode != NULL) {
162*1708Sstevel 		/* find failed chips */
163*1708Sstevel 		pnode = find_failed_node(bnode->nodes);
164*1708Sstevel 		if ((pnode != NULL) && !system_failed) {
165*1708Sstevel 			system_failed = 1;
166*1708Sstevel 			exit_code = 1;
167*1708Sstevel 			if (print_flag == 0) {
168*1708Sstevel 				return (exit_code);
169*1708Sstevel 			}
170*1708Sstevel 			log_printf("\n", 0);
171*1708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "Failed Field "
172*1708Sstevel 				"Replaceable Units (FRU) in System:\n"), 0);
173*1708Sstevel 			log_printf("=========================="
174*1708Sstevel 				"====================\n", 0);
175*1708Sstevel 		}
176*1708Sstevel 
177*1708Sstevel 		while (pnode != NULL) {
178*1708Sstevel 			void *value;
179*1708Sstevel 			char *name;		/* node name string */
180*1708Sstevel 			char *type;		/* node type string */
181*1708Sstevel 			char *board_type = NULL;
182*1708Sstevel 
183*1708Sstevel 			value = get_prop_val(find_prop(pnode, "status"));
184*1708Sstevel 			name = get_node_name(pnode);
185*1708Sstevel 
186*1708Sstevel 			/* sanity check of data retreived from PROM */
187*1708Sstevel 			if ((value == NULL) || (name == NULL)) {
188*1708Sstevel 				pnode = next_failed_node(pnode);
189*1708Sstevel 				continue;
190*1708Sstevel 			}
191*1708Sstevel 
192*1708Sstevel 			/* Find the board type of this board */
193*1708Sstevel 			if (bnode->board_type == CPU_BOARD) {
194*1708Sstevel 				board_type = "CPU";
195*1708Sstevel 			} else {
196*1708Sstevel 				board_type = "IO";
197*1708Sstevel 			}
198*1708Sstevel 
199*1708Sstevel 			log_printf(dgettext(TEXT_DOMAIN, "%s unavailable "
200*1708Sstevel 				"on %s Board #%d\n"), name, board_type,
201*1708Sstevel 					bnode->board_num, 0);
202*1708Sstevel 
203*1708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
204*1708Sstevel 				"\tPROM fault string: %s\n"), value, 0);
205*1708Sstevel 
206*1708Sstevel 			log_printf(dgettext(TEXT_DOMAIN,
207*1708Sstevel 				"\tFailed Field Replaceable Unit is "), 0);
208*1708Sstevel 
209*1708Sstevel 			/*
210*1708Sstevel 			 * Determine whether FRU is CPU module, system
211*1708Sstevel 			 * board, or SBus card.
212*1708Sstevel 			 */
213*1708Sstevel 			if ((name != NULL) && (strstr(name, "sbus"))) {
214*1708Sstevel 
215*1708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
216*1708Sstevel 					"SBus Card %d\n"),
217*1708Sstevel 					get_sbus_slot(pnode), 0);
218*1708Sstevel 
219*1708Sstevel 			} else if (((name = get_node_name(pnode->parent)) !=
220*1708Sstevel 			    NULL) && (strstr(name, "pci"))) {
221*1708Sstevel 
222*1708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
223*1708Sstevel 					"PCI Card %d"),
224*1708Sstevel 					get_pci_device(pnode), 0);
225*1708Sstevel 
226*1708Sstevel 			} else if (((type = get_node_type(pnode)) != NULL) &&
227*1708Sstevel 			    (strstr(type, "cpu"))) {
228*1708Sstevel 
229*1708Sstevel 				log_printf(dgettext(TEXT_DOMAIN, "UltraSPARC "
230*1708Sstevel 					"module Board %d Module %d\n"), 0,
231*1708Sstevel 						get_id(pnode));
232*1708Sstevel 
233*1708Sstevel 			} else {
234*1708Sstevel 				log_printf(dgettext(TEXT_DOMAIN,
235*1708Sstevel 					"%s board %d\n"), board_type,
236*1708Sstevel 					bnode->board_num, 0);
237*1708Sstevel 			}
238*1708Sstevel 			pnode = next_failed_node(pnode);
239*1708Sstevel 		}
240*1708Sstevel 		bnode = bnode->next;
241*1708Sstevel 	}
242*1708Sstevel 
243*1708Sstevel 	if (!system_failed) {
244*1708Sstevel 		log_printf("\n", 0);
245*1708Sstevel 		log_printf(dgettext(TEXT_DOMAIN,
246*1708Sstevel 			"No failures found in System\n"), 0);
247*1708Sstevel 		log_printf("===========================\n", 0);
248*1708Sstevel 	}
249*1708Sstevel 
250*1708Sstevel 	if (system_failed)
251*1708Sstevel 		return (1);
252*1708Sstevel 	else
253*1708Sstevel 		return (0);
254*1708Sstevel }
255*1708Sstevel 
256*1708Sstevel 
257*1708Sstevel void
display_hp_fail_fault(Sys_tree * tree,struct system_kstat_data * kstats)258*1708Sstevel display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats)
259*1708Sstevel {
260*1708Sstevel 
261*1708Sstevel #ifdef lint
262*1708Sstevel 	kstats = kstats;
263*1708Sstevel #endif
264*1708Sstevel 	/* Display failed units */
265*1708Sstevel 	(void) disp_fail_parts(tree);
266*1708Sstevel }
267*1708Sstevel 
268*1708Sstevel void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)269*1708Sstevel display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
270*1708Sstevel 	struct system_kstat_data *kstats)
271*1708Sstevel {
272*1708Sstevel 
273*1708Sstevel #ifdef	lint
274*1708Sstevel 	kstats = kstats;
275*1708Sstevel #endif
276*1708Sstevel 	/*
277*1708Sstevel 	 * Now display the last powerfail time and the fatal hardware
278*1708Sstevel 	 * reset information. We do this under a couple of conditions.
279*1708Sstevel 	 * First if the user asks for it. The second is iof the user
280*1708Sstevel 	 * told us to do logging, and we found a system failure.
281*1708Sstevel 	 */
282*1708Sstevel 	if (flag) {
283*1708Sstevel 		/*
284*1708Sstevel 		 * display time of latest powerfail. Not all systems
285*1708Sstevel 		 * have this capability. For those that do not, this
286*1708Sstevel 		 * is just a no-op.
287*1708Sstevel 		 */
288*1708Sstevel 		disp_powerfail(root);
289*1708Sstevel 
290*1708Sstevel 		dt_disp_asic_revs(tree);
291*1708Sstevel 
292*1708Sstevel 		platform_disp_prom_version(tree);
293*1708Sstevel 	}
294*1708Sstevel 	return;
295*1708Sstevel 
296*1708Sstevel }
297*1708Sstevel 
298*1708Sstevel void
display_pci(Board_node * bnode)299*1708Sstevel display_pci(Board_node *bnode)
300*1708Sstevel {
301*1708Sstevel 	Prom_node	*pci;
302*1708Sstevel 
303*1708Sstevel 	/*
304*1708Sstevel 	 * We have different routines for walking/displaying PCI
305*1708Sstevel 	 * devices depending on whether the PCI device is a
306*1708Sstevel 	 * Psycho or a Sabre.
307*1708Sstevel 	 */
308*1708Sstevel 	pci = dev_find_node_by_type(bnode->nodes, "model", "SUNW,psycho");
309*1708Sstevel 	if (pci != NULL) {
310*1708Sstevel 		display_psycho_pci(bnode);
311*1708Sstevel 		return;
312*1708Sstevel 	}
313*1708Sstevel 
314*1708Sstevel 	pci = dev_find_node_by_type(bnode->nodes, "model", "SUNW,sabre");
315*1708Sstevel 	if (pci != NULL) {
316*1708Sstevel 		display_sabre_pci(bnode);
317*1708Sstevel 		return;
318*1708Sstevel 	}
319*1708Sstevel }
320*1708Sstevel 
321*1708Sstevel void
read_platform_kstats(Sys_tree * tree,struct system_kstat_data * sys_kstat,struct bd_kstat_data * bdp,struct envctrl_kstat_data * ep)322*1708Sstevel read_platform_kstats(Sys_tree *tree, struct system_kstat_data *sys_kstat,
323*1708Sstevel 	struct bd_kstat_data *bdp, struct envctrl_kstat_data *ep)
324*1708Sstevel 
325*1708Sstevel {
326*1708Sstevel #ifdef	lint
327*1708Sstevel 	tree = tree;
328*1708Sstevel 	sys_kstat = sys_kstat;
329*1708Sstevel 	bdp = bdp;
330*1708Sstevel 	ep = ep;
331*1708Sstevel #endif
332*1708Sstevel }
333*1708Sstevel 
334*1708Sstevel 
335*1708Sstevel /*
336*1708Sstevel  * local functions
337*1708Sstevel  */
338*1708Sstevel 
339*1708Sstevel void
dt_disp_asic_revs(Sys_tree * tree)340*1708Sstevel dt_disp_asic_revs(Sys_tree *tree)
341*1708Sstevel {
342*1708Sstevel 	Board_node *bnode;
343*1708Sstevel 	Prom_node *pnode;
344*1708Sstevel 	char *name;
345*1708Sstevel 	int *version;
346*1708Sstevel 
347*1708Sstevel 	/* Print the header */
348*1708Sstevel 	log_printf("\n", 0);
349*1708Sstevel 	log_printf("=========================", 0);
350*1708Sstevel 	log_printf(" HW Revisions ", 0);
351*1708Sstevel 	log_printf("=========================", 0);
352*1708Sstevel 	log_printf("\n", 0);
353*1708Sstevel 	log_printf("\n", 0);
354*1708Sstevel 
355*1708Sstevel 	bnode = tree->bd_list;
356*1708Sstevel 
357*1708Sstevel 	log_printf("ASIC Revisions:\n", 0);
358*1708Sstevel 	log_printf("---------------\n", 0);
359*1708Sstevel 
360*1708Sstevel 	/* Find sysio and print rev */
361*1708Sstevel 	for (pnode = dev_find_node(bnode->nodes, "sbus"); pnode != NULL;
362*1708Sstevel 	    pnode = dev_next_node(pnode, "sbus")) {
363*1708Sstevel 		version = (int *)get_prop_val(find_prop(pnode, "version#"));
364*1708Sstevel 		name = get_prop_val(find_prop(pnode, "name"));
365*1708Sstevel 
366*1708Sstevel 		if ((version != NULL) && (name != NULL)) {
367*1708Sstevel 			log_printf("SBus: %s Rev %d\n",
368*1708Sstevel 				name, *version, 0);
369*1708Sstevel 		}
370*1708Sstevel 	}
371*1708Sstevel 
372*1708Sstevel 	/* Find Psycho and print rev */
373*1708Sstevel 	for (pnode = dev_find_node(bnode->nodes, "pci"); pnode != NULL;
374*1708Sstevel 	    pnode = dev_next_node(pnode, "pci")) {
375*1708Sstevel 		version = (int *)get_prop_val(find_prop(pnode, "version#"));
376*1708Sstevel 		name = get_prop_val(find_prop(pnode, "name"));
377*1708Sstevel 
378*1708Sstevel 		if ((version != NULL) && (name != NULL))
379*1708Sstevel 			log_printf("PCI: %s Rev %d\n",
380*1708Sstevel 				name, *version, 0);
381*1708Sstevel 	}
382*1708Sstevel 
383*1708Sstevel 	/* Find Cheerio and print rev */
384*1708Sstevel 	for (pnode = dev_find_node(bnode->nodes, "ebus"); pnode != NULL;
385*1708Sstevel 	    pnode = dev_next_node(pnode, "ebus")) {
386*1708Sstevel 		version = (int *)get_prop_val(find_prop(pnode, "revision-id"));
387*1708Sstevel 		name = get_prop_val(find_prop(pnode, "name"));
388*1708Sstevel 
389*1708Sstevel 		if ((version != NULL) && (name != NULL))
390*1708Sstevel 			log_printf("Cheerio: %s Rev %d\n", name, *version, 0);
391*1708Sstevel 	}
392*1708Sstevel 
393*1708Sstevel 
394*1708Sstevel 	/* Find the FEPS and print rev */
395*1708Sstevel 	for (pnode = dev_find_node(bnode->nodes, "SUNW,hme"); pnode != NULL;
396*1708Sstevel 	    pnode = dev_next_node(pnode, "SUNW,hme")) {
397*1708Sstevel 		version = (int *)get_prop_val(find_prop(pnode,	"hm-rev"));
398*1708Sstevel 		name = get_prop_val(find_prop(pnode, "name"));
399*1708Sstevel 
400*1708Sstevel 		if ((version != NULL) && (name != NULL)) {
401*1708Sstevel 			log_printf("FEPS: %s Rev ", name);
402*1708Sstevel 			if (*version == 0xa0) {
403*1708Sstevel 				log_printf("2.0\n", 0);
404*1708Sstevel 			} else if (*version == 0x20) {
405*1708Sstevel 				log_printf("2.1\n", 0);
406*1708Sstevel 			} else {
407*1708Sstevel 				log_printf("%x\n", *version, 0);
408*1708Sstevel 			}
409*1708Sstevel 		}
410*1708Sstevel 	}
411*1708Sstevel 	log_printf("\n", 0);
412*1708Sstevel 
413*1708Sstevel 	display_ffb(bnode, 0);
414*1708Sstevel }
415*1708Sstevel 
416*1708Sstevel /*
417*1708Sstevel  * print the header and call display_dev_node() to walk the device
418*1708Sstevel  * tree (darwin platform only).
419*1708Sstevel  */
420*1708Sstevel static void
display_sabre_pci(Board_node * board)421*1708Sstevel display_sabre_pci(Board_node *board)
422*1708Sstevel {
423*1708Sstevel 	if (board == NULL)
424*1708Sstevel 		return;
425*1708Sstevel 
426*1708Sstevel 	log_printf("     Bus#  Freq\n", 0);
427*1708Sstevel 	log_printf("Brd  Type  MHz   Slot  "
428*1708Sstevel 		"Name                              Model", 0);
429*1708Sstevel 	log_printf("\n", 0);
430*1708Sstevel 	log_printf("---  ----  ----  ----  "
431*1708Sstevel 		"--------------------------------  ----------------------", 0);
432*1708Sstevel 	log_printf("\n", 0);
433*1708Sstevel 	display_dev_node(board->nodes, 0);
434*1708Sstevel 	log_printf("\n", 0);
435*1708Sstevel }
436*1708Sstevel 
437*1708Sstevel 
438*1708Sstevel /*
439*1708Sstevel  * Recursively traverse the device tree and use tree depth as filter.
440*1708Sstevel  * called by: display_sabre_pci()
441*1708Sstevel  */
442*1708Sstevel static void
display_dev_node(Prom_node * np,int depth)443*1708Sstevel display_dev_node(Prom_node *np, int depth)
444*1708Sstevel {
445*1708Sstevel 	char *name, *model, *compat, *regval;
446*1708Sstevel 	unsigned int reghi;
447*1708Sstevel 
448*1708Sstevel 	if (!np)
449*1708Sstevel 		return;
450*1708Sstevel 	if (depth > 2)
451*1708Sstevel 		return;
452*1708Sstevel 
453*1708Sstevel 	name = get_prop_val(find_prop(np, "name"));
454*1708Sstevel 	model = get_prop_val(find_prop(np, "model"));
455*1708Sstevel 	compat = get_prop_val(find_prop(np, "compatible"));
456*1708Sstevel 	regval = get_prop_val(find_prop(np, "reg"));
457*1708Sstevel 
458*1708Sstevel 	if (!regval)
459*1708Sstevel 		return;
460*1708Sstevel 	else
461*1708Sstevel 		reghi = *(int *)regval;
462*1708Sstevel 
463*1708Sstevel 	if (!model)
464*1708Sstevel 		model = "";
465*1708Sstevel 	if (!name)
466*1708Sstevel 		name = "";
467*1708Sstevel 
468*1708Sstevel 	if (depth == 2) {
469*1708Sstevel 		char buf[256];
470*1708Sstevel 		if (compat)
471*1708Sstevel 			(void) sprintf(buf, "%s-%s", name, compat);
472*1708Sstevel 		else
473*1708Sstevel 			(void) sprintf(buf, "%s", name);
474*1708Sstevel 
475*1708Sstevel 		log_printf(" 0   PCI-%d  33   ", PCI_BUS(reghi), 0);
476*1708Sstevel 		log_printf("%3d   ", PCI_DEVICE(reghi), 0);
477*1708Sstevel 		log_printf("%-32.32s", buf, 0);
478*1708Sstevel 		log_printf(strlen(buf) > 32 ? "+ " : "  ", 0);
479*1708Sstevel 		log_printf("%-22.22s", model, 0);
480*1708Sstevel 		log_printf(strlen(model) > 22 ? "+" : "", 0);
481*1708Sstevel 		log_printf("\n", 0);
482*1708Sstevel 
483*1708Sstevel #ifdef DEBUG
484*1708Sstevel 		if (!compat)
485*1708Sstevel 			compat = "";
486*1708Sstevel 		printf("bus=%d slot=%d name=%s model=%s compat=%s\n",
487*1708Sstevel 			PCI_BUS(reghi), PCI_DEVICE(reghi), name, model, compat);
488*1708Sstevel #endif
489*1708Sstevel 	}
490*1708Sstevel 
491*1708Sstevel 	if ((!strstr(name, "ebus")) && (!strstr(name, "ide")))
492*1708Sstevel 		display_dev_node(np->child, depth+1);
493*1708Sstevel 	display_dev_node(np->sibling, depth);
494*1708Sstevel }
495*1708Sstevel 
496*1708Sstevel /*
497*1708Sstevel  * display_sbus
498*1708Sstevel  * Display all the SBus IO cards on this board.
499*1708Sstevel  */
500*1708Sstevel void
display_sbus(Board_node * board)501*1708Sstevel display_sbus(Board_node *board)
502*1708Sstevel {
503*1708Sstevel 	struct io_card card;
504*1708Sstevel 	struct io_card *card_list = NULL;
505*1708Sstevel 	int freq;
506*1708Sstevel 	int card_num;
507*1708Sstevel 	void *value;
508*1708Sstevel 	Prom_node *sbus;
509*1708Sstevel 	Prom_node *card_node;
510*1708Sstevel 
511*1708Sstevel 	if (board == NULL)
512*1708Sstevel 		return;
513*1708Sstevel 
514*1708Sstevel 	for (sbus = dev_find_node(board->nodes, SBUS_NAME); sbus != NULL;
515*1708Sstevel 	    sbus = dev_next_node(sbus, SBUS_NAME)) {
516*1708Sstevel 
517*1708Sstevel 		/* Skip failed nodes for now */
518*1708Sstevel 		if (node_failed(sbus))
519*1708Sstevel 			continue;
520*1708Sstevel 
521*1708Sstevel 		/* Calculate SBus frequency in MHz */
522*1708Sstevel 		value = get_prop_val(find_prop(sbus, "clock-frequency"));
523*1708Sstevel 		if (value != NULL)
524*1708Sstevel 			freq = ((*(int *)value) + 500000) / 1000000;
525*1708Sstevel 		else
526*1708Sstevel 			freq = -1;
527*1708Sstevel 
528*1708Sstevel 		for (card_node = sbus->child; card_node != NULL;
529*1708Sstevel 		    card_node = card_node->sibling) {
530*1708Sstevel 			char *model;
531*1708Sstevel 			char *name;
532*1708Sstevel 			char *child_name;
533*1708Sstevel 
534*1708Sstevel 			card_num = get_sbus_slot(card_node);
535*1708Sstevel 			if (card_num == -1)
536*1708Sstevel 				continue;
537*1708Sstevel 
538*1708Sstevel 			/* Fill in card information */
539*1708Sstevel 			card.display = 1;
540*1708Sstevel 			card.freq = freq;
541*1708Sstevel 			card.board = board->board_num;
542*1708Sstevel 			(void) sprintf(card.bus_type, "SBus");
543*1708Sstevel 			card.slot = card_num;
544*1708Sstevel 			card.status[0] = '\0';
545*1708Sstevel 
546*1708Sstevel 			/* Try and get card status */
547*1708Sstevel 			value = get_prop_val(find_prop(card_node, "status"));
548*1708Sstevel 			if (value != NULL)
549*1708Sstevel 				(void) strncpy(card.status, (char *)value,
550*1708Sstevel 					MAXSTRLEN);
551*1708Sstevel 
552*1708Sstevel 			/* XXX - For now, don't display failed cards */
553*1708Sstevel 			if (strstr(card.status, "fail") != NULL)
554*1708Sstevel 				continue;
555*1708Sstevel 
556*1708Sstevel 			/*
557*1708Sstevel 			 * sets the machine_type var if not already set
558*1708Sstevel 			 */
559*1708Sstevel 			get_machine_type();
560*1708Sstevel 
561*1708Sstevel 			/*
562*1708Sstevel 			 * For desktops, the only high slot number that
563*1708Sstevel 			 * needs to be displayed is the # 14 slot.
564*1708Sstevel 			 */
565*1708Sstevel 			if (machine_type == MTYPE_DEFAULT &&
566*1708Sstevel 			    card_num >= MX_SBUS_SLOTS && card_num != 14) {
567*1708Sstevel 				continue;
568*1708Sstevel 			}
569*1708Sstevel 
570*1708Sstevel 			/* Now gather all of the node names for that card */
571*1708Sstevel 			model = (char *)get_prop_val(find_prop(card_node,
572*1708Sstevel 				"model"));
573*1708Sstevel 			name = get_node_name(card_node);
574*1708Sstevel 
575*1708Sstevel 			if (name == NULL)
576*1708Sstevel 				continue;
577*1708Sstevel 
578*1708Sstevel 			card.name[0] = '\0';
579*1708Sstevel 			card.model[0] = '\0';
580*1708Sstevel 
581*1708Sstevel 			/* Figure out how we want to display the name */
582*1708Sstevel 			child_name = get_node_name(card_node->child);
583*1708Sstevel 			if ((card_node->child != NULL) &&
584*1708Sstevel 			    (child_name != NULL)) {
585*1708Sstevel 				value = get_prop_val(find_prop(card_node->child,
586*1708Sstevel 					"device_type"));
587*1708Sstevel 				if (value != NULL)
588*1708Sstevel 					(void) sprintf(card.name, "%s/%s (%s)",
589*1708Sstevel 						name, child_name,
590*1708Sstevel 						(char *)value);
591*1708Sstevel 				else
592*1708Sstevel 					(void) sprintf(card.name, "%s/%s", name,
593*1708Sstevel 						child_name);
594*1708Sstevel 			} else {
595*1708Sstevel 				(void) strncpy(card.name, name, MAXSTRLEN);
596*1708Sstevel 			}
597*1708Sstevel 
598*1708Sstevel 			if (model != NULL)
599*1708Sstevel 				(void) strncpy(card.model, model, MAXSTRLEN);
600*1708Sstevel 
601*1708Sstevel 			card_list = insert_io_card(card_list, &card);
602*1708Sstevel 		}
603*1708Sstevel 	}
604*1708Sstevel 
605*1708Sstevel 	/* We're all done gathering card info, now print it out */
606*1708Sstevel 	display_io_cards(card_list);
607*1708Sstevel 	free_io_cards(card_list);
608*1708Sstevel }
609*1708Sstevel 
610*1708Sstevel static void
get_machine_type(void)611*1708Sstevel get_machine_type(void)
612*1708Sstevel {
613*1708Sstevel 	char name[MAXSTRLEN];
614*1708Sstevel 
615*1708Sstevel 	machine_type = MTYPE_DEFAULT;
616*1708Sstevel 
617*1708Sstevel 	/* Figure out what kind of machine we're on */
618*1708Sstevel 	if (sysinfo(SI_PLATFORM, name, MAXSTRLEN) != -1) {
619*1708Sstevel 		if (strcmp(name, "SUNW,Ultra-5_10") == 0)
620*1708Sstevel 			machine_type = MTYPE_DARWIN;
621*1708Sstevel 	}
622*1708Sstevel }
623