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
39static descriptor_t	**get_assoc_buses(descriptor_t *desc, int *errp);
40static descriptor_t	**get_assoc_drives(descriptor_t *desc, int *errp);
41static descriptor_t	**get_assoc_paths(descriptor_t *desc, int *errp);
42
43descriptor_t **
44controller_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
60nvlist_t *
61controller_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
137descriptor_t *
138controller_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 */
167descriptor_t **
168controller_get_descriptors(int filter[], int *errp)
169{
170	return (cache_get_descriptors(DM_CONTROLLER, errp));
171}
172
173char *
174controller_get_name(descriptor_t *desc)
175{
176	return (desc->p.controller->name);
177}
178
179/* ARGSUSED */
180nvlist_t *
181controller_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
188int
189controller_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
206static descriptor_t **
207get_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
235static descriptor_t **
236get_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
269static descriptor_t **
270get_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