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 2005 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-880 (Daktari) 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_motherboard_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 left right 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	IOBRD		0
81*0Sstevel@tonic-gate #define	RSC		1
82*0Sstevel@tonic-gate #define	FCAL0		2
83*0Sstevel@tonic-gate #define	FCAL1		3
84*0Sstevel@tonic-gate #define	FCALGBIC	4
85*0Sstevel@tonic-gate #define	PDB		5
86*0Sstevel@tonic-gate #define	PS0		6
87*0Sstevel@tonic-gate #define	PS1		7
88*0Sstevel@tonic-gate #define	PS2		8
89*0Sstevel@tonic-gate #define	SYSBRD		9
90*0Sstevel@tonic-gate #define	CPUMOD0		10
91*0Sstevel@tonic-gate #define	CPUMOD1		11
92*0Sstevel@tonic-gate #define	CPUMOD2		12
93*0Sstevel@tonic-gate #define	CPUMOD3		13
94*0Sstevel@tonic-gate #define	CPU0_DIMM0	14
95*0Sstevel@tonic-gate #define	DIMMS_PER_MOD	8
96*0Sstevel@tonic-gate #define	DIMMS_PER_SLOT	16
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate /*
100*0Sstevel@tonic-gate  * Local variables
101*0Sstevel@tonic-gate  */
102*0Sstevel@tonic-gate static picld_plugin_reg_t  my_reg_info = {
103*0Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
104*0Sstevel@tonic-gate 	PICLD_PLUGIN_NON_CRITICAL,
105*0Sstevel@tonic-gate 	"SUNW_Sun-Fire-880_frutree",
106*0Sstevel@tonic-gate 	picl_frutree_init,
107*0Sstevel@tonic-gate 	picl_frutree_fini
108*0Sstevel@tonic-gate };
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate /*
111*0Sstevel@tonic-gate  * List of all the FRUs in the /platform tree with SEEPROMs
112*0Sstevel@tonic-gate  */
113*0Sstevel@tonic-gate static char *platform_frupath[] = {
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,30/fru@0,a6", /* RSC */
116*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a8", /* FCAL 0 */
117*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ac", /* FCAL 1 */
118*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,aa", /* FCAL-GBIC */
119*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,ae", /* PDB */
120*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a0", /* PS 0 */
121*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a2", /* PS 1 */
122*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,30/fru@0,a4", /* PS 2 */
123*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a8", /* SYS BRD */
124*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0", /* CPU MOD 0 */
125*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2", /* CPU MOD 1 */
126*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a4", /* CPU MOD 2 */
127*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@4,a6", /* CPU MOD 3 */
128*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0", /* CPU0 DIMM0 */
129*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2", /* CPU0 DIMM1 */
130*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4", /* CPU0 DIMM2 */
131*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6", /* CPU0 DIMM3 */
132*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8", /* CPU0 DIMM4 */
133*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa", /* CPU0 DIMM5 */
134*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac", /* CPU0 DIMM6 */
135*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae", /* CPU0 DIMM7 */
136*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0", /* CPU2 DIMM0 */
137*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2", /* CPU2 DIMM1 */
138*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4", /* CPU2 DIMM2 */
139*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6", /* CPU2 DIMM3 */
140*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8", /* CPU2 DIMM4 */
141*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa", /* CPU2 DIMM5 */
142*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac", /* CPU2 DIMM6 */
143*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae", /* CPU2 DIMM7 */
144*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0", /* CPU1 DIMM0 */
145*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2", /* CPU1 DIMM1 */
146*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4", /* CPU1 DIMM2 */
147*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6", /* CPU1 DIMM3 */
148*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8", /* CPU1 DIMM4 */
149*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa", /* CPU1 DIMM5 */
150*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac", /* CPU1 DIMM6 */
151*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae", /* CPU1 DIMM7 */
152*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0", /* CPU3 DIMM0 */
153*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2", /* CPU3 DIMM1 */
154*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4", /* CPU3 DIMM2 */
155*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6", /* CPU3 DIMM3 */
156*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8", /* CPU3 DIMM4 */
157*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa", /* CPU3 DIMM5 */
158*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac", /* CPU3 DIMM6 */
159*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae", /* CPU3 DIMM7 */
160*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a0", /* CPU4 DIMM0 */
161*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a2", /* CPU4 DIMM1 */
162*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a4", /* CPU4 DIMM2 */
163*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a6", /* CPU4 DIMM3 */
164*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,a8", /* CPU4 DIMM4 */
165*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,aa", /* CPU4 DIMM5 */
166*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ac", /* CPU4 DIMM6 */
167*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@0,ae", /* CPU4 DIMM7 */
168*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a0", /* CPU6 DIMM0 */
169*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a2", /* CPU6 DIMM1 */
170*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a4", /* CPU6 DIMM2 */
171*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a6", /* CPU6 DIMM3 */
172*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,a8", /* CPU6 DIMM4 */
173*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,aa", /* CPU6 DIMM5 */
174*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ac", /* CPU6 DIMM6 */
175*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@2,ae", /* CPU6 DIMM7 */
176*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a0", /* CPU5 DIMM0 */
177*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a2", /* CPU5 DIMM1 */
178*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a4", /* CPU5 DIMM2 */
179*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a6", /* CPU5 DIMM3 */
180*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,a8", /* CPU5 DIMM4 */
181*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,aa", /* CPU5 DIMM5 */
182*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ac", /* CPU5 DIMM6 */
183*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@1,ae", /* CPU5 DIMM7 */
184*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a0", /* CPU7 DIMM0 */
185*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a2", /* CPU7 DIMM1 */
186*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a4", /* CPU7 DIMM2 */
187*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a6", /* CPU7 DIMM3 */
188*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,a8", /* CPU7 DIMM4 */
189*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,aa", /* CPU7 DIMM5 */
190*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ac", /* CPU7 DIMM6 */
191*0Sstevel@tonic-gate 	"/platform/pci@9,700000/ebus@1/i2c@1,50002e/fru@3,ae", /* CPU7 DIMM7 */
192*0Sstevel@tonic-gate 	NULL};
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate /*
195*0Sstevel@tonic-gate  * List of Labels for FRU locations (uses the #define's from above)
196*0Sstevel@tonic-gate  */
197*0Sstevel@tonic-gate static char *location_label[] = {
198*0Sstevel@tonic-gate 	NULL,			/* IOBRD */
199*0Sstevel@tonic-gate 	NULL,			/* RSC */
200*0Sstevel@tonic-gate 	"0",			/* FCAL0 */
201*0Sstevel@tonic-gate 	"1",			/* FCAL1 */
202*0Sstevel@tonic-gate 	NULL,			/* FCALGBIC */
203*0Sstevel@tonic-gate 	NULL,			/* PDB */
204*0Sstevel@tonic-gate 	"0",			/* PS0 */
205*0Sstevel@tonic-gate 	"1",			/* PS1 */
206*0Sstevel@tonic-gate 	"2",			/* PS2 */
207*0Sstevel@tonic-gate 	NULL,			/* SYSBRD */
208*0Sstevel@tonic-gate 	"A",			/* CPUMOD0 */
209*0Sstevel@tonic-gate 	"B",			/* CPUMOD1 */
210*0Sstevel@tonic-gate 	"C",			/* CPUMOD2 */
211*0Sstevel@tonic-gate 	"D",			/* CPUMOD3 */
212*0Sstevel@tonic-gate 	"J2900",		/* CPU0 DIMM0 */
213*0Sstevel@tonic-gate 	"J3100",		/* CPU0 DIMM1 */
214*0Sstevel@tonic-gate 	"J2901",		/* CPU0 DIMM2 */
215*0Sstevel@tonic-gate 	"J3101",		/* CPU0 DIMM3 */
216*0Sstevel@tonic-gate 	"J3000",		/* CPU0 DIMM4 */
217*0Sstevel@tonic-gate 	"J3200",		/* CPU0 DIMM5 */
218*0Sstevel@tonic-gate 	"J3001",		/* CPU0 DIMM6 */
219*0Sstevel@tonic-gate 	"J3201",		/* CPU0 DIMM7 */
220*0Sstevel@tonic-gate 	"J7900",		/* CPU1 DIMM0 */
221*0Sstevel@tonic-gate 	"J8100",		/* CPU1 DIMM1 */
222*0Sstevel@tonic-gate 	"J7901",		/* CPU1 DIMM2 */
223*0Sstevel@tonic-gate 	"J8101",		/* CPU1 DIMM3 */
224*0Sstevel@tonic-gate 	"J8000",		/* CPU1 DIMM4 */
225*0Sstevel@tonic-gate 	"J8200",		/* CPU1 DIMM5 */
226*0Sstevel@tonic-gate 	"J8001",		/* CPU1 DIMM6 */
227*0Sstevel@tonic-gate 	"J8201",		/* CPU1 DIMM7 */
228*0Sstevel@tonic-gate 	"0",			/* CPU0 label */
229*0Sstevel@tonic-gate 	"1",			/* CPU1 label */
230*0Sstevel@tonic-gate 	NULL};
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate /*
233*0Sstevel@tonic-gate  * List of all the FRU slots for power supplies (hotpluggable)
234*0Sstevel@tonic-gate  */
235*0Sstevel@tonic-gate static char *frutree_power_supply[] = {
236*0Sstevel@tonic-gate 	"/frutree/chassis/power-dist-board/power-supply-slot?Slot=0",
237*0Sstevel@tonic-gate 	"/frutree/chassis/power-dist-board/power-supply-slot?Slot=1",
238*0Sstevel@tonic-gate 	"/frutree/chassis/power-dist-board/power-supply-slot?Slot=2",
239*0Sstevel@tonic-gate 	NULL};
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate /*
242*0Sstevel@tonic-gate  * List of all the FRU slots for CPU Memory modules (hotpluggable)
243*0Sstevel@tonic-gate  */
244*0Sstevel@tonic-gate static char *frutree_cpu_module[] = {
245*0Sstevel@tonic-gate 	"/frutree/chassis/system-board/cpu-mem-slot?Slot=0",
246*0Sstevel@tonic-gate 	"/frutree/chassis/system-board/cpu-mem-slot?Slot=1",
247*0Sstevel@tonic-gate 	"/frutree/chassis/system-board/cpu-mem-slot?Slot=2",
248*0Sstevel@tonic-gate 	"/frutree/chassis/system-board/cpu-mem-slot?Slot=3",
249*0Sstevel@tonic-gate 	NULL};
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate /* PICL handle for the root node of the "frutree" */
252*0Sstevel@tonic-gate static picl_nodehdl_t	frutreeh;
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate static int	do_ioboard_init(picl_nodehdl_t);
255*0Sstevel@tonic-gate static int	do_rscboard_init(picl_nodehdl_t);
256*0Sstevel@tonic-gate static int	do_fcal_init(picl_nodehdl_t);
257*0Sstevel@tonic-gate static int	do_power_supplies_init(picl_nodehdl_t);
258*0Sstevel@tonic-gate static int	do_motherboard_init(picl_nodehdl_t);
259*0Sstevel@tonic-gate static int	do_cpu_module_init(picl_nodehdl_t, int);
260*0Sstevel@tonic-gate static int	do_dimms_init(picl_nodehdl_t, int, int);
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate static int	add_ref_prop(picl_nodehdl_t, picl_nodehdl_t, char *);
263*0Sstevel@tonic-gate static int	add_slot_prop(picl_nodehdl_t, int);
264*0Sstevel@tonic-gate static int	add_label_prop(picl_nodehdl_t, char *);
265*0Sstevel@tonic-gate static int	add_void_fda_prop(picl_nodehdl_t);
266*0Sstevel@tonic-gate static int	add_viewpoints_prop(picl_nodehdl_t, char *);
267*0Sstevel@tonic-gate static int	add_all_nodes();
268*0Sstevel@tonic-gate static int	remove_all_nodes(picl_nodehdl_t);
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate static int	add_hotplug_fru_device(void);
271*0Sstevel@tonic-gate static int	rem_hotplug_fru_device(void);
272*0Sstevel@tonic-gate static int	is_added_device(char *, char *);
273*0Sstevel@tonic-gate static int	is_removed_device(char *, char *);
274*0Sstevel@tonic-gate static int	add_power_supply(int);
275*0Sstevel@tonic-gate static int	remove_power_supply(int);
276*0Sstevel@tonic-gate static int	add_cpu_module(int);
277*0Sstevel@tonic-gate static int	remove_cpu_module(int);
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate /*
280*0Sstevel@tonic-gate  * This function is executed as part of .init when the plugin is
281*0Sstevel@tonic-gate  * dlopen()ed
282*0Sstevel@tonic-gate  */
283*0Sstevel@tonic-gate static void
picl_frutree_register()284*0Sstevel@tonic-gate picl_frutree_register()
285*0Sstevel@tonic-gate {
286*0Sstevel@tonic-gate 	(void) picld_plugin_register(&my_reg_info);
287*0Sstevel@tonic-gate }
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate /*
290*0Sstevel@tonic-gate  * This function is the init entry point of the plugin.
291*0Sstevel@tonic-gate  * It initializes the /frutree tree
292*0Sstevel@tonic-gate  */
293*0Sstevel@tonic-gate static void
picl_frutree_init()294*0Sstevel@tonic-gate picl_frutree_init()
295*0Sstevel@tonic-gate {
296*0Sstevel@tonic-gate 	int		err;
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	err = add_all_nodes();
299*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
300*0Sstevel@tonic-gate 		(void) remove_all_nodes(frutreeh);
301*0Sstevel@tonic-gate 		return;
302*0Sstevel@tonic-gate 	}
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 	/* Register the event handler routine */
305*0Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
306*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
307*0Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
308*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
309*0Sstevel@tonic-gate }
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate /*
312*0Sstevel@tonic-gate  * This function is the fini entry point of the plugin
313*0Sstevel@tonic-gate  */
314*0Sstevel@tonic-gate static void
picl_frutree_fini(void)315*0Sstevel@tonic-gate picl_frutree_fini(void)
316*0Sstevel@tonic-gate {
317*0Sstevel@tonic-gate 	/* Unregister the event handler routine */
318*0Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
319*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
320*0Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
321*0Sstevel@tonic-gate 	    picl_frutree_evhandler, NULL);
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 	(void) remove_all_nodes(frutreeh);
324*0Sstevel@tonic-gate }
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate /*
327*0Sstevel@tonic-gate  * This function is the event handler of this plug-in.
328*0Sstevel@tonic-gate  *
329*0Sstevel@tonic-gate  * It processes the following events:
330*0Sstevel@tonic-gate  *
331*0Sstevel@tonic-gate  * 	PICLEVENT_SYSEVENT_DEVICE_ADDED
332*0Sstevel@tonic-gate  * 	PICLEVENT_SYSEVENT_DEVICE_REMOVED
333*0Sstevel@tonic-gate  */
334*0Sstevel@tonic-gate /* ARGSUSED */
335*0Sstevel@tonic-gate static void
picl_frutree_evhandler(const char * ename,const void * earg,size_t size,void * cookie)336*0Sstevel@tonic-gate picl_frutree_evhandler(const char *ename, const void *earg, size_t size,
337*0Sstevel@tonic-gate     void *cookie)
338*0Sstevel@tonic-gate {
339*0Sstevel@tonic-gate 	if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
340*0Sstevel@tonic-gate 		/* Check for and add any hotplugged device(s) */
341*0Sstevel@tonic-gate 		(void) add_hotplug_fru_device();
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	} else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
344*0Sstevel@tonic-gate 		/* Check for and remove any hotplugged device(s) */
345*0Sstevel@tonic-gate 		(void) rem_hotplug_fru_device();
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate }
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate /* Initializes the FRU nodes for the IO board */
350*0Sstevel@tonic-gate static int
do_ioboard_init(picl_nodehdl_t rooth)351*0Sstevel@tonic-gate do_ioboard_init(picl_nodehdl_t rooth)
352*0Sstevel@tonic-gate {
353*0Sstevel@tonic-gate 	picl_nodehdl_t		iobrdh;
354*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
355*0Sstevel@tonic-gate 	int			err;
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate 	/* Create the node for the IO board (if it exists) */
358*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[IOBRD], &tmph) ==
359*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
360*0Sstevel@tonic-gate 		err = ptree_create_node("io-board", "fru", &iobrdh);
361*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
362*0Sstevel@tonic-gate 			return (err);
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 		err = add_ref_prop(iobrdh, tmph, SEEPROM_SOURCE);
365*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
366*0Sstevel@tonic-gate 			return (err);
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 		err = add_void_fda_prop(iobrdh);
369*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
370*0Sstevel@tonic-gate 			return (err);
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, iobrdh);
373*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
374*0Sstevel@tonic-gate 			return (err);
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, iobrdh, FRU_PARENT);
377*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
378*0Sstevel@tonic-gate 			return (err);
379*0Sstevel@tonic-gate 	}
380*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
381*0Sstevel@tonic-gate }
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate /* Initializes the FRU node for the RSC card */
384*0Sstevel@tonic-gate static int
do_rscboard_init(picl_nodehdl_t rooth)385*0Sstevel@tonic-gate do_rscboard_init(picl_nodehdl_t rooth)
386*0Sstevel@tonic-gate {
387*0Sstevel@tonic-gate 	picl_nodehdl_t		rscbrdh;
388*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
389*0Sstevel@tonic-gate 	int			err;
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	/* Create the node for the RSC board (if it exists) */
392*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[RSC], &tmph) ==
393*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
394*0Sstevel@tonic-gate 		err = ptree_create_node("rsc-board", "fru", &rscbrdh);
395*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
396*0Sstevel@tonic-gate 			return (err);
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 		err = add_ref_prop(rscbrdh, tmph, SEEPROM_SOURCE);
399*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
400*0Sstevel@tonic-gate 			return (err);
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 		err = add_void_fda_prop(rscbrdh);
403*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
404*0Sstevel@tonic-gate 			return (err);
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, rscbrdh);
407*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
408*0Sstevel@tonic-gate 			return (err);
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, rscbrdh, FRU_PARENT);
411*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
412*0Sstevel@tonic-gate 			return (err);
413*0Sstevel@tonic-gate 	}
414*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
415*0Sstevel@tonic-gate }
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate /* Initializes the FRU nodes for the FCAL backplanes and GBIC card */
418*0Sstevel@tonic-gate static int
do_fcal_init(picl_nodehdl_t rooth)419*0Sstevel@tonic-gate do_fcal_init(picl_nodehdl_t rooth)
420*0Sstevel@tonic-gate {
421*0Sstevel@tonic-gate 	picl_nodehdl_t		fcalsloth;
422*0Sstevel@tonic-gate 	picl_nodehdl_t		fcalmodh;
423*0Sstevel@tonic-gate 	picl_nodehdl_t		fcalgbich;
424*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
425*0Sstevel@tonic-gate 	int			i, err, slotnum;
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 	for (i = FCAL0; i <= FCAL1; i++) {
428*0Sstevel@tonic-gate 		/* Create the node for the FCAL backplane slot */
429*0Sstevel@tonic-gate 		err = ptree_create_node("fcal-backplane-slot",
430*0Sstevel@tonic-gate 		    "location", &fcalsloth);
431*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
432*0Sstevel@tonic-gate 			return (err);
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate 		slotnum = i - FCAL0;
435*0Sstevel@tonic-gate 		err = add_slot_prop(fcalsloth, slotnum);
436*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
437*0Sstevel@tonic-gate 			return (err);
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 		err = add_label_prop(fcalsloth, location_label[i]);
440*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
441*0Sstevel@tonic-gate 			return (err);
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, fcalsloth);
444*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
445*0Sstevel@tonic-gate 			return (err);
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 		/* If the FCAL backplane exists, create a node for it */
448*0Sstevel@tonic-gate 		if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
449*0Sstevel@tonic-gate 		    PICL_SUCCESS) {
450*0Sstevel@tonic-gate 			err = ptree_create_node("fcal-backplane", "fru",
451*0Sstevel@tonic-gate 			    &fcalmodh);
452*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
453*0Sstevel@tonic-gate 				return (err);
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate 			err = add_ref_prop(fcalmodh, tmph, SEEPROM_SOURCE);
456*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
457*0Sstevel@tonic-gate 				return (err);
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 			err = add_void_fda_prop(fcalmodh);
460*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
461*0Sstevel@tonic-gate 				return (err);
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate 			err = ptree_add_node(fcalsloth, fcalmodh);
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(tmph, fcalmodh, FRU_PARENT);
468*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
469*0Sstevel@tonic-gate 				return (err);
470*0Sstevel@tonic-gate 		}
471*0Sstevel@tonic-gate 	}
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate 	/* If the FCAL GBIC board exists, create a node for it */
474*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[FCALGBIC], &tmph) ==
475*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
476*0Sstevel@tonic-gate 		err = ptree_create_node("fcal-gbic-board", "fru",
477*0Sstevel@tonic-gate 		    &fcalgbich);
478*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
479*0Sstevel@tonic-gate 			return (err);
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate 		err = add_ref_prop(fcalgbich, tmph, SEEPROM_SOURCE);
482*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
483*0Sstevel@tonic-gate 			return (err);
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 		err = add_void_fda_prop(fcalgbich);
486*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
487*0Sstevel@tonic-gate 			return (err);
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, fcalgbich);
490*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
491*0Sstevel@tonic-gate 			return (err);
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, fcalgbich, FRU_PARENT);
494*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
495*0Sstevel@tonic-gate 			return (err);
496*0Sstevel@tonic-gate 	}
497*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
498*0Sstevel@tonic-gate }
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate /* Initializes the FRU nodes for the PDB and the power supplies */
501*0Sstevel@tonic-gate static int
do_power_supplies_init(picl_nodehdl_t rooth)502*0Sstevel@tonic-gate do_power_supplies_init(picl_nodehdl_t rooth)
503*0Sstevel@tonic-gate {
504*0Sstevel@tonic-gate 	picl_nodehdl_t		powerbrdh;
505*0Sstevel@tonic-gate 	picl_nodehdl_t		powersloth;
506*0Sstevel@tonic-gate 	picl_nodehdl_t		powermodh;
507*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
508*0Sstevel@tonic-gate 	int			i, err, slotnum;
509*0Sstevel@tonic-gate 
510*0Sstevel@tonic-gate 	/* Create the node for the PDB (if it exists) */
511*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[PDB], &tmph) ==
512*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
513*0Sstevel@tonic-gate 		err = ptree_create_node("power-dist-board", "fru", &powerbrdh);
514*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
515*0Sstevel@tonic-gate 			return (err);
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate 		err = add_ref_prop(powerbrdh, tmph, SEEPROM_SOURCE);
518*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
519*0Sstevel@tonic-gate 			return (err);
520*0Sstevel@tonic-gate 
521*0Sstevel@tonic-gate 		err = add_void_fda_prop(powerbrdh);
522*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
523*0Sstevel@tonic-gate 			return (err);
524*0Sstevel@tonic-gate 
525*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, powerbrdh);
526*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
527*0Sstevel@tonic-gate 			return (err);
528*0Sstevel@tonic-gate 
529*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, powerbrdh, FRU_PARENT);
530*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
531*0Sstevel@tonic-gate 			return (err);
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate 		for (i = PS0; i <= PS2; i++) {
534*0Sstevel@tonic-gate 			/* Create the node for the power supply slot */
535*0Sstevel@tonic-gate 			err = ptree_create_node("power-supply-slot",
536*0Sstevel@tonic-gate 			    "location", &powersloth);
537*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
538*0Sstevel@tonic-gate 				return (err);
539*0Sstevel@tonic-gate 
540*0Sstevel@tonic-gate 			slotnum = i - PS0;
541*0Sstevel@tonic-gate 			err = add_slot_prop(powersloth, slotnum);
542*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
543*0Sstevel@tonic-gate 				return (err);
544*0Sstevel@tonic-gate 
545*0Sstevel@tonic-gate 			err = add_label_prop(powersloth, location_label[i]);
546*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
547*0Sstevel@tonic-gate 				return (err);
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate 			err = ptree_add_node(powerbrdh, powersloth);
550*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
551*0Sstevel@tonic-gate 				return (err);
552*0Sstevel@tonic-gate 
553*0Sstevel@tonic-gate 			/* If the PS exists, create a node for it */
554*0Sstevel@tonic-gate 			if (ptree_get_node_by_path(platform_frupath[i],
555*0Sstevel@tonic-gate 			    &tmph) == PICL_SUCCESS) {
556*0Sstevel@tonic-gate 				err = ptree_create_node("power-supply",
557*0Sstevel@tonic-gate 				    "fru", &powermodh);
558*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
559*0Sstevel@tonic-gate 					return (err);
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 				err = add_ref_prop(powermodh, tmph,
562*0Sstevel@tonic-gate 				    SEEPROM_SOURCE);
563*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
564*0Sstevel@tonic-gate 					return (err);
565*0Sstevel@tonic-gate 
566*0Sstevel@tonic-gate 				err = add_void_fda_prop(powermodh);
567*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
568*0Sstevel@tonic-gate 					return (err);
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 				err = ptree_add_node(powersloth, powermodh);
571*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
572*0Sstevel@tonic-gate 					return (err);
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate 				err = add_ref_prop(tmph, powermodh, FRU_PARENT);
575*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
576*0Sstevel@tonic-gate 					return (err);
577*0Sstevel@tonic-gate 			}
578*0Sstevel@tonic-gate 		}
579*0Sstevel@tonic-gate 	}
580*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
581*0Sstevel@tonic-gate }
582*0Sstevel@tonic-gate 
583*0Sstevel@tonic-gate /* Initializes the FRU nodes for the motherboard and CPU Memory modules */
584*0Sstevel@tonic-gate static int
do_motherboard_init(picl_nodehdl_t rooth)585*0Sstevel@tonic-gate do_motherboard_init(picl_nodehdl_t rooth)
586*0Sstevel@tonic-gate {
587*0Sstevel@tonic-gate 	picl_nodehdl_t		sysboardh;
588*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemsloth;
589*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemmodh;
590*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
591*0Sstevel@tonic-gate 	int			i, err, slotnum;
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate 	/* Create the node for the system board (if it exists) */
594*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(platform_frupath[SYSBRD], &tmph) ==
595*0Sstevel@tonic-gate 	    PICL_SUCCESS) {
596*0Sstevel@tonic-gate 		err = ptree_create_node("system-board", "fru",
597*0Sstevel@tonic-gate 		    &sysboardh);
598*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
599*0Sstevel@tonic-gate 			return (err);
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate 		err = add_ref_prop(sysboardh, tmph, SEEPROM_SOURCE);
602*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
603*0Sstevel@tonic-gate 			return (err);
604*0Sstevel@tonic-gate 
605*0Sstevel@tonic-gate 		err = add_void_fda_prop(sysboardh);
606*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
607*0Sstevel@tonic-gate 			return (err);
608*0Sstevel@tonic-gate 
609*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, sysboardh);
610*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
611*0Sstevel@tonic-gate 			return (err);
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 		err = add_ref_prop(tmph, sysboardh, FRU_PARENT);
614*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
615*0Sstevel@tonic-gate 			return (err);
616*0Sstevel@tonic-gate 
617*0Sstevel@tonic-gate 		for (i = CPUMOD0; i <= CPUMOD3; i++) {
618*0Sstevel@tonic-gate 			/* Create the node for the CPU Memory slot */
619*0Sstevel@tonic-gate 			err = ptree_create_node("cpu-mem-slot", "location",
620*0Sstevel@tonic-gate 			    &cpumemsloth);
621*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
622*0Sstevel@tonic-gate 				return (err);
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate 			slotnum = i - CPUMOD0;
625*0Sstevel@tonic-gate 			err = add_slot_prop(cpumemsloth, slotnum);
626*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
627*0Sstevel@tonic-gate 				return (err);
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 			err = add_label_prop(cpumemsloth, location_label[i]);
630*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
631*0Sstevel@tonic-gate 				return (err);
632*0Sstevel@tonic-gate 
633*0Sstevel@tonic-gate 			err = ptree_add_node(sysboardh, cpumemsloth);
634*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
635*0Sstevel@tonic-gate 				return (err);
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 			/* If CPU Mem module exists, create a node for it */
638*0Sstevel@tonic-gate 			if (ptree_get_node_by_path(platform_frupath[i],
639*0Sstevel@tonic-gate 			    &tmph) == PICL_SUCCESS) {
640*0Sstevel@tonic-gate 				err = ptree_create_node("cpu-mem-module",
641*0Sstevel@tonic-gate 				    "fru", &cpumemmodh);
642*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
643*0Sstevel@tonic-gate 					return (err);
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate 				err = add_ref_prop(cpumemmodh, tmph,
646*0Sstevel@tonic-gate 				    SEEPROM_SOURCE);
647*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
648*0Sstevel@tonic-gate 					return (err);
649*0Sstevel@tonic-gate 
650*0Sstevel@tonic-gate 				err = add_void_fda_prop(cpumemmodh);
651*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
652*0Sstevel@tonic-gate 					return (err);
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate 				err = ptree_add_node(cpumemsloth, cpumemmodh);
655*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
656*0Sstevel@tonic-gate 					return (err);
657*0Sstevel@tonic-gate 
658*0Sstevel@tonic-gate 				err = add_ref_prop(tmph, cpumemmodh,
659*0Sstevel@tonic-gate 				    FRU_PARENT);
660*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
661*0Sstevel@tonic-gate 					return (err);
662*0Sstevel@tonic-gate 
663*0Sstevel@tonic-gate 				err = do_cpu_module_init(cpumemmodh, slotnum);
664*0Sstevel@tonic-gate 				if (err != PICL_SUCCESS)
665*0Sstevel@tonic-gate 					return (err);
666*0Sstevel@tonic-gate 			}
667*0Sstevel@tonic-gate 		}
668*0Sstevel@tonic-gate 	}
669*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
670*0Sstevel@tonic-gate }
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate /* Creates the FRU nodes for the CPU Module and associated DIMMs */
673*0Sstevel@tonic-gate static int
do_cpu_module_init(picl_nodehdl_t rooth,int slot)674*0Sstevel@tonic-gate do_cpu_module_init(picl_nodehdl_t rooth, int slot)
675*0Sstevel@tonic-gate {
676*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumodh;
677*0Sstevel@tonic-gate 	int			i, c, err;
678*0Sstevel@tonic-gate 
679*0Sstevel@tonic-gate 	for (i = 0; i <= 1; i++) {
680*0Sstevel@tonic-gate 		err = ptree_create_node("cpu-module", "location",
681*0Sstevel@tonic-gate 		    &cpumodh);
682*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
683*0Sstevel@tonic-gate 			return (err);
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate 		err = add_slot_prop(cpumodh, i);
686*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
687*0Sstevel@tonic-gate 			return (err);
688*0Sstevel@tonic-gate 
689*0Sstevel@tonic-gate 		c = CPU0_DIMM0 + DIMMS_PER_SLOT + i;
690*0Sstevel@tonic-gate 
691*0Sstevel@tonic-gate 		err = add_label_prop(cpumodh, location_label[c]);
692*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
693*0Sstevel@tonic-gate 			return (err);
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, cpumodh);
696*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
697*0Sstevel@tonic-gate 			return (err);
698*0Sstevel@tonic-gate 
699*0Sstevel@tonic-gate 		/* Create the nodes for the memory (if they exist) */
700*0Sstevel@tonic-gate 		err = do_dimms_init(cpumodh, slot, i);
701*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
702*0Sstevel@tonic-gate 			return (err);
703*0Sstevel@tonic-gate 	}
704*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
705*0Sstevel@tonic-gate }
706*0Sstevel@tonic-gate 
707*0Sstevel@tonic-gate /* Creates the FRU nodes for the DIMMs on a particular CPU Module */
708*0Sstevel@tonic-gate static int
do_dimms_init(picl_nodehdl_t rooth,int slot,int module)709*0Sstevel@tonic-gate do_dimms_init(picl_nodehdl_t rooth, int slot, int module)
710*0Sstevel@tonic-gate {
711*0Sstevel@tonic-gate 	picl_nodehdl_t		dimmsloth;
712*0Sstevel@tonic-gate 	picl_nodehdl_t		dimmmodh;
713*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
714*0Sstevel@tonic-gate 	int			i, c, l, err;
715*0Sstevel@tonic-gate 
716*0Sstevel@tonic-gate 	for (i = 0; i < DIMMS_PER_MOD; i++) {
717*0Sstevel@tonic-gate 		/* Create the node for the memory slot */
718*0Sstevel@tonic-gate 		err = ptree_create_node("dimm-slot", "location",
719*0Sstevel@tonic-gate 		    &dimmsloth);
720*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
721*0Sstevel@tonic-gate 			return (err);
722*0Sstevel@tonic-gate 
723*0Sstevel@tonic-gate 		err = add_slot_prop(dimmsloth, i);
724*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
725*0Sstevel@tonic-gate 			return (err);
726*0Sstevel@tonic-gate 
727*0Sstevel@tonic-gate 		c = ((slot * DIMMS_PER_SLOT) +
728*0Sstevel@tonic-gate 		    (module * DIMMS_PER_MOD) + i) + CPU0_DIMM0;
729*0Sstevel@tonic-gate 
730*0Sstevel@tonic-gate 		l = c - (DIMMS_PER_SLOT * slot);
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate 		err = add_label_prop(dimmsloth, location_label[l]);
733*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
734*0Sstevel@tonic-gate 			return (err);
735*0Sstevel@tonic-gate 
736*0Sstevel@tonic-gate 		err = ptree_add_node(rooth, dimmsloth);
737*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
738*0Sstevel@tonic-gate 			return (err);
739*0Sstevel@tonic-gate 
740*0Sstevel@tonic-gate 		/* If the memory module exists, create a node for it */
741*0Sstevel@tonic-gate 		if (ptree_get_node_by_path(platform_frupath[c], &tmph) ==
742*0Sstevel@tonic-gate 		    PICL_SUCCESS) {
743*0Sstevel@tonic-gate 			err = ptree_create_node("dimm-module", "fru",
744*0Sstevel@tonic-gate 			    &dimmmodh);
745*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
746*0Sstevel@tonic-gate 				return (err);
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate 			err = add_ref_prop(dimmmodh, tmph, SEEPROM_SOURCE);
749*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
750*0Sstevel@tonic-gate 				return (err);
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 			err = add_void_fda_prop(dimmmodh);
753*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
754*0Sstevel@tonic-gate 				return (err);
755*0Sstevel@tonic-gate 
756*0Sstevel@tonic-gate 			err = ptree_add_node(dimmsloth, dimmmodh);
757*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
758*0Sstevel@tonic-gate 				return (err);
759*0Sstevel@tonic-gate 
760*0Sstevel@tonic-gate 			err = add_ref_prop(tmph, dimmmodh, FRU_PARENT);
761*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
762*0Sstevel@tonic-gate 				return (err);
763*0Sstevel@tonic-gate 		}
764*0Sstevel@tonic-gate 	}
765*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
766*0Sstevel@tonic-gate }
767*0Sstevel@tonic-gate 
768*0Sstevel@tonic-gate /* Creates a "reference" property between two PICL nodes */
769*0Sstevel@tonic-gate static int
add_ref_prop(picl_nodehdl_t nodeh,picl_nodehdl_t tmph,char * str)770*0Sstevel@tonic-gate add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str)
771*0Sstevel@tonic-gate {
772*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
773*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
774*0Sstevel@tonic-gate 	int			err;
775*0Sstevel@tonic-gate 
776*0Sstevel@tonic-gate 	if (str == NULL)
777*0Sstevel@tonic-gate 		return (PICL_FAILURE);
778*0Sstevel@tonic-gate 
779*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
780*0Sstevel@tonic-gate 	    PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
781*0Sstevel@tonic-gate 	    str, NULL, NULL);
782*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
783*0Sstevel@tonic-gate 		return (err);
784*0Sstevel@tonic-gate 
785*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph);
786*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
787*0Sstevel@tonic-gate 		return (err);
788*0Sstevel@tonic-gate 
789*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
790*0Sstevel@tonic-gate }
791*0Sstevel@tonic-gate 
792*0Sstevel@tonic-gate /* Creates a "slot" property for a given PICL node */
793*0Sstevel@tonic-gate static int
add_slot_prop(picl_nodehdl_t nodeh,int slotnum)794*0Sstevel@tonic-gate add_slot_prop(picl_nodehdl_t nodeh, int slotnum)
795*0Sstevel@tonic-gate {
796*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
797*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
798*0Sstevel@tonic-gate 	int			err;
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
801*0Sstevel@tonic-gate 	    PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL);
802*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
803*0Sstevel@tonic-gate 		return (err);
804*0Sstevel@tonic-gate 
805*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph);
806*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
807*0Sstevel@tonic-gate 		return (err);
808*0Sstevel@tonic-gate 
809*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
810*0Sstevel@tonic-gate }
811*0Sstevel@tonic-gate 
812*0Sstevel@tonic-gate /* Creates a "Label" property for a given PICL node */
813*0Sstevel@tonic-gate static int
add_label_prop(picl_nodehdl_t nodeh,char * label)814*0Sstevel@tonic-gate add_label_prop(picl_nodehdl_t nodeh, char *label)
815*0Sstevel@tonic-gate {
816*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
817*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
818*0Sstevel@tonic-gate 	int			err;
819*0Sstevel@tonic-gate 
820*0Sstevel@tonic-gate 	if (label == NULL)
821*0Sstevel@tonic-gate 		return (PICL_FAILURE);
822*0Sstevel@tonic-gate 
823*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
824*0Sstevel@tonic-gate 	    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label",
825*0Sstevel@tonic-gate 	    NULL, NULL);
826*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
827*0Sstevel@tonic-gate 		return (err);
828*0Sstevel@tonic-gate 
829*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph);
830*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
831*0Sstevel@tonic-gate 		return (err);
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
834*0Sstevel@tonic-gate }
835*0Sstevel@tonic-gate 
836*0Sstevel@tonic-gate /* Creates a "FRUDataAvailable" void property for the given PICL node */
837*0Sstevel@tonic-gate static int
add_void_fda_prop(picl_nodehdl_t nodeh)838*0Sstevel@tonic-gate add_void_fda_prop(picl_nodehdl_t nodeh)
839*0Sstevel@tonic-gate {
840*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
841*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
842*0Sstevel@tonic-gate 	int			err;
843*0Sstevel@tonic-gate 
844*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
845*0Sstevel@tonic-gate 	    PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL);
846*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
847*0Sstevel@tonic-gate 		return (err);
848*0Sstevel@tonic-gate 
849*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
850*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
851*0Sstevel@tonic-gate 		return (err);
852*0Sstevel@tonic-gate 
853*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
854*0Sstevel@tonic-gate }
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate /* Creates a "ViewPoints" property -- used for chassis */
857*0Sstevel@tonic-gate static int
add_viewpoints_prop(picl_nodehdl_t nodeh,char * string)858*0Sstevel@tonic-gate add_viewpoints_prop(picl_nodehdl_t nodeh, char *string)
859*0Sstevel@tonic-gate {
860*0Sstevel@tonic-gate 	picl_prophdl_t		proph;
861*0Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
862*0Sstevel@tonic-gate 	int			err;
863*0Sstevel@tonic-gate 
864*0Sstevel@tonic-gate 	if (string == NULL)
865*0Sstevel@tonic-gate 		return (PICL_FAILURE);
866*0Sstevel@tonic-gate 
867*0Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
868*0Sstevel@tonic-gate 	    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints",
869*0Sstevel@tonic-gate 	    NULL, NULL);
870*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
871*0Sstevel@tonic-gate 		return (err);
872*0Sstevel@tonic-gate 
873*0Sstevel@tonic-gate 	err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph);
874*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
875*0Sstevel@tonic-gate 		return (err);
876*0Sstevel@tonic-gate 
877*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
878*0Sstevel@tonic-gate }
879*0Sstevel@tonic-gate 
880*0Sstevel@tonic-gate /* Creates and adds all of the frutree nodes */
881*0Sstevel@tonic-gate static int
add_all_nodes()882*0Sstevel@tonic-gate add_all_nodes()
883*0Sstevel@tonic-gate {
884*0Sstevel@tonic-gate 	picl_nodehdl_t	rooth;
885*0Sstevel@tonic-gate 	picl_nodehdl_t	chassish;
886*0Sstevel@tonic-gate 	int		err;
887*0Sstevel@tonic-gate 
888*0Sstevel@tonic-gate 	/* Get the root node of the PICL tree */
889*0Sstevel@tonic-gate 	err = ptree_get_root(&rooth);
890*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
891*0Sstevel@tonic-gate 		return (err);
892*0Sstevel@tonic-gate 	}
893*0Sstevel@tonic-gate 
894*0Sstevel@tonic-gate 	/* Create and add the root node of the FRU subtree */
895*0Sstevel@tonic-gate 	err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh);
896*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
897*0Sstevel@tonic-gate 		syslog(LOG_ERR, CREATE_FRUTREE_FAIL);
898*0Sstevel@tonic-gate 		return (err);
899*0Sstevel@tonic-gate 	}
900*0Sstevel@tonic-gate 
901*0Sstevel@tonic-gate 	/* Create and add the chassis node */
902*0Sstevel@tonic-gate 	err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish);
903*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
904*0Sstevel@tonic-gate 		syslog(LOG_ERR, CREATE_CHASSIS_FAIL);
905*0Sstevel@tonic-gate 		return (err);
906*0Sstevel@tonic-gate 	}
907*0Sstevel@tonic-gate 
908*0Sstevel@tonic-gate 	/* Add ViewPoints prop to chassis node */
909*0Sstevel@tonic-gate 	err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS);
910*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
911*0Sstevel@tonic-gate 		return (err);
912*0Sstevel@tonic-gate 
913*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the IO board */
914*0Sstevel@tonic-gate 	err = do_ioboard_init(chassish);
915*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
916*0Sstevel@tonic-gate 		syslog(LOG_ERR, IOBRD_INIT_FAIL);
917*0Sstevel@tonic-gate 		return (err);
918*0Sstevel@tonic-gate 	}
919*0Sstevel@tonic-gate 
920*0Sstevel@tonic-gate 	/* Initialize the FRU node for the RSC card */
921*0Sstevel@tonic-gate 	err = do_rscboard_init(chassish);
922*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
923*0Sstevel@tonic-gate 		syslog(LOG_ERR, RSCBRD_INIT_FAIL);
924*0Sstevel@tonic-gate 		return (err);
925*0Sstevel@tonic-gate 	}
926*0Sstevel@tonic-gate 
927*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the FCAL backplanes and GBIC board */
928*0Sstevel@tonic-gate 	err = do_fcal_init(chassish);
929*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
930*0Sstevel@tonic-gate 		syslog(LOG_ERR, FCAL_INIT_FAIL);
931*0Sstevel@tonic-gate 		return (err);
932*0Sstevel@tonic-gate 	}
933*0Sstevel@tonic-gate 
934*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the PDB and the power supplies */
935*0Sstevel@tonic-gate 	err = do_power_supplies_init(chassish);
936*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
937*0Sstevel@tonic-gate 		syslog(LOG_ERR, PS_INIT_FAIL);
938*0Sstevel@tonic-gate 		return (err);
939*0Sstevel@tonic-gate 	}
940*0Sstevel@tonic-gate 
941*0Sstevel@tonic-gate 	/* Initialize the FRU nodes for the CPU Memory modules */
942*0Sstevel@tonic-gate 	err = do_motherboard_init(chassish);
943*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
944*0Sstevel@tonic-gate 		syslog(LOG_ERR, SYSBOARD_INIT_FAIL);
945*0Sstevel@tonic-gate 		return (err);
946*0Sstevel@tonic-gate 	}
947*0Sstevel@tonic-gate 
948*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
949*0Sstevel@tonic-gate }
950*0Sstevel@tonic-gate 
951*0Sstevel@tonic-gate /* Deletes and destroys all PICL nodes for which rooth is a ancestor */
952*0Sstevel@tonic-gate static int
remove_all_nodes(picl_nodehdl_t rooth)953*0Sstevel@tonic-gate remove_all_nodes(picl_nodehdl_t rooth)
954*0Sstevel@tonic-gate {
955*0Sstevel@tonic-gate 	picl_nodehdl_t		chdh;
956*0Sstevel@tonic-gate 	int			err, done = 0;
957*0Sstevel@tonic-gate 
958*0Sstevel@tonic-gate 	while (!done) {
959*0Sstevel@tonic-gate 		err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
960*0Sstevel@tonic-gate 		    sizeof (picl_nodehdl_t));
961*0Sstevel@tonic-gate 		if (err != PICL_PROPNOTFOUND) {
962*0Sstevel@tonic-gate 			(void) remove_all_nodes(chdh);
963*0Sstevel@tonic-gate 		} else {
964*0Sstevel@tonic-gate 			err = ptree_delete_node(rooth);
965*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
966*0Sstevel@tonic-gate 				return (err);
967*0Sstevel@tonic-gate 			} else {
968*0Sstevel@tonic-gate 				(void) ptree_destroy_node(rooth);
969*0Sstevel@tonic-gate 			}
970*0Sstevel@tonic-gate 			done = 1;
971*0Sstevel@tonic-gate 		}
972*0Sstevel@tonic-gate 	}
973*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
974*0Sstevel@tonic-gate }
975*0Sstevel@tonic-gate 
976*0Sstevel@tonic-gate /* Searches the list of hotpluggable FRUs, adds the appropriate node(s) */
977*0Sstevel@tonic-gate static int
add_hotplug_fru_device()978*0Sstevel@tonic-gate add_hotplug_fru_device()
979*0Sstevel@tonic-gate {
980*0Sstevel@tonic-gate 	int		i, err, slotnum;
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 	/* Check for hotplugged power supplies */
983*0Sstevel@tonic-gate 	for (i = PS0; i <= PS2; i++) {
984*0Sstevel@tonic-gate 		/* Compare the /platform tree to the frutree */
985*0Sstevel@tonic-gate 		slotnum = i - PS0;
986*0Sstevel@tonic-gate 		err = is_added_device(platform_frupath[i],
987*0Sstevel@tonic-gate 		    frutree_power_supply[slotnum]);
988*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
989*0Sstevel@tonic-gate 			continue;
990*0Sstevel@tonic-gate 
991*0Sstevel@tonic-gate 		/* If they are different, then add a power supply */
992*0Sstevel@tonic-gate 		err = add_power_supply(slotnum);
993*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
994*0Sstevel@tonic-gate 			continue;
995*0Sstevel@tonic-gate 	}
996*0Sstevel@tonic-gate 
997*0Sstevel@tonic-gate 	/* Check for hotplugged CPU Memory modules */
998*0Sstevel@tonic-gate 	for (i = CPUMOD0; i <= CPUMOD3; i++) {
999*0Sstevel@tonic-gate 		/* Compare the /platform tree to the frutree */
1000*0Sstevel@tonic-gate 		slotnum = i - CPUMOD0;
1001*0Sstevel@tonic-gate 		err = is_added_device(platform_frupath[i],
1002*0Sstevel@tonic-gate 		    frutree_cpu_module[slotnum]);
1003*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1004*0Sstevel@tonic-gate 			continue;
1005*0Sstevel@tonic-gate 
1006*0Sstevel@tonic-gate 		/* If they are different, then add a CPU Mem module */
1007*0Sstevel@tonic-gate 		err = add_cpu_module(slotnum);
1008*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1009*0Sstevel@tonic-gate 			continue;
1010*0Sstevel@tonic-gate 	}
1011*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1012*0Sstevel@tonic-gate }
1013*0Sstevel@tonic-gate 
1014*0Sstevel@tonic-gate /* Searches the list of hotpluggable FRUs, removes the appropriate node(s) */
1015*0Sstevel@tonic-gate static int
rem_hotplug_fru_device()1016*0Sstevel@tonic-gate rem_hotplug_fru_device()
1017*0Sstevel@tonic-gate {
1018*0Sstevel@tonic-gate 	int		i, err, slotnum;
1019*0Sstevel@tonic-gate 
1020*0Sstevel@tonic-gate 	/* Check for hotplugged power supplies */
1021*0Sstevel@tonic-gate 	for (i = PS0; i <= PS2; i++) {
1022*0Sstevel@tonic-gate 		/* Compare the /platform tree to the frutree */
1023*0Sstevel@tonic-gate 		slotnum = i - PS0;
1024*0Sstevel@tonic-gate 		err = is_removed_device(platform_frupath[i],
1025*0Sstevel@tonic-gate 		    frutree_power_supply[slotnum]);
1026*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1027*0Sstevel@tonic-gate 			continue;
1028*0Sstevel@tonic-gate 
1029*0Sstevel@tonic-gate 		/* If they are different, then remove a power supply */
1030*0Sstevel@tonic-gate 		err = remove_power_supply(slotnum);
1031*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1032*0Sstevel@tonic-gate 			continue;
1033*0Sstevel@tonic-gate 	}
1034*0Sstevel@tonic-gate 
1035*0Sstevel@tonic-gate 	/* Check for hotplugged CPU Memory modules */
1036*0Sstevel@tonic-gate 	for (i = CPUMOD0; i <= CPUMOD3; i++) {
1037*0Sstevel@tonic-gate 		/* Compare the /platform tree to the frutree */
1038*0Sstevel@tonic-gate 		slotnum = i - CPUMOD0;
1039*0Sstevel@tonic-gate 		err = is_removed_device(platform_frupath[i],
1040*0Sstevel@tonic-gate 		    frutree_cpu_module[slotnum]);
1041*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1042*0Sstevel@tonic-gate 			continue;
1043*0Sstevel@tonic-gate 
1044*0Sstevel@tonic-gate 		/* If they are different, then remove a CPU Mem module */
1045*0Sstevel@tonic-gate 		err = remove_cpu_module(slotnum);
1046*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1047*0Sstevel@tonic-gate 			continue;
1048*0Sstevel@tonic-gate 	}
1049*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1050*0Sstevel@tonic-gate }
1051*0Sstevel@tonic-gate 
1052*0Sstevel@tonic-gate /*
1053*0Sstevel@tonic-gate  * Compare the /platform tree to the /frutree to determine if a
1054*0Sstevel@tonic-gate  * new device has been added
1055*0Sstevel@tonic-gate  */
1056*0Sstevel@tonic-gate static int
is_added_device(char * plat,char * fru)1057*0Sstevel@tonic-gate is_added_device(char *plat, char *fru)
1058*0Sstevel@tonic-gate {
1059*0Sstevel@tonic-gate 	int		err;
1060*0Sstevel@tonic-gate 	picl_nodehdl_t	plath, frusloth, frumodh;
1061*0Sstevel@tonic-gate 
1062*0Sstevel@tonic-gate 	/* Check for node in the /platform tree */
1063*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(plat, &plath);
1064*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1065*0Sstevel@tonic-gate 		return (err);
1066*0Sstevel@tonic-gate 
1067*0Sstevel@tonic-gate 	/*
1068*0Sstevel@tonic-gate 	 * The node is in /platform, so find the corresponding slot in
1069*0Sstevel@tonic-gate 	 * the frutree
1070*0Sstevel@tonic-gate 	 */
1071*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(fru, &frusloth);
1072*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1073*0Sstevel@tonic-gate 		return (err);
1074*0Sstevel@tonic-gate 
1075*0Sstevel@tonic-gate 	/*
1076*0Sstevel@tonic-gate 	 * If the slot in the frutree has a child, then return
1077*0Sstevel@tonic-gate 	 * PICL_FAILURE.  This means that the /platform tree and
1078*0Sstevel@tonic-gate 	 * the frutree are consistent and no action is necessary.
1079*0Sstevel@tonic-gate 	 * Otherwise return PICL_SUCCESS to indicate that a node needs
1080*0Sstevel@tonic-gate 	 * to be added to the frutree
1081*0Sstevel@tonic-gate 	 */
1082*0Sstevel@tonic-gate 	err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
1083*0Sstevel@tonic-gate 	    &frumodh, sizeof (picl_nodehdl_t));
1084*0Sstevel@tonic-gate 	if (err == PICL_SUCCESS)
1085*0Sstevel@tonic-gate 		return (PICL_FAILURE);
1086*0Sstevel@tonic-gate 
1087*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1088*0Sstevel@tonic-gate }
1089*0Sstevel@tonic-gate 
1090*0Sstevel@tonic-gate /*
1091*0Sstevel@tonic-gate  * Compare the /platform tree to the /frutree to determine if a
1092*0Sstevel@tonic-gate  * device has been removed
1093*0Sstevel@tonic-gate  */
1094*0Sstevel@tonic-gate static int
is_removed_device(char * plat,char * fru)1095*0Sstevel@tonic-gate is_removed_device(char *plat, char *fru)
1096*0Sstevel@tonic-gate {
1097*0Sstevel@tonic-gate 	int		err;
1098*0Sstevel@tonic-gate 	picl_nodehdl_t	plath, frusloth, frumodh;
1099*0Sstevel@tonic-gate 
1100*0Sstevel@tonic-gate 
1101*0Sstevel@tonic-gate 	/* Check for node in /platform tree */
1102*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(plat, &plath);
1103*0Sstevel@tonic-gate 	if (err == PICL_SUCCESS)
1104*0Sstevel@tonic-gate 		return (PICL_FAILURE);
1105*0Sstevel@tonic-gate 
1106*0Sstevel@tonic-gate 	/*
1107*0Sstevel@tonic-gate 	 * The node is not in /platform, so find the corresponding slot in
1108*0Sstevel@tonic-gate 	 * the frutree
1109*0Sstevel@tonic-gate 	 */
1110*0Sstevel@tonic-gate 	err = ptree_get_node_by_path(fru, &frusloth);
1111*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1112*0Sstevel@tonic-gate 		return (err);
1113*0Sstevel@tonic-gate 
1114*0Sstevel@tonic-gate 	/*
1115*0Sstevel@tonic-gate 	 * If the slot in the frutree does not have a child, then return
1116*0Sstevel@tonic-gate 	 * PICL_FAILURE.  This means that the /platform tree and
1117*0Sstevel@tonic-gate 	 * the frutree are consistent and no action is necessary.
1118*0Sstevel@tonic-gate 	 * Otherwise return PICL_SUCCESS to indicate that the needs
1119*0Sstevel@tonic-gate 	 * to be removed from the frutree
1120*0Sstevel@tonic-gate 	 */
1121*0Sstevel@tonic-gate 	err = ptree_get_propval_by_name(frusloth, PICL_PROP_CHILD,
1122*0Sstevel@tonic-gate 	    &frumodh, sizeof (picl_nodehdl_t));
1123*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1124*0Sstevel@tonic-gate 		return (err);
1125*0Sstevel@tonic-gate 
1126*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1127*0Sstevel@tonic-gate }
1128*0Sstevel@tonic-gate 
1129*0Sstevel@tonic-gate static int
remove_picl_node(picl_nodehdl_t nodeh)1130*0Sstevel@tonic-gate remove_picl_node(picl_nodehdl_t nodeh)
1131*0Sstevel@tonic-gate {
1132*0Sstevel@tonic-gate 	int err;
1133*0Sstevel@tonic-gate 	err = ptree_delete_node(nodeh);
1134*0Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1135*0Sstevel@tonic-gate 		return (err);
1136*0Sstevel@tonic-gate 	(void) ptree_destroy_node(nodeh);
1137*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1138*0Sstevel@tonic-gate }
1139*0Sstevel@tonic-gate 
1140*0Sstevel@tonic-gate /* event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events */
1141*0Sstevel@tonic-gate /*ARGSUSED2*/
1142*0Sstevel@tonic-gate static void
frudr_completion_handler(char * ename,void * earg,size_t size)1143*0Sstevel@tonic-gate frudr_completion_handler(char *ename, void *earg, size_t size)
1144*0Sstevel@tonic-gate {
1145*0Sstevel@tonic-gate 	picl_nodehdl_t	fruh;
1146*0Sstevel@tonic-gate 
1147*0Sstevel@tonic-gate 	if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
1148*0Sstevel@tonic-gate 		/*
1149*0Sstevel@tonic-gate 		 * now frudata has been notified that the node is to be
1150*0Sstevel@tonic-gate 		 * removed, we can actually remove it
1151*0Sstevel@tonic-gate 		 */
1152*0Sstevel@tonic-gate 		fruh = NULL;
1153*0Sstevel@tonic-gate 		(void) nvlist_lookup_uint64(earg,
1154*0Sstevel@tonic-gate 		    PICLEVENTARG_FRUHANDLE, &fruh);
1155*0Sstevel@tonic-gate 		if (fruh != NULL) {
1156*0Sstevel@tonic-gate 			(void) remove_picl_node(fruh);
1157*0Sstevel@tonic-gate 		}
1158*0Sstevel@tonic-gate 	}
1159*0Sstevel@tonic-gate 	nvlist_free(earg);
1160*0Sstevel@tonic-gate 	free(earg);
1161*0Sstevel@tonic-gate 	free(ename);
1162*0Sstevel@tonic-gate }
1163*0Sstevel@tonic-gate 
1164*0Sstevel@tonic-gate /*
1165*0Sstevel@tonic-gate  * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
1166*0Sstevel@tonic-gate  */
1167*0Sstevel@tonic-gate static void
post_frudr_event(char * ename,picl_nodehdl_t parenth,picl_nodehdl_t fruh)1168*0Sstevel@tonic-gate post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh)
1169*0Sstevel@tonic-gate {
1170*0Sstevel@tonic-gate 	nvlist_t	*nvl;
1171*0Sstevel@tonic-gate 	char		*ev_name;
1172*0Sstevel@tonic-gate 
1173*0Sstevel@tonic-gate 	ev_name = strdup(ename);
1174*0Sstevel@tonic-gate 	if (ev_name == NULL)
1175*0Sstevel@tonic-gate 		return;
1176*0Sstevel@tonic-gate 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) {
1177*0Sstevel@tonic-gate 		free(ev_name);
1178*0Sstevel@tonic-gate 		return;
1179*0Sstevel@tonic-gate 	}
1180*0Sstevel@tonic-gate 	if (parenth != 0L &&
1181*0Sstevel@tonic-gate 	    nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) {
1182*0Sstevel@tonic-gate 		free(ev_name);
1183*0Sstevel@tonic-gate 		nvlist_free(nvl);
1184*0Sstevel@tonic-gate 		return;
1185*0Sstevel@tonic-gate 	}
1186*0Sstevel@tonic-gate 	if (fruh != 0L &&
1187*0Sstevel@tonic-gate 	    nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) {
1188*0Sstevel@tonic-gate 		free(ev_name);
1189*0Sstevel@tonic-gate 		nvlist_free(nvl);
1190*0Sstevel@tonic-gate 		return;
1191*0Sstevel@tonic-gate 	}
1192*0Sstevel@tonic-gate 	if (ptree_post_event(ev_name, nvl, sizeof (nvl),
1193*0Sstevel@tonic-gate 	    frudr_completion_handler) != 0) {
1194*0Sstevel@tonic-gate 		free(ev_name);
1195*0Sstevel@tonic-gate 		nvlist_free(nvl);
1196*0Sstevel@tonic-gate 	}
1197*0Sstevel@tonic-gate }
1198*0Sstevel@tonic-gate 
1199*0Sstevel@tonic-gate /* Hotplug routine used to add a new power supply */
1200*0Sstevel@tonic-gate static int
add_power_supply(int slotnum)1201*0Sstevel@tonic-gate add_power_supply(int slotnum)
1202*0Sstevel@tonic-gate {
1203*0Sstevel@tonic-gate 	picl_nodehdl_t		powersloth;
1204*0Sstevel@tonic-gate 	picl_nodehdl_t		powermodh;
1205*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
1206*0Sstevel@tonic-gate 	int			i, err;
1207*0Sstevel@tonic-gate 
1208*0Sstevel@tonic-gate 	/* Find the node for the given power supply slot */
1209*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1210*0Sstevel@tonic-gate 	    &powersloth) == PICL_SUCCESS) {
1211*0Sstevel@tonic-gate 
1212*0Sstevel@tonic-gate 		i = slotnum + PS0;
1213*0Sstevel@tonic-gate 
1214*0Sstevel@tonic-gate 		/* Make sure it's in /platform and create the frutree node */
1215*0Sstevel@tonic-gate 		if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
1216*0Sstevel@tonic-gate 		    PICL_SUCCESS) {
1217*0Sstevel@tonic-gate 			err = ptree_create_node("power-supply", "fru",
1218*0Sstevel@tonic-gate 			    &powermodh);
1219*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1220*0Sstevel@tonic-gate 				return (err);
1221*0Sstevel@tonic-gate 
1222*0Sstevel@tonic-gate 			err = add_ref_prop(powermodh, tmph, SEEPROM_SOURCE);
1223*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1224*0Sstevel@tonic-gate 				return (err);
1225*0Sstevel@tonic-gate 
1226*0Sstevel@tonic-gate 			err = add_void_fda_prop(powermodh);
1227*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1228*0Sstevel@tonic-gate 				return (err);
1229*0Sstevel@tonic-gate 
1230*0Sstevel@tonic-gate 			err = ptree_add_node(powersloth, powermodh);
1231*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1232*0Sstevel@tonic-gate 				return (err);
1233*0Sstevel@tonic-gate 
1234*0Sstevel@tonic-gate 			err = add_ref_prop(tmph, powermodh, FRU_PARENT);
1235*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1236*0Sstevel@tonic-gate 				return (err);
1237*0Sstevel@tonic-gate 
1238*0Sstevel@tonic-gate 			/* Post picl-fru-added event */
1239*0Sstevel@tonic-gate 			post_frudr_event(PICL_FRU_ADDED, NULL, powermodh);
1240*0Sstevel@tonic-gate 		}
1241*0Sstevel@tonic-gate 	}
1242*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1243*0Sstevel@tonic-gate }
1244*0Sstevel@tonic-gate 
1245*0Sstevel@tonic-gate /* Hotplug routine used to remove an existing power supply */
1246*0Sstevel@tonic-gate static int
remove_power_supply(int slotnum)1247*0Sstevel@tonic-gate remove_power_supply(int slotnum)
1248*0Sstevel@tonic-gate {
1249*0Sstevel@tonic-gate 	picl_nodehdl_t		powersloth;
1250*0Sstevel@tonic-gate 	picl_nodehdl_t		powermodh;
1251*0Sstevel@tonic-gate 	int			err;
1252*0Sstevel@tonic-gate 
1253*0Sstevel@tonic-gate 	/* Find the node for the given power supply slot */
1254*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(frutree_power_supply[slotnum],
1255*0Sstevel@tonic-gate 	    &powersloth) == PICL_SUCCESS) {
1256*0Sstevel@tonic-gate 		/* Make sure it's got a child, then delete it */
1257*0Sstevel@tonic-gate 		err = ptree_get_propval_by_name(powersloth, PICL_PROP_CHILD,
1258*0Sstevel@tonic-gate 		    &powermodh, sizeof (picl_nodehdl_t));
1259*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
1260*0Sstevel@tonic-gate 			return (err);
1261*0Sstevel@tonic-gate 		}
1262*0Sstevel@tonic-gate 
1263*0Sstevel@tonic-gate 		err = ptree_delete_node(powermodh);
1264*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
1265*0Sstevel@tonic-gate 			return (err);
1266*0Sstevel@tonic-gate 		} else {
1267*0Sstevel@tonic-gate 			(void) ptree_destroy_node(powermodh);
1268*0Sstevel@tonic-gate 		}
1269*0Sstevel@tonic-gate 
1270*0Sstevel@tonic-gate 		/* Post picl-fru-removed event */
1271*0Sstevel@tonic-gate 		post_frudr_event(PICL_FRU_REMOVED, NULL, powermodh);
1272*0Sstevel@tonic-gate 
1273*0Sstevel@tonic-gate 	}
1274*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1275*0Sstevel@tonic-gate }
1276*0Sstevel@tonic-gate 
1277*0Sstevel@tonic-gate /* Hotplug routine used to add a new CPU Mem Module (with associated DIMMs) */
1278*0Sstevel@tonic-gate static int
add_cpu_module(int slotnum)1279*0Sstevel@tonic-gate add_cpu_module(int slotnum)
1280*0Sstevel@tonic-gate {
1281*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemsloth;
1282*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemmodh;
1283*0Sstevel@tonic-gate 	picl_nodehdl_t		tmph;
1284*0Sstevel@tonic-gate 	int			i, err;
1285*0Sstevel@tonic-gate 
1286*0Sstevel@tonic-gate 	/* Find the node for the given CPU Memory module slot */
1287*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
1288*0Sstevel@tonic-gate 	    &cpumemsloth) == PICL_SUCCESS) {
1289*0Sstevel@tonic-gate 
1290*0Sstevel@tonic-gate 		i = slotnum + CPUMOD0;
1291*0Sstevel@tonic-gate 
1292*0Sstevel@tonic-gate 		/* Make sure it's in /platform and create the frutree nodes */
1293*0Sstevel@tonic-gate 		if (ptree_get_node_by_path(platform_frupath[i], &tmph) ==
1294*0Sstevel@tonic-gate 		    PICL_SUCCESS) {
1295*0Sstevel@tonic-gate 			err = ptree_create_node("cpu-mem-module", "fru",
1296*0Sstevel@tonic-gate 			    &cpumemmodh);
1297*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1298*0Sstevel@tonic-gate 				return (err);
1299*0Sstevel@tonic-gate 
1300*0Sstevel@tonic-gate 			err = add_ref_prop(cpumemmodh, tmph, SEEPROM_SOURCE);
1301*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1302*0Sstevel@tonic-gate 				return (err);
1303*0Sstevel@tonic-gate 
1304*0Sstevel@tonic-gate 			err = add_void_fda_prop(cpumemmodh);
1305*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1306*0Sstevel@tonic-gate 				return (err);
1307*0Sstevel@tonic-gate 
1308*0Sstevel@tonic-gate 			err = ptree_add_node(cpumemsloth, cpumemmodh);
1309*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1310*0Sstevel@tonic-gate 				return (err);
1311*0Sstevel@tonic-gate 
1312*0Sstevel@tonic-gate 			err = add_ref_prop(tmph, cpumemmodh, FRU_PARENT);
1313*0Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
1314*0Sstevel@tonic-gate 				return (err);
1315*0Sstevel@tonic-gate 		}
1316*0Sstevel@tonic-gate 
1317*0Sstevel@tonic-gate 		err = do_cpu_module_init(cpumemmodh, slotnum);
1318*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1319*0Sstevel@tonic-gate 			return (err);
1320*0Sstevel@tonic-gate 	}
1321*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1322*0Sstevel@tonic-gate }
1323*0Sstevel@tonic-gate 
1324*0Sstevel@tonic-gate /* Hotplug routine used to remove an existing CPU Mem Module */
1325*0Sstevel@tonic-gate static int
remove_cpu_module(int slotnum)1326*0Sstevel@tonic-gate remove_cpu_module(int slotnum)
1327*0Sstevel@tonic-gate {
1328*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemsloth;
1329*0Sstevel@tonic-gate 	picl_nodehdl_t		cpumemmodh;
1330*0Sstevel@tonic-gate 	int			err;
1331*0Sstevel@tonic-gate 
1332*0Sstevel@tonic-gate 	/* Find the node for the given CPU Memory module slot */
1333*0Sstevel@tonic-gate 	if (ptree_get_node_by_path(frutree_cpu_module[slotnum],
1334*0Sstevel@tonic-gate 	    &cpumemsloth) == PICL_SUCCESS) {
1335*0Sstevel@tonic-gate 		/* Make sure it's got a child, then delete it */
1336*0Sstevel@tonic-gate 		err = ptree_get_propval_by_name(cpumemsloth, PICL_PROP_CHILD,
1337*0Sstevel@tonic-gate 		    &cpumemmodh, sizeof (picl_nodehdl_t));
1338*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
1339*0Sstevel@tonic-gate 			return (err);
1340*0Sstevel@tonic-gate 		}
1341*0Sstevel@tonic-gate 
1342*0Sstevel@tonic-gate 		err = remove_all_nodes(cpumemmodh);
1343*0Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
1344*0Sstevel@tonic-gate 			return (err);
1345*0Sstevel@tonic-gate 		}
1346*0Sstevel@tonic-gate 	}
1347*0Sstevel@tonic-gate 	return (PICL_SUCCESS);
1348*0Sstevel@tonic-gate }
1349