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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <scsi/libses.h>
27 #include "ses_impl.h"
28
29 #define NEXT_ED(eip) \
30 ((ses2_ed_impl_t *)((uint8_t *)(eip) + \
31 ((eip)->st_hdr.sehi_ed_len + sizeof (ses2_ed_hdr_impl_t))))
32
33 static ses_node_t *
34 ses_find_enclosure(ses_snap_t *sp, uint64_t number)
35 {
36 ses_node_t *np;
37
38 for (np = sp->ss_root->sn_first_child; np != NULL;
39 np = np->sn_next_sibling) {
40 ASSERT(np->sn_type == SES_NODE_ENCLOSURE);
41 if (np->sn_enc_num == number)
42 return ((ses_node_t *)np);
43 }
151 pip = (ses2_config_page_impl_t *)pp->ssp_page;
152
153 if (pp->ssp_len < offsetof(ses2_config_page_impl_t, scpi_data))
154 return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
155 "descriptors found"));
156
157 /*
158 * Start with the root of the tree, which is a target node, containing
159 * just the SCSI inquiry properties.
160 */
161 if ((root = ses_node_alloc(sp, sp->ss_root)) == NULL)
162 return (-1);
163
164 root->sn_type = SES_NODE_TARGET;
165 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_VENDOR,
166 libscsi_vendor(sp->ss_target->st_target));
167 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_PRODUCT,
168 libscsi_product(sp->ss_target->st_target));
169 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_REVISION,
170 libscsi_revision(sp->ss_target->st_target));
171
172 for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
173 i < pip->scpi_n_subenclosures + 1;
174 i++, eip = NEXT_ED(eip)) {
175 if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
176 break;
177
178 n_etds += eip->st_hdr.sehi_n_etd_hdrs;
179 }
180 ftip = (ses2_td_hdr_impl_t *)eip;
181
182 /*
183 * There should really be only one Enclosure element possible for a
184 * give subenclosure ID. The standard never comes out and says this,
185 * but it does describe this element as "managing the enclosure itself"
186 * which implies rather strongly that the subenclosure ID field is that
187 * of, well, the enclosure itself. Since an enclosure can't contain
188 * itself, it follows logically that each subenclosure has at most one
189 * Enclosure type descriptor elements matching its ID. Of course, some
190 * enclosure firmware is buggy, so this may not always work out; in
193 */
194 for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
195 i < pip->scpi_n_subenclosures + 1;
196 i++, eip = NEXT_ED(eip)) {
197 if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
198 break;
199
200 if ((np = ses_node_alloc(sp, root)) == NULL)
201 return (-1);
202
203 np->sn_type = SES_NODE_ENCLOSURE;
204 np->sn_enc_num = eip->st_hdr.sehi_subenclosure_id;
205
206 if (!SES_WITHIN_PAGE(eip, eip->st_hdr.sehi_ed_len +
207 sizeof (ses2_ed_hdr_impl_t),
208 pp->ssp_page, pp->ssp_len))
209 break;
210
211 if (enc_parse_ed(eip, np->sn_props) != 0)
212 return (-1);
213 }
214
215 if (root->sn_first_child == NULL)
216 return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
217 "descriptors found"));
218
219 tp = (char *)(ftip + n_etds);
220
221 for (i = 0, toff = 0, idx = eidx = 0; i < n_etds; i++) {
222 tip = ftip + i;
223
224 if (!SES_WITHIN_PAGE_STRUCT(tip, pp->ssp_page, pp->ssp_len))
225 break;
226
227 pnp = ses_find_enclosure(sp,
228 tip->sthi_subenclosure_id);
229 if (pnp == NULL) {
230 idx += tip->sthi_max_elements + 1;
231 eidx += tip->sthi_max_elements;
232 toff += tip->sthi_text_len;
|
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <scsi/libses.h>
28 #include "ses_impl.h"
29
30 #define NEXT_ED(eip) \
31 ((ses2_ed_impl_t *)((uint8_t *)(eip) + \
32 ((eip)->st_hdr.sehi_ed_len + sizeof (ses2_ed_hdr_impl_t))))
33
34 static ses_node_t *
35 ses_find_enclosure(ses_snap_t *sp, uint64_t number)
36 {
37 ses_node_t *np;
38
39 for (np = sp->ss_root->sn_first_child; np != NULL;
40 np = np->sn_next_sibling) {
41 ASSERT(np->sn_type == SES_NODE_ENCLOSURE);
42 if (np->sn_enc_num == number)
43 return ((ses_node_t *)np);
44 }
152 pip = (ses2_config_page_impl_t *)pp->ssp_page;
153
154 if (pp->ssp_len < offsetof(ses2_config_page_impl_t, scpi_data))
155 return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
156 "descriptors found"));
157
158 /*
159 * Start with the root of the tree, which is a target node, containing
160 * just the SCSI inquiry properties.
161 */
162 if ((root = ses_node_alloc(sp, sp->ss_root)) == NULL)
163 return (-1);
164
165 root->sn_type = SES_NODE_TARGET;
166 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_VENDOR,
167 libscsi_vendor(sp->ss_target->st_target));
168 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_PRODUCT,
169 libscsi_product(sp->ss_target->st_target));
170 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_REVISION,
171 libscsi_revision(sp->ss_target->st_target));
172 if (libscsi_usn(sp->ss_target->st_target) != NULL)
173 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_USN,
174 libscsi_usn(sp->ss_target->st_target));
175 if (libscsi_lid(sp->ss_target->st_target) != NULL)
176 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_LID,
177 libscsi_lid(sp->ss_target->st_target));
178
179 for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
180 i < pip->scpi_n_subenclosures + 1;
181 i++, eip = NEXT_ED(eip)) {
182 if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
183 break;
184
185 n_etds += eip->st_hdr.sehi_n_etd_hdrs;
186 }
187 ftip = (ses2_td_hdr_impl_t *)eip;
188
189 /*
190 * There should really be only one Enclosure element possible for a
191 * give subenclosure ID. The standard never comes out and says this,
192 * but it does describe this element as "managing the enclosure itself"
193 * which implies rather strongly that the subenclosure ID field is that
194 * of, well, the enclosure itself. Since an enclosure can't contain
195 * itself, it follows logically that each subenclosure has at most one
196 * Enclosure type descriptor elements matching its ID. Of course, some
197 * enclosure firmware is buggy, so this may not always work out; in
200 */
201 for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
202 i < pip->scpi_n_subenclosures + 1;
203 i++, eip = NEXT_ED(eip)) {
204 if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
205 break;
206
207 if ((np = ses_node_alloc(sp, root)) == NULL)
208 return (-1);
209
210 np->sn_type = SES_NODE_ENCLOSURE;
211 np->sn_enc_num = eip->st_hdr.sehi_subenclosure_id;
212
213 if (!SES_WITHIN_PAGE(eip, eip->st_hdr.sehi_ed_len +
214 sizeof (ses2_ed_hdr_impl_t),
215 pp->ssp_page, pp->ssp_len))
216 break;
217
218 if (enc_parse_ed(eip, np->sn_props) != 0)
219 return (-1);
220
221 if (libscsi_usn(sp->ss_target->st_target) != NULL)
222 SES_NV_ADD(string, err, np->sn_props, SCSI_PROP_USN,
223 libscsi_usn(sp->ss_target->st_target));
224
225 if (libscsi_lid(sp->ss_target->st_target) != NULL)
226 SES_NV_ADD(string, err, np->sn_props, SCSI_PROP_LID,
227 libscsi_lid(sp->ss_target->st_target));
228 }
229
230 if (root->sn_first_child == NULL)
231 return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
232 "descriptors found"));
233
234 tp = (char *)(ftip + n_etds);
235
236 for (i = 0, toff = 0, idx = eidx = 0; i < n_etds; i++) {
237 tip = ftip + i;
238
239 if (!SES_WITHIN_PAGE_STRUCT(tip, pp->ssp_page, pp->ssp_len))
240 break;
241
242 pnp = ses_find_enclosure(sp,
243 tip->sthi_subenclosure_id);
244 if (pnp == NULL) {
245 idx += tip->sthi_max_elements + 1;
246 eidx += tip->sthi_max_elements;
247 toff += tip->sthi_text_len;
|