1275c9da8Seschrock /*
2275c9da8Seschrock  * CDDL HEADER START
3275c9da8Seschrock  *
4275c9da8Seschrock  * The contents of this file are subject to the terms of the
5275c9da8Seschrock  * Common Development and Distribution License (the "License").
6275c9da8Seschrock  * You may not use this file except in compliance with the License.
7275c9da8Seschrock  *
8275c9da8Seschrock  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9275c9da8Seschrock  * or http://www.opensolaris.org/os/licensing.
10275c9da8Seschrock  * See the License for the specific language governing permissions
11275c9da8Seschrock  * and limitations under the License.
12275c9da8Seschrock  *
13275c9da8Seschrock  * When distributing Covered Code, include this CDDL HEADER in each
14275c9da8Seschrock  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15275c9da8Seschrock  * If applicable, add the following below this CDDL HEADER, with the
16275c9da8Seschrock  * fields enclosed by brackets "[]" replaced with your own identifying
17275c9da8Seschrock  * information: Portions Copyright [yyyy] [name of copyright owner]
18275c9da8Seschrock  *
19275c9da8Seschrock  * CDDL HEADER END
20275c9da8Seschrock  */
21275c9da8Seschrock 
22275c9da8Seschrock /*
23*791a814cSSundeep Panicker  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24275c9da8Seschrock  * Use is subject to license terms.
25275c9da8Seschrock  */
26275c9da8Seschrock 
27275c9da8Seschrock #include <scsi/libses.h>
28275c9da8Seschrock #include "ses_impl.h"
29275c9da8Seschrock 
30275c9da8Seschrock int
enc_parse_td(ses2_td_hdr_impl_t * tip,const char * tp,nvlist_t * nvl)31275c9da8Seschrock enc_parse_td(ses2_td_hdr_impl_t *tip, const char *tp, nvlist_t *nvl)
32275c9da8Seschrock {
33275c9da8Seschrock 	int nverr;
34275c9da8Seschrock 
35275c9da8Seschrock 	if (tp != NULL)
36275c9da8Seschrock 		SES_NV_ADD(fixed_string, nverr, nvl, SES_PROP_CLASS_DESCRIPTION,
37275c9da8Seschrock 		    tp, tip->sthi_text_len);
38275c9da8Seschrock 
39275c9da8Seschrock 	return (0);
40275c9da8Seschrock }
41275c9da8Seschrock 
42275c9da8Seschrock static int
enc_eid(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)43275c9da8Seschrock enc_eid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
44275c9da8Seschrock {
45275c9da8Seschrock 	int nverr;
46275c9da8Seschrock 
47275c9da8Seschrock 	SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_subenclosure_id);
48275c9da8Seschrock 
49275c9da8Seschrock 	return (0);
50275c9da8Seschrock }
51275c9da8Seschrock 
52275c9da8Seschrock static int
enc_espid(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)53275c9da8Seschrock enc_espid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
54275c9da8Seschrock {
55275c9da8Seschrock 	int nverr;
56275c9da8Seschrock 
57275c9da8Seschrock 	SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_rel_esp_id);
58275c9da8Seschrock 
59275c9da8Seschrock 	return (0);
60275c9da8Seschrock }
61275c9da8Seschrock 
62275c9da8Seschrock static int
enc_nesp(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)63275c9da8Seschrock enc_nesp(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
64275c9da8Seschrock {
65275c9da8Seschrock 	int nverr;
66275c9da8Seschrock 
67275c9da8Seschrock 	SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_n_esps);
68275c9da8Seschrock 
69275c9da8Seschrock 	return (0);
70275c9da8Seschrock }
71275c9da8Seschrock 
72275c9da8Seschrock static int
enc_lid(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)73275c9da8Seschrock enc_lid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
74275c9da8Seschrock {
75275c9da8Seschrock 	nvlist_t *lid;
76275c9da8Seschrock 	int nverr;
77275c9da8Seschrock 
78275c9da8Seschrock 	if ((nverr = nvlist_alloc(&lid, NV_UNIQUE_NAME, 0)) != 0)
79275c9da8Seschrock 		return (ses_set_nverrno(nverr, NULL));
80275c9da8Seschrock 
81275c9da8Seschrock 	SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_INT,
82275c9da8Seschrock 	    SCSI_READ64(&tp->st_logical_id));
83275c9da8Seschrock 
84275c9da8Seschrock 	switch (tp->st_logical_id.sni8i_naa) {
85275c9da8Seschrock 	case NAA_IEEE_EXT:
86275c9da8Seschrock 		SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE,
87275c9da8Seschrock 		    NAA_IEEE_EXT);
88275c9da8Seschrock 		SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID,
89275c9da8Seschrock 		    NAA_IEEE_EXT_COMPANY_ID(&tp->st_logical_id.sni8i_ext_id));
90275c9da8Seschrock 		SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A,
91275c9da8Seschrock 		    NAA_IEEE_EXT_VENDOR_A(&tp->st_logical_id.sni8i_ext_id));
92275c9da8Seschrock 		SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_B,
93275c9da8Seschrock 		    NAA_IEEE_EXT_VENDOR_B(&tp->st_logical_id.sni8i_ext_id));
94275c9da8Seschrock 		break;
95275c9da8Seschrock 	case NAA_IEEE_REG:
96275c9da8Seschrock 		SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE,
97275c9da8Seschrock 		    NAA_IEEE_REG);
98275c9da8Seschrock 		SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID,
99275c9da8Seschrock 		    NAA_IEEE_REG_COMPANY_ID(&tp->st_logical_id.sni8i_reg_id));
100275c9da8Seschrock 		SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A,
101275c9da8Seschrock 		    NAA_IEEE_REG_VENDOR_ID(&tp->st_logical_id.sni8i_reg_id));
102275c9da8Seschrock 		break;
103275c9da8Seschrock 	default:
104275c9da8Seschrock 		break;
105275c9da8Seschrock 	}
106275c9da8Seschrock 
107275c9da8Seschrock 	if ((nverr = nvlist_add_nvlist(nvl, name, lid)) != 0) {
108275c9da8Seschrock 		nvlist_free(lid);
109275c9da8Seschrock 		return (ses_set_nverrno(nverr, name));
110275c9da8Seschrock 	}
111275c9da8Seschrock 
112275c9da8Seschrock 	nvlist_free(lid);
113275c9da8Seschrock 
114275c9da8Seschrock 	return (0);
115275c9da8Seschrock }
116275c9da8Seschrock 
117275c9da8Seschrock static int
enc_vid(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)118275c9da8Seschrock enc_vid(const ses2_ed_impl_t *tp, nvlist_t *nvl,
119275c9da8Seschrock     const char *name)
120275c9da8Seschrock {
121275c9da8Seschrock 	int nverr;
122275c9da8Seschrock 
123275c9da8Seschrock 	SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_vendor_id);
124275c9da8Seschrock 
125275c9da8Seschrock 	return (0);
126275c9da8Seschrock }
127275c9da8Seschrock 
128275c9da8Seschrock static int
enc_pid(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)129275c9da8Seschrock enc_pid(const ses2_ed_impl_t *tp, nvlist_t *nvl,
130275c9da8Seschrock     const char *name)
131275c9da8Seschrock {
132275c9da8Seschrock 	int nverr;
133275c9da8Seschrock 
134275c9da8Seschrock 	SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_id);
135275c9da8Seschrock 
136275c9da8Seschrock 	return (0);
137275c9da8Seschrock }
138275c9da8Seschrock 
139275c9da8Seschrock static int
enc_rev(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)140275c9da8Seschrock enc_rev(const ses2_ed_impl_t *tp, nvlist_t *nvl,
141275c9da8Seschrock     const char *name)
142275c9da8Seschrock {
143275c9da8Seschrock 	int nverr;
144275c9da8Seschrock 
145275c9da8Seschrock 	SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_revision);
146275c9da8Seschrock 
147275c9da8Seschrock 	return (0);
148275c9da8Seschrock }
149275c9da8Seschrock 
150275c9da8Seschrock static int
enc_vs(const ses2_ed_impl_t * tp,nvlist_t * nvl,const char * name)151275c9da8Seschrock enc_vs(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
152275c9da8Seschrock {
153275c9da8Seschrock 	int nverr;
154275c9da8Seschrock 
155275c9da8Seschrock 	SES_NV_ADD(byte_array, nverr, nvl, name, (uchar_t *)tp->st_priv,
156*791a814cSSundeep Panicker 	    tp->st_hdr.sehi_ed_len - offsetof(ses2_ed_impl_t, st_priv[0]) +
157*791a814cSSundeep Panicker 	    offsetof(ses2_ed_impl_t, st_hdr.sehi_ed_len) + 1);
158275c9da8Seschrock 
159275c9da8Seschrock 	return (0);
160275c9da8Seschrock }
161275c9da8Seschrock 
162275c9da8Seschrock /* LINTED - unused */
163275c9da8Seschrock static const ses2_ed_impl_t __ed = { 0 };
164275c9da8Seschrock 
165275c9da8Seschrock #define	ED_REQ_LEN(member)	\
166275c9da8Seschrock 	(offsetof(ses2_ed_impl_t, member) - sizeof (ses2_ed_hdr_impl_t) + \
167275c9da8Seschrock 	    sizeof (__ed.member))
168275c9da8Seschrock 
169275c9da8Seschrock static const struct config_member {
170275c9da8Seschrock 	const char *name;
171275c9da8Seschrock 	size_t minsz;
172275c9da8Seschrock 	int (*func)(const ses2_ed_impl_t *, nvlist_t *, const char *);
173275c9da8Seschrock } config_members[] = {
174275c9da8Seschrock 	{ SES_EN_PROP_EID, 0, enc_eid },
175275c9da8Seschrock 	{ SES_EN_PROP_ESPID, 0, enc_espid },
176275c9da8Seschrock 	{ SES_EN_PROP_NESP, 0, enc_nesp },
177275c9da8Seschrock 	{ SES_EN_PROP_LID, ED_REQ_LEN(st_logical_id), enc_lid },
178275c9da8Seschrock 	{ SES_EN_PROP_VID, ED_REQ_LEN(st_vendor_id), enc_vid },
179275c9da8Seschrock 	{ SES_EN_PROP_PID, ED_REQ_LEN(st_product_id), enc_pid },
180275c9da8Seschrock 	{ SES_EN_PROP_REV, ED_REQ_LEN(st_product_revision), enc_rev },
181275c9da8Seschrock 	{ SES_EN_PROP_VS, ED_REQ_LEN(st_priv), enc_vs },
182275c9da8Seschrock 	{ NULL, 0, NULL }
183275c9da8Seschrock };
184275c9da8Seschrock 
185275c9da8Seschrock int
enc_parse_ed(ses2_ed_impl_t * tp,nvlist_t * nvl)186275c9da8Seschrock enc_parse_ed(ses2_ed_impl_t *tp, nvlist_t *nvl)
187275c9da8Seschrock {
188275c9da8Seschrock 	const struct config_member *mp;
189275c9da8Seschrock 	int err;
190275c9da8Seschrock 
191275c9da8Seschrock 	if (tp == NULL)
192275c9da8Seschrock 		return (0);
193275c9da8Seschrock 
194275c9da8Seschrock 	for (mp = &config_members[0]; mp->name != NULL; mp++) {
195275c9da8Seschrock 		if (mp->func != NULL && tp->st_hdr.sehi_ed_len >= mp->minsz) {
196275c9da8Seschrock 			err = mp->func(tp, nvl, mp->name);
197275c9da8Seschrock 			if (err != 0)
198275c9da8Seschrock 				return (err);
199275c9da8Seschrock 		}
200275c9da8Seschrock 	}
201275c9da8Seschrock 
202275c9da8Seschrock 	return (0);
203275c9da8Seschrock }
204275c9da8Seschrock 
205275c9da8Seschrock ses_target_t *
ses_open_scsi(uint_t version,libscsi_target_t * stp)206275c9da8Seschrock ses_open_scsi(uint_t version, libscsi_target_t *stp)
207275c9da8Seschrock {
208275c9da8Seschrock 	ses_target_t *tp;
209275c9da8Seschrock 	ses_snap_t *sp;
210275c9da8Seschrock 
211275c9da8Seschrock 	if (version != LIBSES_VERSION) {
212275c9da8Seschrock 		(void) ses_set_errno(ESES_VERSION);
213275c9da8Seschrock 		return (NULL);
214275c9da8Seschrock 	}
215275c9da8Seschrock 
216275c9da8Seschrock 	if ((tp = ses_zalloc(sizeof (ses_target_t))) == NULL)
217275c9da8Seschrock 		return (NULL);
218275c9da8Seschrock 
219275c9da8Seschrock 	tp->st_target = stp;
220275c9da8Seschrock 	tp->st_scsi_hdl = libscsi_get_handle(stp);
221275c9da8Seschrock 	tp->st_truncate = (getenv("LIBSES_TRUNCATE") != NULL);
222275c9da8Seschrock 	if (tp->st_truncate)
223275c9da8Seschrock 		srand48(gethrtime());
224275c9da8Seschrock 
225275c9da8Seschrock 	(void) pthread_mutex_init(&tp->st_lock, NULL);
226275c9da8Seschrock 
227275c9da8Seschrock 	if (ses_plugin_load(tp) != 0) {
228275c9da8Seschrock 		ses_close(tp);
229275c9da8Seschrock 		return (NULL);
230275c9da8Seschrock 	}
231275c9da8Seschrock 
232275c9da8Seschrock 	if ((sp = ses_snap_new(tp)) == NULL) {
233275c9da8Seschrock 		ses_close(tp);
234275c9da8Seschrock 		return (NULL);
235275c9da8Seschrock 	}
236275c9da8Seschrock 
237275c9da8Seschrock 	ses_snap_rele(sp);
238275c9da8Seschrock 
239275c9da8Seschrock 	return (tp);
240275c9da8Seschrock }
241275c9da8Seschrock 
242275c9da8Seschrock ses_target_t *
ses_open(uint_t version,const char * target)243275c9da8Seschrock ses_open(uint_t version, const char *target)
244275c9da8Seschrock {
245275c9da8Seschrock 	ses_target_t *tp;
246275c9da8Seschrock 	libscsi_errno_t serr;
247275c9da8Seschrock 	libscsi_target_t *stp;
248275c9da8Seschrock 	libscsi_hdl_t *hp;
249275c9da8Seschrock 
250275c9da8Seschrock 	if ((hp = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
251275c9da8Seschrock 		(void) ses_error(ESES_LIBSCSI, "failed to initialize "
252275c9da8Seschrock 		    "libscsi: %s", libscsi_strerror(serr));
253275c9da8Seschrock 		return (NULL);
254275c9da8Seschrock 	}
255275c9da8Seschrock 
256275c9da8Seschrock 	if ((stp = libscsi_open(hp, NULL, target)) == NULL) {
257275c9da8Seschrock 		(void) ses_libscsi_error(hp, "failed to open SES target");
258275c9da8Seschrock 		libscsi_fini(hp);
259275c9da8Seschrock 		return (NULL);
260275c9da8Seschrock 	}
261275c9da8Seschrock 
262275c9da8Seschrock 	if ((tp = ses_open_scsi(version, stp)) == NULL) {
263275c9da8Seschrock 		libscsi_close(hp, stp);
264275c9da8Seschrock 		libscsi_fini(hp);
265275c9da8Seschrock 		return (NULL);
266275c9da8Seschrock 	}
267275c9da8Seschrock 
268275c9da8Seschrock 	tp->st_closescsi = B_TRUE;
269275c9da8Seschrock 
270275c9da8Seschrock 	return (tp);
271275c9da8Seschrock }
272275c9da8Seschrock 
273275c9da8Seschrock libscsi_target_t *
ses_scsi_target(ses_target_t * tp)274275c9da8Seschrock ses_scsi_target(ses_target_t *tp)
275275c9da8Seschrock {
276275c9da8Seschrock 	return (tp->st_target);
277275c9da8Seschrock }
278275c9da8Seschrock 
279275c9da8Seschrock void
ses_close(ses_target_t * tp)280275c9da8Seschrock ses_close(ses_target_t *tp)
281275c9da8Seschrock {
282275c9da8Seschrock 	if (tp->st_snapshots != NULL)
283275c9da8Seschrock 		ses_snap_rele(tp->st_snapshots);
284275c9da8Seschrock 	if (tp->st_snapshots != NULL)
285275c9da8Seschrock 		ses_panic("attempt to close SES target with active snapshots");
286275c9da8Seschrock 	ses_plugin_unload(tp);
287275c9da8Seschrock 	if (tp->st_closescsi) {
288275c9da8Seschrock 		libscsi_close(tp->st_scsi_hdl, tp->st_target);
289275c9da8Seschrock 		libscsi_fini(tp->st_scsi_hdl);
290275c9da8Seschrock 	}
291275c9da8Seschrock 	ses_free(tp);
292275c9da8Seschrock }
293