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