xref: /titanic_53/usr/src/uts/sun4v/os/fillsysinfo.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/clock.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/promif.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/promimpl.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/cmp.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/async.h>
46*7c478bd9Sstevel@tonic-gate #include <vm/page.h>
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate /*
49*7c478bd9Sstevel@tonic-gate  * The OpenBoot Standalone Interface supplies the kernel with
50*7c478bd9Sstevel@tonic-gate  * implementation dependent parameters through the devinfo/property mechanism
51*7c478bd9Sstevel@tonic-gate  */
52*7c478bd9Sstevel@tonic-gate typedef enum { XDRBOOL, XDRINT, XDRSTRING } xdrs;
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * structure describing properties that we are interested in querying the
56*7c478bd9Sstevel@tonic-gate  * OBP for.
57*7c478bd9Sstevel@tonic-gate  */
58*7c478bd9Sstevel@tonic-gate struct getprop_info {
59*7c478bd9Sstevel@tonic-gate 	char	*name;
60*7c478bd9Sstevel@tonic-gate 	xdrs	type;
61*7c478bd9Sstevel@tonic-gate 	uint_t	*var;
62*7c478bd9Sstevel@tonic-gate };
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * structure used to convert between a string returned by the OBP & a type
66*7c478bd9Sstevel@tonic-gate  * used within the kernel. We prefer to paramaterize rather than type.
67*7c478bd9Sstevel@tonic-gate  */
68*7c478bd9Sstevel@tonic-gate struct convert_info {
69*7c478bd9Sstevel@tonic-gate 	char	*name;
70*7c478bd9Sstevel@tonic-gate 	uint_t	var;
71*7c478bd9Sstevel@tonic-gate 	char	*realname;
72*7c478bd9Sstevel@tonic-gate };
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /*
75*7c478bd9Sstevel@tonic-gate  * structure describing nodes that we are interested in querying the OBP for
76*7c478bd9Sstevel@tonic-gate  * properties.
77*7c478bd9Sstevel@tonic-gate  */
78*7c478bd9Sstevel@tonic-gate struct node_info {
79*7c478bd9Sstevel@tonic-gate 	char			*name;
80*7c478bd9Sstevel@tonic-gate 	int			size;
81*7c478bd9Sstevel@tonic-gate 	struct getprop_info	*prop;
82*7c478bd9Sstevel@tonic-gate 	struct getprop_info	*prop_end;
83*7c478bd9Sstevel@tonic-gate 	unsigned int		*value;
84*7c478bd9Sstevel@tonic-gate };
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /*
87*7c478bd9Sstevel@tonic-gate  * macro definitions for routines that form the OBP interface
88*7c478bd9Sstevel@tonic-gate  */
89*7c478bd9Sstevel@tonic-gate #define	NEXT			prom_nextnode
90*7c478bd9Sstevel@tonic-gate #define	CHILD			prom_childnode
91*7c478bd9Sstevel@tonic-gate #define	GETPROP			prom_getprop
92*7c478bd9Sstevel@tonic-gate #define	GETPROPLEN		prom_getproplen
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate /* 0=quiet; 1=verbose; 2=debug */
95*7c478bd9Sstevel@tonic-gate int	debug_fillsysinfo = 0;
96*7c478bd9Sstevel@tonic-gate #define	VPRINTF if (debug_fillsysinfo) prom_printf
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate int ncpunode;
99*7c478bd9Sstevel@tonic-gate struct cpu_node cpunodes[NCPU];
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate void	fill_cpu(dnode_t);
102*7c478bd9Sstevel@tonic-gate void	plat_fill_mc(dnode_t);
103*7c478bd9Sstevel@tonic-gate #pragma weak plat_fill_mc
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate uint64_t	system_clock_freq;
106*7c478bd9Sstevel@tonic-gate int		niobus = 0;
107*7c478bd9Sstevel@tonic-gate uint_t		niommu_tsbs = 0;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate /*
110*7c478bd9Sstevel@tonic-gate  * Hardware watchdog support.
111*7c478bd9Sstevel@tonic-gate  */
112*7c478bd9Sstevel@tonic-gate #define	CHOSEN_EEPROM	"eeprom"
113*7c478bd9Sstevel@tonic-gate static dnode_t 		chosen_eeprom;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate /*
116*7c478bd9Sstevel@tonic-gate  * If this variable is non-zero, cpr should return "not supported" when
117*7c478bd9Sstevel@tonic-gate  * it is queried even though it would normally be supported on this platform.
118*7c478bd9Sstevel@tonic-gate  */
119*7c478bd9Sstevel@tonic-gate int cpr_supported_override;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate /*
122*7c478bd9Sstevel@tonic-gate  * Some platforms may need to support CPR even in the absence of the
123*7c478bd9Sstevel@tonic-gate  * energystar-v* property (Enchilada server, for example).  If this
124*7c478bd9Sstevel@tonic-gate  * variable is non-zero, cpr should proceed even in the absence
125*7c478bd9Sstevel@tonic-gate  * of the energystar-v* property.
126*7c478bd9Sstevel@tonic-gate  */
127*7c478bd9Sstevel@tonic-gate int cpr_platform_enable = 0;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /*
130*7c478bd9Sstevel@tonic-gate  * Some nodes have functions that need to be called when they're seen.
131*7c478bd9Sstevel@tonic-gate  */
132*7c478bd9Sstevel@tonic-gate static void	have_pci(dnode_t);
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate static struct wkdevice {
135*7c478bd9Sstevel@tonic-gate 	char *wk_namep;
136*7c478bd9Sstevel@tonic-gate 	void (*wk_func)(dnode_t);
137*7c478bd9Sstevel@tonic-gate 	caddr_t *wk_vaddrp;
138*7c478bd9Sstevel@tonic-gate 	ushort_t wk_flags;
139*7c478bd9Sstevel@tonic-gate #define	V_OPTIONAL	0x0000
140*7c478bd9Sstevel@tonic-gate #define	V_MUSTHAVE	0x0001
141*7c478bd9Sstevel@tonic-gate #define	V_MAPPED	0x0002
142*7c478bd9Sstevel@tonic-gate #define	V_MULTI		0x0003	/* optional, may be more than one */
143*7c478bd9Sstevel@tonic-gate } wkdevice[] = {
144*7c478bd9Sstevel@tonic-gate 	{ "pci", have_pci, NULL, V_MULTI },
145*7c478bd9Sstevel@tonic-gate 	{ 0, },
146*7c478bd9Sstevel@tonic-gate };
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate static void map_wellknown(dnode_t);
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate void
151*7c478bd9Sstevel@tonic-gate map_wellknown_devices()
152*7c478bd9Sstevel@tonic-gate {
153*7c478bd9Sstevel@tonic-gate 	struct wkdevice *wkp;
154*7c478bd9Sstevel@tonic-gate 	phandle_t	ieeprom;
155*7c478bd9Sstevel@tonic-gate 	dnode_t	root;
156*7c478bd9Sstevel@tonic-gate 	uint_t	stick_freq;
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	/*
159*7c478bd9Sstevel@tonic-gate 	 * if there is a chosen eeprom, note it (for have_eeprom())
160*7c478bd9Sstevel@tonic-gate 	 */
161*7c478bd9Sstevel@tonic-gate 	if (GETPROPLEN(prom_chosennode(), CHOSEN_EEPROM) ==
162*7c478bd9Sstevel@tonic-gate 	    sizeof (phandle_t) &&
163*7c478bd9Sstevel@tonic-gate 	    GETPROP(prom_chosennode(), CHOSEN_EEPROM, (caddr_t)&ieeprom) != -1)
164*7c478bd9Sstevel@tonic-gate 		chosen_eeprom = (dnode_t)prom_decode_int(ieeprom);
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	root = prom_nextnode((dnode_t)0);
167*7c478bd9Sstevel@tonic-gate 	/*
168*7c478bd9Sstevel@tonic-gate 	 * Get System clock frequency from root node if it exists.
169*7c478bd9Sstevel@tonic-gate 	 */
170*7c478bd9Sstevel@tonic-gate 	if (GETPROP(root, "stick-frequency", (caddr_t)&stick_freq) != -1)
171*7c478bd9Sstevel@tonic-gate 		system_clock_freq = stick_freq;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	map_wellknown(NEXT((dnode_t)0));
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	/*
176*7c478bd9Sstevel@tonic-gate 	 * See if it worked
177*7c478bd9Sstevel@tonic-gate 	 */
178*7c478bd9Sstevel@tonic-gate 	for (wkp = wkdevice; wkp->wk_namep; ++wkp) {
179*7c478bd9Sstevel@tonic-gate 		if (wkp->wk_flags == V_MUSTHAVE) {
180*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_PANIC, "map_wellknown_devices: required "
181*7c478bd9Sstevel@tonic-gate 			    "device %s not mapped", wkp->wk_namep);
182*7c478bd9Sstevel@tonic-gate 		}
183*7c478bd9Sstevel@tonic-gate 	}
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate /*
187*7c478bd9Sstevel@tonic-gate  * map_wellknown - map known devices & registers
188*7c478bd9Sstevel@tonic-gate  */
189*7c478bd9Sstevel@tonic-gate static void
190*7c478bd9Sstevel@tonic-gate map_wellknown(dnode_t curnode)
191*7c478bd9Sstevel@tonic-gate {
192*7c478bd9Sstevel@tonic-gate 	extern int status_okay(int, char *, int);
193*7c478bd9Sstevel@tonic-gate 	char tmp_name[MAXSYSNAME];
194*7c478bd9Sstevel@tonic-gate 	static void fill_address(dnode_t, char *);
195*7c478bd9Sstevel@tonic-gate 	int sok;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate #ifdef VPRINTF
198*7c478bd9Sstevel@tonic-gate 	VPRINTF("map_wellknown(%x)\n", curnode);
199*7c478bd9Sstevel@tonic-gate #endif /* VPRINTF */
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	for (curnode = CHILD(curnode); curnode; curnode = NEXT(curnode)) {
202*7c478bd9Sstevel@tonic-gate 		/*
203*7c478bd9Sstevel@tonic-gate 		 * prune subtree if status property indicating not okay
204*7c478bd9Sstevel@tonic-gate 		 */
205*7c478bd9Sstevel@tonic-gate 		sok = status_okay((int)curnode, (char *)NULL, 0);
206*7c478bd9Sstevel@tonic-gate 		if (!sok) {
207*7c478bd9Sstevel@tonic-gate 			char devtype_buf[OBP_MAXPROPNAME];
208*7c478bd9Sstevel@tonic-gate 			int size;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate #ifdef VPRINTF
211*7c478bd9Sstevel@tonic-gate 			VPRINTF("map_wellknown: !okay status property\n");
212*7c478bd9Sstevel@tonic-gate #endif /* VPRINTF */
213*7c478bd9Sstevel@tonic-gate 			/*
214*7c478bd9Sstevel@tonic-gate 			 * a status property indicating bad memory will be
215*7c478bd9Sstevel@tonic-gate 			 * associated with a node which has a "device_type"
216*7c478bd9Sstevel@tonic-gate 			 * property with a value of "memory-controller"
217*7c478bd9Sstevel@tonic-gate 			 */
218*7c478bd9Sstevel@tonic-gate 			if ((size = GETPROPLEN(curnode,
219*7c478bd9Sstevel@tonic-gate 			    OBP_DEVICETYPE)) == -1)
220*7c478bd9Sstevel@tonic-gate 				continue;
221*7c478bd9Sstevel@tonic-gate 			if (size > OBP_MAXPROPNAME) {
222*7c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT, "node %x '%s' prop too "
223*7c478bd9Sstevel@tonic-gate 				    "big\n", curnode, OBP_DEVICETYPE);
224*7c478bd9Sstevel@tonic-gate 				continue;
225*7c478bd9Sstevel@tonic-gate 			}
226*7c478bd9Sstevel@tonic-gate 			if (GETPROP(curnode, OBP_DEVICETYPE,
227*7c478bd9Sstevel@tonic-gate 			    devtype_buf) == -1) {
228*7c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT, "node %x '%s' get failed\n",
229*7c478bd9Sstevel@tonic-gate 				    curnode, OBP_DEVICETYPE);
230*7c478bd9Sstevel@tonic-gate 				continue;
231*7c478bd9Sstevel@tonic-gate 			}
232*7c478bd9Sstevel@tonic-gate 			if (strcmp(devtype_buf, "memory-controller") != 0)
233*7c478bd9Sstevel@tonic-gate 				continue;
234*7c478bd9Sstevel@tonic-gate 			/*
235*7c478bd9Sstevel@tonic-gate 			 * ...else fall thru and process the node...
236*7c478bd9Sstevel@tonic-gate 			 */
237*7c478bd9Sstevel@tonic-gate 		}
238*7c478bd9Sstevel@tonic-gate 		bzero(tmp_name, MAXSYSNAME);
239*7c478bd9Sstevel@tonic-gate 		if (GETPROP(curnode, OBP_NAME, (caddr_t)tmp_name) != -1)
240*7c478bd9Sstevel@tonic-gate 			fill_address(curnode, tmp_name);
241*7c478bd9Sstevel@tonic-gate 		if (GETPROP(curnode, OBP_DEVICETYPE, tmp_name) != -1 &&
242*7c478bd9Sstevel@tonic-gate 		    strcmp(tmp_name, "cpu") == 0) {
243*7c478bd9Sstevel@tonic-gate 			fill_cpu(curnode);
244*7c478bd9Sstevel@tonic-gate 		}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 		if (sok && (strcmp(tmp_name, "memory-controller") == 0) &&
247*7c478bd9Sstevel@tonic-gate 		    (&plat_fill_mc != NULL))
248*7c478bd9Sstevel@tonic-gate 			plat_fill_mc(curnode);
249*7c478bd9Sstevel@tonic-gate 		map_wellknown(curnode);
250*7c478bd9Sstevel@tonic-gate 	}
251*7c478bd9Sstevel@tonic-gate }
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate static void
254*7c478bd9Sstevel@tonic-gate fill_address(dnode_t curnode, char *namep)
255*7c478bd9Sstevel@tonic-gate {
256*7c478bd9Sstevel@tonic-gate 	struct wkdevice *wkp;
257*7c478bd9Sstevel@tonic-gate 	int size;
258*7c478bd9Sstevel@tonic-gate 	uint32_t vaddr;
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	for (wkp = wkdevice; wkp->wk_namep; ++wkp) {
261*7c478bd9Sstevel@tonic-gate 		if (strcmp(wkp->wk_namep, namep) != 0)
262*7c478bd9Sstevel@tonic-gate 			continue;
263*7c478bd9Sstevel@tonic-gate 		if (wkp->wk_flags == V_MAPPED)
264*7c478bd9Sstevel@tonic-gate 			return;
265*7c478bd9Sstevel@tonic-gate 		if (wkp->wk_vaddrp != NULL) {
266*7c478bd9Sstevel@tonic-gate 			if ((size = GETPROPLEN(curnode, OBP_ADDRESS)) == -1) {
267*7c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT, "device %s size %d\n",
268*7c478bd9Sstevel@tonic-gate 				    namep, size);
269*7c478bd9Sstevel@tonic-gate 				continue;
270*7c478bd9Sstevel@tonic-gate 			}
271*7c478bd9Sstevel@tonic-gate 			if (size != sizeof (vaddr)) {
272*7c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT, "device %s address prop too "
273*7c478bd9Sstevel@tonic-gate 				    "big\n", namep);
274*7c478bd9Sstevel@tonic-gate 				continue;
275*7c478bd9Sstevel@tonic-gate 			}
276*7c478bd9Sstevel@tonic-gate 			if (GETPROP(curnode, OBP_ADDRESS,
277*7c478bd9Sstevel@tonic-gate 			    (caddr_t)&vaddr) == -1) {
278*7c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT, "device %s not mapped\n",
279*7c478bd9Sstevel@tonic-gate 				    namep);
280*7c478bd9Sstevel@tonic-gate 				continue;
281*7c478bd9Sstevel@tonic-gate 			}
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 			/* make into a native pointer */
284*7c478bd9Sstevel@tonic-gate 			*wkp->wk_vaddrp = (caddr_t)vaddr;
285*7c478bd9Sstevel@tonic-gate #ifdef VPRINTF
286*7c478bd9Sstevel@tonic-gate 			VPRINTF("fill_address: %s mapped to %x\n", namep,
287*7c478bd9Sstevel@tonic-gate 			    *wkp->wk_vaddrp);
288*7c478bd9Sstevel@tonic-gate #endif /* VPRINTF */
289*7c478bd9Sstevel@tonic-gate 		}
290*7c478bd9Sstevel@tonic-gate 		if (wkp->wk_func != NULL)
291*7c478bd9Sstevel@tonic-gate 			(*wkp->wk_func)(curnode);
292*7c478bd9Sstevel@tonic-gate 		/*
293*7c478bd9Sstevel@tonic-gate 		 * If this one is optional and there may be more than
294*7c478bd9Sstevel@tonic-gate 		 * one, don't set V_MAPPED, which would cause us to skip it
295*7c478bd9Sstevel@tonic-gate 		 * next time around
296*7c478bd9Sstevel@tonic-gate 		 */
297*7c478bd9Sstevel@tonic-gate 		if (wkp->wk_flags != V_MULTI)
298*7c478bd9Sstevel@tonic-gate 			wkp->wk_flags = V_MAPPED;
299*7c478bd9Sstevel@tonic-gate 	}
300*7c478bd9Sstevel@tonic-gate }
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate void
303*7c478bd9Sstevel@tonic-gate fill_cpu(dnode_t node)
304*7c478bd9Sstevel@tonic-gate {
305*7c478bd9Sstevel@tonic-gate 	struct cpu_node *cpunode;
306*7c478bd9Sstevel@tonic-gate 	processorid_t cpuid;
307*7c478bd9Sstevel@tonic-gate 	uint_t clk_freq;
308*7c478bd9Sstevel@tonic-gate 	char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN];
309*7c478bd9Sstevel@tonic-gate 	char *namebufp;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	if (GETPROP(node, "cpuid", (caddr_t)&cpuid) == -1) {
312*7c478bd9Sstevel@tonic-gate 		if (GETPROP(node, "reg", (caddr_t)&cpuid) == -1)
313*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_PANIC, "reg prop not found in cpu node");
314*7c478bd9Sstevel@tonic-gate 		cpuid = PROM_CFGHDL_TO_CPUID(cpuid);
315*7c478bd9Sstevel@tonic-gate 	}
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	if (cpuid < 0 || cpuid >= NCPU) {
318*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "cpu (dnode %x): out of range cpuid %d - "
319*7c478bd9Sstevel@tonic-gate 		    "cpu excluded from configuration\n", node, cpuid);
320*7c478bd9Sstevel@tonic-gate 		return;
321*7c478bd9Sstevel@tonic-gate 	}
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	cpunode = &cpunodes[cpuid];
324*7c478bd9Sstevel@tonic-gate 	cpunode->cpuid = cpuid;
325*7c478bd9Sstevel@tonic-gate 	cpunode->device_id = cpuid;
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate 	unum[0] = '\0';
328*7c478bd9Sstevel@tonic-gate 	(void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri),
329*7c478bd9Sstevel@tonic-gate 		"%s%s", CPU_FRU_FMRI, unum);
330*7c478bd9Sstevel@tonic-gate 	(void) GETPROP(node, "compatible", namebuf);
331*7c478bd9Sstevel@tonic-gate 	namebufp = namebuf;
332*7c478bd9Sstevel@tonic-gate 	if (strncmp(namebufp, "SUNW,", 5) == 0)
333*7c478bd9Sstevel@tonic-gate 		namebufp += 5;
334*7c478bd9Sstevel@tonic-gate 	(void) strcpy(cpunode->name, namebufp);
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	if (GETPROP(node, "clock-frequency", (caddr_t)&clk_freq) == -1) {
337*7c478bd9Sstevel@tonic-gate 		/*
338*7c478bd9Sstevel@tonic-gate 		 * If we didn't find it in the CPU node, look in the root node.
339*7c478bd9Sstevel@tonic-gate 		 */
340*7c478bd9Sstevel@tonic-gate 		dnode_t root = prom_nextnode((dnode_t)0);
341*7c478bd9Sstevel@tonic-gate 		if (GETPROP(root, "clock-frequency", (caddr_t)&clk_freq) == -1)
342*7c478bd9Sstevel@tonic-gate 			clk_freq = 0;
343*7c478bd9Sstevel@tonic-gate 	}
344*7c478bd9Sstevel@tonic-gate 	cpunode->clock_freq = clk_freq;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	ASSERT(cpunode->clock_freq != 0);
347*7c478bd9Sstevel@tonic-gate 	/*
348*7c478bd9Sstevel@tonic-gate 	 * Compute scaling factor based on rate of %tick. This is used
349*7c478bd9Sstevel@tonic-gate 	 * to convert from ticks derived from %tick to nanoseconds. See
350*7c478bd9Sstevel@tonic-gate 	 * comment in sun4u/sys/clock.h for details.
351*7c478bd9Sstevel@tonic-gate 	 */
352*7c478bd9Sstevel@tonic-gate 	cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC <<
353*7c478bd9Sstevel@tonic-gate 	    (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq);
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 	cpunode->nodeid = node;
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 	/*
359*7c478bd9Sstevel@tonic-gate 	 * Call cpu module specific code to fill in the cpu properities
360*7c478bd9Sstevel@tonic-gate 	 */
361*7c478bd9Sstevel@tonic-gate 	cpu_fiximp(cpunode);
362*7c478bd9Sstevel@tonic-gate }
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate #define	IOMMU_PER_SCHIZO	2
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate /*
367*7c478bd9Sstevel@tonic-gate  * The first psycho must always programmed up for the system clock and error
368*7c478bd9Sstevel@tonic-gate  * handling purposes.
369*7c478bd9Sstevel@tonic-gate  */
370*7c478bd9Sstevel@tonic-gate static void
371*7c478bd9Sstevel@tonic-gate have_pci(dnode_t node)
372*7c478bd9Sstevel@tonic-gate {
373*7c478bd9Sstevel@tonic-gate 	int size;
374*7c478bd9Sstevel@tonic-gate 	uint_t portid;
375*7c478bd9Sstevel@tonic-gate 	char compatible[OBP_MAXDRVNAME];
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	size = GETPROPLEN(node, "portid");
378*7c478bd9Sstevel@tonic-gate 	if (size == -1) size = GETPROPLEN(node, "upa-portid");
379*7c478bd9Sstevel@tonic-gate 	if (size == -1)
380*7c478bd9Sstevel@tonic-gate 		return;
381*7c478bd9Sstevel@tonic-gate 	if (size > sizeof (portid))
382*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "portid size wrong");
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	if (GETPROP(node, "portid", (caddr_t)&portid) == -1)
385*7c478bd9Sstevel@tonic-gate 		if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1)
386*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_PANIC, "portid not found");
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 	niobus++;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	/*
392*7c478bd9Sstevel@tonic-gate 	 * Need two physical TSBs for Schizo-compatible nodes,
393*7c478bd9Sstevel@tonic-gate 	 * one otherwise.
394*7c478bd9Sstevel@tonic-gate 	 */
395*7c478bd9Sstevel@tonic-gate 	compatible[0] = '\0';
396*7c478bd9Sstevel@tonic-gate 	(void) prom_getprop(node, OBP_COMPATIBLE, compatible);
397*7c478bd9Sstevel@tonic-gate 	if (strcmp(compatible, "pci108e,8001") == 0)
398*7c478bd9Sstevel@tonic-gate 		niommu_tsbs += IOMMU_PER_SCHIZO;
399*7c478bd9Sstevel@tonic-gate 	else
400*7c478bd9Sstevel@tonic-gate 		niommu_tsbs++;
401*7c478bd9Sstevel@tonic-gate }
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate int
405*7c478bd9Sstevel@tonic-gate get_cpu_pagesizes(void)
406*7c478bd9Sstevel@tonic-gate {
407*7c478bd9Sstevel@tonic-gate 	/*
408*7c478bd9Sstevel@tonic-gate 	 * XXXQ Get supported page sizes information from the PD
409*7c478bd9Sstevel@tonic-gate 	 * and return a bit mask indicating which page sizes are
410*7c478bd9Sstevel@tonic-gate 	 * supported.
411*7c478bd9Sstevel@tonic-gate 	 *
412*7c478bd9Sstevel@tonic-gate 	 * Return 0 when no information is available.
413*7c478bd9Sstevel@tonic-gate 	 */
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	return (0);			/* XXXQ for now return 0 as no PD */
416*7c478bd9Sstevel@tonic-gate }
417