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 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * Create a generic topology node.
29 */
30#include <sys/types.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 <x86pi_impl.h>
36
37#define	_ENUM_NAME	"enum_generic"
38#define	_FAC_PROV	"fac_prov_ipmi"
39
40/*
41 * Create a generic topo node based on the hcfmri strcuture passed in.
42 */
43int
44x86pi_enum_generic(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri,
45    tnode_t *t_bindparent, tnode_t *t_fmriparent, tnode_t **t_node, int flag)
46{
47	int		rv;
48	int		err;
49	nvlist_t	*out;
50	nvlist_t	*fmri;
51	nvlist_t	*auth;
52
53	topo_mod_dprintf(mod, "%s adding entry for type (%s)\n",
54	    _ENUM_NAME, hcfmri->hc_name);
55
56	if (t_bindparent == NULL) {
57		topo_mod_dprintf(mod,
58		    "%s called with NULL parent for type %s\n",
59		    _ENUM_NAME, hcfmri->hc_name);
60		return (-1);
61	}
62
63	/* Create the FMRI for this node */
64	auth = topo_mod_auth(mod, t_bindparent);
65	fmri = topo_mod_hcfmri(mod, t_fmriparent, FM_HC_SCHEME_VERSION,
66	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
67	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
68
69	nvlist_free(auth);
70
71	if (fmri == NULL) {
72		topo_mod_dprintf(mod,
73		    "%s failed to create %s fmri : %s\n", _ENUM_NAME,
74		    hcfmri->hc_name, topo_strerror(topo_mod_errno(mod)));
75		return (-1);
76	}
77
78	rv = topo_node_range_create(mod, t_bindparent, hcfmri->hc_name, 0, 4);
79	if (rv != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
80		topo_mod_dprintf(mod, "%s range create failed for node %s\n",
81		    _ENUM_NAME, hcfmri->hc_name);
82	}
83
84	/* Bind this node to the parent */
85	*t_node = x86pi_node_bind(mod, t_bindparent, hcfmri, fmri, flag);
86	nvlist_free(fmri);
87	if (*t_node == NULL) {
88		topo_mod_dprintf(mod,
89		    "%s failed to bind %s node instance %d: %s\n",
90		    _ENUM_NAME, hcfmri->hc_name, hcfmri->instance,
91		    topo_strerror(topo_mod_errno(mod)));
92		return (-1);
93	}
94
95	/* call IPMI facility provider to register fac methods */
96	if (topo_mod_load(mod, _FAC_PROV, TOPO_VERSION) == NULL) {
97		topo_mod_dprintf(mod,
98		    "%s: Failed to load %s module: %s\n", _ENUM_NAME, _FAC_PROV,
99		    topo_mod_errmsg(mod));
100		return (-1);
101	}
102
103	rv = topo_mod_enumerate(mod, *t_node, _FAC_PROV, _FAC_PROV, 0, 0, NULL);
104	if (rv != 0) {
105		topo_mod_dprintf(mod,
106		    "%s: %s failed: %s\n", _ENUM_NAME, _FAC_PROV,
107		    topo_mod_errmsg(mod));
108		return (-1);
109	}
110
111	/* invoke fac_prov_ipmi_enum method */
112	if (topo_method_supported(*t_node, TOPO_METH_FAC_ENUM, 0)) {
113		if (topo_method_invoke(*t_node, TOPO_METH_FAC_ENUM, 0, NULL,
114		    &out, &err) != 0) {
115			/* log the error and drive on */
116			topo_mod_dprintf(mod,
117			    "%s: TOPO_METH_FAC_ENUM failed\n", _ENUM_NAME);
118		} else {
119			fac_done = 1;
120		}
121	}
122
123	topo_mod_dprintf(mod, "%s added (%s) node\n", _ENUM_NAME,
124	    topo_node_name(*t_node));
125
126	return (0);
127}
128
129
130tnode_t *
131x86pi_node_bind(topo_mod_t *mod, tnode_t *t_parent, x86pi_hcfmri_t *hcfmri,
132    nvlist_t *fmri, int flag)
133{
134	int	result;
135	tnode_t	*t_node;
136	char	*f = "x86pi_node_bind";
137
138	if (t_parent == NULL) {
139		topo_mod_dprintf(mod,
140		    "%s: NULL parent for %s node instance %d\n",
141		    f, hcfmri->hc_name, hcfmri->instance);
142		return (NULL);
143	}
144
145	/* Bind this node to the parent */
146	t_node = topo_node_bind(mod, t_parent, hcfmri->hc_name,
147	    hcfmri->instance, fmri);
148	if (t_node == NULL) {
149		topo_mod_dprintf(mod,
150		    "%s: failed to bind %s node instance %d: %s\n",
151		    f, hcfmri->hc_name, (uint32_t)hcfmri->instance,
152		    topo_strerror(topo_mod_errno(mod)));
153		return (NULL);
154	}
155	topo_mod_dprintf(mod, "%s: bound %s node instance %d type %s\n",
156	    f, hcfmri->hc_name, hcfmri->instance, hcfmri->hc_name);
157
158	/*
159	 * We have bound the node.  Now decorate it with an appropriate
160	 * FRU and label (which may be inherited from the parent).
161	 */
162	result = x86pi_set_frufmri(mod, hcfmri, t_parent, t_node, flag);
163	if (result != 0) {
164		/*
165		 * Though we have failed to set the FRU FMRI we still continue.
166		 * The module errno is set by the called routine, so we report
167		 * the problem and move on.
168		 */
169		topo_mod_dprintf(mod,
170		    "%s: failed to set FRU FMRI for %s node\n",
171		    f, hcfmri->hc_name);
172	}
173
174	result = x86pi_set_label(mod, hcfmri->location, hcfmri->hc_name,
175	    t_node);
176	if (result != 0) {
177		/*
178		 * Though we have failed to set the label, we still continue.
179		 * The module errno is set by the called routine, so we report
180		 * the problem and move on.
181		 */
182		topo_mod_dprintf(mod, "%s: no label for %s node\n",
183		    f, hcfmri->hc_name);
184	}
185
186	result = x86pi_set_auth(mod, hcfmri, t_parent, t_node);
187	if (result != 0) {
188		/*
189		 * Though we have failed to set the authority, we still
190		 * continue. The module errno is set by the called routine, so
191		 * we report the problem and move on.
192		 */
193		topo_mod_dprintf(mod,
194		    "%s: no authority information for %s node\n",
195		    f, hcfmri->hc_name);
196	}
197
198	result = x86pi_set_system(mod, t_node);
199	if (result != 0) {
200		/*
201		 * Though we have failed to set the system group, we still
202		 * continue. The module errno is set by the called routine, so
203		 * we report the problem and move on.
204		 */
205		topo_mod_dprintf(mod,
206		    "%s: no system information for %s node\n",
207		    f, hcfmri->hc_name);
208	}
209
210	return (t_node);
211}
212