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