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.
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.
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]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/fm/protocol.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>
34 static const topo_pgroup_info_t storage_pgroup
=
35 { TOPO_PGROUP_STORAGE
, TOPO_STABILITY_PRIVATE
,
36 TOPO_STABILITY_PRIVATE
, 1 };
39 pci_di_prop_set(tnode_t
*tn
, di_node_t din
, char *dpnm
, char *tpnm
)
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
);
50 pci_pi_prop_set(tnode_t
*tn
, di_path_t din
, char *dpnm
, char *tpnm
)
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
);
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
)
69 fmri
= topo_mod_hcfmri(mod
, parent
, FM_HC_SCHEME_VERSION
, SCSI_DEVICE
,
70 instance
, NULL
, auth
, NULL
, NULL
, NULL
);
73 child
= topo_node_bind(mod
, parent
, SCSI_DEVICE
, instance
, fmri
);
77 if (topo_pgroup_create(child
, &storage_pgroup
, &e
) < 0)
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
,
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
,
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
);
121 pci_smp_device_create(topo_mod_t
*mod
, nvlist_t
*auth
, tnode_t
*parent
,
122 di_node_t cn
, int instance
)
128 fmri
= topo_mod_hcfmri(mod
, parent
, FM_HC_SCHEME_VERSION
, SMP_DEVICE
,
129 instance
, NULL
, auth
, NULL
, NULL
, NULL
);
132 child
= topo_node_bind(mod
, parent
, SMP_DEVICE
, instance
, fmri
);
136 if (topo_pgroup_create(child
, &storage_pgroup
, &e
) < 0)
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
);
155 pci_iport_device_create(topo_mod_t
*mod
, nvlist_t
*auth
, tnode_t
*parent
,
156 di_node_t cn
, int instance
)
162 fmri
= topo_mod_hcfmri(mod
, parent
, FM_HC_SCHEME_VERSION
, IPORT
,
163 instance
, NULL
, auth
, NULL
, NULL
, NULL
);
166 child
= topo_node_bind(mod
, parent
, IPORT
, instance
, fmri
);
170 if (topo_pgroup_create(child
, &storage_pgroup
, &e
) < 0)
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
);
181 pci_iports_instantiate(topo_mod_t
*mod
, tnode_t
*parent
, di_node_t pn
,
184 di_node_t cn
, smp
, sd
;
190 if (topo_node_range_create(mod
, parent
, IPORT
, 0, niports
) < 0)
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
)) {
196 * First create any iport nodes.
198 if (strcmp(di_node_name(cn
), "iport") != 0)
200 iport
= pci_iport_device_create(mod
, auth
, parent
, cn
, i
++);
205 * Now create any scsi-device nodes.
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)
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
)),
217 if (topo_node_range_create(mod
, iport
, SCSI_DEVICE
, 0, j
) < 0)
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
,
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
)),
229 pci_scsi_device_create(mod
, auth
, iport
,
230 di_path_client_node(pi
), j
++, pi
);
233 * Now create any smp-device nodes.
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)
239 if (topo_node_range_create(mod
, iport
, SMP_DEVICE
, 0, j
) < 0)
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
,
251 pci_receptacle_instantiate(topo_mod_t
*mod
, tnode_t
*parent
, di_node_t pnode
)
253 int err
, i
, rcnt
, lcnt
;
254 char *propstrpm
, *propstrlabel
, *pm
, *label
;
255 nvlist_t
*fmri
, *auth
;
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");
269 topo_mod_dprintf(mod
,
270 "pci_receptacle_instantiate: rececptacle label count %d "
271 "doesn match with phy mask count %d\n", lcnt
, rcnt
);
274 label
= propstrlabel
;
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
);
281 topo_mod_dprintf(mod
, "topo_mod_hcfmri() failed: %s",
282 topo_mod_errmsg(mod
));
285 recep
= topo_node_bind(mod
, parent
, RECEPTACLE
, i
, fmri
);
288 topo_mod_dprintf(mod
, "topo_node_bind() failed: %s",
289 topo_mod_errmsg(mod
));
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",
301 label
= label
+ strlen(label
) + 1;
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
));
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;