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