xref: /illumos-gate/usr/src/lib/fm/topo/modules/common/pcibus/util.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <sys/fm/protocol.h>
33 #include <fm/topo_mod.h>
34 #include <fm/topo_hc.h>
35 #include <fm/libtopo.h>
36 
37 int
38 child_range_add(topo_mod_t *mp, tnode_t *tn, const char *cnm,
39     topo_instance_t imin, topo_instance_t imax)
40 {
41 	int e;
42 
43 	e = topo_node_range_create(mp, tn, cnm, imin, imax);
44 	if (e != 0) {
45 		topo_mod_dprintf(mp, "add child range (%s) failed: %s\n",
46 		    cnm, topo_strerror(topo_mod_errno(mp)));
47 		return (-1);
48 	}
49 	return (0);
50 }
51 
52 ulong_t
53 strtonum(topo_mod_t *mp, char *str, int *err)
54 {
55 	ulong_t r;
56 	char *e;
57 
58 	r = strtoul(str, &e, 16);
59 	if (e == str) {
60 		topo_mod_dprintf(mp,
61 		    "Trouble converting %s to a number!\n", str);
62 		*err = -1;
63 		return (0);
64 	}
65 	*err = 0;
66 	return (r);
67 }
68 
69 static int
70 get_pci_vpd_sn_pn(topo_mod_t *mp, di_node_t dn, char **serial, char **part)
71 {
72 	char *s = NULL, *p = NULL;
73 	di_prom_handle_t promtree = DI_PROM_HANDLE_NIL;
74 
75 	if ((promtree = topo_mod_prominfo(mp)) == DI_PROM_HANDLE_NIL) {
76 		topo_mod_dprintf(mp,
77 			"get vpd data: di_prom_handle_init failed.\n");
78 		return (-1);
79 	}
80 
81 	/* Get Serial Number and Part Number */
82 	if ((di_prom_prop_lookup_bytes(promtree, dn, "vpd-serial-number",
83 		(uchar_t **)&s) > 0) && (s != NULL))
84 		*serial = topo_mod_strdup(mp, s);
85 
86 	if ((di_prom_prop_lookup_bytes(promtree, dn, "vpd-part-number",
87 		(uchar_t **)&p) > 0) && (p != NULL))
88 		*part = topo_mod_strdup(mp, p);
89 
90 	return (0);
91 }
92 
93 tnode_t *
94 tnode_create(topo_mod_t *mp, tnode_t *parent,
95     const char *name, topo_instance_t i, void *priv)
96 {
97 	nvlist_t *fmri;
98 	tnode_t *ntn;
99 	nvlist_t *auth;
100 	char *serial = NULL, *part = NULL;
101 
102 	auth = topo_mod_auth(mp, parent);
103 	/*
104 	 * Get PCI/PCIEX Device Serial Number and Part Number
105 	 * from PCI VPD
106 	 */
107 	if ((strcmp(name, PCI_DEVICE) == 0) ||
108 	    (strcmp(name, PCIEX_DEVICE) == 0))
109 		(void) get_pci_vpd_sn_pn(mp, priv, &serial, &part);
110 
111 	fmri = topo_mod_hcfmri(mp, parent, FM_HC_SCHEME_VERSION, name, i, NULL,
112 		auth, part, NULL, serial);
113 	nvlist_free(auth);
114 	topo_mod_strfree(mp, serial);
115 	topo_mod_strfree(mp, part);
116 
117 	if (fmri == NULL) {
118 		topo_mod_dprintf(mp,
119 		    "Unable to make nvlist for %s bind.\n", name);
120 		return (NULL);
121 	}
122 
123 	ntn = topo_node_bind(mp, parent, name, i, fmri);
124 	if (ntn == NULL) {
125 		topo_mod_dprintf(mp,
126 		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
127 		    topo_node_name(parent), topo_node_instance(parent),
128 		    name, i,
129 		    topo_strerror(topo_mod_errno(mp)));
130 		nvlist_free(fmri);
131 		return (NULL);
132 	}
133 	nvlist_free(fmri);
134 	topo_node_setspecific(ntn, priv);
135 
136 	return (ntn);
137 }
138 
139 /*ARGSUSED*/
140 int
141 labelmethod_inherit(topo_mod_t *mp, tnode_t *tn, nvlist_t *in, nvlist_t **out)
142 {
143 	int err;
144 
145 	/*
146 	 * Ignore the input and output nvlists and directly set the
147 	 * label as inheritance from the parent
148 	 */
149 	*out = NULL;
150 	if (topo_node_label_set(tn, NULL, &err) < 0) {
151 		if (err != ETOPO_PROP_NOENT)
152 			return (topo_mod_seterrno(mp, err));
153 	}
154 	return (0);
155 }
156