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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
32 #include <sys/types.h>
35 #include <sys/fm/protocol.h>
36 #include <fm/topo_mod.h>
37 #include <fm/topo_hc.h>
38 #include <libdevinfo.h>
39 #include <hostbridge.h>
42 #include <did_props.h>
43 #include <fm/libtopo.h>
45 static int ASRU_set(tnode_t
*, did_t
*,
46 const char *, const char *, const char *);
47 static int FRU_set(tnode_t
*, did_t
*,
48 const char *, const char *, const char *);
49 static int DEVprop_set(tnode_t
*, did_t
*,
50 const char *, const char *, const char *);
51 static int DRIVERprop_set(tnode_t
*, did_t
*,
52 const char *, const char *, const char *);
53 static int MODULEprop_set(tnode_t
*, did_t
*,
54 const char *, const char *, const char *);
55 static int EXCAP_set(tnode_t
*, did_t
*,
56 const char *, const char *, const char *);
57 static int BDF_set(tnode_t
*, did_t
*,
58 const char *, const char *, const char *);
59 static int label_set(tnode_t
*, did_t
*,
60 const char *, const char *, const char *);
61 static int maybe_di_chars_copy(tnode_t
*, did_t
*,
62 const char *, const char *, const char *);
63 static int maybe_di_uint_to_str(tnode_t
*, did_t
*,
64 const char *, const char *, const char *);
65 static int maybe_di_uint_to_dec_str(tnode_t
*, did_t
*,
66 const char *, const char *, const char *);
67 static int AADDR_set(tnode_t
*, did_t
*,
68 const char *, const char *, const char *);
71 * Arrays of "property translation routines" to set the properties a
72 * given type of topology node should have.
74 * Note that the label_set translation *MUST COME BEFORE* the FRU
75 * translation. For the near term we're setting the FRU fmri to
76 * be a legacy-hc style FMRI based on the label, so the label needs
77 * to have been set before we do the FRU translation.
81 static const topo_pgroup_info_t io_pgroup
=
82 { TOPO_PGROUP_IO
, TOPO_STABILITY_PRIVATE
, TOPO_STABILITY_PRIVATE
, 1 };
83 static const topo_pgroup_info_t pci_pgroup
=
84 { TOPO_PGROUP_PCI
, TOPO_STABILITY_PRIVATE
, TOPO_STABILITY_PRIVATE
, 1 };
86 static const topo_pgroup_info_t protocol_pgroup
= {
88 TOPO_STABILITY_PRIVATE
,
89 TOPO_STABILITY_PRIVATE
,
91 }; /* Request to create protocol will be ignored by libtopo */
93 txprop_t Fn_common_props
[] = {
94 { NULL
, &io_pgroup
, TOPO_IO_DEV
, DEVprop_set
},
95 { DI_DEVTYPPROP
, &io_pgroup
, TOPO_IO_DEVTYPE
, maybe_di_chars_copy
},
96 { DI_DEVIDPROP
, &pci_pgroup
, TOPO_PCI_DEVID
, maybe_di_uint_to_str
},
97 { NULL
, &io_pgroup
, TOPO_IO_DRIVER
, DRIVERprop_set
},
98 { NULL
, &io_pgroup
, TOPO_IO_MODULE
, MODULEprop_set
},
99 { "serd_io_device_nonfatal_n", &io_pgroup
, "serd_io_device_nonfatal_n",
100 maybe_di_uint_to_dec_str
},
101 { "serd_io_device_nonfatal_t", &io_pgroup
, "serd_io_device_nonfatal_t",
102 maybe_di_chars_copy
},
103 { "serd_io_device_nonfatal_btlp_n", &io_pgroup
,
104 "serd_io_device_nonfatal_btlp_n", maybe_di_uint_to_dec_str
},
105 { "serd_io_device_nonfatal_btlp_t", &io_pgroup
,
106 "serd_io_device_nonfatal_btlp_t", maybe_di_chars_copy
},
107 { "serd_io_device_nonfatal_bdllp_n", &io_pgroup
,
108 "serd_io_device_nonfatal_bdllp_n", maybe_di_uint_to_dec_str
},
109 { "serd_io_device_nonfatal_bdllp_t", &io_pgroup
,
110 "serd_io_device_nonfatal_bdllp_t", maybe_di_chars_copy
},
111 { "serd_io_device_nonfatal_re_n", &io_pgroup
,
112 "serd_io_device_nonfatal_re_n", maybe_di_uint_to_dec_str
},
113 { "serd_io_device_nonfatal_re_t", &io_pgroup
,
114 "serd_io_device_nonfatal_re_t", maybe_di_chars_copy
},
115 { "serd_io_device_nonfatal_rto_n", &io_pgroup
,
116 "serd_io_device_nonfatal_rto_n", maybe_di_uint_to_dec_str
},
117 { "serd_io_device_nonfatal_rto_t", &io_pgroup
,
118 "serd_io_device_nonfatal_rto_t", maybe_di_chars_copy
},
119 { "serd_io_device_nonfatal_rnr_n", &io_pgroup
,
120 "serd_io_device_nonfatal_rnr_n", maybe_di_uint_to_dec_str
},
121 { "serd_io_device_nonfatal_rnr_t", &io_pgroup
,
122 "serd_io_pciex_corrlink-bus_rnr_t", maybe_di_chars_copy
},
123 { "serd_io_pciex_corrlink-bus_btlp_n", &io_pgroup
,
124 "serd_io_pciex_corrlink-bus_btlp_n", maybe_di_uint_to_dec_str
},
125 { "serd_io_pciex_corrlink-bus_btlp_t", &io_pgroup
,
126 "serd_io_pciex_corrlink-bus_btlp_t", maybe_di_chars_copy
},
127 { "serd_io_pciex_corrlink-bus_bdllp_n", &io_pgroup
,
128 "serd_io_pciex_corrlink-bus_bdllp_n", maybe_di_uint_to_dec_str
},
129 { "serd_io_pciex_corrlink-bus_bdllp_t", &io_pgroup
,
130 "serd_io_pciex_corrlink-bus_bdllp_t", maybe_di_chars_copy
},
131 { "serd_io_pciex_corrlink-bus_re_n", &io_pgroup
,
132 "serd_io_pciex_corrlink-bus_re_n", maybe_di_uint_to_dec_str
},
133 { "serd_io_pciex_corrlink-bus_re_t", &io_pgroup
,
134 "serd_io_pciex_corrlink-bus_re_t", maybe_di_chars_copy
},
135 { "serd_io_pciex_corrlink-bus_rto_n", &io_pgroup
,
136 "serd_io_pciex_corrlink-bus_rto_n", maybe_di_uint_to_dec_str
},
137 { "serd_io_pciex_corrlink-bus_rto_t", &io_pgroup
,
138 "serd_io_pciex_corrlink-bus_rto_t", maybe_di_chars_copy
},
139 { "serd_io_pciex_corrlink-bus_rnr_n", &io_pgroup
,
140 "serd_io_pciex_corrlink-bus_rnr_n", maybe_di_uint_to_dec_str
},
141 { "serd_io_pciex_corrlink-bus_rnr_t", &io_pgroup
,
142 "serd_io_pciex_corrlink-bus_rnr_t", maybe_di_chars_copy
},
143 { NULL
, &pci_pgroup
, TOPO_PCI_EXCAP
, EXCAP_set
},
144 { DI_CLASSPROP
, &pci_pgroup
, TOPO_PCI_CLASS
, maybe_di_uint_to_str
},
145 { DI_VENDIDPROP
, &pci_pgroup
, TOPO_PCI_VENDID
, maybe_di_uint_to_str
},
146 { DI_AADDRPROP
, &pci_pgroup
, TOPO_PCI_AADDR
, AADDR_set
},
147 { NULL
, &protocol_pgroup
, TOPO_PROP_LABEL
, label_set
},
148 { NULL
, &protocol_pgroup
, TOPO_PROP_FRU
, FRU_set
},
149 { NULL
, &protocol_pgroup
, TOPO_PROP_ASRU
, ASRU_set
}
152 txprop_t Dev_common_props
[] = {
153 { NULL
, &protocol_pgroup
, TOPO_PROP_LABEL
, label_set
},
154 { NULL
, &protocol_pgroup
, TOPO_PROP_FRU
, FRU_set
},
155 { NULL
, &protocol_pgroup
, TOPO_PROP_ASRU
, ASRU_set
}
158 txprop_t Bus_common_props
[] = {
159 { DI_DEVTYPPROP
, &io_pgroup
, TOPO_IO_DEVTYPE
, maybe_di_chars_copy
},
160 { NULL
, &io_pgroup
, TOPO_IO_DRIVER
, DRIVERprop_set
},
161 { NULL
, &io_pgroup
, TOPO_IO_MODULE
, MODULEprop_set
},
162 { NULL
, &protocol_pgroup
, TOPO_PROP_LABEL
, label_set
},
163 { NULL
, &protocol_pgroup
, TOPO_PROP_FRU
, FRU_set
},
164 { NULL
, &protocol_pgroup
, TOPO_PROP_ASRU
, ASRU_set
}
167 txprop_t RC_common_props
[] = {
168 { NULL
, &io_pgroup
, TOPO_IO_DEV
, DEVprop_set
},
169 { DI_DEVTYPPROP
, &io_pgroup
, TOPO_IO_DEVTYPE
, maybe_di_chars_copy
},
170 { NULL
, &io_pgroup
, TOPO_IO_DRIVER
, DRIVERprop_set
},
171 { NULL
, &io_pgroup
, TOPO_IO_MODULE
, MODULEprop_set
},
172 { NULL
, &pci_pgroup
, TOPO_PCI_EXCAP
, EXCAP_set
},
173 { NULL
, &pci_pgroup
, TOPO_PCI_BDF
, BDF_set
},
174 { NULL
, &protocol_pgroup
, TOPO_PROP_ASRU
, ASRU_set
},
176 * These props need to be put at the end of table. x86pi has its
177 * own way to set them.
179 { NULL
, &protocol_pgroup
, TOPO_PROP_LABEL
, label_set
},
180 { NULL
, &protocol_pgroup
, TOPO_PROP_FRU
, FRU_set
}
183 txprop_t ExHB_common_props
[] = {
184 { NULL
, &protocol_pgroup
, TOPO_PROP_ASRU
, ASRU_set
},
186 * These props need to be put at the end of table. x86pi has its
187 * own way to set them.
189 { NULL
, &protocol_pgroup
, TOPO_PROP_LABEL
, label_set
},
190 { NULL
, &protocol_pgroup
, TOPO_PROP_FRU
, FRU_set
}
193 txprop_t IOB_common_props
[] = {
194 { NULL
, &protocol_pgroup
, TOPO_PROP_LABEL
, label_set
},
195 { NULL
, &protocol_pgroup
, TOPO_PROP_FRU
, FRU_set
},
196 { NULL
, &protocol_pgroup
, TOPO_PROP_ASRU
, ASRU_set
}
199 txprop_t HB_common_props
[] = {
200 { NULL
, &io_pgroup
, TOPO_IO_DEV
, DEVprop_set
},
201 { NULL
, &io_pgroup
, TOPO_IO_DRIVER
, DRIVERprop_set
},
202 { NULL
, &io_pgroup
, TOPO_IO_MODULE
, MODULEprop_set
},
203 { NULL
, &protocol_pgroup
, TOPO_PROP_ASRU
, ASRU_set
},
205 * These props need to be put at the end of table. x86pi has its
206 * own way to set them.
208 { NULL
, &protocol_pgroup
, TOPO_PROP_LABEL
, label_set
},
209 { NULL
, &protocol_pgroup
, TOPO_PROP_FRU
, FRU_set
}
212 int Bus_propcnt
= sizeof (Bus_common_props
) / sizeof (txprop_t
);
213 int Dev_propcnt
= sizeof (Dev_common_props
) / sizeof (txprop_t
);
214 int ExHB_propcnt
= sizeof (ExHB_common_props
) / sizeof (txprop_t
);
215 int HB_propcnt
= sizeof (HB_common_props
) / sizeof (txprop_t
);
216 int IOB_propcnt
= sizeof (IOB_common_props
) / sizeof (txprop_t
);
217 int RC_propcnt
= sizeof (RC_common_props
) / sizeof (txprop_t
);
218 int Fn_propcnt
= sizeof (Fn_common_props
) / sizeof (txprop_t
);
221 * If this devinfo node came originally from OBP data, we'll have prom
222 * properties associated with the node where we can find properties of
223 * interest. We ignore anything after the the first four bytes of the
224 * property, and interpet those first four bytes as our unsigned
225 * integer. If we don't find the property or it's not large enough,
226 * 'val' will remained unchanged and we'll return -1. Otherwise 'val'
227 * gets updated with the property value and we return 0.
230 promprop2uint(topo_mod_t
*mod
, di_node_t n
, const char *propnm
, uint_t
*val
)
232 di_prom_handle_t ptp
= DI_PROM_HANDLE_NIL
;
233 di_prom_prop_t pp
= DI_PROM_PROP_NIL
;
236 if ((ptp
= topo_mod_prominfo(mod
)) == DI_PROM_HANDLE_NIL
)
239 while ((pp
= di_prom_prop_next(ptp
, n
, pp
)) != DI_PROM_PROP_NIL
) {
240 if (strcmp(di_prom_prop_name(pp
), propnm
) == 0) {
241 if (di_prom_prop_data(pp
, &buf
) < sizeof (uint_t
))
243 bcopy(buf
, val
, sizeof (uint_t
));
251 * If this devinfo node was added by the PCI hotplug framework it
252 * doesn't have the PROM properties, but hopefully has the properties
253 * we're looking for attached directly to the devinfo node. We only
254 * care about the first four bytes of the property, which we read as
255 * our unsigned integer. The remaining bytes are ignored. If we
256 * don't find the property we're looking for, or can't get its value,
257 * 'val' remains unchanged and we return -1. Otherwise 'val' gets the
258 * property value and we return 0.
261 hwprop2uint(di_node_t n
, const char *propnm
, uint_t
*val
)
263 di_prop_t hp
= DI_PROP_NIL
;
266 while ((hp
= di_prop_next(n
, hp
)) != DI_PROP_NIL
) {
267 if (strcmp(di_prop_name(hp
), propnm
) == 0) {
268 if (di_prop_bytes(hp
, &buf
) < sizeof (uint_t
))
270 bcopy(buf
, val
, sizeof (uint_t
));
278 di_uintprop_get(topo_mod_t
*mod
, di_node_t n
, const char *pnm
, uint_t
*pv
)
280 if (hwprop2uint(n
, pnm
, pv
) < 0)
281 if (promprop2uint(mod
, n
, pnm
, pv
) < 0)
287 di_bytes_get(topo_mod_t
*mod
, di_node_t n
, const char *pnm
, int *sz
,
290 di_prom_handle_t ptp
= DI_PROM_HANDLE_NIL
;
291 di_prom_prop_t pp
= DI_PROM_PROP_NIL
;
292 di_prop_t hp
= DI_PROP_NIL
;
294 if ((ptp
= topo_mod_prominfo(mod
)) == DI_PROM_HANDLE_NIL
)
298 while ((hp
= di_prop_next(n
, hp
)) != DI_PROP_NIL
) {
299 if (strcmp(di_prop_name(hp
), pnm
) == 0) {
300 if ((*sz
= di_prop_bytes(hp
, db
)) < 0)
306 while ((pp
= di_prom_prop_next(ptp
, n
, pp
)) !=
308 if (strcmp(di_prom_prop_name(pp
), pnm
) == 0) {
309 *sz
= di_prom_prop_data(pp
, db
);
323 * fix_dev_prop -- sometimes di_devfs_path() doesn't tell the whole
324 * story, leaving off the device and function number. Chances are if
325 * devfs doesn't put these on then we'll never see this device as an
326 * error detector called out in an ereport. Unfortunately, there are
327 * races and we sometimes do get ereports from devices that devfs
328 * decides aren't there. For example, the error injector card seems
329 * to bounce in and out of existence according to devfs. We tack on
330 * the missing dev and fn here so that the DEV property used to look
331 * up the topology node is correct.
334 dev_path_fix(topo_mod_t
*mp
, char *path
, int devno
, int fnno
)
341 * We only care about the last component of the dev path. If
342 * we don't find a slash, something is weird.
344 lastslash
= strrchr(path
, '/');
345 assert(lastslash
!= NULL
);
348 * If an @ sign is present in the last component, the
349 * di_devfs_path() result had the device,fn unit-address.
350 * In that case there's nothing we need do.
352 if (strchr(lastslash
, '@') != NULL
)
356 need
= snprintf(NULL
, 0, "%s@%x", path
, devno
);
358 need
= snprintf(NULL
, 0, "%s@%x,%x", path
, devno
, fnno
);
361 if ((newpath
= topo_mod_alloc(mp
, need
)) == NULL
) {
362 topo_mod_strfree(mp
, path
);
367 (void) snprintf(newpath
, need
, "%s@%x", path
, devno
);
369 (void) snprintf(newpath
, need
, "%s@%x,%x", path
, devno
, fnno
);
371 topo_mod_strfree(mp
, path
);
376 * dev_for_hostbridge() -- For hostbridges we truncate the devfs path
377 * after the first element in the bus address.
380 dev_for_hostbridge(topo_mod_t
*mp
, char *path
)
387 plen
= strlen(path
) + 1;
390 * We only care about the last component of the dev path. If
391 * we don't find a slash, something is weird.
393 lastslash
= strrchr(path
, '/');
394 assert(lastslash
!= NULL
);
397 * Find the comma in the last component component@x,y, and
398 * truncate the comma and any following number.
400 comma
= strchr(lastslash
, ',');
401 assert(comma
!= NULL
);
404 if ((newpath
= topo_mod_strdup(mp
, path
)) == NULL
) {
405 topo_mod_free(mp
, path
, plen
);
410 topo_mod_free(mp
, path
, plen
);
416 ASRU_set(tnode_t
*tn
, did_t
*pd
,
417 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
421 char *dnpath
, *path
, *fpath
, *nm
;
425 * If this topology node represents a function of device,
426 * set the ASRU to a dev scheme FMRI based on the value of
427 * di_devfs_path(). If that path is NULL, set the ASRU to
428 * be the resource describing this topology node. If this
429 * isn't a function, inherit any ASRU from the parent.
432 nm
= topo_node_name(tn
);
433 if ((strcmp(nm
, PCI_BUS
) == 0 && did_gettnode(pd
) &&
434 strcmp(topo_node_name(did_gettnode(pd
)), HOSTBRIDGE
) == 0) ||
435 strcmp(nm
, PCI_FUNCTION
) == 0 || strcmp(nm
, PCIEX_FUNCTION
) == 0 ||
436 strcmp(nm
, PCIEX_ROOT
) == 0) {
437 if ((dnpath
= di_devfs_path(did_dinode(pd
))) != NULL
) {
439 * Dup the path, dev_path_fix() may replace it and
440 * dev_path_fix() wouldn't know to use
441 * di_devfs_path_free()
443 if ((path
= topo_mod_strdup(mp
, dnpath
)) == NULL
) {
444 di_devfs_path_free(dnpath
);
445 return (topo_mod_seterrno(mp
, EMOD_NOMEM
));
447 di_devfs_path_free(dnpath
);
448 did_BDF(pd
, NULL
, &d
, &f
);
449 if ((fpath
= dev_path_fix(mp
, path
, d
, f
)) == NULL
)
450 return (topo_mod_seterrno(mp
, EMOD_NOMEM
));
452 fmri
= topo_mod_devfmri(mp
, FM_DEV_SCHEME_VERSION
,
456 "dev:///%s fmri creation failed.\n", fpath
);
457 topo_mod_strfree(mp
, fpath
);
460 topo_mod_strfree(mp
, fpath
);
462 topo_mod_dprintf(mp
, "NULL di_devfs_path.\n");
463 if (topo_prop_get_fmri(tn
, TOPO_PGROUP_PROTOCOL
,
464 TOPO_PROP_RESOURCE
, &fmri
, &e
) < 0)
465 return (topo_mod_seterrno(mp
, e
));
467 if (topo_node_asru_set(tn
, fmri
, 0, &e
) < 0) {
469 return (topo_mod_seterrno(mp
, e
));
474 (void) topo_node_asru_set(tn
, NULL
, 0, &e
);
480 * Set the FRU property to the hc fmri of this tnode
483 FRU_fmri_set(topo_mod_t
*mp
, tnode_t
*tn
)
488 if (topo_node_resource(tn
, &fmri
, &err
) < 0 ||
490 topo_mod_dprintf(mp
, "FRU_fmri_set error: %s\n",
491 topo_strerror(topo_mod_errno(mp
)));
492 return (topo_mod_seterrno(mp
, err
));
494 e
= topo_node_fru_set(tn
, fmri
, 0, &err
);
497 return (topo_mod_seterrno(mp
, err
));
502 find_predecessor(tnode_t
*tn
, char *mod_name
)
504 tnode_t
*pnode
= topo_node_parent(tn
);
506 while (pnode
&& (strcmp(topo_node_name(pnode
), mod_name
) != 0)) {
507 pnode
= topo_node_parent(pnode
);
513 use_predecessor_fru(tnode_t
*tn
, char *mod_name
)
515 tnode_t
*pnode
= NULL
;
516 nvlist_t
*fru
= NULL
;
519 if ((pnode
= find_predecessor(tn
, mod_name
)) == NULL
)
521 if ((pnode
= topo_node_parent(pnode
)) == NULL
)
523 if (topo_node_fru(pnode
, &fru
, NULL
, &err
) != 0)
526 (void) topo_node_fru_set(tn
, fru
, 0, &err
);
533 use_predecessor_label(topo_mod_t
*mod
, tnode_t
*tn
, char *mod_name
)
535 tnode_t
*pnode
= NULL
;
539 if ((pnode
= find_predecessor(tn
, mod_name
)) == NULL
)
541 if ((pnode
= topo_node_parent(pnode
)) == NULL
)
543 if (topo_node_label(pnode
, &plabel
, &err
) != 0 || plabel
== NULL
)
546 (void) topo_node_label_set(tn
, plabel
, &err
);
548 topo_mod_strfree(mod
, plabel
);
556 FRU_set(tnode_t
*tn
, did_t
*pd
,
557 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
563 nm
= topo_node_name(tn
);
567 * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
568 * check for a CPUBOARD predecessor. If found, inherit its
569 * parent's FRU. Otherwise, continue with FRU set.
571 if ((strcmp(nm
, PCIEX_BUS
) == 0) &&
572 (strcmp(topo_node_name(topo_node_parent(tn
)), PCIEX_ROOT
) == 0)) {
574 if (use_predecessor_fru(tn
, CPUBOARD
) == 0)
578 * If this topology node represents something other than an
579 * ioboard or a device that implements a slot, inherit the
580 * parent's FRU value. If there is no label, inherit our
581 * parent's FRU value. Otherwise, munge up an fmri based on
584 if (strcmp(nm
, IOBOARD
) != 0 && strcmp(nm
, PCI_DEVICE
) != 0 &&
585 strcmp(nm
, PCIEX_DEVICE
) != 0 && strcmp(nm
, PCIEX_BUS
) != 0) {
586 (void) topo_node_fru_set(tn
, NULL
, 0, &e
);
591 * If ioboard, set fru fmri to hc fmri
593 if (strcmp(nm
, IOBOARD
) == 0) {
594 e
= FRU_fmri_set(mp
, tn
);
596 } else if (strcmp(nm
, PCI_DEVICE
) == 0 ||
597 strcmp(nm
, PCIEX_DEVICE
) == 0 || strcmp(nm
, PCIEX_BUS
) == 0) {
601 if (topo_mod_nvalloc(mp
, &in
, NV_UNIQUE_NAME
) != 0)
602 return (topo_mod_seterrno(mp
, EMOD_FMRI_NVL
));
603 if (nvlist_add_uint64(in
, "nv1", (uintptr_t)pd
) != 0) {
605 return (topo_mod_seterrno(mp
, EMOD_NOMEM
));
607 if (topo_method_invoke(tn
,
608 TOPO_METH_FRU_COMPUTE
, TOPO_METH_FRU_COMPUTE_VERSION
,
609 in
, &out
, &err
) != 0) {
611 return (topo_mod_seterrno(mp
, err
));
614 (void) topo_node_fru_set(tn
, out
, 0, &err
);
617 (void) topo_node_fru_set(tn
, NULL
, 0, &err
);
624 label_set(tnode_t
*tn
, did_t
*pd
,
625 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
634 * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
635 * check for a CPUBOARD predecessor. If found, inherit its
636 * parent's Label. Otherwise, continue with label set.
638 if ((strcmp(topo_node_name(tn
), PCIEX_BUS
) == 0) &&
639 (strcmp(topo_node_name(topo_node_parent(tn
)), PCIEX_ROOT
) == 0)) {
641 if (use_predecessor_label(mp
, tn
, CPUBOARD
) == 0)
644 if (topo_mod_nvalloc(mp
, &in
, NV_UNIQUE_NAME
) != 0)
645 return (topo_mod_seterrno(mp
, EMOD_FMRI_NVL
));
646 if (nvlist_add_uint64(in
, TOPO_METH_LABEL_ARG_NVL
, (uintptr_t)pd
) !=
649 return (topo_mod_seterrno(mp
, EMOD_NOMEM
));
651 if (topo_method_invoke(tn
,
652 TOPO_METH_LABEL
, TOPO_METH_LABEL_VERSION
, in
, &out
, &err
) != 0) {
654 return (topo_mod_seterrno(mp
, err
));
658 nvlist_lookup_string(out
, TOPO_METH_LABEL_RET_STR
, &label
) == 0) {
659 if (topo_prop_set_string(tn
, TOPO_PGROUP_PROTOCOL
,
660 TOPO_PROP_LABEL
, TOPO_PROP_IMMUTABLE
, label
, &err
) != 0) {
662 return (topo_mod_seterrno(mp
, err
));
671 EXCAP_set(tnode_t
*tn
, did_t
*pd
,
672 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
674 int excap
= did_excap(pd
);
678 switch (excap
& PCIE_PCIECAP_DEV_TYPE_MASK
) {
679 case PCIE_PCIECAP_DEV_TYPE_ROOT
:
680 e
= topo_prop_set_string(tn
, TOPO_PGROUP_PCI
,
681 TOPO_PCI_EXCAP
, TOPO_PROP_IMMUTABLE
, PCIEX_ROOT
, &err
);
683 case PCIE_PCIECAP_DEV_TYPE_UP
:
684 e
= topo_prop_set_string(tn
, TOPO_PGROUP_PCI
,
685 TOPO_PCI_EXCAP
, TOPO_PROP_IMMUTABLE
, PCIEX_SWUP
, &err
);
687 case PCIE_PCIECAP_DEV_TYPE_DOWN
:
688 e
= topo_prop_set_string(tn
, TOPO_PGROUP_PCI
,
689 TOPO_PCI_EXCAP
, TOPO_PROP_IMMUTABLE
, PCIEX_SWDWN
, &err
);
691 case PCIE_PCIECAP_DEV_TYPE_PCI2PCIE
:
692 e
= topo_prop_set_string(tn
, TOPO_PGROUP_PCI
,
693 TOPO_PCI_EXCAP
, TOPO_PROP_IMMUTABLE
, PCIEX_BUS
, &err
);
695 case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI
:
696 e
= topo_prop_set_string(tn
, TOPO_PGROUP_PCI
,
697 TOPO_PCI_EXCAP
, TOPO_PROP_IMMUTABLE
, PCI_BUS
, &err
);
699 case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV
:
700 e
= topo_prop_set_string(tn
, TOPO_PGROUP_PCI
,
701 TOPO_PCI_EXCAP
, TOPO_PROP_IMMUTABLE
, PCIEX_DEVICE
, &err
);
705 return (topo_mod_seterrno(did_mod(pd
), err
));
711 DEVprop_set(tnode_t
*tn
, did_t
*pd
,
712 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
721 if ((dnpath
= di_devfs_path(did_dinode(pd
))) == NULL
) {
722 topo_mod_dprintf(mp
, "NULL di_devfs_path.\n");
723 return (topo_mod_seterrno(mp
, ETOPO_PROP_NOENT
));
725 if ((path
= topo_mod_strdup(mp
, dnpath
)) == NULL
) {
726 di_devfs_path_free(dnpath
);
729 di_devfs_path_free(dnpath
);
731 /* The DEV path is modified for hostbridges */
732 if (strcmp(topo_node_name(tn
), HOSTBRIDGE
) == 0) {
733 fpath
= dev_for_hostbridge(did_mod(pd
), path
);
735 did_BDF(pd
, NULL
, &d
, &f
);
736 fpath
= dev_path_fix(mp
, path
, d
, f
);
740 e
= topo_prop_set_string(tn
,
741 tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
, fpath
, &err
);
742 topo_mod_strfree(mp
, fpath
);
744 return (topo_mod_seterrno(mp
, err
));
750 DRIVERprop_set(tnode_t
*tn
, did_t
*pd
,
751 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
756 if ((dnm
= di_driver_name(did_dinode(pd
))) == NULL
)
758 if (topo_prop_set_string(tn
,
759 tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
, dnm
, &err
) < 0)
760 return (topo_mod_seterrno(did_mod(pd
), err
));
767 MODULEprop_set(tnode_t
*tn
, did_t
*pd
,
768 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
775 if ((dnm
= di_driver_name(did_dinode(pd
))) == NULL
)
779 if ((mod
= topo_mod_modfmri(mp
, FM_MOD_SCHEME_VERSION
, dnm
)) == NULL
)
780 return (0); /* driver maybe detached, return success */
782 if (topo_prop_set_fmri(tn
, tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
, mod
,
785 return (topo_mod_seterrno(mp
, err
));
794 maybe_di_chars_copy(tnode_t
*tn
, did_t
*pd
,
795 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
803 if (di_bytes_get(did_mod(pd
), did_dinode(pd
), dpnm
, &sz
, &typbuf
) < 0)
807 if ((tmpbuf
= topo_mod_alloc(mp
, sz
+ 1)) == NULL
)
808 return (topo_mod_seterrno(mp
, EMOD_NOMEM
));
810 bcopy(typbuf
, tmpbuf
, sz
);
812 e
= topo_prop_set_string(tn
,
813 tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
, tmpbuf
, &err
);
814 topo_mod_free(mp
, tmpbuf
, sz
+ 1);
816 return (topo_mod_seterrno(mp
, err
));
821 uint_to_strprop(topo_mod_t
*mp
, uint_t v
, tnode_t
*tn
,
822 const char *tpgrp
, const char *tpnm
)
824 char str
[21]; /* sizeof (UINT64_MAX) + '\0' */
827 (void) snprintf(str
, 21, "%x", v
);
828 if (topo_prop_set_string(tn
,
829 tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
, str
, &e
) < 0)
830 return (topo_mod_seterrno(mp
, e
));
835 maybe_di_uint_to_str(tnode_t
*tn
, did_t
*pd
,
836 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
840 if (di_uintprop_get(did_mod(pd
), did_dinode(pd
), dpnm
, &v
) < 0)
843 return (uint_to_strprop(did_mod(pd
), v
, tn
, tpgrp
, tpnm
));
847 uint_to_dec_strprop(topo_mod_t
*mp
, uint_t v
, tnode_t
*tn
,
848 const char *tpgrp
, const char *tpnm
)
850 char str
[21]; /* sizeof (UINT64_MAX) + '\0' */
853 (void) snprintf(str
, 21, "%d", v
);
854 if (topo_prop_set_string(tn
,
855 tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
, str
, &e
) < 0)
856 return (topo_mod_seterrno(mp
, e
));
861 maybe_di_uint_to_dec_str(tnode_t
*tn
, did_t
*pd
,
862 const char *dpnm
, const char *tpgrp
, const char *tpnm
)
866 if (di_uintprop_get(did_mod(pd
), did_dinode(pd
), dpnm
, &v
) < 0)
869 return (uint_to_dec_strprop(did_mod(pd
), v
, tn
, tpgrp
, tpnm
));
873 AADDR_set(tnode_t
*tn
, did_t
*pd
, const char *dpnm
, const char *tpgrp
,
881 if (di_bytes_get(did_mod(pd
), did_dinode(pd
), dpnm
, &sz
, &typbuf
) < 0)
886 e
= topo_prop_set_uint32_array(tn
, tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
,
888 (uint32_t *)typbuf
, sz
/4, &err
);
891 return (topo_mod_seterrno(mp
, err
));
897 BDF_set(tnode_t
*tn
, did_t
*pd
, const char *dpnm
, const char *tpgrp
,
901 char str
[23]; /* '0x' + sizeof (UINT64_MAX) + '\0' */
904 if ((bdf
= did_bdf(pd
)) <= 0)
907 (void) snprintf(str
, 23, "0x%x", bdf
);
908 if (topo_prop_set_string(tn
,
909 tpgrp
, tpnm
, TOPO_PROP_IMMUTABLE
, str
, &e
) < 0)
910 return (topo_mod_seterrno(did_mod(pd
), e
));
915 did_props_set(tnode_t
*tn
, did_t
*pd
, txprop_t txarray
[], int txnum
)
921 for (i
= 0; i
< txnum
; i
++) {
923 * Ensure the property group has been created.
925 if (txarray
[i
].tx_tpgroup
!= NULL
) {
926 if (topo_pgroup_create(tn
, txarray
[i
].tx_tpgroup
, &e
)
928 if (e
!= ETOPO_PROP_DEFD
)
929 return (topo_mod_seterrno(mp
, e
));
934 "Setting property %s in group %s.\n",
935 txarray
[i
].tx_tprop
, txarray
[i
].tx_tpgroup
->tpi_name
);
936 r
= txarray
[i
].tx_xlate(tn
, pd
,
937 txarray
[i
].tx_diprop
, txarray
[i
].tx_tpgroup
->tpi_name
,
938 txarray
[i
].tx_tprop
);
940 topo_mod_dprintf(mp
, "failed.\n");
941 topo_mod_dprintf(mp
, "Error was %s.\n",
942 topo_strerror(topo_mod_errno(mp
)));
945 topo_mod_dprintf(mp
, "succeeded.\n");