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 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "cfga_sata.h" 30 31 32 33 #define MAX_FORMAT 80 /* for info table */ 34 35 cfga_sata_ret_t sata_rcm_offline(const char *, char **, char *, 36 cfga_flags_t); 37 cfga_sata_ret_t sata_rcm_online(const char *, char **, char *, 38 cfga_flags_t); 39 cfga_sata_ret_t sata_rcm_remove(const char *, char **, char *, 40 cfga_flags_t); 41 static cfga_sata_ret_t sata_rcm_info_table(rcm_info_t *, char **); 42 static cfga_sata_ret_t sata_rcm_init(const char *, cfga_flags_t, char **, 43 uint_t *); 44 45 46 static rcm_handle_t *rcm_handle = NULL; 47 static mutex_t rcm_handle_lock = DEFAULTMUTEX; 48 49 /* 50 * sata_rcm_offline: 51 * Offline SATA resource consumers. 52 */ 53 cfga_sata_ret_t 54 sata_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 */ 90 cfga_sata_ret_t 91 sata_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 */ 118 cfga_sata_ret_t 119 sata_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 */ 149 static cfga_sata_ret_t 150 sata_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 */ 185 static cfga_sata_ret_t 186 sata_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