riverwalk.c revision 6433:b80c8a854640
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
37typedef 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*/
73static int
74sun_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
229int
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