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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include "cfga_scsi.h"
30 static scfga_ret_t
scsi_rcm_info_table(rcm_info_t
*, char **);
31 static scfga_ret_t
scsi_rcm_init(uint_t
, char **, rcm_handle_t
**);
36 * Offline SCSI resource consumers.
39 scsi_rcm_offline(char **rsrclist
, char **errstring
, cfga_flags_t flags
)
43 rcm_info_t
*rinfo
= NULL
;
44 scfga_ret_t ret
= SCFGA_OK
;
45 rcm_handle_t
*rcm_handle
;
50 if ((ret
= scsi_rcm_init(0, errstring
, &rcm_handle
))
54 if (flags
& CFGA_FLAG_FORCE
)
57 if ((rret
= rcm_request_offline_list(rcm_handle
, rsrclist
, rflags
,
58 &rinfo
)) != RCM_SUCCESS
) {
59 if ((flags
& FLAG_CLIENT_DEV
) == FLAG_CLIENT_DEV
) {
60 cfga_err(errstring
, 0, ERRARG_RCM_CLIENT_OFFLINE
, 0);
62 cfga_err(errstring
, 0, ERRARG_RCM_OFFLINE
, 0);
65 (void) scsi_rcm_info_table(rinfo
, errstring
);
68 if (rret
== RCM_FAILURE
)
69 (void) rcm_notify_online_list(rcm_handle
, rsrclist
,
70 rflags
& ~RCM_FORCE
, NULL
);
73 (void) rcm_free_handle(rcm_handle
);
80 * Online SCSI resource consumers that were previously offlined.
84 scsi_rcm_online(char **rsrclist
, char **errstring
, cfga_flags_t flags
)
86 rcm_info_t
*rinfo
= NULL
;
87 scfga_ret_t ret
= SCFGA_OK
;
88 rcm_handle_t
*rcm_handle
;
93 if ((ret
= scsi_rcm_init(0, errstring
, &rcm_handle
))
97 if (rcm_notify_online_list(rcm_handle
, rsrclist
, 0, &rinfo
)
99 cfga_err(errstring
, 0, ERRARG_RCM_ONLINE
, 0);
101 (void) scsi_rcm_info_table(rinfo
, errstring
);
102 rcm_free_info(rinfo
);
106 (void) rcm_free_handle(rcm_handle
);
113 * Remove SCSI resource consumers after their kernel removal.
117 scsi_rcm_remove(char **rsrclist
, char **errstring
, cfga_flags_t flags
)
119 rcm_info_t
*rinfo
= NULL
;
120 scfga_ret_t ret
= SCFGA_OK
;
121 rcm_handle_t
*rcm_handle
;
123 if (rsrclist
== NULL
)
126 if ((ret
= scsi_rcm_init(0, errstring
, &rcm_handle
))
130 if (rcm_notify_remove_list(rcm_handle
, rsrclist
, 0, &rinfo
)
132 cfga_err(errstring
, 0, ERRARG_RCM_REMOVE
, 0);
134 (void) scsi_rcm_info_table(rinfo
, errstring
);
135 rcm_free_info(rinfo
);
140 (void) rcm_free_handle(rcm_handle
);
147 * Suspend SCSI resource consumers before a bus quiesce.
150 scsi_rcm_suspend(char **rsrclist
, char **errstring
, cfga_flags_t flags
,
155 rcm_info_t
*rinfo
= NULL
;
156 scfga_ret_t ret
= SCFGA_OK
;
157 rcm_handle_t
*rcm_handle
;
158 timespec_t zerotime
= { 0, 0 };
160 if (rsrclist
== NULL
)
163 pflag
= pflag
? RCM_NOPID
: 0;
164 if ((ret
= scsi_rcm_init(pflag
, errstring
, &rcm_handle
))
168 if (flags
& CFGA_FLAG_FORCE
)
172 * attempt a suspension on a list of resources
174 if ((rret
= rcm_request_suspend_list(rcm_handle
, rsrclist
, rflags
,
175 &zerotime
, &rinfo
)) != RCM_SUCCESS
) {
176 cfga_err(errstring
, 0, ERRARG_RCM_SUSPEND
, 0);
178 (void) scsi_rcm_info_table(rinfo
, errstring
);
179 rcm_free_info(rinfo
);
181 if (rret
== RCM_FAILURE
)
182 (void) rcm_notify_resume_list(rcm_handle
, rsrclist
,
183 (rflags
& (~RCM_FORCE
)), NULL
);
186 (void) rcm_free_handle(rcm_handle
);
193 * Resume SCSI resource consumers after a bus has been unquiesced.
197 scsi_rcm_resume(char **rsrclist
, char **errstring
, cfga_flags_t flags
,
200 rcm_info_t
*rinfo
= NULL
;
201 scfga_ret_t ret
= SCFGA_OK
;
202 rcm_handle_t
*rcm_handle
;
204 if (rsrclist
== NULL
)
207 pflag
= pflag
? RCM_NOPID
: 0;
208 if ((ret
= scsi_rcm_init(pflag
, errstring
, &rcm_handle
))
213 * resume the resource list.
215 if (rcm_notify_resume_list(rcm_handle
, rsrclist
, 0, &rinfo
)
217 cfga_err(errstring
, 0, ERRARG_RCM_RESUME
, 0);
219 (void) scsi_rcm_info_table(rinfo
, errstring
);
220 rcm_free_info(rinfo
);
224 (void) rcm_free_handle(rcm_handle
);
231 * Contains common initialization code for entering a scsi_rcm_xx()
235 scsi_rcm_init(uint_t rcm_flag
, char **errstring
, rcm_handle_t
**hdlp
)
237 /* Get a handle for the RCM operations */
238 if (rcm_alloc_handle(NULL
, rcm_flag
, NULL
, hdlp
) != RCM_SUCCESS
) {
239 cfga_err(errstring
, 0, ERR_RCM_HANDLE
, 0);
240 return (SCFGA_LIB_ERR
);
247 * scsi_rcm_info_table
249 * Takes an opaque rcm_info_t pointer and a character pointer, and appends
250 * the rcm_info_t data in the form of a table to the given character pointer.
253 scsi_rcm_info_table(rcm_info_t
*rinfo
, char **table
)
260 size_t table_size
= 0;
262 rcm_info_tuple_t
*tuple
= NULL
;
266 static char format
[MAX_FORMAT
];
269 /* Protect against invalid arguments */
270 if (rinfo
== NULL
|| table
== NULL
)
273 /* Set localized table header strings */
274 rsrc
= dgettext(TEXT_DOMAIN
, "Resource");
275 info
= dgettext(TEXT_DOMAIN
, "Information");
277 /* A first pass, to size up the RCM information */
278 while (tuple
= rcm_info_next(rinfo
, tuple
)) {
279 if ((infostr
= rcm_info_info(tuple
)) != NULL
) {
281 if ((w
= strlen(rcm_info_rsrc(tuple
))) > w_rsrc
)
283 if ((w
= strlen(infostr
)) > w_info
)
288 /* If nothing was sized up above, stop early */
292 /* Adjust column widths for column headings */
293 if ((w
= strlen(rsrc
)) > w_rsrc
)
295 else if ((w_rsrc
- w
) % 2)
297 if ((w
= strlen(info
)) > w_info
)
299 else if ((w_info
- w
) % 2)
303 * Compute the total line width of each line,
304 * accounting for intercolumn spacing.
306 width
= w_info
+ w_rsrc
+ 4;
308 /* Allocate space for the table */
309 table_size
= (2 + tuples
) * (width
+ 1) + 2;
310 if (*table
== NULL
) {
311 /* zero fill for the strcat() call below */
312 *table
= calloc(table_size
, sizeof (char));
316 newtable
= realloc(*table
, strlen(*table
) + table_size
);
317 if (newtable
== NULL
)
323 /* Place a table header into the string */
325 /* The resource header */
326 (void) strcat(*table
, "\n");
328 for (i
= 0; i
< ((w_rsrc
- w
) / 2); i
++)
329 (void) strcat(*table
, " ");
330 (void) strcat(*table
, rsrc
);
331 for (i
= 0; i
< ((w_rsrc
- w
) / 2); i
++)
332 (void) strcat(*table
, " ");
334 /* The information header */
335 (void) strcat(*table
, " ");
337 for (i
= 0; i
< ((w_info
- w
) / 2); i
++)
338 (void) strcat(*table
, " ");
339 (void) strcat(*table
, info
);
340 for (i
= 0; i
< ((w_info
- w
) / 2); i
++)
341 (void) strcat(*table
, " ");
343 /* Underline the headers */
344 (void) strcat(*table
, "\n");
345 for (i
= 0; i
< w_rsrc
; i
++)
346 (void) strcat(*table
, "-");
347 (void) strcat(*table
, " ");
348 for (i
= 0; i
< w_info
; i
++)
349 (void) strcat(*table
, "-");
351 /* Construct the format string */
352 (void) snprintf(format
, MAX_FORMAT
, "%%-%ds %%-%ds",
353 (int)w_rsrc
, (int)w_info
);
355 /* Add the tuples to the table string */
357 while ((tuple
= rcm_info_next(rinfo
, tuple
)) != NULL
) {
358 if ((infostr
= rcm_info_info(tuple
)) != NULL
) {
359 (void) strcat(*table
, "\n");
360 (void) sprintf(&((*table
)[strlen(*table
)]),
361 format
, rcm_info_rsrc(tuple
),