xref: /illumos-gate/usr/src/lib/libdiskmgt/common/controller.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 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 <fcntl.h>
30 #include <libdevinfo.h>
31 #include <stdlib.h>
32 #include <sys/sunddi.h>
33 #include <sys/types.h>
34 #include <sys/scsi/conf/autoconf.h>
35 
36 #include "libdiskmgt.h"
37 #include "disks_private.h"
38 
39 static descriptor_t	**get_assoc_buses(descriptor_t *desc, int *errp);
40 static descriptor_t	**get_assoc_drives(descriptor_t *desc, int *errp);
41 static descriptor_t	**get_assoc_paths(descriptor_t *desc, int *errp);
42 
43 descriptor_t **
44 controller_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
45     int *errp)
46 {
47 	switch (type) {
48 	case DM_DRIVE:
49 	    return (get_assoc_drives(desc, errp));
50 	case DM_PATH:
51 	    return (get_assoc_paths(desc, errp));
52 	case DM_BUS:
53 	    return (get_assoc_buses(desc, errp));
54 	}
55 
56 	*errp = EINVAL;
57 	return (NULL);
58 }
59 
60 nvlist_t *
61 controller_get_attributes(descriptor_t *dp, int *errp)
62 {
63 	controller_t	*cp;
64 	nvlist_t	*attrs;
65 
66 	if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
67 	    *errp = ENOMEM;
68 	    return (NULL);
69 	}
70 
71 	cp = dp->p.controller;
72 
73 	if (nvlist_add_string(attrs, DM_CTYPE, cp->ctype) != 0) {
74 	    nvlist_free(attrs);
75 	    *errp = ENOMEM;
76 	    return (NULL);
77 	}
78 
79 	if (cp->multiplex) {
80 	    if (nvlist_add_boolean(attrs, DM_MULTIPLEX) != 0) {
81 		nvlist_free(attrs);
82 		*errp = ENOMEM;
83 		return (NULL);
84 	    }
85 	}
86 
87 	if (cp->scsi_options != -1) {
88 	    if (cp->scsi_options & SCSI_OPTIONS_FAST) {
89 		if (nvlist_add_boolean(attrs, DM_FAST) != 0) {
90 		    nvlist_free(attrs);
91 		    *errp = ENOMEM;
92 		    return (NULL);
93 		}
94 	    }
95 	    if (cp->scsi_options & SCSI_OPTIONS_WIDE) {
96 		if (nvlist_add_boolean(attrs, DM_WIDE) != 0) {
97 		    nvlist_free(attrs);
98 		    *errp = ENOMEM;
99 		    return (NULL);
100 		}
101 	    }
102 	    if (cp->scsi_options & SCSI_OPTIONS_FAST20) {
103 		if (nvlist_add_boolean(attrs, DM_FAST20) != 0) {
104 		    nvlist_free(attrs);
105 		    *errp = ENOMEM;
106 		    return (NULL);
107 		}
108 	    }
109 	    if (cp->scsi_options & SCSI_OPTIONS_FAST40) {
110 		if (nvlist_add_boolean(attrs, DM_FAST40) != 0) {
111 		    nvlist_free(attrs);
112 		    *errp = ENOMEM;
113 		    return (NULL);
114 		}
115 	    }
116 	    if (cp->scsi_options & SCSI_OPTIONS_FAST80) {
117 		if (nvlist_add_boolean(attrs, DM_FAST80) != 0) {
118 		    nvlist_free(attrs);
119 		    *errp = ENOMEM;
120 		    return (NULL);
121 		}
122 	    }
123 	}
124 
125 	if (cp->freq != 0) {
126 	    if (nvlist_add_uint32(attrs, DM_CLOCK, cp->freq) != 0) {
127 		nvlist_free(attrs);
128 		*errp = ENOMEM;
129 		return (NULL);
130 	    }
131 	}
132 
133 	*errp = 0;
134 	return (attrs);
135 }
136 
137 descriptor_t *
138 controller_get_descriptor_by_name(char *name, int *errp)
139 {
140 	descriptor_t	**controllers;
141 	int		i;
142 	descriptor_t	*controller = NULL;
143 
144 	controllers = cache_get_descriptors(DM_CONTROLLER, errp);
145 	if (*errp != 0) {
146 	    return (NULL);
147 	}
148 
149 	for (i = 0; controllers[i]; i++) {
150 	    if (libdiskmgt_str_eq(name, controllers[i]->p.controller->name)) {
151 		controller = controllers[i];
152 	    } else {
153 		/* clean up the unused descriptors */
154 		cache_free_descriptor(controllers[i]);
155 	    }
156 	}
157 	free(controllers);
158 
159 	if (controller == NULL) {
160 	    *errp = ENODEV;
161 	}
162 
163 	return (controller);
164 }
165 
166 /* ARGSUSED */
167 descriptor_t **
168 controller_get_descriptors(int filter[], int *errp)
169 {
170 	return (cache_get_descriptors(DM_CONTROLLER, errp));
171 }
172 
173 char *
174 controller_get_name(descriptor_t *desc)
175 {
176 	return (desc->p.controller->name);
177 }
178 
179 /* ARGSUSED */
180 nvlist_t *
181 controller_get_stats(descriptor_t *dp, int stat_type, int *errp)
182 {
183 	/* There are no stat types defined for controllers */
184 	*errp = EINVAL;
185 	return (NULL);
186 }
187 
188 int
189 controller_make_descriptors()
190 {
191 	int		error;
192 	controller_t	*cp;
193 
194 	cp = cache_get_controllerlist();
195 	while (cp != NULL) {
196 	    cache_load_desc(DM_CONTROLLER, cp, NULL, NULL, &error);
197 	    if (error != 0) {
198 		return (error);
199 	    }
200 	    cp = cp->next;
201 	}
202 
203 	return (0);
204 }
205 
206 static descriptor_t **
207 get_assoc_buses(descriptor_t *desc, int *errp)
208 {
209 	controller_t	*cp;
210 	descriptor_t	**buses;
211 	int		pos = 0;
212 
213 	cp = desc->p.controller;
214 
215 	/* make the snapshot */
216 	buses = (descriptor_t **)calloc(2, sizeof (descriptor_t *));
217 	if (buses == NULL) {
218 	    *errp = ENOMEM;
219 	    return (NULL);
220 	}
221 
222 	if (cp->bus != NULL) {
223 	    buses[pos++] = cache_get_desc(DM_BUS, cp->bus, NULL, NULL, errp);
224 	    if (*errp != 0) {
225 		cache_free_descriptors(buses);
226 		return (NULL);
227 	    }
228 	}
229 	buses[pos] = NULL;
230 
231 	*errp = 0;
232 	return (buses);
233 }
234 
235 static descriptor_t **
236 get_assoc_drives(descriptor_t *desc, int *errp)
237 {
238 	controller_t	*cp;
239 	descriptor_t	**drives;
240 	int		cnt;
241 	int		i;
242 
243 	cp = desc->p.controller;
244 
245 	/* Count how many we have. */
246 	for (cnt = 0; cp->disks[cnt]; cnt++);
247 
248 	/* make the snapshot */
249 	drives = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
250 	if (drives == NULL) {
251 	    *errp = ENOMEM;
252 	    return (NULL);
253 	}
254 
255 	for (i = 0; cp->disks[i]; i++) {
256 	    drives[i] = cache_get_desc(DM_DRIVE, cp->disks[i], NULL, NULL,
257 		errp);
258 	    if (*errp != 0) {
259 		cache_free_descriptors(drives);
260 		return (NULL);
261 	    }
262 	}
263 	drives[i] = NULL;
264 
265 	*errp = 0;
266 	return (drives);
267 }
268 
269 static descriptor_t **
270 get_assoc_paths(descriptor_t *desc, int *errp)
271 {
272 	path_t		**pp;
273 	int		cnt;
274 	descriptor_t	**paths;
275 	int		i;
276 
277 	pp = desc->p.controller->paths;
278 
279 	/* Count how many we have. */
280 	cnt = 0;
281 	if (pp != NULL) {
282 	    for (; pp[cnt]; cnt++);
283 	}
284 
285 	/* make the snapshot */
286 	paths = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
287 	if (paths == NULL) {
288 	    *errp = ENOMEM;
289 	    return (NULL);
290 	}
291 
292 	/*
293 	 * The name field of the descriptor is not filled in.  Thus, we
294 	 * know not to try to lookup drive-path state information within
295 	 * the path code if we try to get attributes for this descriptor.
296 	 */
297 	for (i = 0; i < cnt; i++) {
298 	    paths[i] = cache_get_desc(DM_PATH, pp[i], NULL, NULL, errp);
299 	    if (*errp != 0) {
300 		cache_free_descriptors(paths);
301 		return (NULL);
302 	    }
303 	}
304 
305 	paths[i] = NULL;
306 
307 	*errp = 0;
308 	return (paths);
309 }
310