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_controllers(descriptor_t *desc, int *errp);
41
42descriptor_t **
43bus_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type, int *errp)
44{
45	switch (type) {
46	case DM_BUS:
47	    return (get_assoc_buses(desc, errp));
48	case DM_CONTROLLER:
49	    return (get_assoc_controllers(desc, errp));
50	}
51
52	*errp = EINVAL;
53	return (NULL);
54}
55
56nvlist_t *
57bus_get_attributes(descriptor_t *dp, int *errp)
58{
59	bus_t		*bp;
60	nvlist_t	*attrs;
61
62	if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
63	    *errp = ENOMEM;
64	    return (NULL);
65	}
66
67	bp = dp->p.bus;
68
69	if (nvlist_add_string(attrs, DM_BTYPE, bp->btype) != 0) {
70	    nvlist_free(attrs);
71	    *errp = ENOMEM;
72	    return (NULL);
73	}
74
75	if (bp->freq != 0) {
76	    if (nvlist_add_uint32(attrs, DM_CLOCK, bp->freq) != 0) {
77		nvlist_free(attrs);
78		*errp = ENOMEM;
79		return (NULL);
80	    }
81	}
82
83	if (bp->pname != NULL) {
84	    if (nvlist_add_string(attrs, DM_PNAME, bp->pname) != 0) {
85		nvlist_free(attrs);
86		*errp = ENOMEM;
87		return (NULL);
88	    }
89	}
90
91	*errp = 0;
92	return (attrs);
93}
94
95descriptor_t *
96bus_get_descriptor_by_name(char *name, int *errp)
97{
98	descriptor_t	**buses;
99	int		i;
100	descriptor_t	*bus = NULL;
101
102	buses = cache_get_descriptors(DM_BUS, errp);
103	if (*errp != 0) {
104	    return (NULL);
105	}
106
107	for (i = 0; buses[i]; i++) {
108	    if (libdiskmgt_str_eq(name, buses[i]->p.bus->name)) {
109		bus = buses[i];
110	    } else {
111		/* clean up the unused descriptors */
112		cache_free_descriptor(buses[i]);
113	    }
114	}
115	free(buses);
116
117	if (bus == NULL) {
118	    *errp = ENODEV;
119	}
120
121	return (bus);
122}
123
124/* ARGSUSED */
125descriptor_t **
126bus_get_descriptors(int filter[], int *errp)
127{
128	return (cache_get_descriptors(DM_BUS, errp));
129}
130
131char *
132bus_get_name(descriptor_t *desc)
133{
134	return (desc->p.bus->name);
135}
136
137/* ARGSUSED */
138nvlist_t *
139bus_get_stats(descriptor_t *dp, int stat_type, int *errp)
140{
141	/* There are no stat types defined for controllers */
142	*errp = EINVAL;
143	return (NULL);
144}
145
146int
147bus_make_descriptors()
148{
149	int	error;
150	bus_t	*bp;
151
152	bp = cache_get_buslist();
153	while (bp != NULL) {
154	    cache_load_desc(DM_BUS, bp, NULL, NULL, &error);
155	    if (error != 0) {
156		return (error);
157	    }
158	    bp = bp->next;
159	}
160
161	return (0);
162}
163
164static descriptor_t **
165get_assoc_buses(descriptor_t *desc, int *errp)
166{
167	bus_t		*bp;
168	char		*name;
169	descriptor_t	**allbuses;
170	descriptor_t	**buses;
171	int		cnt;
172	int		i;
173	int		pos;
174
175	bp = desc->p.bus;
176	name = bp->name;
177
178	allbuses = cache_get_descriptors(DM_BUS, errp);
179	if (*errp != 0) {
180	    return (NULL);
181	}
182
183	/* Count how many we have (we overcount, but thats ok). */
184	for (cnt = 0; allbuses[cnt]; cnt++);
185
186	/* make the snapshot */
187	buses = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
188	if (buses == NULL) {
189	    *errp = ENOMEM;
190	    cache_free_descriptors(allbuses);
191	    return (NULL);
192	}
193
194	/*
195	 * Get this buses parent bus and get the buses that I am the parent of.
196	 */
197	pos = 0;
198	for (i = 0; allbuses[i]; i++) {
199	    if (libdiskmgt_str_eq(name, allbuses[i]->p.bus->pname)) {
200		buses[pos++] = allbuses[i];
201	    } else if (bp->pname != NULL &&
202		libdiskmgt_str_eq(bp->pname, allbuses[i]->p.bus->name)) {
203
204		buses[pos++] = allbuses[i];
205	    } else {
206		/* clean up the unused descriptor */
207		cache_free_descriptor(allbuses[i]);
208	    }
209	}
210	buses[pos] = NULL;
211
212	free(allbuses);
213
214	*errp = 0;
215	return (buses);
216}
217
218static descriptor_t **
219get_assoc_controllers(descriptor_t *desc, int *errp)
220{
221	bus_t		*bp;
222	descriptor_t	**controllers;
223	int		cnt;
224	int		i;
225
226	bp = desc->p.bus;
227
228	/* Count how many we have. */
229	for (cnt = 0; bp->controllers[cnt]; cnt++);
230
231	/* make the snapshot */
232	controllers = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
233	if (controllers == NULL) {
234	    *errp = ENOMEM;
235	    return (NULL);
236	}
237
238	for (i = 0; bp->controllers[i]; i++) {
239	    controllers[i] = cache_get_desc(DM_CONTROLLER, bp->controllers[i],
240		NULL, NULL, errp);
241	    if (*errp != 0) {
242		cache_free_descriptors(controllers);
243		return (NULL);
244	    }
245	}
246	controllers[i] = NULL;
247
248	*errp = 0;
249	return (controllers);
250}
251