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 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 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