xref: /titanic_51/usr/src/lib/scsi/plugins/ses/SUN-Storage-J4400/common/riverwalk.c (revision a6e6969cf9cfe2070eae4cd6071f76b0fa4f539f)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <string.h>
30 #include <strings.h>
31 
32 #include <scsi/libses.h>
33 #include <scsi/libses_plugin.h>
34 
35 #pragma pack(1)
36 
37 typedef struct ses_riverwalk_stringin {
38 	uint8_t		rws_download_status;
39 	uint8_t		rws_descriptor_start;
40 	uint16_t	rws_descriptor_length;
41 	char		rws_sim0_id[4];
42 	char		rws_sim0_pn[15];
43 	char		rws_sim0_sn[20];
44 	char		rws_sim1_id[4];
45 	char		rws_sim1_pn[15];
46 	char		rws_sim1_sn[20];
47 	char		rws_mid_id[4];
48 	char		rws_mid_pn[15];
49 	char		rws_mid_sn[20];
50 	char		rws_ps0_id[4];
51 	char		rws_ps0_pn[15];
52 	char		rws_ps0_sn[20];
53 	char		rws_ps1_id[4];
54 	char		rws_ps1_pn[15];
55 	char		rws_ps1_sn[20];
56 	char		__reserved1[29];
57 	uint8_t		rws_diag_start;
58 	uint8_t		rws_eid;
59 	uint16_t	rws_diag_length;
60 	uint8_t		rws_sim_id;
61 	uint8_t		rws_numport;
62 	uint16_t	__reserved2;
63 	uint8_t		rws_sasaddr[8];
64 	uint8_t		rws_sys_sn[8];
65 	char		rws_port0[16];
66 	char		rws_port1[16];
67 	char		rws_port2[16];
68 } ses_riverwalk_stringin_t;
69 
70 #pragma pack()
71 
72 /*ARGSUSED*/
73 static int
74 sun_riverwalk_parse_node(ses_plugin_t *sp, ses_node_t *np)
75 {
76 	nvlist_t *props = ses_node_props(np);
77 	int nverr;
78 	ses_riverwalk_stringin_t *strp;
79 	char buf[32];
80 	uint64_t type, index;
81 	char *pn, *sn;
82 	ses_node_t *encp;
83 	nvlist_t *encprops;
84 	uint8_t *stringin;
85 	uint_t len;
86 
87 	if (ses_node_type(np) != SES_NODE_ENCLOSURE &&
88 	    ses_node_type(np) != SES_NODE_ELEMENT)
89 		return (0);
90 
91 	/*
92 	 * Find the containing enclosure node and extract the STRING IN
93 	 * information.
94 	 */
95 	for (encp = np; ses_node_type(encp) != SES_NODE_ENCLOSURE;
96 	    encp = ses_node_parent(encp))
97 		;
98 
99 	encprops = ses_node_props(encp);
100 	if (nvlist_lookup_byte_array(encprops, SES_EN_PROP_STRING,
101 	    &stringin, &len) != 0)
102 		return (0);
103 
104 	if (len < sizeof (ses_riverwalk_stringin_t))
105 		return (0);
106 
107 	strp = (ses_riverwalk_stringin_t *)stringin;
108 
109 	switch (ses_node_type(np)) {
110 	case SES_NODE_ELEMENT:
111 		/*
112 		 * We can get part and serial information for power supplies and
113 		 * the SIM cards (ESC_ELECTRONICS elements).
114 		 */
115 		VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
116 		    &type) == 0);
117 		VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_CLASS_INDEX,
118 		    &index) == 0);
119 
120 		sn = pn = NULL;
121 		switch (type) {
122 		case SES_ET_POWER_SUPPLY:
123 			switch (index) {
124 			case 0:
125 				if (strncmp(strp->rws_ps0_id, "SPS0", 4) != 0)
126 					break;
127 
128 				pn = strp->rws_ps0_pn;
129 				sn = strp->rws_ps0_sn;
130 				break;
131 
132 			case 1:
133 				if (strncmp(strp->rws_ps1_id, "SPS1", 4) != 0)
134 					break;
135 
136 				pn = strp->rws_ps1_pn;
137 				sn = strp->rws_ps1_sn;
138 				break;
139 			}
140 			break;
141 
142 		case SES_ET_ESC_ELECTRONICS:
143 			switch (index) {
144 			case 0:
145 				if (strncmp(strp->rws_sim0_id, "SIM0", 4) != 0)
146 					break;
147 
148 				pn = strp->rws_sim0_pn;
149 				sn = strp->rws_sim0_sn;
150 				break;
151 
152 			case 1:
153 				if (strncmp(strp->rws_sim1_id, "SIM1", 4) != 0)
154 					break;
155 
156 				pn = strp->rws_sim1_pn;
157 				sn = strp->rws_sim1_sn;
158 				break;
159 			}
160 			break;
161 
162 		case SES_ET_COOLING:
163 			/*
164 			 * The J4200 uses identical STRING IN data except that
165 			 * the PSU part numbers are replaced with fan part
166 			 * numbers.  The power supply part and serial number
167 			 * information are not available.
168 			 */
169 			switch (index) {
170 			case 0:
171 				if (strncmp(strp->rws_ps0_id, "FAN0", 4) != 0)
172 					break;
173 
174 				pn = strp->rws_ps0_pn;
175 				sn = strp->rws_ps0_sn;
176 				break;
177 
178 			case 1:
179 				if (strncmp(strp->rws_ps1_id, "FAN1", 4) != 0)
180 					break;
181 
182 				pn = strp->rws_ps1_pn;
183 				sn = strp->rws_ps1_sn;
184 				break;
185 			}
186 			break;
187 
188 		}
189 
190 		if (pn == NULL)
191 			return (0);
192 
193 		if (pn[0] != '\0') {
194 			(void) bcopy(pn, buf, sizeof (strp->rws_ps0_pn));
195 			buf[sizeof (strp->rws_ps0_pn)] = '\0';
196 			SES_NV_ADD(string, nverr, props, LIBSES_PROP_PART,
197 			    buf);
198 		}
199 
200 		if (sn[0] != '\0') {
201 			(void) bcopy(sn, buf, sizeof (strp->rws_ps0_sn));
202 			buf[sizeof (strp->rws_ps0_sn)] = '\0';
203 			SES_NV_ADD(string, nverr, props, LIBSES_PROP_SERIAL,
204 			    sn);
205 		}
206 
207 		break;
208 
209 	case SES_NODE_ENCLOSURE:
210 		/*
211 		 * The chassis serial number is derived from the MID FRU
212 		 * descriptor.
213 		 */
214 		if (strncmp(strp->rws_mid_id, "MID ", 4) == 0 &&
215 		    strp->rws_mid_sn[0] != '\0') {
216 			(void) bcopy(strp->rws_mid_sn, buf,
217 			    sizeof (strp->rws_mid_sn));
218 			buf[sizeof (strp->rws_mid_sn)] = '\0';
219 			SES_NV_ADD(string, nverr, props, LIBSES_EN_PROP_CSN,
220 			    buf);
221 		}
222 
223 		break;
224 	}
225 
226 	return (0);
227 }
228 
229 int
230 _ses_init(ses_plugin_t *sp)
231 {
232 	ses_plugin_config_t config = {
233 		.spc_node_parse = sun_riverwalk_parse_node
234 	};
235 
236 	return (ses_plugin_register(sp, LIBSES_PLUGIN_VERSION,
237 	    &config) != 0);
238 }
239