cfga_rcm.c revision 1258:9961d7d3ec8c
119370Spst/*
298944Sobrien * CDDL HEADER START
319370Spst *
498944Sobrien * The contents of this file are subject to the terms of the
598944Sobrien * Common Development and Distribution License (the "License").
698944Sobrien * You may not use this file except in compliance with the License.
798944Sobrien *
819370Spst * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
998944Sobrien * or http://www.opensolaris.org/os/licensing.
1098944Sobrien * See the License for the specific language governing permissions
1198944Sobrien * and limitations under the License.
1298944Sobrien *
1319370Spst * When distributing Covered Code, include this CDDL HEADER in each
1498944Sobrien * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1598944Sobrien * If applicable, add the following below this CDDL HEADER, with the
1698944Sobrien * fields enclosed by brackets "[]" replaced with your own identifying
1798944Sobrien * information: Portions Copyright [yyyy] [name of copyright owner]
1819370Spst *
1919370Spst * CDDL HEADER END
2019370Spst */
2119370Spst
2219370Spst/*
2319370Spst * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2419370Spst * Use is subject to license terms.
2598944Sobrien */
2698944Sobrien
2798944Sobrien#pragma ident	"%Z%%M%	%I%	%E% SMI"
2898944Sobrien
2998944Sobrien#include "cfga_sata.h"
3098944Sobrien
3198944Sobrien
3298944Sobrien
3398944Sobrien#define	MAX_FORMAT	80	/* for info table */
3498944Sobrien
3598944Sobriencfga_sata_ret_t	sata_rcm_offline(const char *, char **, char *,
3619370Spst				cfga_flags_t);
3798944Sobriencfga_sata_ret_t	sata_rcm_online(const char *, char **, char *,
3819370Spst				cfga_flags_t);
3998944Sobriencfga_sata_ret_t	sata_rcm_remove(const char *, char **, char *,
4019370Spst				cfga_flags_t);
4198944Sobrienstatic cfga_sata_ret_t	sata_rcm_info_table(rcm_info_t *, char **);
4219370Spststatic cfga_sata_ret_t	sata_rcm_init(const char *, cfga_flags_t, char **,
4398944Sobrien				uint_t *);
4419370Spst
4598944Sobrien
4619370Spststatic rcm_handle_t *rcm_handle = NULL;
4798944Sobrienstatic mutex_t rcm_handle_lock = DEFAULTMUTEX;
4819370Spst
4998944Sobrien/*
5019370Spst * sata_rcm_offline:
5198944Sobrien *      Offline SATA resource consumers.
52 */
53cfga_sata_ret_t
54sata_rcm_offline(const char *rsrc, char **errstring, char *rsrc_fixed,
55		cfga_flags_t flags)
56{
57	int		rret;
58	uint_t		rflags = 0;
59	rcm_info_t	*rinfo = NULL;
60	cfga_sata_ret_t	ret = CFGA_SATA_OK;
61
62	if ((ret = sata_rcm_init(rsrc, flags, errstring, &rflags)) !=
63	    CFGA_SATA_OK) {
64
65		return (ret);
66	}
67
68	if ((rret = rcm_request_offline(rcm_handle, rsrc_fixed, rflags,
69	    &rinfo)) != RCM_SUCCESS) {
70		if (rinfo) {
71			(void) sata_rcm_info_table(rinfo, errstring);
72			rcm_free_info(rinfo);
73			rinfo = NULL;
74		}
75
76		if (rret == RCM_FAILURE) {
77			(void) sata_rcm_online(rsrc, errstring,
78					rsrc_fixed, flags);
79		}
80		ret = CFGA_SATA_RCM_OFFLINE;
81	}
82	return (ret);
83}
84
85
86/*
87 * sata_rcm_online:
88 *      Online SATA resource consumers that were previously offlined.
89 */
90cfga_sata_ret_t
91sata_rcm_online(const char *rsrc, char **errstring, char *rsrc_fixed,
92		cfga_flags_t flags)
93{
94	rcm_info_t	*rinfo = NULL;
95	cfga_sata_ret_t	ret = CFGA_SATA_OK;
96
97	if ((ret = sata_rcm_init(rsrc, flags, errstring, NULL)) !=
98	    CFGA_SATA_OK) {
99
100		return (ret);
101	}
102
103	if (rcm_notify_online(rcm_handle, rsrc_fixed, 0, &rinfo) !=
104	    RCM_SUCCESS && (rinfo != NULL)) {
105		(void) sata_rcm_info_table(rinfo, errstring);
106		rcm_free_info(rinfo);
107		rinfo = NULL;
108		ret = CFGA_SATA_RCM_ONLINE;
109	}
110
111	return (ret);
112}
113
114/*
115 * sata_rcm_remove:
116 *      Remove SATA resource consumers after their kernel removal.
117 */
118cfga_sata_ret_t
119sata_rcm_remove(const char *rsrc, char **errstring, char *rsrc_fixed,
120		cfga_flags_t flags)
121{
122	rcm_info_t	*rinfo = NULL;
123	cfga_sata_ret_t	ret = CFGA_SATA_OK;
124
125	if ((ret = sata_rcm_init(rsrc, flags, errstring, NULL)) !=
126	    CFGA_SATA_OK) {
127
128		return (ret);
129	}
130
131	if (rcm_notify_remove(rcm_handle, rsrc_fixed, 0, &rinfo) !=
132	    RCM_SUCCESS && (rinfo != NULL)) {
133
134		(void) sata_rcm_info_table(rinfo, errstring);
135		rcm_free_info(rinfo);
136		rinfo = NULL;
137		ret = CFGA_SATA_RCM_ONLINE;
138	}
139
140	return (ret);
141}
142
143
144/*
145 * sata_rcm_init:
146 * Contains common initialization code for entering a sata_rcm_xx() routine.
147 */
148/* ARGSUSED */
149static cfga_sata_ret_t
150sata_rcm_init(const char *rsrc, cfga_flags_t flags, char **errstring,
151		uint_t *rflags)
152{
153	/* Validate the rsrc argument */
154	if (rsrc == NULL) {
155		return (CFGA_SATA_INTERNAL_ERROR);
156	}
157
158	/* Translate the cfgadm flags to RCM flags */
159	if (rflags && (flags & CFGA_FLAG_FORCE)) {
160		*rflags |= RCM_FORCE;
161	}
162
163	/* Get a handle for the RCM operations */
164	(void) mutex_lock(&rcm_handle_lock);
165	if (rcm_handle == NULL) {
166		if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm_handle) !=
167		    RCM_SUCCESS) {
168			(void) mutex_unlock(&rcm_handle_lock);
169
170			return (CFGA_SATA_RCM_HANDLE);
171		}
172	}
173	(void) mutex_unlock(&rcm_handle_lock);
174
175	return (CFGA_SATA_OK);
176}
177
178
179/*
180 * sata_rcm_info_table:
181 * Takes an opaque rcm_info_t pointer and a character pointer,
182 * and appends the rcm_info_t data in the form of a table to the
183 * given character pointer.
184 */
185static cfga_sata_ret_t
186sata_rcm_info_table(rcm_info_t *rinfo, char **table)
187{
188	int i;
189	size_t w;
190	size_t width = 0;
191	size_t w_rsrc = 0;
192	size_t w_info = 0;
193	size_t table_size = 0;
194	uint_t tuples = 0;
195	rcm_info_tuple_t *tuple = NULL;
196	char *rsrc;
197	char *info;
198	char *newtable;
199	static char format[MAX_FORMAT];
200	const char *infostr;
201
202	/* Protect against invalid arguments */
203	if (rinfo == NULL || table == NULL) {
204		return (CFGA_SATA_INTERNAL_ERROR);
205	}
206
207	/* Set localized table header strings */
208	rsrc = dgettext(TEXT_DOMAIN, "Resource");
209	info = dgettext(TEXT_DOMAIN, "Information");
210
211
212	/* A first pass, to size up the RCM information */
213	while (tuple = rcm_info_next(rinfo, tuple)) {
214		if ((infostr = rcm_info_info(tuple)) != NULL) {
215			tuples++;
216			if ((w = strlen(rcm_info_rsrc(tuple))) > w_rsrc)
217				w_rsrc = w;
218			if ((w = strlen(infostr)) > w_info)
219				w_info = w;
220		}
221	}
222
223	/* If nothing was sized up above, stop early */
224	if (tuples == 0) {
225		return (CFGA_SATA_OK);
226	}
227
228	/* Adjust column widths for column headings */
229	if ((w = strlen(rsrc)) > w_rsrc) {
230		w_rsrc = w;
231	} else if ((w_rsrc - w) % 2) {
232		w_rsrc++;
233	}
234
235	if ((w = strlen(info)) > w_info) {
236		w_info = w;
237	} else if ((w_info - w) % 2) {
238		w_info++;
239	}
240
241
242	/*
243	 * Compute the total line width of each line,
244	 * accounting for intercolumn spacing.
245	 */
246	width = w_info + w_rsrc + 4;
247
248	/* Allocate space for the table */
249	table_size = (2 + tuples) * (width + 1) + 2;
250	if (*table == NULL) {
251		/* zero fill for the strcat() call below */
252		*table = calloc(table_size, sizeof (char));
253		if (*table == NULL) {
254			return (CFGA_SATA_ALLOC_FAIL);
255		}
256	} else {
257		newtable = realloc(*table, strlen(*table) + table_size);
258		if (newtable == NULL) {
259			return (CFGA_SATA_ALLOC_FAIL);
260		} else {
261			*table = newtable;
262		}
263	}
264
265	/* Place a table header into the string */
266
267
268	/* The resource header */
269	(void) strcat(*table, "\n");
270	w = strlen(rsrc);
271
272	for (i = 0; i < ((w_rsrc - w) / 2); i++) {
273		(void) strcat(*table, " ");
274	}
275	(void) strcat(*table, rsrc);
276
277	for (i = 0; i < ((w_rsrc - w) / 2); i++) {
278		(void) strcat(*table, " ");
279	}
280
281	/* The information header */
282	(void) strcat(*table, "  ");
283	w = strlen(info);
284	for (i = 0; i < ((w_info - w) / 2); i++) {
285		(void) strcat(*table, " ");
286	}
287	(void) strcat(*table, info);
288
289	for (i = 0; i < ((w_info - w) / 2); i++) {
290		(void) strcat(*table, " ");
291	}
292
293	(void) strcat(*table, "\n");
294
295	/* Underline the headers */
296	for (i = 0; i < w_rsrc; i++) {
297		(void) strcat(*table, "-");
298	}
299
300	(void) strcat(*table, "  ");
301	for (i = 0; i < w_info; i++) {
302		(void) strcat(*table, "-");
303	}
304
305
306	(void) strcat(*table, "\n");
307
308	/* Construct the format string */
309	(void) snprintf(format, MAX_FORMAT, "%%-%ds  %%-%ds",
310			(int)w_rsrc, (int)w_info);
311
312	/* Add the tuples to the table string */
313	tuple = NULL;
314	while ((tuple = rcm_info_next(rinfo, tuple)) != NULL) {
315		if ((infostr = rcm_info_info(tuple)) != NULL) {
316			(void) sprintf(&((*table)[strlen(*table)]),
317					format, rcm_info_rsrc(tuple), infostr);
318			(void) strcat(*table, "\n");
319		}
320	}
321
322	return (CFGA_SATA_OK);
323}
324