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