1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * PICL plug-in that creates the FRU Hierarchy for the
31*0Sstevel@tonic-gate  * SUNW,Sun-Fire-480R (Cherrystone) platform
32*0Sstevel@tonic-gate  */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <stdio.h>
35*0Sstevel@tonic-gate #include <string.h>
36*0Sstevel@tonic-gate #include <libintl.h>
37*0Sstevel@tonic-gate #include <libnvpair.h>
38*0Sstevel@tonic-gate #include <syslog.h>
39*0Sstevel@tonic-gate #include <picl.h>
40*0Sstevel@tonic-gate #include <picltree.h>
41*0Sstevel@tonic-gate #include <picldefs.h>
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate /*
44*0Sstevel@tonic-gate  * Plugin registration entry points
45*0Sstevel@tonic-gate  */
46*0Sstevel@tonic-gate static void	picl_frutree_register(void);
47*0Sstevel@tonic-gate static void	picl_frutree_init(void);
48*0Sstevel@tonic-gate static void	picl_frutree_fini(void);
49*0Sstevel@tonic-gate static void	picl_frutree_evhandler(const char *ename, const void *earg,
50*0Sstevel@tonic-gate 		    size_t size, void *cookie);
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate #pragma	init(picl_frutree_register)
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /*
55*0Sstevel@tonic-gate  * Log message texts
56*0Sstevel@tonic-gate  */
57*0Sstevel@tonic-gate #define	CREATE_FRUTREE_FAIL	gettext("Failed to create frutree node\n")
58*0Sstevel@tonic-gate #define	CREATE_CHASSIS_FAIL	gettext("Failed to create chassis node\n")
59*0Sstevel@tonic-gate #define	IOBRD_INIT_FAIL		gettext("do_ioboard_init() failed\n")
60*0Sstevel@tonic-gate #define	RSCBRD_INIT_FAIL	gettext("do_rscboard_init() failed\n")
61*0Sstevel@tonic-gate #define	FCAL_INIT_FAIL		gettext("do_fcal_init() failed\n")
62*0Sstevel@tonic-gate #define	PS_INIT_FAIL		gettext("do_power_supplies_init() failed\n")
63*0Sstevel@tonic-gate #define	SYSBOARD_INIT_FAIL	gettext("do_centerplane_init() failed\n")
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate /*
66*0Sstevel@tonic-gate  * Viewpoints property field used by SunMC
67*0Sstevel@tonic-gate  */
68*0Sstevel@tonic-gate #define	CHASSIS_VIEWPOINTS	gettext("front top rear")
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate /*
71*0Sstevel@tonic-gate  * Ref prop values
72*0Sstevel@tonic-gate  */
73*0Sstevel@tonic-gate #define	SEEPROM_SOURCE		"_seeprom_source"
74*0Sstevel@tonic-gate #define	FRU_PARENT		"_fru_parent"
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate /*
77*0Sstevel@tonic-gate  * List of all the FRU locations in the platform_frupath[] array, and
78*0Sstevel@tonic-gate  * location_label[] array
79*0Sstevel@tonic-gate  */
80*0Sstevel@tonic-gate #define	PS0		0
81*0Sstevel@tonic-gate #define	PS1		1
82*0Sstevel@tonic-gate #define	RSC		2
83*0Sstevel@tonic-gate #define	DISKBACKPLANE	3
84*0Sstevel@tonic-gate #define	PDB		4
85*0Sstevel@tonic-gate #define	CENTERPLANE	5
86*0Sstevel@tonic-gate #define	IOBRD		6
87*0Sstevel@tonic-gate #define	CPUMOD0		7
88*0Sstevel@tonic-gate #define	CPUMOD1		8
89*0Sstevel@tonic-gate #define	CPU0_DIMM0	9
90*0Sstevel@tonic-gate #define	DIMMS_PER_MOD	8
91*0Sstevel@tonic-gate #define	DIMMS_PER_SLOT	16
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate /*
94*0Sstevel@tonic-gate  * Local variables
95*0Sstevel@tonic-gate  */
96*0Sstevel@tonic-gate static picld_plugin_reg_t  my_reg_info = {
97*0Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
98*0Sstevel@tonic-gate 	PICLD_PLUGIN_NON_CRITICAL,
99*0Sstevel@tonic-gate 	"SUNW_Cherrystone_frutree",
100*0Sstevel@tonic-gate 	picl_frutree_init,
101*0Sstevel@tonic-gate 	picl_frutree_fini
102*0Sstevel@tonic-gate };
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate /*
105*0Sstevel@tonic-gate  * List of all the FRUs in the /platform tree with SEEPROMs
106*0Sstevel@tonic-gate  */
107*0Sstevel@tonic-gate static char *platform_frupath[] = {
108*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a2", /* PS 0 */
109*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a0", /* PS 1 */
110*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6", /* RSC */
111*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a8", /* Disk Backplane */
112*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ae", /* PDB */
113*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a8", /* Centerplane */
114*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,aa", /* IO */
115*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0", /* CPU MOD 0 */
116*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2", /* CPU MOD 1 */
117*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0", /* CPU0 DIMM0 */
118*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2", /* CPU0 DIMM1 */
119*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4", /* CPU0 DIMM2 */
120*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6", /* CPU0 DIMM3 */
121*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8", /* CPU0 DIMM4 */
122*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa", /* CPU0 DIMM5 */
123*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac", /* CPU0 DIMM6 */
124*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae", /* CPU0 DIMM7 */
125*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0", /* CPU2 DIMM0 */
126*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2", /* CPU2 DIMM1 */
127*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4", /* CPU2 DIMM2 */
128*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6", /* CPU2 DIMM3 */
129*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8", /* CPU2 DIMM4 */
130*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa", /* CPU2 DIMM5 */
131*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac", /* CPU2 DIMM6 */
132*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae", /* CPU2 DIMM7 */
133*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0", /* CPU1 DIMM0 */
134*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2", /* CPU1 DIMM1 */
135*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4", /* CPU1 DIMM2 */
136*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6", /* CPU1 DIMM3 */
137*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8", /* CPU1 DIMM4 */
138*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa", /* CPU1 DIMM5 */
139*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac", /* CPU1 DIMM6 */
140*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae", /* CPU1 DIMM7 */
141*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0", /* CPU3 DIMM0 */
142*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2", /* CPU3 DIMM1 */
143*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4", /* CPU3 DIMM2 */
144*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6", /* CPU3 DIMM3 */
145*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8", /* CPU3 DIMM4 */
146*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa", /* CPU3 DIMM5 */
147*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac", /* CPU3 DIMM6 */
148*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae", /* CPU3 DIMM7 */
149*0Sstevel@tonic-gate 	NULL};
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate /*
152*0Sstevel@tonic-gate  * List of Labels for FRU locations (uses the #define's from above)
153*0Sstevel@tonic-gate  */
154*0Sstevel@tonic-gate static char *location_label[] = {
155*0Sstevel@tonic-gate 	"0",			/* PS0 */
156*0Sstevel@tonic-gate 	"1",			/* PS1 */
157*0Sstevel@tonic-gate 	NULL,			/* RSC */
158*0Sstevel@tonic-gate 	NULL,			/* DISKBACKPLANE */
159*0Sstevel@tonic-gate 	NULL,			/* PDB */
160*0Sstevel@tonic-gate 	NULL,			/* CENTERPLANE */
161*0Sstevel@tonic-gate 	NULL,			/* IOBRD */
162*0Sstevel@tonic-gate 	"A",			/* CPUMOD0 */
163*0Sstevel@tonic-gate 	"B",			/* CPUMOD1 */
164*0Sstevel@tonic-gate 	"J2900",		/* CPU0 DIMM0 */
165*0Sstevel@tonic-gate 	"J3100",		/* CPU0 DIMM1 */
166*0Sstevel@tonic-gate 	"J2901",		/* CPU0 DIMM2 */
167*0Sstevel@tonic-gate 	"J3101",		/* CPU0 DIMM3 */
168*0Sstevel@tonic-gate 	"J3000",		/* CPU0 DIMM4 */
169*0Sstevel@tonic-gate 	"J3200",		/* CPU0 DIMM5 */
170*0Sstevel@tonic-gate 	"J3001",		/* CPU0 DIMM6 */
171*0Sstevel@tonic-gate 	"J3201",		/* CPU0 DIMM7 */
172*0Sstevel@tonic-gate 	"J7900",		/* CPU1 DIMM0 */
173*0Sstevel@tonic-gate 	"J8100",		/* CPU1 DIMM1 */
174*0Sstevel@tonic-gate 	"J7901",		/* CPU1 DIMM2 */
175*0Sstevel@tonic-gate 	"J8101",		/* CPU1 DIMM3 */
176*0Sstevel@tonic-gate 	"J8000",		/* CPU1 DIMM4 */
177*0Sstevel@tonic-gate 	"J8200",		/* CPU1 DIMM5 */
178*0Sstevel@tonic-gate 	"J8001",		/* CPU1 DIMM6 */
179*0Sstevel@tonic-gate 	"J8201",		/* CPU1 DIMM7 */
180*0Sstevel@tonic-gate 	"0",			/* CPU0 label */
181*0Sstevel@tonic-gate 	"1",			/* CPU1 label */
182*0Sstevel@tonic-gate 	NULL};
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate /*
185*0Sstevel@tonic-gate  * List of all the FRU slots for power supplies (hotpluggable)
186*0Sstevel@tonic-gate  */
187*0Sstevel@tonic-gate static char *frutree_power_supply[] = {
188*0Sstevel@tonic-gate 	"/frutree/chassis/power-dist-board/power-supply-slot?Slot=0",
189*0Sstevel@tonic-gate 	"/frutree/chassis/power-dist-board/power-supply-slot?Slot=1",
190*0Sstevel@tonic-gate 	NULL};
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate /* PICL handle for the root node of the "frutree" */
193*0Sstevel@tonic-gate static picl_nodehdl_t	frutreeh;
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate static int	do_ioboard_init(picl_nodehdl_t);
196*0Sstevel@tonic-gate static int	do_rscboard_init(picl_nodehdl_t);
197*0Sstevel@tonic-gate static int	do_fcal_init(picl_nodehdl_t);
198*0Sstevel@tonic-gate static int	do_power_supplies_init(picl_nodehdl_t);
199*0Sstevel@tonic-gate static int	do_centerplane_init(picl_nodehdl_t);
200*0Sstevel@tonic-gate static int	do_cpu_module_init(picl_nodehdl_t, int);
201*0Sstevel@tonic-gate static int	do_dimms_init(picl_nodehdl_t, int, int);
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate static int	add_ref_prop(picl_nodehdl_t, picl_nodehdl_t, char *);
204*0Sstevel@tonic-gate static int	add_slot_prop(picl_nodehdl_t, int);
205*0Sstevel@tonic-gate static int	add_label_prop(picl_nodehdl_t, char *);
206*0Sstevel@tonic-gate static int	add_void_fda_prop(picl_nodehdl_t);
207*0Sstevel@tonic-gate static int	add_viewpoints_prop(picl_nodehdl_t, char *);
208*0Sstevel@tonic-gate static int	add_all_nodes();
209*0Sstevel@tonic-gate static int	remove_all_nodes(picl_nodehdl_t);
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate static int	add_hotplug_fru_device(void);
212*0Sstevel@tonic-gate static int	rem_hotplug_fru_device(void);
213*0Sstevel@tonic-gate static int	is_added_device(char *, char *);
214*0Sstevel@tonic-gate static int	is_removed_device(char *, char *);
215*0Sstevel@tonic-gate static int	add_power_supply(int);
216*0Sstevel@tonic-gate static int	remove_power_supply(int);
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate /*
219*0Sstevel@tonic-gate  * This function is executed as part of .init when the plugin is
220*0Sstevel@tonic-gate  * dlopen()ed
221*0Sstevel@tonic-gate  */
222*0Sstevel@tonic-gate static void
picl_frutree_register()223*0Sstevel@tonic-gate picl_frutree_register()
224*0Sstevel@tonic-gate {
225*0Sstevel@tonic-gate 	(void) picld_plugin_register(&my_reg_info);
226*0Sstevel@tonic-gate }
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate /*
229*0Sstevel@tonic-gate  * This function is the init entry point of the plugin.
230*0Sstevel@tonic-gate  * It initializes the /frutree tree
231*0Sstevel@tonic-gate  */
232*0Sstevel@tonic-gate static void
picl_frutree_init()233*0Sstevel@tonic-gate picl_frutree_init()
234*0Sstevel@tonic-gate {
235*0Sstevel@tonic-gate 	int		err;
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	err = add_all_nodes();
238*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
239*0Sstevel@tonic-gate 		(void) remove_all_nodes(frutreeh);
240*0Sstevel@tonic-gate 		return;
241*0Sstevel@tonic-gate 	}
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	/* Register the event handler routine */
244*0Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
245*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
246*0Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
247*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
248*0Sstevel@tonic-gate }
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate /*
251*0Sstevel@tonic-gate  * This function is the fini entry point of the plugin
252*0Sstevel@tonic-gate  */
253*0Sstevel@tonic-gate static void
picl_frutree_fini(void)254*0Sstevel@tonic-gate picl_frutree_fini(void)
255*0Sstevel@tonic-gate {
256*0Sstevel@tonic-gate 	/* Unregister the event handler routine */
257*0Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
258*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
259*0Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
260*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 	(void) remove_all_nodes(frutreeh);
263*0Sstevel@tonic-gate }
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate /*
266*0Sstevel@tonic-gate  * This function is the event handler of this plug-in.
267*0Sstevel@tonic-gate  *
268*0Sstevel@tonic-gate  * It processes the following events:
269*0Sstevel@tonic-gate  *
270*0Sstevel@tonic-gate  * 	PICLEVENT_SYSEVENT_DEVICE_ADDED
271*0Sstevel@tonic-gate  * 	PICLEVENT_SYSEVENT_DEVICE_REMOVED
272*0Sstevel@tonic-gate  */
273*0Sstevel@tonic-gate /* ARGSUSED */
274*0Sstevel@tonic-gate static void
picl_frutree_evhandler(const char * ename,const void * earg,size_t size,void * cookie)275*0Sstevel@tonic-gate picl_frutree_evhandler(const char *ename, const void *earg, size_t size,
276*0Sstevel@tonic-gate     void *cookie)
277*0Sstevel@tonic-gate {
278*0Sstevel@tonic-gate 	if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
279*0Sstevel@tonic-gate 		/* Check for and add any hotplugged device(s) */
280*0Sstevel@tonic-gate 		(void) add_hotplug_fru_device();
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	} else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
283*0Sstevel@tonic-gate 		/* Check for and remove any hotplugged device(s) */
284*0Sstevel@tonic-gate 		(void) rem_hotplug_fru_device();
285*0Sstevel@tonic-gate 	}
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate /* Initializes the FRU nodes for the IO board */
289*0Sstevel@tonic-gate static int
do_ioboard_init(picl_nodehdl_t rooth)290*0Sstevel@tonic-gate do_ioboard_init(picl_nodehdl_t rooth)
291*0Sstevel@tonic-gate {
292*0Sstevel@tonic-gate 	picl_nodehdl_t		iobrdh;
293*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
294*0Sstevel@tonic-gate 	int			err;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	/* Create the node for the IO board (if it exists) */
297*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[IOBRD], &tmph) ==
298*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
299*0Sstevel@tonic-gate 		err = ptree_create_node("io-board", "fru", &iobrdh);
300*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
301*0Sstevel@tonic-gate 			return (err);
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 		err = add_ref_prop(iobrdh, tmph, SEEPROM_SOURCE);
304*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
305*0Sstevel@tonic-gate 			return (err);
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 		err = add_void_fda_prop(iobrdh);
308*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
309*0Sstevel@tonic-gate 			return (err);
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, iobrdh);
312*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
313*0Sstevel@tonic-gate 			return (err);
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, iobrdh, FRU_PARENT);
316*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
317*0Sstevel@tonic-gate 			return (err);
318*0Sstevel@tonic-gate 	}
319*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate /* Initializes the FRU node for the RSC card */
323*0Sstevel@tonic-gate static int
do_rscboard_init(picl_nodehdl_t rooth)324*0Sstevel@tonic-gate do_rscboard_init(picl_nodehdl_t rooth)
325*0Sstevel@tonic-gate {
326*0Sstevel@tonic-gate 	picl_nodehdl_t		rscbrdh;
327*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
328*0Sstevel@tonic-gate 	int			err;
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	/* Create the node for the RSC board (if it exists) */
331*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[RSC], &tmph) ==
332*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
333*0Sstevel@tonic-gate 		err = ptree_create_node("rsc-board", "fru", &rscbrdh);
334*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
335*0Sstevel@tonic-gate 			return (err);
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 		err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE);
338*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
339*0Sstevel@tonic-gate 			return (err);
340*0Sstevel@tonic-gate 
341*0Sstevel@tonic-gate 		err = add_void_fda_prop(rscbrdh);
342*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
343*0Sstevel@tonic-gate 			return (err);
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, rscbrdh);
346*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
347*0Sstevel@tonic-gate 			return (err);
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, rscbrdh, FRU_PARENT);
350*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
351*0Sstevel@tonic-gate 			return (err);
352*0Sstevel@tonic-gate 	}
353*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
354*0Sstevel@tonic-gate }
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate /* Initializes the FRU nodes for the FCAL backplaned */
357*0Sstevel@tonic-gate static int
do_fcal_init(picl_nodehdl_t rooth)358*0Sstevel@tonic-gate do_fcal_init(picl_nodehdl_t rooth)
359*0Sstevel@tonic-gate {
360*0Sstevel@tonic-gate 	picl_nodehdl_t		fcalsloth;
361*0Sstevel@tonic-gate 	picl_nodehdl_t		fcalmodh;
362*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
363*0Sstevel@tonic-gate 	int			err;
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	/* Create the node for the FCAL backplane slot */
366*0Sstevel@tonic-gate 	err = ptree_create_node("fcal-backplane-slot",
367*0Sstevel@tonic-gate 	    "location", &fcalsloth);
368*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
369*0Sstevel@tonic-gate 		return (err);
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate 	err = add_slot_prop(fcalsloth, 0);
372*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
373*0Sstevel@tonic-gate 		return (err);
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate 	err = ptree_add_node(rooth, fcalsloth);
376*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
377*0Sstevel@tonic-gate 		return (err);
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 	/* If the FCAL backplane exists, create a node for it */
380*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[DISKBACKPLANE], &tmph) ==
381*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
382*0Sstevel@tonic-gate 		err = ptree_create_node("fcal-backplane", "fru",
383*0Sstevel@tonic-gate 		    &fcalmodh);
384*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
385*0Sstevel@tonic-gate 			return (err);
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 		err = add_ref_prop(fcalmodh, tmph, SEEPROM_SOURCE);
388*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
389*0Sstevel@tonic-gate 			return (err);
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 		err = add_void_fda_prop(fcalmodh);
392*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
393*0Sstevel@tonic-gate 			return (err);
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 		err = ptree_add_node(fcalsloth, fcalmodh);
396*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
397*0Sstevel@tonic-gate 			return (err);
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, fcalmodh, FRU_PARENT);
400*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
401*0Sstevel@tonic-gate 			return (err);
402*0Sstevel@tonic-gate 	}
403*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
404*0Sstevel@tonic-gate }
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate /* Initializes the FRU nodes for the PDB and the power supplies */
407*0Sstevel@tonic-gate static int
do_power_supplies_init(picl_nodehdl_t rooth)408*0Sstevel@tonic-gate do_power_supplies_init(picl_nodehdl_t rooth)
409*0Sstevel@tonic-gate {
410*0Sstevel@tonic-gate 	picl_nodehdl_t		powerbrdh;
411*0Sstevel@tonic-gate 	picl_nodehdl_t		powersloth;
412*0Sstevel@tonic-gate 	picl_nodehdl_t		powermodh;
413*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
414*0Sstevel@tonic-gate 	int			i, err, slotnum;
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	/* Create the node for the PDB (if it exists) */
417*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[PDB], &tmph) ==
418*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
419*0Sstevel@tonic-gate 		err = ptree_create_node("power-dist-board", "fru", &powerbrdh);
420*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
421*0Sstevel@tonic-gate 			return (err);
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 		err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE);
424*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
425*0Sstevel@tonic-gate 			return (err);
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 		err = add_void_fda_prop(powerbrdh);
428*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
429*0Sstevel@tonic-gate 			return (err);
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, powerbrdh);
432*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
433*0Sstevel@tonic-gate 			return (err);
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, powerbrdh, FRU_PARENT);
436*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
437*0Sstevel@tonic-gate 			return (err);
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 		for (i = PS0; i <= PS1; i++) {
440*0Sstevel@tonic-gate 			/* Create the node for the power supply slot */
441*0Sstevel@tonic-gate 			err = ptree_create_node("power-supply-slot",
442*0Sstevel@tonic-gate 			    "location", &powersloth);
443*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
444*0Sstevel@tonic-gate 				return (err);
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 			slotnum = i - PS0;
447*0Sstevel@tonic-gate 			err = add_slot_prop(powersloth, slotnum);
448*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
449*0Sstevel@tonic-gate 				return (err);
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 			err = add_label_prop(powersloth, location_label[i]);
452*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
453*0Sstevel@tonic-gate 				return (err);
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate 			err = ptree_add_node(powerbrdh, powersloth);
456*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
457*0Sstevel@tonic-gate 				return (err);
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 			/* If the PS exists, create a node for it */
460*0Sstevel@tonic-gate 			if (ptree_get_node_by_path(platform_frupath[i],
461*0Sstevel@tonic-gate 			    &tmph) == PICL_SUCCESS) {
462*0Sstevel@tonic-gate 				err = ptree_create_node("power-supply",
463*0Sstevel@tonic-gate 				    "fru", &powermodh);
464*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
465*0Sstevel@tonic-gate 					return (err);
466*0Sstevel@tonic-gate 
467*0Sstevel@tonic-gate 				err = add_ref_prop(powermodh, tmph,
468*0Sstevel@tonic-gate 				    SEEPROM_SOURCE);
469*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
470*0Sstevel@tonic-gate 					return (err);
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate 				err = add_void_fda_prop(powermodh);
473*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
474*0Sstevel@tonic-gate 					return (err);
475*0Sstevel@tonic-gate 
476*0Sstevel@tonic-gate 				err = ptree_add_node(powersloth, powermodh);
477*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
478*0Sstevel@tonic-gate 					return (err);
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 				err = add_ref_prop(tmph, powermodh, FRU_PARENT);
481*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
482*0Sstevel@tonic-gate 					return (err);
483*0Sstevel@tonic-gate 			}
484*0Sstevel@tonic-gate 		}
485*0Sstevel@tonic-gate 	}
486*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
487*0Sstevel@tonic-gate }
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate /* Initializes the FRU nodes for the centerplane and CPU Memory modules */
490*0Sstevel@tonic-gate static int
do_centerplane_init(picl_nodehdl_t rooth)491*0Sstevel@tonic-gate do_centerplane_init(picl_nodehdl_t rooth)
492*0Sstevel@tonic-gate {
493*0Sstevel@tonic-gate 	picl_nodehdl_t		sysboardh;
494*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemsloth;
495*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemmodh;
496*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
497*0Sstevel@tonic-gate 	int			i, err, slotnum;
498*0Sstevel@tonic-gate 
499*0Sstevel@tonic-gate 	/* Create the node for the system board (if it exists) */
500*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[CENTERPLANE], &tmph) ==
501*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
502*0Sstevel@tonic-gate 		err = ptree_create_node("centerplane", "fru",
503*0Sstevel@tonic-gate 		    &sysboardh);
504*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
505*0Sstevel@tonic-gate 			return (err);
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate 		err = add_ref_prop(sysboardh, tmph, SEEPROM_SOURCE);
508*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
509*0Sstevel@tonic-gate 			return (err);
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate 		err = add_void_fda_prop(sysboardh);
512*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
513*0Sstevel@tonic-gate 			return (err);
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, sysboardh);
516*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
517*0Sstevel@tonic-gate 			return (err);
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, sysboardh, FRU_PARENT);
520*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
521*0Sstevel@tonic-gate 			return (err);
522*0Sstevel@tonic-gate 
523*0Sstevel@tonic-gate 		for (i = CPUMOD0; i <= CPUMOD1; i++) {
524*0Sstevel@tonic-gate 			/* Create the node for the CPU Memory slot */
525*0Sstevel@tonic-gate 			err = ptree_create_node("cpu-mem-slot", "location",
526*0Sstevel@tonic-gate 			    &cpumemsloth);
527*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
528*0Sstevel@tonic-gate 				return (err);
529*0Sstevel@tonic-gate 
530*0Sstevel@tonic-gate 			slotnum = i - CPUMOD0;
531*0Sstevel@tonic-gate 			err = add_slot_prop(cpumemsloth, slotnum);
532*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
533*0Sstevel@tonic-gate 				return (err);
534*0Sstevel@tonic-gate 
535*0Sstevel@tonic-gate 			err = add_label_prop(cpumemsloth, location_label[i]);
536*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
537*0Sstevel@tonic-gate 				return (err);
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate 			err = ptree_add_node(sysboardh, cpumemsloth);
540*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
541*0Sstevel@tonic-gate 				return (err);
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 			/* If CPU Mem module exists, create a node for it */
544*0Sstevel@tonic-gate 			if (ptree_get_node_by_path(platform_frupath[i],
545*0Sstevel@tonic-gate 			    &tmph) == PICL_SUCCESS) {
546*0Sstevel@tonic-gate 				err = ptree_create_node("cpu-mem-module",
547*0Sstevel@tonic-gate 				    "fru", &cpumemmodh);
548*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
549*0Sstevel@tonic-gate 					return (err);
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 				err = add_ref_prop(cpumemmodh, tmph,
552*0Sstevel@tonic-gate 				    SEEPROM_SOURCE);
553*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
554*0Sstevel@tonic-gate 					return (err);
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate 				err = add_void_fda_prop(cpumemmodh);
557*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
558*0Sstevel@tonic-gate 					return (err);
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 				err = ptree_add_node(cpumemsloth, cpumemmodh);
561*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
562*0Sstevel@tonic-gate 					return (err);
563*0Sstevel@tonic-gate 
564*0Sstevel@tonic-gate 				err = add_ref_prop(tmph, cpumemmodh,
565*0Sstevel@tonic-gate 				    FRU_PARENT);
566*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
567*0Sstevel@tonic-gate 					return (err);
568*0Sstevel@tonic-gate 
569*0Sstevel@tonic-gate 				err = do_cpu_module_init(cpumemmodh, slotnum);
570*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
571*0Sstevel@tonic-gate 					return (err);
572*0Sstevel@tonic-gate 			}
573*0Sstevel@tonic-gate 		}
574*0Sstevel@tonic-gate 	}
575*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
576*0Sstevel@tonic-gate }
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate /* Creates the FRU nodes for the CPU Module and associated DIMMs */
579*0Sstevel@tonic-gate static int
do_cpu_module_init(picl_nodehdl_t rooth,int slot)580*0Sstevel@tonic-gate do_cpu_module_init(picl_nodehdl_t rooth, int slot)
581*0Sstevel@tonic-gate {
582*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumodh;
583*0Sstevel@tonic-gate 	int			i, c, err;
584*0Sstevel@tonic-gate 
585*0Sstevel@tonic-gate 	for (i = 0; i <= 1; i++) {
586*0Sstevel@tonic-gate 		err = ptree_create_node("cpu-module", "location",
587*0Sstevel@tonic-gate 		    &cpumodh);
588*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
589*0Sstevel@tonic-gate 			return (err);
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 		err = add_slot_prop(cpumodh, i);
592*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
593*0Sstevel@tonic-gate 			return (err);
594*0Sstevel@tonic-gate 
595*0Sstevel@tonic-gate 		c = CPU0_DIMM0 + DIMMS_PER_SLOT + i;
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate 		err = add_label_prop(cpumodh, location_label[c]);
598*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
599*0Sstevel@tonic-gate 			return (err);
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, cpumodh);
602*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
603*0Sstevel@tonic-gate 			return (err);
604*0Sstevel@tonic-gate 
605*0Sstevel@tonic-gate 		/* Create the nodes for the memory (if they exist) */
606*0Sstevel@tonic-gate 		err = do_dimms_init(cpumodh, slot, i);
607*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
608*0Sstevel@tonic-gate 			return (err);
609*0Sstevel@tonic-gate 	}
610*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
611*0Sstevel@tonic-gate }
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate /* Creates the FRU nodes for the DIMMs on a particular CPU Module */
614*0Sstevel@tonic-gate static int
do_dimms_init(picl_nodehdl_t rooth,int slot,int module)615*0Sstevel@tonic-gate do_dimms_init(picl_nodehdl_t rooth, int slot, int module)
616*0Sstevel@tonic-gate {
617*0Sstevel@tonic-gate 	picl_nodehdl_t		dimmsloth;
618*0Sstevel@tonic-gate 	picl_nodehdl_t		dimmmodh;
619*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
620*0Sstevel@tonic-gate 	int			i, c, l, err;
621*0Sstevel@tonic-gate 
622*0Sstevel@tonic-gate 	for (i = 0; i < DIMMS_PER_MOD; i++) {
623*0Sstevel@tonic-gate 		/* Create the node for the memory slot */
624*0Sstevel@tonic-gate 		err = ptree_create_node("dimm-slot", "location",
625*0Sstevel@tonic-gate 		    &dimmsloth);
626*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
627*0Sstevel@tonic-gate 			return (err);
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 		err = add_slot_prop(dimmsloth, i);
630*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
631*0Sstevel@tonic-gate 			return (err);
632*0Sstevel@tonic-gate 
633*0Sstevel@tonic-gate 		c = ((slot * DIMMS_PER_SLOT) +
634*0Sstevel@tonic-gate 		    (module * DIMMS_PER_MOD) + i) + CPU0_DIMM0;
635*0Sstevel@tonic-gate 
636*0Sstevel@tonic-gate 		l = c - (DIMMS_PER_SLOT * slot);
637*0Sstevel@tonic-gate 
638*0Sstevel@tonic-gate 		err = add_label_prop(dimmsloth, location_label[l]);
639*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
640*0Sstevel@tonic-gate 			return (err);
641*0Sstevel@tonic-gate 
642*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, dimmsloth);
643*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
644*0Sstevel@tonic-gate 			return (err);
645*0Sstevel@tonic-gate 
646*0Sstevel@tonic-gate 		/* If the memory module exists, create a node for it */
647*0Sstevel@tonic-gate 		if (ptree_get_node_by_path(platform_frupath[c], &tmph) ==
648*0Sstevel@tonic-gate 		    PICL_SUCCESS) {
649*0Sstevel@tonic-gate 			err = ptree_create_node("dimm-module", "fru",
650*0Sstevel@tonic-gate 			    &dimmmodh);
651*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
652*0Sstevel@tonic-gate 				return (err);
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate 			err = add_ref_prop(dimmmodh, tmph, SEEPROM_SOURCE);
655*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
656*0Sstevel@tonic-gate 				return (err);
657*0Sstevel@tonic-gate 
658*0Sstevel@tonic-gate 			err = add_void_fda_prop(dimmmodh);
659*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
660*0Sstevel@tonic-gate 				return (err);
661*0Sstevel@tonic-gate 
662*0Sstevel@tonic-gate 			err = ptree_add_node(dimmsloth, dimmmodh);
663*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
664*0Sstevel@tonic-gate 				return (err);
665*0Sstevel@tonic-gate 
666*0Sstevel@tonic-gate 			err = add_ref_prop(tmph, dimmmodh, FRU_PARENT);
667*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
668*0Sstevel@tonic-gate 				return (err);
669*0Sstevel@tonic-gate 		}
670*0Sstevel@tonic-gate 	}
671*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
672*0Sstevel@tonic-gate }
673*0Sstevel@tonic-gate 
674*0Sstevel@tonic-gate /* Creates a "reference" property between two PICL nodes */
675*0Sstevel@tonic-gate static int
add_ref_prop(picl_nodehdl_t nodeh,picl_nodehdl_t tmph,char * str)676*0Sstevel@tonic-gate add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str)
677*0Sstevel@tonic-gate {
678*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
679*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
680*0Sstevel@tonic-gate 	int			err;
681*0Sstevel@tonic-gate 
682*0Sstevel@tonic-gate 	if (str == NULL)
683*0Sstevel@tonic-gate 		return (PICL_FAILURE);
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
686*0Sstevel@tonic-gate 	    PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
687*0Sstevel@tonic-gate 	    str, NULL, NULL);
688*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
689*0Sstevel@tonic-gate 		return (err);
690*0Sstevel@tonic-gate 
691*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph);
692*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
693*0Sstevel@tonic-gate 		return (err);
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
696*0Sstevel@tonic-gate }
697*0Sstevel@tonic-gate 
698*0Sstevel@tonic-gate /* Creates a "slot" property for a given PICL node */
699*0Sstevel@tonic-gate static int
add_slot_prop(picl_nodehdl_t nodeh,int slotnum)700*0Sstevel@tonic-gate add_slot_prop(picl_nodehdl_t nodeh, int slotnum)
701*0Sstevel@tonic-gate {
702*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
703*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
704*0Sstevel@tonic-gate 	int			err;
705*0Sstevel@tonic-gate 
706*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
707*0Sstevel@tonic-gate 	    PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL);
708*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
709*0Sstevel@tonic-gate 		return (err);
710*0Sstevel@tonic-gate 
711*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph);
712*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
713*0Sstevel@tonic-gate 		return (err);
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
716*0Sstevel@tonic-gate }
717*0Sstevel@tonic-gate 
718*0Sstevel@tonic-gate /* Creates a "Label" property for a given PICL node */
719*0Sstevel@tonic-gate static int
add_label_prop(picl_nodehdl_t nodeh,char * label)720*0Sstevel@tonic-gate add_label_prop(picl_nodehdl_t nodeh, char *label)
721*0Sstevel@tonic-gate {
722*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
723*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
724*0Sstevel@tonic-gate 	int			err;
725*0Sstevel@tonic-gate 
726*0Sstevel@tonic-gate 	if (label == NULL)
727*0Sstevel@tonic-gate 		return (PICL_FAILURE);
728*0Sstevel@tonic-gate 
729*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
730*0Sstevel@tonic-gate 	    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label",
731*0Sstevel@tonic-gate 	    NULL, NULL);
732*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
733*0Sstevel@tonic-gate 		return (err);
734*0Sstevel@tonic-gate 
735*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph);
736*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
737*0Sstevel@tonic-gate 		return (err);
738*0Sstevel@tonic-gate 
739*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
740*0Sstevel@tonic-gate }
741*0Sstevel@tonic-gate 
742*0Sstevel@tonic-gate /* Creates a "FRUDataAvailable" void property for the given PICL node */
743*0Sstevel@tonic-gate static int
add_void_fda_prop(picl_nodehdl_t nodeh)744*0Sstevel@tonic-gate add_void_fda_prop(picl_nodehdl_t nodeh)
745*0Sstevel@tonic-gate {
746*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
747*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
748*0Sstevel@tonic-gate 	int			err;
749*0Sstevel@tonic-gate 
750*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
751*0Sstevel@tonic-gate 	    PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL);
752*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
753*0Sstevel@tonic-gate 		return (err);
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
756*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
757*0Sstevel@tonic-gate 		return (err);
758*0Sstevel@tonic-gate 
759*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
760*0Sstevel@tonic-gate }
761*0Sstevel@tonic-gate 
762*0Sstevel@tonic-gate /* Creates a "ViewPoints" property -- used for chassis */
763*0Sstevel@tonic-gate static int
add_viewpoints_prop(picl_nodehdl_t nodeh,char * string)764*0Sstevel@tonic-gate add_viewpoints_prop(picl_nodehdl_t nodeh, char *string)
765*0Sstevel@tonic-gate {
766*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
767*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
768*0Sstevel@tonic-gate 	int			err;
769*0Sstevel@tonic-gate 
770*0Sstevel@tonic-gate 	if (string == NULL)
771*0Sstevel@tonic-gate 		return (PICL_FAILURE);
772*0Sstevel@tonic-gate 
773*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
774*0Sstevel@tonic-gate 	    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints",
775*0Sstevel@tonic-gate 	    NULL, NULL);
776*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
777*0Sstevel@tonic-gate 		return (err);
778*0Sstevel@tonic-gate 
779*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph);
780*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
781*0Sstevel@tonic-gate 		return (err);
782*0Sstevel@tonic-gate 
783*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
784*0Sstevel@tonic-gate }
785*0Sstevel@tonic-gate 
786*0Sstevel@tonic-gate /* Creates and adds all of the frutree nodes */
787*0Sstevel@tonic-gate static int
add_all_nodes()788*0Sstevel@tonic-gate add_all_nodes()
789*0Sstevel@tonic-gate {
790*0Sstevel@tonic-gate 	picl_nodehdl_t	rooth;
791*0Sstevel@tonic-gate 	picl_nodehdl_t	chassish;
792*0Sstevel@tonic-gate 	int		err;
793*0Sstevel@tonic-gate 
794*0Sstevel@tonic-gate 	/* Get the root node of the PICL tree */
795*0Sstevel@tonic-gate 	err = ptree_get_root(&rooth);
796*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
797*0Sstevel@tonic-gate 		return (err);
798*0Sstevel@tonic-gate 	}
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate 	/* Create and add the root node of the FRU subtree */
801*0Sstevel@tonic-gate 	err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh);
802*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
803*0Sstevel@tonic-gate 		syslog(LOG_ERR, CREATE_FRUTREE_FAIL);
804*0Sstevel@tonic-gate 		return (err);
805*0Sstevel@tonic-gate 	}
806*0Sstevel@tonic-gate 
807*0Sstevel@tonic-gate 	/* Create and add the chassis node */
808*0Sstevel@tonic-gate 	err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish);
809*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
810*0Sstevel@tonic-gate 		syslog(LOG_ERR, CREATE_CHASSIS_FAIL);
811*0Sstevel@tonic-gate 		return (err);
812*0Sstevel@tonic-gate 	}
813*0Sstevel@tonic-gate 
814*0Sstevel@tonic-gate 	/* Add ViewPoints prop to chassis node */
815*0Sstevel@tonic-gate 	err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS);
816*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
817*0Sstevel@tonic-gate 		return (err);
818*0Sstevel@tonic-gate 
819*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the IO board */
820*0Sstevel@tonic-gate 	err = do_ioboard_init(chassish);
821*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
822*0Sstevel@tonic-gate 		syslog(LOG_ERR, IOBRD_INIT_FAIL);
823*0Sstevel@tonic-gate 		return (err);
824*0Sstevel@tonic-gate 	}
825*0Sstevel@tonic-gate 
826*0Sstevel@tonic-gate 	/* Initialize the FRU node for the RSC card */
827*0Sstevel@tonic-gate 	err = do_rscboard_init(chassish);
828*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
829*0Sstevel@tonic-gate 		syslog(LOG_ERR, RSCBRD_INIT_FAIL);
830*0Sstevel@tonic-gate 		return (err);
831*0Sstevel@tonic-gate 	}
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the DISK backplane */
834*0Sstevel@tonic-gate 	err = do_fcal_init(chassish);
835*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
836*0Sstevel@tonic-gate 		syslog(LOG_ERR, FCAL_INIT_FAIL);
837*0Sstevel@tonic-gate 		return (err);
838*0Sstevel@tonic-gate 	}
839*0Sstevel@tonic-gate 
840*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the PDB and the power supplies */
841*0Sstevel@tonic-gate 	err = do_power_supplies_init(chassish);
842*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
843*0Sstevel@tonic-gate 		syslog(LOG_ERR, PS_INIT_FAIL);
844*0Sstevel@tonic-gate 		return (err);
845*0Sstevel@tonic-gate 	}
846*0Sstevel@tonic-gate 
847*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the CPU Memory modules */
848*0Sstevel@tonic-gate 	err = do_centerplane_init(chassish);
849*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
850*0Sstevel@tonic-gate 		syslog(LOG_ERR, SYSBOARD_INIT_FAIL);
851*0Sstevel@tonic-gate 		return (err);
852*0Sstevel@tonic-gate 	}
853*0Sstevel@tonic-gate 
854*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
855*0Sstevel@tonic-gate }
856*0Sstevel@tonic-gate 
857*0Sstevel@tonic-gate /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
858*0Sstevel@tonic-gate static int
remove_all_nodes(picl_nodehdl_t rooth)859*0Sstevel@tonic-gate remove_all_nodes(picl_nodehdl_t rooth)
860*0Sstevel@tonic-gate {
861*0Sstevel@tonic-gate 	picl_nodehdl_t		chdh;
862*0Sstevel@tonic-gate 	int			err, done = 0;
863*0Sstevel@tonic-gate 
864*0Sstevel@tonic-gate 	while (!done) {
865*0Sstevel@tonic-gate 		err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
866*0Sstevel@tonic-gate 		    sizeof (picl_nodehdl_t));
867*0Sstevel@tonic-gate 		if (err != PICL_PROPNOTFOUND) {
868*0Sstevel@tonic-gate 			(void) remove_all_nodes(chdh);
869*0Sstevel@tonic-gate 		} else {
870*0Sstevel@tonic-gate 			err = ptree_delete_node(rooth);
871*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
872*0Sstevel@tonic-gate 				return (err);
873*0Sstevel@tonic-gate 			} else {
874*0Sstevel@tonic-gate 				(void) ptree_destroy_node(rooth);
875*0Sstevel@tonic-gate 			}
876*0Sstevel@tonic-gate 			done = 1;
877*0Sstevel@tonic-gate 		}
878*0Sstevel@tonic-gate 	}
879*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
880*0Sstevel@tonic-gate }
881*0Sstevel@tonic-gate 
882*0Sstevel@tonic-gate /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */
883*0Sstevel@tonic-gate static int
add_hotplug_fru_device()884*0Sstevel@tonic-gate add_hotplug_fru_device()
885*0Sstevel@tonic-gate {
886*0Sstevel@tonic-gate 	int		i, err, slotnum;
887*0Sstevel@tonic-gate 
888*0Sstevel@tonic-gate 	/* Check for hotplugged power supplies */
889*0Sstevel@tonic-gate 	for (i = PS0; i <= PS1; i++) {
890*0Sstevel@tonic-gate 		/* Compare the /platform tree to the frutree */
891*0Sstevel@tonic-gate 		slotnum = i - PS0;
892*0Sstevel@tonic-gate 		err = is_added_device(platform_frupath[i],
893*0Sstevel@tonic-gate 		    frutree_power_supply[slotnum]);
894*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
895*0Sstevel@tonic-gate 			continue;
896*0Sstevel@tonic-gate 
897*0Sstevel@tonic-gate 		/* If they are different, then add a power supply */
898*0Sstevel@tonic-gate 		err = add_power_supply(slotnum);
899*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
900*0Sstevel@tonic-gate 			continue;
901*0Sstevel@tonic-gate 	}
902*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
903*0Sstevel@tonic-gate }
904*0Sstevel@tonic-gate 
905*0Sstevel@tonic-gate /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */
906*0Sstevel@tonic-gate static int
rem_hotplug_fru_device()907*0Sstevel@tonic-gate rem_hotplug_fru_device()
908*0Sstevel@tonic-gate {
909*0Sstevel@tonic-gate 	int		i, err, slotnum;
910*0Sstevel@tonic-gate 
911*0Sstevel@tonic-gate 	/* Check for hotplugged power supplies */
912*0Sstevel@tonic-gate 	for (i = PS0; i <= PS1; i++) {
913*0Sstevel@tonic-gate 		/* Compare the /platform tree to the frutree */
914*0Sstevel@tonic-gate 		slotnum = i - PS0;
915*0Sstevel@tonic-gate 		err = is_removed_device(platform_frupath[i],
916*0Sstevel@tonic-gate 		    frutree_power_supply[slotnum]);
917*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
918*0Sstevel@tonic-gate 			continue;
919*0Sstevel@tonic-gate 
920*0Sstevel@tonic-gate 		/* If they are different, then remove a power supply */
921*0Sstevel@tonic-gate 		err = remove_power_supply(slotnum);
922*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
923*0Sstevel@tonic-gate 			continue;
924*0Sstevel@tonic-gate 	}
925*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
926*0Sstevel@tonic-gate }
927*0Sstevel@tonic-gate 
928*0Sstevel@tonic-gate /*
929*0Sstevel@tonic-gate  * Compare the /platform tree to the /frutree to determine if a
930*0Sstevel@tonic-gate  * new device has been added
931*0Sstevel@tonic-gate  */
932*0Sstevel@tonic-gate static int
is_added_device(char * plat,char * fru)933*0Sstevel@tonic-gate is_added_device(char *plat, char *fru)
934*0Sstevel@tonic-gate {
935*0Sstevel@tonic-gate 	int		err;
936*0Sstevel@tonic-gate 	picl_nodehdl_t	plath, frusloth, frumodh;
937*0Sstevel@tonic-gate 
938*0Sstevel@tonic-gate 	/* Check for node in the /platform tree */
939*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(plat, &plath);
940*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
941*0Sstevel@tonic-gate 		return (err);
942*0Sstevel@tonic-gate 
943*0Sstevel@tonic-gate 	/*
944*0Sstevel@tonic-gate 	 * The node is in /platform, so find the corresponding slot in
945*0Sstevel@tonic-gate 	 * the frutree
946*0Sstevel@tonic-gate 	 */
947*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(fru, &frusloth);
948*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
949*0Sstevel@tonic-gate 		return (err);
950*0Sstevel@tonic-gate 
951*0Sstevel@tonic-gate 	/*
952*0Sstevel@tonic-gate 	 * If the slot in the frutree has a child, then return
953*0Sstevel@tonic-gate 	 * PICL_FAILURE.  This means that the /platform tree and
954*0Sstevel@tonic-gate 	 * the frutree are consistent and no action is necessary.
955*0Sstevel@tonic-gate 	 * Otherwise return PICL_SUCCESS to indicate that a node needs
956*0Sstevel@tonic-gate 	 * to be added to the frutree
957*0Sstevel@tonic-gate 	 */
958*0Sstevel@tonic-gate 	err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
959*0Sstevel@tonic-gate 	    &frumodh, sizeof (picl_nodehdl_t));
960*0Sstevel@tonic-gate 	if (err == PICL_SUCCESS)
961*0Sstevel@tonic-gate 		return (PICL_FAILURE);
962*0Sstevel@tonic-gate 
963*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
964*0Sstevel@tonic-gate }
965*0Sstevel@tonic-gate 
966*0Sstevel@tonic-gate /*
967*0Sstevel@tonic-gate  * Compare the /platform tree to the /frutree to determine if a
968*0Sstevel@tonic-gate  * device has been removed
969*0Sstevel@tonic-gate  */
970*0Sstevel@tonic-gate static int
is_removed_device(char * plat,char * fru)971*0Sstevel@tonic-gate is_removed_device(char *plat, char *fru)
972*0Sstevel@tonic-gate {
973*0Sstevel@tonic-gate 	int		err;
974*0Sstevel@tonic-gate 	picl_nodehdl_t	plath, frusloth, frumodh;
975*0Sstevel@tonic-gate 
976*0Sstevel@tonic-gate 
977*0Sstevel@tonic-gate 	/* Check for node in /platform tree */
978*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(plat, &plath);
979*0Sstevel@tonic-gate 	if (err == PICL_SUCCESS)
980*0Sstevel@tonic-gate 		return (PICL_FAILURE);
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 	/*
983*0Sstevel@tonic-gate 	 * The node is not in /platform, so find the corresponding slot in
984*0Sstevel@tonic-gate 	 * the frutree
985*0Sstevel@tonic-gate 	 */
986*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(fru, &frusloth);
987*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
988*0Sstevel@tonic-gate 		return (err);
989*0Sstevel@tonic-gate 
990*0Sstevel@tonic-gate 	/*
991*0Sstevel@tonic-gate 	 * If the slot in the frutree does not have a child, then return
992*0Sstevel@tonic-gate 	 * PICL_FAILURE.  This means that the /platform tree and
993*0Sstevel@tonic-gate 	 * the frutree are consistent and no action is necessary.
994*0Sstevel@tonic-gate 	 * Otherwise return PICL_SUCCESS to indicate that the needs
995*0Sstevel@tonic-gate 	 * to be removed from the frutree
996*0Sstevel@tonic-gate 	 */
997*0Sstevel@tonic-gate 	err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
998*0Sstevel@tonic-gate 	    &frumodh, sizeof (picl_nodehdl_t));
999*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1000*0Sstevel@tonic-gate 		return (err);
1001*0Sstevel@tonic-gate 
1002*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1003*0Sstevel@tonic-gate }
1004*0Sstevel@tonic-gate 
1005*0Sstevel@tonic-gate static int
remove_picl_node(picl_nodehdl_t nodeh)1006*0Sstevel@tonic-gate remove_picl_node(picl_nodehdl_t nodeh)
1007*0Sstevel@tonic-gate {
1008*0Sstevel@tonic-gate 	int err;
1009*0Sstevel@tonic-gate 	err = ptree_delete_node(nodeh);
1010*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1011*0Sstevel@tonic-gate 		return (err);
1012*0Sstevel@tonic-gate 	(void) ptree_destroy_node(nodeh);
1013*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1014*0Sstevel@tonic-gate }
1015*0Sstevel@tonic-gate 
1016*0Sstevel@tonic-gate /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
1017*0Sstevel@tonic-gate static void
frudr_completion_handler(char * ename,void * earg,size_t size)1018*0Sstevel@tonic-gate frudr_completion_handler(char *ename, void *earg, size_t size)
1019*0Sstevel@tonic-gate {
1020*0Sstevel@tonic-gate 	picl_nodehdl_t	fruh;
1021*0Sstevel@tonic-gate 
1022*0Sstevel@tonic-gate 	if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
1023*0Sstevel@tonic-gate 		/*
1024*0Sstevel@tonic-gate 		 * now frudata has been notified that the node is to be
1025*0Sstevel@tonic-gate 		 * removed, we can actually remove it
1026*0Sstevel@tonic-gate 		 */
1027*0Sstevel@tonic-gate 		fruh = NULL;
1028*0Sstevel@tonic-gate 		(void) nvlist_lookup_uint64(earg,
1029*0Sstevel@tonic-gate 		    PICLEVENTARG_FRUHANDLE, &fruh);
1030*0Sstevel@tonic-gate 		if (fruh != NULL) {
1031*0Sstevel@tonic-gate 			(void) remove_picl_node(fruh);
1032*0Sstevel@tonic-gate 		}
1033*0Sstevel@tonic-gate 	}
1034*0Sstevel@tonic-gate 	nvlist_free(earg);
1035*0Sstevel@tonic-gate 	free(earg);
1036*0Sstevel@tonic-gate 	free(ename);
1037*0Sstevel@tonic-gate }
1038*0Sstevel@tonic-gate 
1039*0Sstevel@tonic-gate /*
1040*0Sstevel@tonic-gate  * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
1041*0Sstevel@tonic-gate  */
1042*0Sstevel@tonic-gate static void
post_frudr_event(char * ename,picl_nodehdl_t parenth,picl_nodehdl_t fruh)1043*0Sstevel@tonic-gate post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh)
1044*0Sstevel@tonic-gate {
1045*0Sstevel@tonic-gate 	nvlist_t	*nvl;
1046*0Sstevel@tonic-gate 	char		*ev_name;
1047*0Sstevel@tonic-gate 
1048*0Sstevel@tonic-gate 	ev_name = strdup(ename);
1049*0Sstevel@tonic-gate 	if (ev_name == NULL)
1050*0Sstevel@tonic-gate 		return;
1051*0Sstevel@tonic-gate 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) {
1052*0Sstevel@tonic-gate 		free(ev_name);
1053*0Sstevel@tonic-gate 		return;
1054*0Sstevel@tonic-gate 	}
1055*0Sstevel@tonic-gate 	if (parenth != 0L &&
1056*0Sstevel@tonic-gate 	    nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) {
1057*0Sstevel@tonic-gate 		free(ev_name);
1058*0Sstevel@tonic-gate 		nvlist_free(nvl);
1059*0Sstevel@tonic-gate 		return;
1060*0Sstevel@tonic-gate 	}
1061*0Sstevel@tonic-gate 	if (fruh != 0L &&
1062*0Sstevel@tonic-gate 	    nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) {
1063*0Sstevel@tonic-gate 		free(ev_name);
1064*0Sstevel@tonic-gate 		nvlist_free(nvl);
1065*0Sstevel@tonic-gate 		return;
1066*0Sstevel@tonic-gate 	}
1067*0Sstevel@tonic-gate 	if (ptree_post_event(ev_name, nvl, sizeof (nvl),
1068*0Sstevel@tonic-gate 	    frudr_completion_handler) != 0) {
1069*0Sstevel@tonic-gate 		free(ev_name);
1070*0Sstevel@tonic-gate 		nvlist_free(nvl);
1071*0Sstevel@tonic-gate 	}
1072*0Sstevel@tonic-gate }
1073*0Sstevel@tonic-gate 
1074*0Sstevel@tonic-gate /* Hotplug routine used to add a new power supply */
1075*0Sstevel@tonic-gate static int
add_power_supply(int slotnum)1076*0Sstevel@tonic-gate add_power_supply(int slotnum)
1077*0Sstevel@tonic-gate {
1078*0Sstevel@tonic-gate 	picl_nodehdl_t		powersloth;
1079*0Sstevel@tonic-gate 	picl_nodehdl_t		powermodh;
1080*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
1081*0Sstevel@tonic-gate 	int			i, err;
1082*0Sstevel@tonic-gate 
1083*0Sstevel@tonic-gate 	/* Find the node for the given power supply slot */
1084*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1085*0Sstevel@tonic-gate 	    &powersloth) == PICL_SUCCESS) {
1086*0Sstevel@tonic-gate 
1087*0Sstevel@tonic-gate 		i = slotnum + PS0;
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate 		/* Make sure it's in /platform and create the frutree node */
1090*0Sstevel@tonic-gate 		if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
1091*0Sstevel@tonic-gate 		    PICL_SUCCESS) {
1092*0Sstevel@tonic-gate 			err = ptree_create_node("power-supply", "fru",
1093*0Sstevel@tonic-gate 			    &powermodh);
1094*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1095*0Sstevel@tonic-gate 				return (err);
1096*0Sstevel@tonic-gate 
1097*0Sstevel@tonic-gate 			err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE);
1098*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1099*0Sstevel@tonic-gate 				return (err);
1100*0Sstevel@tonic-gate 
1101*0Sstevel@tonic-gate 			err = add_void_fda_prop(powermodh);
1102*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1103*0Sstevel@tonic-gate 				return (err);
1104*0Sstevel@tonic-gate 
1105*0Sstevel@tonic-gate 			err = ptree_add_node(powersloth, powermodh);
1106*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1107*0Sstevel@tonic-gate 				return (err);
1108*0Sstevel@tonic-gate 
1109*0Sstevel@tonic-gate 			err = add_ref_prop(tmph, powermodh, FRU_PARENT);
1110*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1111*0Sstevel@tonic-gate 				return (err);
1112*0Sstevel@tonic-gate 
1113*0Sstevel@tonic-gate 			/* Post picl-fru-added event */
1114*0Sstevel@tonic-gate 			post_frudr_event(PICL_FRU_ADDED, NULL, powermodh);
1115*0Sstevel@tonic-gate 		}
1116*0Sstevel@tonic-gate 	}
1117*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1118*0Sstevel@tonic-gate }
1119*0Sstevel@tonic-gate 
1120*0Sstevel@tonic-gate /* Hotplug routine used to remove an existing power supply */
1121*0Sstevel@tonic-gate static int
remove_power_supply(int slotnum)1122*0Sstevel@tonic-gate remove_power_supply(int slotnum)
1123*0Sstevel@tonic-gate {
1124*0Sstevel@tonic-gate 	picl_nodehdl_t		powersloth;
1125*0Sstevel@tonic-gate 	picl_nodehdl_t		powermodh;
1126*0Sstevel@tonic-gate 	int			err;
1127*0Sstevel@tonic-gate 
1128*0Sstevel@tonic-gate 	/* Find the node for the given power supply slot */
1129*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1130*0Sstevel@tonic-gate 	    &powersloth) == PICL_SUCCESS) {
1131*0Sstevel@tonic-gate 		/* Make sure it's got a child, then delete it */
1132*0Sstevel@tonic-gate 		err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD,
1133*0Sstevel@tonic-gate 		    &powermodh, sizeof (picl_nodehdl_t));
1134*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
1135*0Sstevel@tonic-gate 			return (err);
1136*0Sstevel@tonic-gate 		}
1137*0Sstevel@tonic-gate 
1138*0Sstevel@tonic-gate 		err = ptree_delete_node(powermodh);
1139*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
1140*0Sstevel@tonic-gate 			return (err);
1141*0Sstevel@tonic-gate 		}
1142*0Sstevel@tonic-gate 		(void) ptree_destroy_node(powermodh);
1143*0Sstevel@tonic-gate 		/* Post picl-fru-removed event */
1144*0Sstevel@tonic-gate 		post_frudr_event(PICL_FRU_REMOVED, NULL, powermodh);
1145*0Sstevel@tonic-gate 	}
1146*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1147*0Sstevel@tonic-gate }
1148