1*6433Seschrock /*
2*6433Seschrock * CDDL HEADER START
3*6433Seschrock *
4*6433Seschrock * The contents of this file are subject to the terms of the
5*6433Seschrock * Common Development and Distribution License (the "License").
6*6433Seschrock * You may not use this file except in compliance with the License.
7*6433Seschrock *
8*6433Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6433Seschrock * or http://www.opensolaris.org/os/licensing.
10*6433Seschrock * See the License for the specific language governing permissions
11*6433Seschrock * and limitations under the License.
12*6433Seschrock *
13*6433Seschrock * When distributing Covered Code, include this CDDL HEADER in each
14*6433Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6433Seschrock * If applicable, add the following below this CDDL HEADER, with the
16*6433Seschrock * fields enclosed by brackets "[]" replaced with your own identifying
17*6433Seschrock * information: Portions Copyright [yyyy] [name of copyright owner]
18*6433Seschrock *
19*6433Seschrock * CDDL HEADER END
20*6433Seschrock */
21*6433Seschrock
22*6433Seschrock /*
23*6433Seschrock * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24*6433Seschrock * Use is subject to license terms.
25*6433Seschrock */
26*6433Seschrock
27*6433Seschrock #pragma ident "%Z%%M% %I% %E% SMI"
28*6433Seschrock
29*6433Seschrock #include <string.h>
30*6433Seschrock #include <strings.h>
31*6433Seschrock
32*6433Seschrock #include <scsi/libses.h>
33*6433Seschrock #include <scsi/libses_plugin.h>
34*6433Seschrock
35*6433Seschrock #pragma pack(1)
36*6433Seschrock
37*6433Seschrock typedef struct ses_riverwalk_stringin {
38*6433Seschrock uint8_t rws_download_status;
39*6433Seschrock uint8_t rws_descriptor_start;
40*6433Seschrock uint16_t rws_descriptor_length;
41*6433Seschrock char rws_sim0_id[4];
42*6433Seschrock char rws_sim0_pn[15];
43*6433Seschrock char rws_sim0_sn[20];
44*6433Seschrock char rws_sim1_id[4];
45*6433Seschrock char rws_sim1_pn[15];
46*6433Seschrock char rws_sim1_sn[20];
47*6433Seschrock char rws_mid_id[4];
48*6433Seschrock char rws_mid_pn[15];
49*6433Seschrock char rws_mid_sn[20];
50*6433Seschrock char rws_ps0_id[4];
51*6433Seschrock char rws_ps0_pn[15];
52*6433Seschrock char rws_ps0_sn[20];
53*6433Seschrock char rws_ps1_id[4];
54*6433Seschrock char rws_ps1_pn[15];
55*6433Seschrock char rws_ps1_sn[20];
56*6433Seschrock char __reserved1[29];
57*6433Seschrock uint8_t rws_diag_start;
58*6433Seschrock uint8_t rws_eid;
59*6433Seschrock uint16_t rws_diag_length;
60*6433Seschrock uint8_t rws_sim_id;
61*6433Seschrock uint8_t rws_numport;
62*6433Seschrock uint16_t __reserved2;
63*6433Seschrock uint8_t rws_sasaddr[8];
64*6433Seschrock uint8_t rws_sys_sn[8];
65*6433Seschrock char rws_port0[16];
66*6433Seschrock char rws_port1[16];
67*6433Seschrock char rws_port2[16];
68*6433Seschrock } ses_riverwalk_stringin_t;
69*6433Seschrock
70*6433Seschrock #pragma pack()
71*6433Seschrock
72*6433Seschrock /*ARGSUSED*/
73*6433Seschrock static int
sun_riverwalk_parse_node(ses_plugin_t * sp,ses_node_t * np)74*6433Seschrock sun_riverwalk_parse_node(ses_plugin_t *sp, ses_node_t *np)
75*6433Seschrock {
76*6433Seschrock nvlist_t *props = ses_node_props(np);
77*6433Seschrock int nverr;
78*6433Seschrock ses_riverwalk_stringin_t *strp;
79*6433Seschrock char buf[32];
80*6433Seschrock uint64_t type, index;
81*6433Seschrock char *pn, *sn;
82*6433Seschrock ses_node_t *encp;
83*6433Seschrock nvlist_t *encprops;
84*6433Seschrock uint8_t *stringin;
85*6433Seschrock uint_t len;
86*6433Seschrock
87*6433Seschrock if (ses_node_type(np) != SES_NODE_ENCLOSURE &&
88*6433Seschrock ses_node_type(np) != SES_NODE_ELEMENT)
89*6433Seschrock return (0);
90*6433Seschrock
91*6433Seschrock /*
92*6433Seschrock * Find the containing enclosure node and extract the STRING IN
93*6433Seschrock * information.
94*6433Seschrock */
95*6433Seschrock for (encp = np; ses_node_type(encp) != SES_NODE_ENCLOSURE;
96*6433Seschrock encp = ses_node_parent(encp))
97*6433Seschrock ;
98*6433Seschrock
99*6433Seschrock encprops = ses_node_props(encp);
100*6433Seschrock if (nvlist_lookup_byte_array(encprops, SES_EN_PROP_STRING,
101*6433Seschrock &stringin, &len) != 0)
102*6433Seschrock return (0);
103*6433Seschrock
104*6433Seschrock if (len < sizeof (ses_riverwalk_stringin_t))
105*6433Seschrock return (0);
106*6433Seschrock
107*6433Seschrock strp = (ses_riverwalk_stringin_t *)stringin;
108*6433Seschrock
109*6433Seschrock switch (ses_node_type(np)) {
110*6433Seschrock case SES_NODE_ELEMENT:
111*6433Seschrock /*
112*6433Seschrock * We can get part and serial information for power supplies and
113*6433Seschrock * the SIM cards (ESC_ELECTRONICS elements).
114*6433Seschrock */
115*6433Seschrock VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
116*6433Seschrock &type) == 0);
117*6433Seschrock VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_CLASS_INDEX,
118*6433Seschrock &index) == 0);
119*6433Seschrock
120*6433Seschrock sn = pn = NULL;
121*6433Seschrock switch (type) {
122*6433Seschrock case SES_ET_POWER_SUPPLY:
123*6433Seschrock switch (index) {
124*6433Seschrock case 0:
125*6433Seschrock if (strncmp(strp->rws_ps0_id, "SPS0", 4) != 0)
126*6433Seschrock break;
127*6433Seschrock
128*6433Seschrock pn = strp->rws_ps0_pn;
129*6433Seschrock sn = strp->rws_ps0_sn;
130*6433Seschrock break;
131*6433Seschrock
132*6433Seschrock case 1:
133*6433Seschrock if (strncmp(strp->rws_ps1_id, "SPS1", 4) != 0)
134*6433Seschrock break;
135*6433Seschrock
136*6433Seschrock pn = strp->rws_ps1_pn;
137*6433Seschrock sn = strp->rws_ps1_sn;
138*6433Seschrock break;
139*6433Seschrock }
140*6433Seschrock break;
141*6433Seschrock
142*6433Seschrock case SES_ET_ESC_ELECTRONICS:
143*6433Seschrock switch (index) {
144*6433Seschrock case 0:
145*6433Seschrock if (strncmp(strp->rws_sim0_id, "SIM0", 4) != 0)
146*6433Seschrock break;
147*6433Seschrock
148*6433Seschrock pn = strp->rws_sim0_pn;
149*6433Seschrock sn = strp->rws_sim0_sn;
150*6433Seschrock break;
151*6433Seschrock
152*6433Seschrock case 1:
153*6433Seschrock if (strncmp(strp->rws_sim1_id, "SIM1", 4) != 0)
154*6433Seschrock break;
155*6433Seschrock
156*6433Seschrock pn = strp->rws_sim1_pn;
157*6433Seschrock sn = strp->rws_sim1_sn;
158*6433Seschrock break;
159*6433Seschrock }
160*6433Seschrock break;
161*6433Seschrock
162*6433Seschrock case SES_ET_COOLING:
163*6433Seschrock /*
164*6433Seschrock * The J4200 uses identical STRING IN data except that
165*6433Seschrock * the PSU part numbers are replaced with fan part
166*6433Seschrock * numbers. The power supply part and serial number
167*6433Seschrock * information are not available.
168*6433Seschrock */
169*6433Seschrock switch (index) {
170*6433Seschrock case 0:
171*6433Seschrock if (strncmp(strp->rws_ps0_id, "FAN0", 4) != 0)
172*6433Seschrock break;
173*6433Seschrock
174*6433Seschrock pn = strp->rws_ps0_pn;
175*6433Seschrock sn = strp->rws_ps0_sn;
176*6433Seschrock break;
177*6433Seschrock
178*6433Seschrock case 1:
179*6433Seschrock if (strncmp(strp->rws_ps1_id, "FAN1", 4) != 0)
180*6433Seschrock break;
181*6433Seschrock
182*6433Seschrock pn = strp->rws_ps1_pn;
183*6433Seschrock sn = strp->rws_ps1_sn;
184*6433Seschrock break;
185*6433Seschrock }
186*6433Seschrock break;
187*6433Seschrock
188*6433Seschrock }
189*6433Seschrock
190*6433Seschrock if (pn == NULL)
191*6433Seschrock return (0);
192*6433Seschrock
193*6433Seschrock if (pn[0] != '\0') {
194*6433Seschrock (void) bcopy(pn, buf, sizeof (strp->rws_ps0_pn));
195*6433Seschrock buf[sizeof (strp->rws_ps0_pn)] = '\0';
196*6433Seschrock SES_NV_ADD(string, nverr, props, LIBSES_PROP_PART,
197*6433Seschrock buf);
198*6433Seschrock }
199*6433Seschrock
200*6433Seschrock if (sn[0] != '\0') {
201*6433Seschrock (void) bcopy(sn, buf, sizeof (strp->rws_ps0_sn));
202*6433Seschrock buf[sizeof (strp->rws_ps0_sn)] = '\0';
203*6433Seschrock SES_NV_ADD(string, nverr, props, LIBSES_PROP_SERIAL,
204*6433Seschrock sn);
205*6433Seschrock }
206*6433Seschrock
207*6433Seschrock break;
208*6433Seschrock
209*6433Seschrock case SES_NODE_ENCLOSURE:
210*6433Seschrock /*
211*6433Seschrock * The chassis serial number is derived from the MID FRU
212*6433Seschrock * descriptor.
213*6433Seschrock */
214*6433Seschrock if (strncmp(strp->rws_mid_id, "MID ", 4) == 0 &&
215*6433Seschrock strp->rws_mid_sn[0] != '\0') {
216*6433Seschrock (void) bcopy(strp->rws_mid_sn, buf,
217*6433Seschrock sizeof (strp->rws_mid_sn));
218*6433Seschrock buf[sizeof (strp->rws_mid_sn)] = '\0';
219*6433Seschrock SES_NV_ADD(string, nverr, props, LIBSES_EN_PROP_CSN,
220*6433Seschrock buf);
221*6433Seschrock }
222*6433Seschrock
223*6433Seschrock break;
224*6433Seschrock }
225*6433Seschrock
226*6433Seschrock return (0);
227*6433Seschrock }
228*6433Seschrock
229*6433Seschrock int
_ses_init(ses_plugin_t * sp)230*6433Seschrock _ses_init(ses_plugin_t *sp)
231*6433Seschrock {
232*6433Seschrock ses_plugin_config_t config = {
233*6433Seschrock .spc_node_parse = sun_riverwalk_parse_node
234*6433Seschrock };
235*6433Seschrock
236*6433Seschrock return (ses_plugin_register(sp, LIBSES_PLUGIN_VERSION,
237*6433Seschrock &config) != 0);
238*6433Seschrock }
239