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