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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <sys/scsi/impl/spc3_types.h>
27
28 #include <stddef.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <libnvpair.h>
32
33 #include <scsi/libses.h>
34 #include <scsi/libses_plugin.h>
35 #include <scsi/plugins/ses/framework/ses2.h>
36 #include <scsi/plugins/ses/framework/ses2_impl.h>
37 #include <scsi/plugins/ses/framework/libses.h>
38 #include <scsi/plugins/ses/vendor/sun.h>
39 #include <scsi/plugins/ses/vendor/sun_impl.h>
40
41 /*ARGSUSED*/
42 static int
enc_parse_feature_block(ses_plugin_t * sp,ses_node_t * np)43 enc_parse_feature_block(ses_plugin_t *sp, ses_node_t *np)
44 {
45 sun_feature_block_impl_t *sfbip;
46 nvlist_t *encprops;
47 uint8_t *vsp;
48 uint_t vsp_len;
49 uint_t cid_off, cid_len;
50 uint16_t revision;
51 uint64_t chunk;
52 int nverr;
53
54 encprops = ses_node_props(np);
55 if (nvlist_lookup_byte_array(encprops, SES_EN_PROP_VS,
56 &vsp, &vsp_len) != 0 ||
57 vsp_len < offsetof(sun_feature_block_impl_t, _reserved2))
58 return (0);
59
60 sfbip = (sun_feature_block_impl_t *)vsp;
61
62 if (strncmp((char *)sfbip->sfbi_spms_header, "SPMS", 4) != 0 ||
63 sfbip->sfbi_spms_major_ver != 1)
64 return (0);
65
66 revision = SCSI_READ16(&sfbip->sfbi_spms_revision);
67
68 /*
69 * The offset read from the Sun Feature Block needs to be adjusted
70 * so that the difference in the sizes of the Enclosure
71 * Descriptor and the INQUIRY data format is accounted for.
72 */
73 cid_len = sfbip->sfbi_chassis_id_len;
74
75 if (sfbip->sfbi_chassis_id_off >= 96 && cid_len >= 4) {
76 cid_off = sfbip->sfbi_chassis_id_off -
77 (sizeof (ses2_ed_impl_t) - 1);
78 cid_off += offsetof(ses2_ed_impl_t, st_priv[0]) -
79 offsetof(spc3_inquiry_data_t, id_vs_36[0]);
80
81 if (cid_off + cid_len <= vsp_len) {
82 SES_NV_ADD(fixed_string, nverr, encprops,
83 LIBSES_EN_PROP_CSN, (char *)(vsp + cid_off),
84 cid_len);
85 }
86 }
87
88 if (revision >= 104) {
89 SES_NV_ADD(boolean_value, nverr, encprops,
90 LIBSES_EN_PROP_INTERNAL, sfbip->sfbi_int);
91 }
92
93 if (revision >= 105) {
94 if (sfbip->sfbi_fw_upload_max_chunk_sz == 0)
95 chunk = 512;
96 else if (sfbip->sfbi_fw_upload_max_chunk_sz == 0x7f)
97 chunk = 65536;
98 else
99 chunk = 512 * sfbip->sfbi_fw_upload_max_chunk_sz;
100
101 SES_NV_ADD(uint64, nverr, encprops,
102 LIBSES_EN_PROP_FIRMWARE_CHUNK_SIZE, chunk);
103 }
104
105 /*
106 * If this is a subchassis, it will have a subchassis index field
107 * with a value other than 0. See SPMS-1r111 4.1.3.1. If not, we
108 * will see 0 and will not create the subchassis member at all; note
109 * that this is backward-compatible with pre-111 implementations that
110 * treated this as a reserved field. No such implementation contains
111 * a subchassis.
112 */
113 if (sfbip->sfbi_spms_revision >= 111 &&
114 sfbip->sfbi_subchassis_index != 0) {
115 SES_NV_ADD(uint64, nverr, encprops,
116 LIBSES_EN_PROP_SUBCHASSIS_ID,
117 sfbip->sfbi_subchassis_index - 1);
118 }
119
120 return (0);
121 }
122
123 int
sun_fill_enclosure_node(ses_plugin_t * sp,ses_node_t * np)124 sun_fill_enclosure_node(ses_plugin_t *sp, ses_node_t *np)
125 {
126 ses_snap_t *snap = ses_node_snapshot(np);
127 nvlist_t *props = ses_node_props(np);
128 sun_fru_descr_impl_t *sfdi;
129 int err;
130 size_t len;
131
132 if ((err = enc_parse_feature_block(sp, np)) != 0)
133 return (err);
134
135 if ((sfdi = ses_plugin_page_lookup(sp, snap,
136 SUN_DIAGPAGE_FRUID, np, &len)) != NULL) {
137 if ((err = sun_fruid_parse_common(sfdi, props)) != 0)
138 return (err);
139 }
140
141 return (0);
142 }
143