xref: /onnv-gate/usr/src/cmd/picl/plugins/sun4v/mdesc/dr.c (revision 6902:5b004da8de91)
11991Sheppo /*
21991Sheppo  * CDDL HEADER START
31991Sheppo  *
41991Sheppo  * The contents of this file are subject to the terms of the
51991Sheppo  * Common Development and Distribution License (the "License").
61991Sheppo  * You may not use this file except in compliance with the License.
71991Sheppo  *
81991Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91991Sheppo  * or http://www.opensolaris.org/os/licensing.
101991Sheppo  * See the License for the specific language governing permissions
111991Sheppo  * and limitations under the License.
121991Sheppo  *
131991Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141991Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151991Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161991Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171991Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181991Sheppo  *
191991Sheppo  * CDDL HEADER END
201991Sheppo  */
211991Sheppo 
221991Sheppo /*
23*6902Smb158278  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241991Sheppo  * Use is subject to license terms.
251991Sheppo  */
261991Sheppo 
271991Sheppo #pragma ident	"%Z%%M%	%I%	%E% SMI"
281991Sheppo 
291991Sheppo #include "mdescplugin.h"
301991Sheppo 
311991Sheppo static	di_prom_handle_t	ph = DI_PROM_HANDLE_NIL;
321991Sheppo 
331991Sheppo typedef struct cpu_lookup {
341991Sheppo 	di_node_t di_node;
351991Sheppo 	picl_nodehdl_t nodeh;
361991Sheppo 	int result;
371991Sheppo } cpu_lookup_t;
381991Sheppo 
391991Sheppo extern int add_cpu_prop(picl_nodehdl_t node, void *args);
401991Sheppo extern md_t *mdesc_devinit(void);
411991Sheppo 
421991Sheppo /*
431991Sheppo  * This function is identical to the one in the picldevtree plugin.
441991Sheppo  * Unfortunately we can't just reuse that code.
451991Sheppo  */
46*6902Smb158278 int
add_string_list_prop(picl_nodehdl_t nodeh,char * name,char * strlist,unsigned int nrows)471991Sheppo add_string_list_prop(picl_nodehdl_t nodeh, char *name, char *strlist,
481991Sheppo     unsigned int nrows)
491991Sheppo {
501991Sheppo 	ptree_propinfo_t	propinfo;
511991Sheppo 	picl_prophdl_t		proph;
521991Sheppo 	picl_prophdl_t		tblh;
531991Sheppo 	int			err;
541991Sheppo 	unsigned int		i;
551991Sheppo 	unsigned int		j;
561991Sheppo 	picl_prophdl_t		*proprow;
571991Sheppo 	int			len;
581991Sheppo 
591991Sheppo #define	NCOLS_IN_STRING_TABLE	1
601991Sheppo 
611991Sheppo 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
621991Sheppo 	    PICL_PTYPE_TABLE, PICL_READ, sizeof (picl_prophdl_t), name,
631991Sheppo 	    NULL, NULL);
641991Sheppo 	if (err != PICL_SUCCESS)
651991Sheppo 		return (err);
661991Sheppo 
671991Sheppo 	err = ptree_create_table(&tblh);
681991Sheppo 	if (err != PICL_SUCCESS)
691991Sheppo 		return (err);
701991Sheppo 
711991Sheppo 	err = ptree_create_and_add_prop(nodeh, &propinfo, &tblh, &proph);
721991Sheppo 	if (err != PICL_SUCCESS)
731991Sheppo 		return (err);
741991Sheppo 
751991Sheppo 	proprow = alloca(sizeof (picl_prophdl_t) * nrows);
761991Sheppo 	if (proprow == NULL) {
771991Sheppo 		(void) ptree_destroy_prop(proph);
781991Sheppo 		return (PICL_FAILURE);
791991Sheppo 	}
801991Sheppo 
811991Sheppo 	for (j = 0; j < nrows; ++j) {
821991Sheppo 		len = strlen(strlist) + 1;
831991Sheppo 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
841991Sheppo 		    PICL_PTYPE_CHARSTRING, PICL_READ, len, name,
851991Sheppo 		    NULL, NULL);
861991Sheppo 		if (err != PICL_SUCCESS)
871991Sheppo 			break;
881991Sheppo 		err = ptree_create_prop(&propinfo, strlist, &proprow[j]);
891991Sheppo 		if (err != PICL_SUCCESS)
901991Sheppo 			break;
911991Sheppo 		strlist += len;
921991Sheppo 		err = ptree_add_row_to_table(tblh, NCOLS_IN_STRING_TABLE,
931991Sheppo 		    &proprow[j]);
941991Sheppo 		if (err != PICL_SUCCESS)
951991Sheppo 			break;
961991Sheppo 	}
971991Sheppo 
981991Sheppo 	if (err != PICL_SUCCESS) {
991991Sheppo 		for (i = 0; i < j; ++i)
1001991Sheppo 			(void) ptree_destroy_prop(proprow[i]);
1011991Sheppo 		(void) ptree_delete_prop(proph);
1021991Sheppo 		(void) ptree_destroy_prop(proph);
1031991Sheppo 		return (err);
1041991Sheppo 	}
1051991Sheppo 
1061991Sheppo 	return (PICL_SUCCESS);
1071991Sheppo }
1081991Sheppo 
1091991Sheppo /*
1101991Sheppo  * This function is identical to the one in the picldevtree plugin.
1111991Sheppo  * Unfortunately we can't just reuse that code.
1121991Sheppo  */
1131991Sheppo static void
add_devinfo_props(picl_nodehdl_t nodeh,di_node_t di_node)1141991Sheppo add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node)
1151991Sheppo {
1161991Sheppo 	int			instance;
1171991Sheppo 	char			*di_val;
1181991Sheppo 	di_prop_t		di_prop;
1191991Sheppo 	int			di_ptype;
1201991Sheppo 	ptree_propinfo_t	propinfo;
1211991Sheppo 
1221991Sheppo 	instance = di_instance(di_node);
1231991Sheppo 	(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1241991Sheppo 	    PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE,
1251991Sheppo 	    NULL, NULL);
1261991Sheppo 	(void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL);
1271991Sheppo 
1281991Sheppo 	di_val = di_bus_addr(di_node);
1291991Sheppo 	if (di_val) {
1301991Sheppo 		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1311991Sheppo 		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1321991Sheppo 		    PICL_PROP_BUS_ADDR, NULL, NULL);
1331991Sheppo 		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1341991Sheppo 		    NULL);
1351991Sheppo 	}
1361991Sheppo 
1371991Sheppo 	di_val = di_binding_name(di_node);
1381991Sheppo 	if (di_val) {
1391991Sheppo 		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1401991Sheppo 		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1411991Sheppo 		    PICL_PROP_BINDING_NAME, NULL, NULL);
1421991Sheppo 		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1431991Sheppo 		    NULL);
1441991Sheppo 	}
1451991Sheppo 
1461991Sheppo 	di_val = di_driver_name(di_node);
1471991Sheppo 	if (di_val) {
1481991Sheppo 		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1491991Sheppo 		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1501991Sheppo 		    PICL_PROP_DRIVER_NAME, NULL, NULL);
1511991Sheppo 		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1521991Sheppo 		    NULL);
1531991Sheppo 	}
1541991Sheppo 
1551991Sheppo 	di_val = di_devfs_path(di_node);
1561991Sheppo 	if (di_val) {
1571991Sheppo 		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1581991Sheppo 		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1591991Sheppo 		    PICL_PROP_DEVFS_PATH, NULL, NULL);
1601991Sheppo 		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1611991Sheppo 		    NULL);
1621991Sheppo 		di_devfs_path_free(di_val);
1631991Sheppo 	}
1641991Sheppo 
1651991Sheppo 	for (di_prop = di_prop_next(di_node, DI_PROP_NIL);
1661991Sheppo 	    di_prop != DI_PROP_NIL;
167*6902Smb158278 	    di_prop = di_prop_next(di_node, di_prop)) {
1681991Sheppo 
1691991Sheppo 		di_val = di_prop_name(di_prop);
1701991Sheppo 		di_ptype = di_prop_type(di_prop);
1711991Sheppo 		switch (di_ptype) {
1721991Sheppo 		case DI_PROP_TYPE_BOOLEAN:
1731991Sheppo 			(void) ptree_init_propinfo(&propinfo,
1741991Sheppo 			    PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID,
1751991Sheppo 			    PICL_READ, (size_t)0, di_val, NULL, NULL);
1761991Sheppo 			(void) ptree_create_and_add_prop(nodeh, &propinfo,
1771991Sheppo 			    NULL, NULL);
1781991Sheppo 			break;
1791991Sheppo 		case DI_PROP_TYPE_INT: {
1801991Sheppo 			int	*idata;
1811991Sheppo 			int	len;
1821991Sheppo 
1831991Sheppo 			len = di_prop_ints(di_prop, &idata);
1841991Sheppo 			if (len < 0)
1851991Sheppo 				/* Recieved error, so ignore prop */
1861991Sheppo 				break;
1871991Sheppo 
1881991Sheppo 			if (len == 1)
1891991Sheppo 				(void) ptree_init_propinfo(&propinfo,
1901991Sheppo 				    PTREE_PROPINFO_VERSION, PICL_PTYPE_INT,
1911991Sheppo 				    PICL_READ, len * sizeof (int), di_val,
1921991Sheppo 				    NULL, NULL);
1931991Sheppo 			else
1941991Sheppo 				(void) ptree_init_propinfo(&propinfo,
1951991Sheppo 				    PTREE_PROPINFO_VERSION,
1961991Sheppo 				    PICL_PTYPE_BYTEARRAY, PICL_READ,
1971991Sheppo 				    len * sizeof (int), di_val,
1981991Sheppo 				    NULL, NULL);
1991991Sheppo 
2001991Sheppo 			(void) ptree_create_and_add_prop(nodeh, &propinfo,
2011991Sheppo 			    idata, NULL);
2021991Sheppo 		}
2031991Sheppo 		break;
2041991Sheppo 		case DI_PROP_TYPE_STRING: {
2051991Sheppo 			char	*sdata;
2061991Sheppo 			int	len;
2071991Sheppo 
2081991Sheppo 			len = di_prop_strings(di_prop, &sdata);
2091991Sheppo 			if (len < 0)
2101991Sheppo 				break;
2111991Sheppo 
2121991Sheppo 			if (len == 1) {
2131991Sheppo 				(void) ptree_init_propinfo(&propinfo,
2141991Sheppo 				    PTREE_PROPINFO_VERSION,
2151991Sheppo 				    PICL_PTYPE_CHARSTRING, PICL_READ,
2161991Sheppo 				    strlen(sdata) + 1, di_val,
2171991Sheppo 				    NULL, NULL);
2181991Sheppo 				(void) ptree_create_and_add_prop(nodeh,
2191991Sheppo 				    &propinfo, sdata, NULL);
2201991Sheppo 			} else {
2211991Sheppo 				(void) add_string_list_prop(nodeh, di_val,
2221991Sheppo 				    sdata, len);
2231991Sheppo 			}
2241991Sheppo 		}
2251991Sheppo 		break;
2261991Sheppo 		case DI_PROP_TYPE_BYTE: {
2271991Sheppo 			int		len;
2281991Sheppo 			unsigned char *bdata;
2291991Sheppo 
2301991Sheppo 			len = di_prop_bytes(di_prop, &bdata);
2311991Sheppo 			if (len < 0)
2321991Sheppo 				break;
2331991Sheppo 			(void) ptree_init_propinfo(&propinfo,
2341991Sheppo 			    PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY,
2351991Sheppo 			    PICL_READ, len, di_val, NULL, NULL);
2361991Sheppo 			(void) ptree_create_and_add_prop(nodeh, &propinfo,
2371991Sheppo 			    bdata, NULL);
2381991Sheppo 		}
2391991Sheppo 		break;
2401991Sheppo 		case DI_PROP_TYPE_UNKNOWN:
2411991Sheppo 			break;
2421991Sheppo 		case DI_PROP_TYPE_UNDEF_IT:
2431991Sheppo 			break;
2441991Sheppo 		default:
2451991Sheppo 			break;
2461991Sheppo 		}
2471991Sheppo 	}
2481991Sheppo }
2491991Sheppo 
2501991Sheppo /*
251*6902Smb158278  * add OBP_REG property to picl cpu node if it's not already there.
252*6902Smb158278  */
253*6902Smb158278 static void
add_reg_prop(picl_nodehdl_t pn,di_node_t dn)254*6902Smb158278 add_reg_prop(picl_nodehdl_t pn, di_node_t dn)
255*6902Smb158278 {
256*6902Smb158278 	int 			reg_prop[SUN4V_CPU_REGSIZE];
257*6902Smb158278 	int 			status;
258*6902Smb158278 	int 			dlen;
259*6902Smb158278 	int			*pdata;
260*6902Smb158278 	ptree_propinfo_t	propinfo;
261*6902Smb158278 
262*6902Smb158278 	status = ptree_get_propval_by_name(pn, OBP_REG, reg_prop,
263*6902Smb158278 	    sizeof (reg_prop));
264*6902Smb158278 	if (status == PICL_SUCCESS) {
265*6902Smb158278 		return;
266*6902Smb158278 	}
267*6902Smb158278 	dlen = di_prom_prop_lookup_ints(ph, dn, OBP_REG, &pdata);
268*6902Smb158278 	if (dlen < 0) {
269*6902Smb158278 		return;
270*6902Smb158278 	}
271*6902Smb158278 	status = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
272*6902Smb158278 	    PICL_PTYPE_BYTEARRAY, PICL_READ, dlen * sizeof (int), OBP_REG,
273*6902Smb158278 	    NULL, NULL);
274*6902Smb158278 	if (status != PICL_SUCCESS) {
275*6902Smb158278 		return;
276*6902Smb158278 	}
277*6902Smb158278 	(void) ptree_create_and_add_prop(pn, &propinfo, pdata, NULL);
278*6902Smb158278 }
279*6902Smb158278 
280*6902Smb158278 /*
2811991Sheppo  * Create a  picl node of type cpu and fill it.
2821991Sheppo  * properties are filled from both the device tree and the
2831991Sheppo  * Machine description.
2841991Sheppo  */
2851991Sheppo static int
construct_cpu_node(picl_nodehdl_t plath,di_node_t dn)2861991Sheppo construct_cpu_node(picl_nodehdl_t plath, di_node_t dn)
2871991Sheppo {
2881991Sheppo 	int		err;
2891991Sheppo 	char		*nodename;
2901991Sheppo 	picl_nodehdl_t	anodeh;
2911991Sheppo 
2921991Sheppo 	nodename = di_node_name(dn);	/* PICL_PROP_NAME */
2931991Sheppo 
2941991Sheppo 	err = ptree_create_and_add_node(plath, nodename, PICL_CLASS_CPU,
2951991Sheppo 	    &anodeh);
2961991Sheppo 	if (err != PICL_SUCCESS)
2971991Sheppo 		return (err);
2981991Sheppo 
2991991Sheppo 	add_devinfo_props(anodeh, dn);
300*6902Smb158278 	add_reg_prop(anodeh, dn);
3011991Sheppo 	(void) add_cpu_prop(anodeh, NULL);
3021991Sheppo 
3031991Sheppo 	return (err);
3041991Sheppo }
3051991Sheppo 
3061991Sheppo /*
3071991Sheppo  * Given a devinfo node find its reg property.
3081991Sheppo  */
3091991Sheppo static int
get_reg_prop(di_node_t dn,int ** pdata)3101991Sheppo get_reg_prop(di_node_t dn, int **pdata)
3111991Sheppo {
3121991Sheppo 	int dret = 0;
3131991Sheppo 
3141991Sheppo 	dret = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, OBP_REG, pdata);
3151991Sheppo 	if (dret > 0)
3161991Sheppo 		return (dret);
3171991Sheppo 
3181991Sheppo 	if (!ph)
3191991Sheppo 		return (0);
3201991Sheppo 	dret = di_prom_prop_lookup_ints(ph, dn, OBP_REG, pdata);
3211991Sheppo 	return (dret < 0? 0 : dret);
3221991Sheppo }
3231991Sheppo 
3241991Sheppo /*
3251991Sheppo  * Given a devinfo cpu node find its cpuid property.
3261991Sheppo  */
3271991Sheppo int
get_cpuid(di_node_t di_node)3281991Sheppo get_cpuid(di_node_t di_node)
3291991Sheppo {
3301991Sheppo 	int	len;
3311991Sheppo 	int	*idata;
3321991Sheppo 	int	dcpuid = -1;
3331991Sheppo 
3341991Sheppo 	len = get_reg_prop(di_node, &idata);
3351991Sheppo 
3361991Sheppo 	if (len != SUN4V_CPU_REGSIZE)
3371991Sheppo 		return (dcpuid);
3381991Sheppo 	if (len == SUN4V_CPU_REGSIZE)
3391991Sheppo 		dcpuid = CFGHDL_TO_CPUID(idata[0]);
3401991Sheppo 
3411991Sheppo 	return (dcpuid);
3421991Sheppo }
3431991Sheppo 
3441991Sheppo int
find_cpu(di_node_t node,int cpuid)3451991Sheppo find_cpu(di_node_t node, int cpuid)
3461991Sheppo {
3471991Sheppo 	int	dcpuid;
3481991Sheppo 	di_node_t cnode;
3491991Sheppo 	char	*nodename;
3501991Sheppo 
3511991Sheppo 	for (cnode = di_child_node(node); cnode != DI_NODE_NIL;
3521991Sheppo 	    cnode = di_sibling_node(cnode)) {
3531991Sheppo 		nodename = di_node_name(cnode);
3541991Sheppo 		if (nodename == NULL)
3551991Sheppo 			continue;
3561991Sheppo 		if (strcmp(nodename, OBP_CPU) == 0) {
3571991Sheppo 			dcpuid = get_cpuid(cnode);
3581991Sheppo 			if (dcpuid == cpuid) {
3591991Sheppo 				return (1);
3601991Sheppo 			}
3611991Sheppo 		}
3621991Sheppo 	}
3631991Sheppo 	return (0);
3641991Sheppo }
3651991Sheppo 
3661991Sheppo /*
3671991Sheppo  * Callback to the ptree walk function during remove_cpus.
3681991Sheppo  * As a part of the args receives a picl nodeh, searches
3691991Sheppo  * the device tree for a cpu whose cpuid matches the picl cpu node.
3701991Sheppo  * Sets arg struct's result to 1 if it failed to match and terminates
3711991Sheppo  * the walk.
3721991Sheppo  */
3731991Sheppo static int
remove_cpu_candidate(picl_nodehdl_t nodeh,void * c_args)3741991Sheppo remove_cpu_candidate(picl_nodehdl_t nodeh, void *c_args)
3751991Sheppo {
3761991Sheppo 	di_node_t	di_node;
3771991Sheppo 	cpu_lookup_t	*cpu_arg;
3781991Sheppo 	int	err;
3791991Sheppo 	int	pcpuid;
3801991Sheppo 	int reg_prop[SUN4V_CPU_REGSIZE];
3811991Sheppo 
3821991Sheppo 	if (c_args == NULL)
3831991Sheppo 		return (PICL_INVALIDARG);
3841991Sheppo 
3851991Sheppo 	cpu_arg = c_args;
3861991Sheppo 	di_node = cpu_arg->di_node;
3871991Sheppo 
3881991Sheppo 	err = ptree_get_propval_by_name(nodeh, OBP_REG, reg_prop,
3891991Sheppo 	    sizeof (reg_prop));
3901991Sheppo 
3911991Sheppo 	if (err != PICL_SUCCESS) {
3921991Sheppo 		return (PICL_WALK_CONTINUE);
3931991Sheppo 	}
3941991Sheppo 
3951991Sheppo 	pcpuid = CFGHDL_TO_CPUID(reg_prop[0]);
3961991Sheppo 
3971991Sheppo 	if (!find_cpu(di_node, pcpuid)) {
3981991Sheppo 		cpu_arg->result = 1;
3991991Sheppo 		cpu_arg->nodeh = nodeh;
4001991Sheppo 		return (PICL_WALK_TERMINATE);
4011991Sheppo 	}
4021991Sheppo 
4031991Sheppo 	cpu_arg->result = 0;
4041991Sheppo 	return (PICL_WALK_CONTINUE);
4051991Sheppo }
4061991Sheppo 
4071991Sheppo /*
4081991Sheppo  * Given the start node of the device tree.
4091991Sheppo  * find all cpus in the picl tree that don't have
4101991Sheppo  * device tree counterparts and remove them.
4111991Sheppo  */
4121991Sheppo static void
remove_cpus(di_node_t di_start)4131991Sheppo remove_cpus(di_node_t di_start)
4141991Sheppo {
4151991Sheppo 	int		err;
4161991Sheppo 	picl_nodehdl_t	plath;
4171991Sheppo 	cpu_lookup_t	cpu_arg;
4181991Sheppo 
4191991Sheppo 	err = ptree_get_node_by_path(PLATFORM_PATH, &plath);
4201991Sheppo 	if (err != PICL_SUCCESS)
4211991Sheppo 		return;
4221991Sheppo 
4231991Sheppo 	do {
4241991Sheppo 		cpu_arg.di_node = di_start;
4251991Sheppo 		cpu_arg.nodeh = 0;
4261991Sheppo 		cpu_arg.result = 0;
4271991Sheppo 
4281991Sheppo 		if (ptree_walk_tree_by_class(plath,
4291991Sheppo 		    PICL_CLASS_CPU, &cpu_arg, remove_cpu_candidate)
4301991Sheppo 		    != PICL_SUCCESS)
4311991Sheppo 			return;
4321991Sheppo 
4331991Sheppo 		if (cpu_arg.result == 1) {
4341991Sheppo 			err = ptree_delete_node(cpu_arg.nodeh);
4351991Sheppo 			if (err == PICL_SUCCESS)
4361991Sheppo 				ptree_destroy_node(cpu_arg.nodeh);
4371991Sheppo 		}
4381991Sheppo 	} while (cpu_arg.result);
4391991Sheppo }
4401991Sheppo 
4411991Sheppo /*
4421991Sheppo  * Callback to the ptree walk function during add_cpus.
4431991Sheppo  * As a part of the args receives a cpu di_node, compares
4441991Sheppo  * each picl cpu node's cpuid to the device tree node's cpuid.
4451991Sheppo  * Sets arg struct's result to 1 on a match.
4461991Sheppo  */
4471991Sheppo static int
cpu_exists(picl_nodehdl_t nodeh,void * c_args)4481991Sheppo cpu_exists(picl_nodehdl_t nodeh, void *c_args)
4491991Sheppo {
4501991Sheppo 	di_node_t	di_node;
4511991Sheppo 	cpu_lookup_t	*cpu_arg;
4521991Sheppo 	int	err;
4531991Sheppo 	int	dcpuid, pcpuid;
4541991Sheppo 	int reg_prop[4];
4551991Sheppo 
4561991Sheppo 	if (c_args == NULL)
4571991Sheppo 		return (PICL_INVALIDARG);
4581991Sheppo 
4591991Sheppo 	cpu_arg = c_args;
4601991Sheppo 	di_node = cpu_arg->di_node;
4611991Sheppo 	dcpuid = get_cpuid(di_node);
4621991Sheppo 
4631991Sheppo 	err = ptree_get_propval_by_name(nodeh, OBP_REG, reg_prop,
4641991Sheppo 	    sizeof (reg_prop));
4651991Sheppo 
4661991Sheppo 	if (err != PICL_SUCCESS)
4671991Sheppo 		return (PICL_WALK_CONTINUE);
4681991Sheppo 
4691991Sheppo 	pcpuid = CFGHDL_TO_CPUID(reg_prop[0]);
4701991Sheppo 
4711991Sheppo 	if (dcpuid == pcpuid) {
4721991Sheppo 		cpu_arg->result = 1;
4731991Sheppo 		return (PICL_WALK_TERMINATE);
4741991Sheppo 	}
4751991Sheppo 
4761991Sheppo 	cpu_arg->result = 0;
4771991Sheppo 	return (PICL_WALK_CONTINUE);
4781991Sheppo }
4791991Sheppo 
4801991Sheppo /*
4811991Sheppo  * Given the root node of the device tree.
4821991Sheppo  * compare it to the picl tree and add to it cpus
4831991Sheppo  * that are new.
4841991Sheppo  */
4851991Sheppo static void
add_cpus(di_node_t di_node)4861991Sheppo add_cpus(di_node_t di_node)
4871991Sheppo {
4881991Sheppo 	int		err;
4891991Sheppo 	di_node_t	cnode;
4901991Sheppo 	picl_nodehdl_t	plath;
4911991Sheppo 	cpu_lookup_t	cpu_arg;
4921991Sheppo 	char		*nodename;
4931991Sheppo 
4941991Sheppo 	err = ptree_get_node_by_path(PLATFORM_PATH, &plath);
4951991Sheppo 	if (err != PICL_SUCCESS)
4961991Sheppo 		return;
4971991Sheppo 
4981991Sheppo 	for (cnode = di_child_node(di_node); cnode != DI_NODE_NIL;
4991991Sheppo 	    cnode = di_sibling_node(cnode)) {
5001991Sheppo 		nodename = di_node_name(cnode);
5011991Sheppo 		if (nodename == NULL)
5021991Sheppo 			continue;
5031991Sheppo 		if (strcmp(nodename, OBP_CPU) == 0) {
5041991Sheppo 			cpu_arg.di_node = cnode;
5051991Sheppo 
5061991Sheppo 			if (ptree_walk_tree_by_class(plath,
5071991Sheppo 			    PICL_CLASS_CPU, &cpu_arg, cpu_exists)
5081991Sheppo 			    != PICL_SUCCESS)
5091991Sheppo 				return;
5101991Sheppo 
5111991Sheppo 			if (cpu_arg.result == 0)
5121991Sheppo 				/*
5131991Sheppo 				 * Didn't find a matching cpu, add it.
5141991Sheppo 				 */
5151991Sheppo 				(void) construct_cpu_node(plath,
5161991Sheppo 				    cnode);
5171991Sheppo 		}
5181991Sheppo 	}
5191991Sheppo }
5201991Sheppo 
5211991Sheppo /*
5221991Sheppo  * Handle DR events. Only supports cpu add and remove.
5231991Sheppo  */
5241991Sheppo int
update_devices(char * dev,int op)5251991Sheppo update_devices(char *dev, int op)
5261991Sheppo {
5271991Sheppo 	di_node_t	di_root;
5281991Sheppo 
5291991Sheppo 	if ((di_root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL)
5301991Sheppo 		return (PICL_FAILURE);
5311991Sheppo 
5321991Sheppo 	if ((ph = di_prom_init()) == NULL)
5331991Sheppo 		return (PICL_FAILURE);
5341991Sheppo 
5351991Sheppo 	if (op == DEV_ADD) {
5361991Sheppo 		if (strcmp(dev, OBP_CPU) == 0)
5371991Sheppo 			add_cpus(di_root);
5381991Sheppo 	}
5391991Sheppo 
5401991Sheppo 	if (op == DEV_REMOVE) {
5411991Sheppo 		if (strcmp(dev, OBP_CPU) == 0)
5421991Sheppo 			remove_cpus(di_root);
5431991Sheppo 	}
5441991Sheppo 
5451991Sheppo 	di_fini(di_root);
5461991Sheppo 	di_prom_fini(ph);
5471991Sheppo 	return (PICL_SUCCESS);
5481991Sheppo }
549