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 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "cfga_sata.h"
28
29
30
31 #define MAX_FORMAT 80 /* for info table */
32
33 cfga_sata_ret_t sata_rcm_offline(const char *, char **, char *,
34 cfga_flags_t);
35 cfga_sata_ret_t sata_rcm_online(const char *, char **, char *,
36 cfga_flags_t);
37 cfga_sata_ret_t sata_rcm_remove(const char *, char **, char *,
38 cfga_flags_t);
39 static cfga_sata_ret_t sata_rcm_info_table(rcm_info_t *, char **);
40 static cfga_sata_ret_t sata_rcm_init(const char *, cfga_flags_t, char **,
41 uint_t *);
42
43
44 static rcm_handle_t *rcm_handle = NULL;
45 static mutex_t rcm_handle_lock = DEFAULTMUTEX;
46
47 /*
48 * sata_rcm_offline:
49 * Offline SATA resource consumers.
50 */
51 cfga_sata_ret_t
sata_rcm_offline(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)52 sata_rcm_offline(const char *rsrc, char **errstring, char *rsrc_fixed,
53 cfga_flags_t flags)
54 {
55 int rret;
56 uint_t rflags = 0;
57 rcm_info_t *rinfo = NULL;
58 cfga_sata_ret_t ret = CFGA_SATA_OK;
59
60 if ((ret = sata_rcm_init(rsrc, flags, errstring, &rflags)) !=
61 CFGA_SATA_OK) {
62
63 return (ret);
64 }
65
66 if ((rret = rcm_request_offline(rcm_handle, rsrc_fixed, rflags,
67 &rinfo)) != RCM_SUCCESS) {
68 if (rinfo) {
69 (void) sata_rcm_info_table(rinfo, errstring);
70 rcm_free_info(rinfo);
71 rinfo = NULL;
72 }
73
74 if (rret == RCM_FAILURE) {
75 (void) sata_rcm_online(rsrc, errstring,
76 rsrc_fixed, flags);
77 }
78 ret = CFGA_SATA_RCM_OFFLINE;
79 }
80 return (ret);
81 }
82
83
84 /*
85 * sata_rcm_online:
86 * Online SATA resource consumers that were previously offlined.
87 */
88 cfga_sata_ret_t
sata_rcm_online(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)89 sata_rcm_online(const char *rsrc, char **errstring, char *rsrc_fixed,
90 cfga_flags_t flags)
91 {
92 rcm_info_t *rinfo = NULL;
93 cfga_sata_ret_t ret = CFGA_SATA_OK;
94
95 if ((ret = sata_rcm_init(rsrc, flags, errstring, NULL)) !=
96 CFGA_SATA_OK) {
97
98 return (ret);
99 }
100
101 if (rcm_notify_online(rcm_handle, rsrc_fixed, 0, &rinfo) !=
102 RCM_SUCCESS && (rinfo != NULL)) {
103 (void) sata_rcm_info_table(rinfo, errstring);
104 rcm_free_info(rinfo);
105 rinfo = NULL;
106 ret = CFGA_SATA_RCM_ONLINE;
107 }
108
109 return (ret);
110 }
111
112 /*
113 * sata_rcm_remove:
114 * Remove SATA resource consumers after their kernel removal.
115 */
116 cfga_sata_ret_t
sata_rcm_remove(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)117 sata_rcm_remove(const char *rsrc, char **errstring, char *rsrc_fixed,
118 cfga_flags_t flags)
119 {
120 rcm_info_t *rinfo = NULL;
121 cfga_sata_ret_t ret = CFGA_SATA_OK;
122
123 if ((ret = sata_rcm_init(rsrc, flags, errstring, NULL)) !=
124 CFGA_SATA_OK) {
125
126 return (ret);
127 }
128
129 if (rcm_notify_remove(rcm_handle, rsrc_fixed, 0, &rinfo) !=
130 RCM_SUCCESS && (rinfo != NULL)) {
131
132 (void) sata_rcm_info_table(rinfo, errstring);
133 rcm_free_info(rinfo);
134 rinfo = NULL;
135 ret = CFGA_SATA_RCM_ONLINE;
136 }
137
138 return (ret);
139 }
140
141
142 /*
143 * sata_rcm_init:
144 * Contains common initialization code for entering a sata_rcm_xx() routine.
145 */
146 /* ARGSUSED */
147 static cfga_sata_ret_t
sata_rcm_init(const char * rsrc,cfga_flags_t flags,char ** errstring,uint_t * rflags)148 sata_rcm_init(const char *rsrc, cfga_flags_t flags, char **errstring,
149 uint_t *rflags)
150 {
151 /* Validate the rsrc argument */
152 if (rsrc == NULL) {
153 return (CFGA_SATA_INTERNAL_ERROR);
154 }
155
156 /* Translate the cfgadm flags to RCM flags */
157 if (rflags && (flags & CFGA_FLAG_FORCE)) {
158 *rflags |= RCM_FORCE;
159 }
160
161 /* Get a handle for the RCM operations */
162 (void) mutex_lock(&rcm_handle_lock);
163 if (rcm_handle == NULL) {
164 if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm_handle) !=
165 RCM_SUCCESS) {
166 (void) mutex_unlock(&rcm_handle_lock);
167
168 return (CFGA_SATA_RCM_HANDLE);
169 }
170 }
171 (void) mutex_unlock(&rcm_handle_lock);
172
173 return (CFGA_SATA_OK);
174 }
175
176
177 /*
178 * sata_rcm_info_table:
179 * Takes an opaque rcm_info_t pointer and a character pointer,
180 * and appends the rcm_info_t data in the form of a table to the
181 * given character pointer.
182 */
183 static cfga_sata_ret_t
sata_rcm_info_table(rcm_info_t * rinfo,char ** table)184 sata_rcm_info_table(rcm_info_t *rinfo, char **table)
185 {
186 int i;
187 size_t w;
188 size_t width = 0;
189 size_t w_rsrc = 0;
190 size_t w_info = 0;
191 size_t table_size = 0;
192 uint_t tuples = 0;
193 rcm_info_tuple_t *tuple = NULL;
194 char *rsrc;
195 char *info;
196 char *newtable;
197 static char format[MAX_FORMAT];
198 const char *infostr;
199
200 /* Protect against invalid arguments */
201 if (rinfo == NULL || table == NULL) {
202 return (CFGA_SATA_INTERNAL_ERROR);
203 }
204
205 /* Set localized table header strings */
206 rsrc = dgettext(TEXT_DOMAIN, "Resource");
207 info = dgettext(TEXT_DOMAIN, "Information");
208
209
210 /* A first pass, to size up the RCM information */
211 while (tuple = rcm_info_next(rinfo, tuple)) {
212 if ((infostr = rcm_info_info(tuple)) != NULL) {
213 tuples++;
214 if ((w = strlen(rcm_info_rsrc(tuple))) > w_rsrc)
215 w_rsrc = w;
216 if ((w = strlen(infostr)) > w_info)
217 w_info = w;
218 }
219 }
220
221 /* If nothing was sized up above, stop early */
222 if (tuples == 0) {
223 return (CFGA_SATA_OK);
224 }
225
226 /* Adjust column widths for column headings */
227 if ((w = strlen(rsrc)) > w_rsrc) {
228 w_rsrc = w;
229 } else if ((w_rsrc - w) % 2) {
230 w_rsrc++;
231 }
232
233 if ((w = strlen(info)) > w_info) {
234 w_info = w;
235 } else if ((w_info - w) % 2) {
236 w_info++;
237 }
238
239
240 /*
241 * Compute the total line width of each line,
242 * accounting for intercolumn spacing.
243 */
244 width = w_info + w_rsrc + 4;
245
246 /* Allocate space for the table */
247 table_size = (2 + tuples) * (width + 1) + 2;
248 if (*table == NULL) {
249 /* zero fill for the strcat() call below */
250 *table = calloc(table_size, sizeof (char));
251 if (*table == NULL) {
252 return (CFGA_SATA_ALLOC_FAIL);
253 }
254 } else {
255 newtable = realloc(*table, strlen(*table) + table_size);
256 if (newtable == NULL) {
257 return (CFGA_SATA_ALLOC_FAIL);
258 } else {
259 *table = newtable;
260 }
261 }
262
263 /* Place a table header into the string */
264
265
266 /* The resource header */
267 (void) strcat(*table, "\n");
268 w = strlen(rsrc);
269
270 for (i = 0; i < ((w_rsrc - w) / 2); i++) {
271 (void) strcat(*table, " ");
272 }
273 (void) strcat(*table, rsrc);
274
275 for (i = 0; i < ((w_rsrc - w) / 2); i++) {
276 (void) strcat(*table, " ");
277 }
278
279 /* The information header */
280 (void) strcat(*table, " ");
281 w = strlen(info);
282 for (i = 0; i < ((w_info - w) / 2); i++) {
283 (void) strcat(*table, " ");
284 }
285 (void) strcat(*table, info);
286
287 for (i = 0; i < ((w_info - w) / 2); i++) {
288 (void) strcat(*table, " ");
289 }
290
291 (void) strcat(*table, "\n");
292
293 /* Underline the headers */
294 for (i = 0; i < w_rsrc; i++) {
295 (void) strcat(*table, "-");
296 }
297
298 (void) strcat(*table, " ");
299 for (i = 0; i < w_info; i++) {
300 (void) strcat(*table, "-");
301 }
302
303
304 (void) strcat(*table, "\n");
305
306 /* Construct the format string */
307 (void) snprintf(format, MAX_FORMAT, "%%-%ds %%-%ds",
308 (int)w_rsrc, (int)w_info);
309
310 /* Add the tuples to the table string */
311 tuple = NULL;
312 while ((tuple = rcm_info_next(rinfo, tuple)) != NULL) {
313 if ((infostr = rcm_info_info(tuple)) != NULL) {
314 (void) sprintf(&((*table)[strlen(*table)]),
315 format, rcm_info_rsrc(tuple), infostr);
316 (void) strcat(*table, "\n");
317 }
318 }
319
320 return (CFGA_SATA_OK);
321 }
322