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/fm/protocol.h> 27 #include <strings.h> 28 #include <fm/topo_mod.h> 29 #include <sys/scsi/impl/inquiry.h> 30 #include <sys/scsi/impl/scsi_sas.h> 31 #include <sys/scsi/scsi_address.h> 32 #include <did_props.h> 33 34 static const topo_pgroup_info_t storage_pgroup = 35 { TOPO_PGROUP_STORAGE, TOPO_STABILITY_PRIVATE, 36 TOPO_STABILITY_PRIVATE, 1 }; 37 38 void 39 pci_di_prop_set(tnode_t *tn, di_node_t din, char *dpnm, char *tpnm) 40 { 41 int err; 42 char *tmpbuf; 43 44 if (di_prop_lookup_strings(DDI_DEV_T_ANY, din, dpnm, &tmpbuf) == 1) 45 (void) topo_prop_set_string(tn, TOPO_PGROUP_STORAGE, tpnm, 46 TOPO_PROP_IMMUTABLE, tmpbuf, &err); 47 } 48 49 void 50 pci_pi_prop_set(tnode_t *tn, di_path_t din, char *dpnm, char *tpnm) 51 { 52 int err; 53 char *tmpbuf; 54 55 if (di_path_prop_lookup_strings(din, dpnm, &tmpbuf) == 1) 56 (void) topo_prop_set_string(tn, TOPO_PGROUP_STORAGE, tpnm, 57 TOPO_PROP_IMMUTABLE, tmpbuf, &err); 58 } 59 60 static void 61 pci_scsi_device_create(topo_mod_t *mod, nvlist_t *auth, tnode_t *parent, 62 di_node_t cn, int instance, di_path_t pi) 63 { 64 tnode_t *child; 65 nvlist_t *fmri; 66 int e, *val; 67 int64_t *val64; 68 69 fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, SCSI_DEVICE, 70 instance, NULL, auth, NULL, NULL, NULL); 71 if (fmri == NULL) 72 return; 73 child = topo_node_bind(mod, parent, SCSI_DEVICE, instance, fmri); 74 nvlist_free(fmri); 75 if (child == NULL) 76 return; 77 if (topo_pgroup_create(child, &storage_pgroup, &e) < 0) 78 return; 79 if (pi != NULL) { 80 pci_pi_prop_set(child, pi, SCSI_ADDR_PROP_TARGET_PORT, 81 TOPO_STORAGE_TARGET_PORT); 82 pci_pi_prop_set(child, pi, SCSI_ADDR_PROP_ATTACHED_PORT, 83 TOPO_STORAGE_ATTACHED_PORT); 84 pci_pi_prop_set(child, pi, SCSI_ADDR_PROP_TARGET_PORT_PM, 85 TOPO_STORAGE_TARGET_PORT_PM); 86 pci_pi_prop_set(child, pi, SCSI_ADDR_PROP_ATTACHED_PORT_PM, 87 TOPO_STORAGE_ATTACHED_PORT_PM); 88 if (di_path_prop_lookup_int64s(pi, 89 SCSI_ADDR_PROP_LUN64, &val64) == 1) 90 (void) topo_prop_set_int64(child, TOPO_PGROUP_STORAGE, 91 TOPO_STORAGE_LUN64, TOPO_PROP_IMMUTABLE, *val64, 92 &e); 93 } else { 94 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_TARGET_PORT, 95 TOPO_STORAGE_TARGET_PORT); 96 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_ATTACHED_PORT, 97 TOPO_STORAGE_ATTACHED_PORT); 98 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_TARGET_PORT_PM, 99 TOPO_STORAGE_TARGET_PORT_PM); 100 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_ATTACHED_PORT_PM, 101 TOPO_STORAGE_ATTACHED_PORT_PM); 102 if (di_prop_lookup_int64(DDI_DEV_T_ANY, cn, 103 SCSI_ADDR_PROP_LUN64, &val64) == 1) 104 (void) topo_prop_set_int64(child, TOPO_PGROUP_STORAGE, 105 TOPO_STORAGE_LUN64, TOPO_PROP_IMMUTABLE, *val64, 106 &e); 107 } 108 pci_di_prop_set(child, cn, DEVID_PROP_NAME, TOPO_STORAGE_DEVID); 109 pci_di_prop_set(child, cn, INQUIRY_VENDOR_ID, 110 TOPO_STORAGE_MANUFACTURER); 111 pci_di_prop_set(child, cn, INQUIRY_PRODUCT_ID, TOPO_STORAGE_MODEL); 112 pci_di_prop_set(child, cn, INQUIRY_REVISION_ID, 113 TOPO_STORAGE_FIRMWARE_REV); 114 if (di_prop_lookup_ints(DDI_DEV_T_ANY, cn, 115 INQUIRY_DEVICE_TYPE, &val) == 1) 116 (void) topo_prop_set_int32(child, TOPO_PGROUP_STORAGE, 117 TOPO_STORAGE_DEVICE_TYPE, TOPO_PROP_IMMUTABLE, *val, &e); 118 } 119 120 static void 121 pci_smp_device_create(topo_mod_t *mod, nvlist_t *auth, tnode_t *parent, 122 di_node_t cn, int instance) 123 { 124 tnode_t *child; 125 nvlist_t *fmri; 126 int e; 127 128 fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, SMP_DEVICE, 129 instance, NULL, auth, NULL, NULL, NULL); 130 if (fmri == NULL) 131 return; 132 child = topo_node_bind(mod, parent, SMP_DEVICE, instance, fmri); 133 nvlist_free(fmri); 134 if (child == NULL) 135 return; 136 if (topo_pgroup_create(child, &storage_pgroup, &e) < 0) 137 return; 138 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_TARGET_PORT, 139 TOPO_STORAGE_TARGET_PORT); 140 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_ATTACHED_PORT, 141 TOPO_STORAGE_ATTACHED_PORT); 142 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_TARGET_PORT_PM, 143 TOPO_STORAGE_TARGET_PORT_PM); 144 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_ATTACHED_PORT_PM, 145 TOPO_STORAGE_ATTACHED_PORT_PM); 146 pci_di_prop_set(child, cn, DEVID_PROP_NAME, TOPO_STORAGE_DEVID); 147 pci_di_prop_set(child, cn, INQUIRY_VENDOR_ID, 148 TOPO_STORAGE_MANUFACTURER); 149 pci_di_prop_set(child, cn, INQUIRY_PRODUCT_ID, TOPO_STORAGE_MODEL); 150 pci_di_prop_set(child, cn, INQUIRY_REVISION_ID, 151 TOPO_STORAGE_FIRMWARE_REV); 152 } 153 154 static tnode_t * 155 pci_iport_device_create(topo_mod_t *mod, nvlist_t *auth, tnode_t *parent, 156 di_node_t cn, int instance) 157 { 158 tnode_t *child; 159 nvlist_t *fmri; 160 int e; 161 162 fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, IPORT, 163 instance, NULL, auth, NULL, NULL, NULL); 164 if (fmri == NULL) 165 return (NULL); 166 child = topo_node_bind(mod, parent, IPORT, instance, fmri); 167 nvlist_free(fmri); 168 if (child == NULL) 169 return (NULL); 170 if (topo_pgroup_create(child, &storage_pgroup, &e) < 0) 171 return (child); 172 pci_di_prop_set(child, cn, SCSI_ADDR_PROP_INITIATOR_PORT, 173 TOPO_STORAGE_INITIATOR_PORT); 174 (void) topo_prop_set_string(child, TOPO_PGROUP_STORAGE, 175 TOPO_STORAGE_INITIATOR_PORT_PM, TOPO_PROP_IMMUTABLE, 176 di_bus_addr(cn), &e); 177 return (child); 178 } 179 180 void 181 pci_iports_instantiate(topo_mod_t *mod, tnode_t *parent, di_node_t pn, 182 int niports) 183 { 184 di_node_t cn, smp, sd; 185 di_path_t pi; 186 tnode_t *iport; 187 int i, j; 188 nvlist_t *auth; 189 190 if (topo_node_range_create(mod, parent, IPORT, 0, niports) < 0) 191 return; 192 auth = topo_mod_auth(mod, parent); 193 for (i = 0, cn = di_child_node(pn); cn != DI_NODE_NIL; 194 cn = di_sibling_node(cn)) { 195 /* 196 * First create any iport nodes. 197 */ 198 if (strcmp(di_node_name(cn), "iport") != 0) 199 continue; 200 iport = pci_iport_device_create(mod, auth, parent, cn, i++); 201 if (iport == NULL) 202 continue; 203 204 /* 205 * Now create any scsi-device nodes. 206 */ 207 for (j = 0, sd = di_child_node(cn); sd != DI_NODE_NIL; 208 sd = di_sibling_node(sd)) 209 if (strcmp(di_node_name(sd), "smp") != 0) 210 j++; 211 for (pi = di_path_phci_next_path(cn, DI_PATH_NIL); 212 pi != DI_PATH_NIL; pi = di_path_phci_next_path(cn, pi)) 213 if (di_path_client_node(pi) != NULL && 214 strcmp(di_node_name(di_path_client_node(pi)), 215 "smp") != 0) 216 j++; 217 if (topo_node_range_create(mod, iport, SCSI_DEVICE, 0, j) < 0) 218 continue; 219 for (j = 0, sd = di_child_node(cn); sd != DI_NODE_NIL; 220 sd = di_sibling_node(sd)) 221 if (strcmp(di_node_name(sd), "smp") != 0) 222 pci_scsi_device_create(mod, auth, iport, sd, 223 j++, NULL); 224 for (pi = di_path_phci_next_path(cn, DI_PATH_NIL); 225 pi != DI_PATH_NIL; pi = di_path_phci_next_path(cn, pi)) 226 if (di_path_client_node(pi) != NULL && 227 strcmp(di_node_name(di_path_client_node(pi)), 228 "smp") != 0) 229 pci_scsi_device_create(mod, auth, iport, 230 di_path_client_node(pi), j++, pi); 231 232 /* 233 * Now create any smp-device nodes. 234 */ 235 for (j = 0, smp = di_child_node(cn); smp != DI_NODE_NIL; 236 smp = di_sibling_node(smp)) 237 if (strcmp(di_node_name(smp), "smp") == 0) 238 j++; 239 if (topo_node_range_create(mod, iport, SMP_DEVICE, 0, j) < 0) 240 continue; 241 for (j = 0, smp = di_child_node(cn); smp != DI_NODE_NIL; 242 smp = di_sibling_node(smp)) 243 if (strcmp(di_node_name(smp), "smp") == 0) 244 pci_smp_device_create(mod, auth, iport, smp, 245 j++); 246 } 247 nvlist_free(auth); 248 } 249 250 void 251 pci_receptacle_instantiate(topo_mod_t *mod, tnode_t *parent, di_node_t pnode) 252 { 253 int err, i, rcnt, lcnt; 254 char *propstrpm, *propstrlabel, *pm, *label; 255 nvlist_t *fmri, *auth; 256 tnode_t *recep; 257 258 rcnt = di_prop_lookup_strings(DDI_DEV_T_ANY, pnode, 259 DI_RECEPTACLE_PHYMASK, &propstrpm); 260 if ((lcnt = di_prop_lookup_strings(DDI_DEV_T_ANY, pnode, 261 DI_RECEPTACLE_LABEL, &propstrlabel)) <= 0) { 262 topo_mod_dprintf(mod, 263 "pci_receptacle_instanciate: rececptacle label not " 264 "found for the pci function node.\n"); 265 return; 266 } 267 268 if (rcnt != lcnt) { 269 topo_mod_dprintf(mod, 270 "pci_receptacle_instantiate: rececptacle label count %d " 271 "doesn match with phy mask count %d\n", lcnt, rcnt); 272 } 273 274 label = propstrlabel; 275 pm = propstrpm; 276 auth = topo_mod_auth(mod, parent); 277 for (i = 0; i < rcnt; i++) { 278 fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, 279 RECEPTACLE, i, NULL, auth, NULL, NULL, NULL); 280 if (fmri == NULL) { 281 topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s", 282 topo_mod_errmsg(mod)); 283 continue; 284 } 285 recep = topo_node_bind(mod, parent, RECEPTACLE, i, fmri); 286 nvlist_free(fmri); 287 if (recep == NULL) { 288 topo_mod_dprintf(mod, "topo_node_bind() failed: %s", 289 topo_mod_errmsg(mod)); 290 continue; 291 } 292 293 if (label) { 294 if (topo_node_label_set(recep, label, &err) < 0) { 295 topo_mod_dprintf(mod, 296 "topo_receptacle_instantiate: " 297 "topo_node_label_set error(%s)\n", 298 topo_strerror(err)); 299 } 300 if (i < lcnt) { 301 label = label + strlen(label) + 1; 302 } else { 303 label = NULL; 304 } 305 } 306 307 if (topo_pgroup_create(recep, &storage_pgroup, &err) < 0) { 308 topo_mod_dprintf(mod, "ses_set_expander_props: " 309 "create storage error %s\n", topo_strerror(err)); 310 continue; 311 } 312 (void) topo_prop_set_string(recep, TOPO_PGROUP_STORAGE, 313 TOPO_STORAGE_SAS_PHY_MASK, 314 TOPO_PROP_IMMUTABLE, pm, &err); 315 pm = pm + strlen(pm) + 1; 316 } 317 318 nvlist_free(auth); 319 } 320