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 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 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 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 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 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