1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 30*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 31*7c478bd9Sstevel@tonic-gate #include <stdio.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <string.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate #include <ctype.h> 38*7c478bd9Sstevel@tonic-gate #include <libgen.h> 39*7c478bd9Sstevel@tonic-gate #include <unistd.h> 40*7c478bd9Sstevel@tonic-gate #include <devid.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #include "libdiskmgt.h" 43*7c478bd9Sstevel@tonic-gate #include "disks_private.h" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #define CLUSTER_DEV "did" 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* specify which disk links to use in the /dev directory */ 48*7c478bd9Sstevel@tonic-gate #define DEVLINK_REGEX "rdsk/.*" 49*7c478bd9Sstevel@tonic-gate #define DEVLINK_FLOPPY_REGEX "rdiskette[0-9]" 50*7c478bd9Sstevel@tonic-gate #define DEVLINK_DID_REGEX "did/rdsk/.*" 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #define FLOPPY_NAME "rdiskette" 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #define MAXPROPLEN 1024 55*7c478bd9Sstevel@tonic-gate #define DEVICE_ID_PROP "devid" 56*7c478bd9Sstevel@tonic-gate #define PROD_ID_PROP "inquiry-product-id" 57*7c478bd9Sstevel@tonic-gate #define PROD_ID_USB_PROP "usb-product-name" 58*7c478bd9Sstevel@tonic-gate #define REMOVABLE_PROP "removable-media" 59*7c478bd9Sstevel@tonic-gate #define SCSI_OPTIONS_PROP "scsi-options" 60*7c478bd9Sstevel@tonic-gate #define VENDOR_ID_PROP "inquiry-vendor-id" 61*7c478bd9Sstevel@tonic-gate #define VENDOR_ID_USB_PROP "usb-vendor-name" 62*7c478bd9Sstevel@tonic-gate #define WWN_PROP "node-wwn" 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* The list of names of possible disk types used by libdevinfo. */ 65*7c478bd9Sstevel@tonic-gate static char *disktypes[] = { 66*7c478bd9Sstevel@tonic-gate DDI_NT_BLOCK, 67*7c478bd9Sstevel@tonic-gate DDI_NT_BLOCK_CHAN, 68*7c478bd9Sstevel@tonic-gate DDI_NT_BLOCK_WWN, 69*7c478bd9Sstevel@tonic-gate DDI_NT_BLOCK_FABRIC, 70*7c478bd9Sstevel@tonic-gate DDI_NT_CD_CHAN, 71*7c478bd9Sstevel@tonic-gate DDI_NT_CD, 72*7c478bd9Sstevel@tonic-gate DDI_NT_FD, 73*7c478bd9Sstevel@tonic-gate NULL 74*7c478bd9Sstevel@tonic-gate }; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * Most of the removable media will be lumped under here; CD, DVD, MO, etc. 78*7c478bd9Sstevel@tonic-gate */ 79*7c478bd9Sstevel@tonic-gate static char *cdromtypes[] = { 80*7c478bd9Sstevel@tonic-gate DDI_NT_CD_CHAN, 81*7c478bd9Sstevel@tonic-gate DDI_NT_CD, 82*7c478bd9Sstevel@tonic-gate NULL 83*7c478bd9Sstevel@tonic-gate }; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate static char *ctrltypes[] = { 86*7c478bd9Sstevel@tonic-gate DDI_NT_SCSI_NEXUS, 87*7c478bd9Sstevel@tonic-gate DDI_NT_SCSI_ATTACHMENT_POINT, 88*7c478bd9Sstevel@tonic-gate DDI_NT_FC_ATTACHMENT_POINT, 89*7c478bd9Sstevel@tonic-gate NULL 90*7c478bd9Sstevel@tonic-gate }; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static char *bustypes[] = { 93*7c478bd9Sstevel@tonic-gate "sbus", 94*7c478bd9Sstevel@tonic-gate "pci", 95*7c478bd9Sstevel@tonic-gate "usb", 96*7c478bd9Sstevel@tonic-gate NULL 97*7c478bd9Sstevel@tonic-gate }; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate static bus_t *add_bus(struct search_args *args, di_node_t node, 100*7c478bd9Sstevel@tonic-gate di_minor_t minor, controller_t *cp); 101*7c478bd9Sstevel@tonic-gate static int add_cluster_devs(di_node_t node, di_minor_t minor, 102*7c478bd9Sstevel@tonic-gate void *arg); 103*7c478bd9Sstevel@tonic-gate static controller_t *add_controller(struct search_args *args, 104*7c478bd9Sstevel@tonic-gate di_node_t node, di_minor_t minor); 105*7c478bd9Sstevel@tonic-gate static int add_devpath(di_devlink_t devlink, void *arg); 106*7c478bd9Sstevel@tonic-gate static int add_devs(di_node_t node, di_minor_t minor, void *arg); 107*7c478bd9Sstevel@tonic-gate static int add_disk2controller(disk_t *diskp, 108*7c478bd9Sstevel@tonic-gate struct search_args *args); 109*7c478bd9Sstevel@tonic-gate static int add_disk2path(disk_t *dp, path_t *pp, 110*7c478bd9Sstevel@tonic-gate di_path_state_t st, char *wwn); 111*7c478bd9Sstevel@tonic-gate static int add_int2array(int p, int **parray); 112*7c478bd9Sstevel@tonic-gate static int add_ptr2array(void *p, void ***parray); 113*7c478bd9Sstevel@tonic-gate static char *bus_type(di_node_t node, di_minor_t minor, 114*7c478bd9Sstevel@tonic-gate di_prom_handle_t ph); 115*7c478bd9Sstevel@tonic-gate static int can_remove_controller(controller_t *cp, 116*7c478bd9Sstevel@tonic-gate controller_t *currp); 117*7c478bd9Sstevel@tonic-gate static void clean_paths(struct search_args *args); 118*7c478bd9Sstevel@tonic-gate static disk_t *create_disk(char *deviceid, char *kernel_name, 119*7c478bd9Sstevel@tonic-gate struct search_args *args); 120*7c478bd9Sstevel@tonic-gate static char *ctype(di_node_t node, di_minor_t minor); 121*7c478bd9Sstevel@tonic-gate static boolean_t disk_is_cdrom(char *type); 122*7c478bd9Sstevel@tonic-gate static alias_t *find_alias(disk_t *diskp, char *kernel_name); 123*7c478bd9Sstevel@tonic-gate static bus_t *find_bus(struct search_args *args, char *name); 124*7c478bd9Sstevel@tonic-gate static controller_t *find_controller(struct search_args *args, char *name); 125*7c478bd9Sstevel@tonic-gate static int fix_cluster_devpath(di_devlink_t devlink, void *arg); 126*7c478bd9Sstevel@tonic-gate static disk_t *get_disk_by_deviceid(disk_t *listp, char *devid); 127*7c478bd9Sstevel@tonic-gate static void get_disk_name_from_path(char *path, char *name, 128*7c478bd9Sstevel@tonic-gate int size); 129*7c478bd9Sstevel@tonic-gate static char *get_byte_prop(char *prop_name, di_node_t node); 130*7c478bd9Sstevel@tonic-gate static di_node_t get_parent_bus(di_node_t node, 131*7c478bd9Sstevel@tonic-gate struct search_args *args); 132*7c478bd9Sstevel@tonic-gate static int get_prom_int(char *prop_name, di_node_t node, 133*7c478bd9Sstevel@tonic-gate di_prom_handle_t ph); 134*7c478bd9Sstevel@tonic-gate static char *get_prom_str(char *prop_name, di_node_t node, 135*7c478bd9Sstevel@tonic-gate di_prom_handle_t ph); 136*7c478bd9Sstevel@tonic-gate static int get_prop(char *prop_name, di_node_t node); 137*7c478bd9Sstevel@tonic-gate static char *get_str_prop(char *prop_name, di_node_t node); 138*7c478bd9Sstevel@tonic-gate static int have_disk(struct search_args *args, char *devid, 139*7c478bd9Sstevel@tonic-gate char *kernel_name, disk_t **diskp); 140*7c478bd9Sstevel@tonic-gate static int is_cluster_disk(di_node_t node, di_minor_t minor); 141*7c478bd9Sstevel@tonic-gate static int is_ctds(char *name); 142*7c478bd9Sstevel@tonic-gate static int is_drive(di_minor_t minor); 143*7c478bd9Sstevel@tonic-gate static int is_HBA(di_node_t node, di_minor_t minor); 144*7c478bd9Sstevel@tonic-gate static int new_alias(disk_t *diskp, char *kernel_path, 145*7c478bd9Sstevel@tonic-gate char *devlink_path, struct search_args *args); 146*7c478bd9Sstevel@tonic-gate static int new_devpath(alias_t *ap, char *devpath); 147*7c478bd9Sstevel@tonic-gate static path_t *new_path(controller_t *cp, disk_t *diskp, 148*7c478bd9Sstevel@tonic-gate di_node_t node, di_path_state_t st, char *wwn); 149*7c478bd9Sstevel@tonic-gate static void remove_invalid_controller(char *name, 150*7c478bd9Sstevel@tonic-gate controller_t *currp, struct search_args *args); 151*7c478bd9Sstevel@tonic-gate static char *str_case_index(register char *s1, register char *s2); 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate /* 154*7c478bd9Sstevel@tonic-gate * The functions in this file do a dev tree walk to build up a model of the 155*7c478bd9Sstevel@tonic-gate * disks, controllers and paths on the system. This model is returned in the 156*7c478bd9Sstevel@tonic-gate * args->disk_listp and args->controller_listp members of the args param. 157*7c478bd9Sstevel@tonic-gate * There is no global data for this file so it is thread safe. It is up to 158*7c478bd9Sstevel@tonic-gate * the caller to merge the resulting model with any existing model that is 159*7c478bd9Sstevel@tonic-gate * cached. The caller must also free the memory for this model when it is 160*7c478bd9Sstevel@tonic-gate * no longer needed. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate void 163*7c478bd9Sstevel@tonic-gate findevs(struct search_args *args) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate uint_t flags; 166*7c478bd9Sstevel@tonic-gate di_node_t di_root; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate args->dev_walk_status = 0; 169*7c478bd9Sstevel@tonic-gate args->disk_listp = NULL; 170*7c478bd9Sstevel@tonic-gate args->controller_listp = NULL; 171*7c478bd9Sstevel@tonic-gate args->bus_listp = NULL; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate args->handle = di_devlink_init(NULL, 0); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * Have to make several passes at this with the new devfs caching. 177*7c478bd9Sstevel@tonic-gate * First, we find non-mpxio devices. Then we find mpxio/multipath 178*7c478bd9Sstevel@tonic-gate * devices. Finally, we get cluster devices. 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate flags = DINFOCACHE; 181*7c478bd9Sstevel@tonic-gate di_root = di_init("/", flags); 182*7c478bd9Sstevel@tonic-gate args->ph = di_prom_init(); 183*7c478bd9Sstevel@tonic-gate (void) di_walk_minor(di_root, NULL, 0, args, add_devs); 184*7c478bd9Sstevel@tonic-gate di_fini(di_root); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate flags = DINFOCPYALL | DINFOPATH; 187*7c478bd9Sstevel@tonic-gate di_root = di_init("/", flags); 188*7c478bd9Sstevel@tonic-gate (void) di_walk_minor(di_root, NULL, 0, args, add_devs); 189*7c478bd9Sstevel@tonic-gate di_fini(di_root); 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* do another pass to clean up cluster devpaths */ 192*7c478bd9Sstevel@tonic-gate flags = DINFOCACHE; 193*7c478bd9Sstevel@tonic-gate di_root = di_init("/", flags); 194*7c478bd9Sstevel@tonic-gate (void) di_walk_minor(di_root, DDI_PSEUDO, 0, args, add_cluster_devs); 195*7c478bd9Sstevel@tonic-gate if (args->ph != DI_PROM_HANDLE_NIL) { 196*7c478bd9Sstevel@tonic-gate (void) di_prom_fini(args->ph); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate di_fini(di_root); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate (void) di_devlink_fini(&(args->handle)); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate clean_paths(args); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* 206*7c478bd9Sstevel@tonic-gate * Definitions of private functions 207*7c478bd9Sstevel@tonic-gate */ 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate static bus_t * 210*7c478bd9Sstevel@tonic-gate add_bus(struct search_args *args, di_node_t node, di_minor_t minor, 211*7c478bd9Sstevel@tonic-gate controller_t *cp) 212*7c478bd9Sstevel@tonic-gate { 213*7c478bd9Sstevel@tonic-gate char *btype; 214*7c478bd9Sstevel@tonic-gate char *devpath; 215*7c478bd9Sstevel@tonic-gate bus_t *bp; 216*7c478bd9Sstevel@tonic-gate char kstat_name[MAXPATHLEN]; 217*7c478bd9Sstevel@tonic-gate di_node_t pnode; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 220*7c478bd9Sstevel@tonic-gate return (NULL); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate if ((btype = bus_type(node, minor, args->ph)) == NULL) { 224*7c478bd9Sstevel@tonic-gate return (add_bus(args, di_parent_node(node), 225*7c478bd9Sstevel@tonic-gate di_minor_next(di_parent_node(node), NULL), cp)); 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(node); 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate if ((bp = find_bus(args, devpath)) != NULL) { 231*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate if (cp != NULL) { 234*7c478bd9Sstevel@tonic-gate if (add_ptr2array(cp, (void ***)&bp->controllers) != 0) { 235*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 236*7c478bd9Sstevel@tonic-gate return (NULL); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate return (bp); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* Special handling for root node. */ 243*7c478bd9Sstevel@tonic-gate if (strcmp(devpath, "/") == 0) { 244*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 245*7c478bd9Sstevel@tonic-gate return (NULL); 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate if (dm_debug) { 249*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "INFO: add_bus %s\n", devpath); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate bp = (bus_t *)calloc(1, sizeof (bus_t)); 253*7c478bd9Sstevel@tonic-gate if (bp == NULL) { 254*7c478bd9Sstevel@tonic-gate return (NULL); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate bp->name = strdup(devpath); 258*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 259*7c478bd9Sstevel@tonic-gate if (bp->name == NULL) { 260*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 261*7c478bd9Sstevel@tonic-gate cache_free_bus(bp); 262*7c478bd9Sstevel@tonic-gate return (NULL); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate bp->btype = strdup(btype); 266*7c478bd9Sstevel@tonic-gate if (bp->btype == NULL) { 267*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 268*7c478bd9Sstevel@tonic-gate cache_free_bus(bp); 269*7c478bd9Sstevel@tonic-gate return (NULL); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate (void) snprintf(kstat_name, sizeof (kstat_name), "%s%d", 273*7c478bd9Sstevel@tonic-gate di_node_name(node), di_instance(node)); 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if ((bp->kstat_name = strdup(kstat_name)) == NULL) { 276*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 277*7c478bd9Sstevel@tonic-gate cache_free_bus(bp); 278*7c478bd9Sstevel@tonic-gate return (NULL); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* if parent node is a bus, get its name */ 282*7c478bd9Sstevel@tonic-gate if ((pnode = get_parent_bus(node, args)) != NULL) { 283*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(pnode); 284*7c478bd9Sstevel@tonic-gate bp->pname = strdup(devpath); 285*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 286*7c478bd9Sstevel@tonic-gate if (bp->pname == NULL) { 287*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 288*7c478bd9Sstevel@tonic-gate cache_free_bus(bp); 289*7c478bd9Sstevel@tonic-gate return (NULL); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate } else { 293*7c478bd9Sstevel@tonic-gate bp->pname = NULL; 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate bp->freq = get_prom_int("clock-frequency", node, args->ph); 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate bp->controllers = (controller_t **)calloc(1, sizeof (controller_t *)); 299*7c478bd9Sstevel@tonic-gate if (bp->controllers == NULL) { 300*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 301*7c478bd9Sstevel@tonic-gate cache_free_bus(bp); 302*7c478bd9Sstevel@tonic-gate return (NULL); 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate bp->controllers[0] = NULL; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if (cp != NULL) { 307*7c478bd9Sstevel@tonic-gate if (add_ptr2array(cp, (void ***)&bp->controllers) != 0) { 308*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 309*7c478bd9Sstevel@tonic-gate return (NULL); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate bp->next = args->bus_listp; 314*7c478bd9Sstevel@tonic-gate args->bus_listp = bp; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate return (bp); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate static int 320*7c478bd9Sstevel@tonic-gate add_cluster_devs(di_node_t node, di_minor_t minor, void *arg) 321*7c478bd9Sstevel@tonic-gate { 322*7c478bd9Sstevel@tonic-gate struct search_args *args; 323*7c478bd9Sstevel@tonic-gate char *devpath; 324*7c478bd9Sstevel@tonic-gate char slice_path[MAXPATHLEN]; 325*7c478bd9Sstevel@tonic-gate int result = DI_WALK_CONTINUE; 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate if (!is_cluster_disk(node, minor)) { 328*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate args = (struct search_args *)arg; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate if (dm_debug > 1) { 334*7c478bd9Sstevel@tonic-gate /* This is all just debugging code */ 335*7c478bd9Sstevel@tonic-gate char *devpath; 336*7c478bd9Sstevel@tonic-gate char dev_name[MAXPATHLEN]; 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(node); 339*7c478bd9Sstevel@tonic-gate (void) snprintf(dev_name, sizeof (dev_name), "%s:%s", devpath, 340*7c478bd9Sstevel@tonic-gate di_minor_name(minor)); 341*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "INFO: cluster dev: %s\n", dev_name); 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate args->node = node; 347*7c478bd9Sstevel@tonic-gate args->minor = minor; 348*7c478bd9Sstevel@tonic-gate args->dev_walk_status = 0; 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate /* 351*7c478bd9Sstevel@tonic-gate * Fix the devpaths for the cluster drive. 352*7c478bd9Sstevel@tonic-gate * 353*7c478bd9Sstevel@tonic-gate * We will come through here once for each raw slice device name. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(node); 356*7c478bd9Sstevel@tonic-gate (void) snprintf(slice_path, sizeof (slice_path), "%s:%s", devpath, 357*7c478bd9Sstevel@tonic-gate di_minor_name(minor)); 358*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* Walk the /dev tree to get the cluster devlinks. */ 361*7c478bd9Sstevel@tonic-gate (void) di_devlink_walk(args->handle, DEVLINK_DID_REGEX, slice_path, 362*7c478bd9Sstevel@tonic-gate DI_PRIMARY_LINK, arg, fix_cluster_devpath); 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate if (args->dev_walk_status != 0) { 365*7c478bd9Sstevel@tonic-gate result = DI_WALK_TERMINATE; 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate return (result); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate static controller_t * 372*7c478bd9Sstevel@tonic-gate add_controller(struct search_args *args, di_node_t node, di_minor_t minor) 373*7c478bd9Sstevel@tonic-gate { 374*7c478bd9Sstevel@tonic-gate char *devpath; 375*7c478bd9Sstevel@tonic-gate controller_t *cp; 376*7c478bd9Sstevel@tonic-gate char kstat_name[MAXPATHLEN]; 377*7c478bd9Sstevel@tonic-gate char *c_type = DM_CTYPE_UNKNOWN; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(node); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if ((cp = find_controller(args, devpath)) != NULL) { 382*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 383*7c478bd9Sstevel@tonic-gate return (cp); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* Special handling for fp attachment node. */ 387*7c478bd9Sstevel@tonic-gate if (strcmp(di_node_name(node), "fp") == 0) { 388*7c478bd9Sstevel@tonic-gate di_node_t pnode; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate pnode = di_parent_node(node); 391*7c478bd9Sstevel@tonic-gate if (pnode != DI_NODE_NIL) { 392*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 393*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(pnode); 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate if ((cp = find_controller(args, devpath)) != NULL) { 396*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 397*7c478bd9Sstevel@tonic-gate return (cp); 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /* not in the list, create it */ 401*7c478bd9Sstevel@tonic-gate node = pnode; 402*7c478bd9Sstevel@tonic-gate c_type = DM_CTYPE_FIBRE; 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate if (dm_debug) { 407*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "INFO: add_controller %s\n", devpath); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate cp = (controller_t *)calloc(1, sizeof (controller_t)); 411*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 412*7c478bd9Sstevel@tonic-gate return (NULL); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate cp->name = strdup(devpath); 416*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 417*7c478bd9Sstevel@tonic-gate if (cp->name == NULL) { 418*7c478bd9Sstevel@tonic-gate cache_free_controller(cp); 419*7c478bd9Sstevel@tonic-gate return (NULL); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (strcmp(c_type, DM_CTYPE_UNKNOWN) == 0) { 423*7c478bd9Sstevel@tonic-gate c_type = ctype(node, minor); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate cp->ctype = c_type; 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate (void) snprintf(kstat_name, sizeof (kstat_name), "%s%d", 428*7c478bd9Sstevel@tonic-gate di_node_name(node), di_instance(node)); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate if ((cp->kstat_name = strdup(kstat_name)) == NULL) { 431*7c478bd9Sstevel@tonic-gate cache_free_controller(cp); 432*7c478bd9Sstevel@tonic-gate return (NULL); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(cp->ctype, "scsi")) { 436*7c478bd9Sstevel@tonic-gate cp->scsi_options = get_prop(SCSI_OPTIONS_PROP, node); 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(di_node_name(node), "scsi_vhci")) { 440*7c478bd9Sstevel@tonic-gate cp->multiplex = 1; 441*7c478bd9Sstevel@tonic-gate } else { 442*7c478bd9Sstevel@tonic-gate cp->multiplex = 0; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate cp->freq = get_prom_int("clock-frequency", node, args->ph); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate cp->disks = (disk_t **)calloc(1, sizeof (disk_t *)); 448*7c478bd9Sstevel@tonic-gate if (cp->disks == NULL) { 449*7c478bd9Sstevel@tonic-gate cache_free_controller(cp); 450*7c478bd9Sstevel@tonic-gate return (NULL); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate cp->disks[0] = NULL; 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate cp->next = args->controller_listp; 455*7c478bd9Sstevel@tonic-gate args->controller_listp = cp; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate cp->bus = add_bus(args, di_parent_node(node), 458*7c478bd9Sstevel@tonic-gate di_minor_next(di_parent_node(node), NULL), cp); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate return (cp); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate static int 464*7c478bd9Sstevel@tonic-gate add_devpath(di_devlink_t devlink, void *arg) 465*7c478bd9Sstevel@tonic-gate { 466*7c478bd9Sstevel@tonic-gate struct search_args *args; 467*7c478bd9Sstevel@tonic-gate char *devidstr; 468*7c478bd9Sstevel@tonic-gate disk_t *diskp; 469*7c478bd9Sstevel@tonic-gate char kernel_name[MAXPATHLEN]; 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate args = (struct search_args *)arg; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* 474*7c478bd9Sstevel@tonic-gate * Get the diskp value from calling have_disk. Can either be found 475*7c478bd9Sstevel@tonic-gate * by kernel name or devid. 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate diskp = NULL; 479*7c478bd9Sstevel@tonic-gate devidstr = get_str_prop(DEVICE_ID_PROP, args->node); 480*7c478bd9Sstevel@tonic-gate (void) snprintf(kernel_name, sizeof (kernel_name), "%s%d", 481*7c478bd9Sstevel@tonic-gate di_node_name(args->node), di_instance(args->node)); 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate (void) have_disk(args, devidstr, kernel_name, &diskp); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate /* 486*7c478bd9Sstevel@tonic-gate * The devlink_path is usually of the form /dev/rdsk/c0t0d0s0. 487*7c478bd9Sstevel@tonic-gate * For diskettes it is /dev/rdiskette*. 488*7c478bd9Sstevel@tonic-gate * On Intel we would also get each fdisk partition as well 489*7c478bd9Sstevel@tonic-gate * (e.g. /dev/rdsk/c0t0d0p0). 490*7c478bd9Sstevel@tonic-gate */ 491*7c478bd9Sstevel@tonic-gate if (diskp != NULL) { 492*7c478bd9Sstevel@tonic-gate alias_t *ap; 493*7c478bd9Sstevel@tonic-gate char *devlink_path; 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate if (diskp->drv_type != DM_DT_FLOPPY) { 496*7c478bd9Sstevel@tonic-gate /* 497*7c478bd9Sstevel@tonic-gate * Add other controllers for multipath disks. This will have 498*7c478bd9Sstevel@tonic-gate * no effect if the controller relationship is already set up. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate if (add_disk2controller(diskp, args) != 0) { 501*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate (void) snprintf(kernel_name, sizeof (kernel_name), "%s%d", 506*7c478bd9Sstevel@tonic-gate di_node_name(args->node), di_instance(args->node)); 507*7c478bd9Sstevel@tonic-gate devlink_path = (char *)di_devlink_path(devlink); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate if (dm_debug > 1) { 510*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "INFO: devpath %s\n", devlink_path); 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate if ((ap = find_alias(diskp, kernel_name)) == NULL) { 514*7c478bd9Sstevel@tonic-gate if (new_alias(diskp, kernel_name, devlink_path, args) != 0) { 515*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate } else { 518*7c478bd9Sstevel@tonic-gate /* 519*7c478bd9Sstevel@tonic-gate * It is possible that we have already added this devpath. 520*7c478bd9Sstevel@tonic-gate * Do not add it again. new_devpath will return a 0 if 521*7c478bd9Sstevel@tonic-gate * found, and not add the path. 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate if (new_devpath(ap, devlink_path) != 0) { 524*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate static int 533*7c478bd9Sstevel@tonic-gate add_devs(di_node_t node, di_minor_t minor, void *arg) 534*7c478bd9Sstevel@tonic-gate { 535*7c478bd9Sstevel@tonic-gate struct search_args *args; 536*7c478bd9Sstevel@tonic-gate int result = DI_WALK_CONTINUE; 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate args = (struct search_args *)arg; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate if (dm_debug > 1) { 541*7c478bd9Sstevel@tonic-gate /* This is all just debugging code */ 542*7c478bd9Sstevel@tonic-gate char *devpath; 543*7c478bd9Sstevel@tonic-gate char dev_name[MAXPATHLEN]; 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(node); 546*7c478bd9Sstevel@tonic-gate (void) snprintf(dev_name, sizeof (dev_name), "%s:%s", devpath, 547*7c478bd9Sstevel@tonic-gate di_minor_name(minor)); 548*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 551*7c478bd9Sstevel@tonic-gate "INFO: dev: %s, node: %s%d, minor: 0x%x, type: %s\n", 552*7c478bd9Sstevel@tonic-gate dev_name, 553*7c478bd9Sstevel@tonic-gate di_node_name(node), di_instance(node), 554*7c478bd9Sstevel@tonic-gate di_minor_spectype(minor), 555*7c478bd9Sstevel@tonic-gate (di_minor_nodetype(minor) != NULL ? 556*7c478bd9Sstevel@tonic-gate di_minor_nodetype(minor) : "NULL")); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if (bus_type(node, minor, args->ph) != NULL) { 560*7c478bd9Sstevel@tonic-gate if (add_bus(args, node, minor, NULL) == NULL) { 561*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 562*7c478bd9Sstevel@tonic-gate result = DI_WALK_TERMINATE; 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate } else if (is_HBA(node, minor)) { 566*7c478bd9Sstevel@tonic-gate if (add_controller(args, node, minor) == NULL) { 567*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 568*7c478bd9Sstevel@tonic-gate result = DI_WALK_TERMINATE; 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate } else if (di_minor_spectype(minor) == S_IFCHR && is_drive(minor)) { 572*7c478bd9Sstevel@tonic-gate char *devidstr; 573*7c478bd9Sstevel@tonic-gate char kernel_name[MAXPATHLEN]; 574*7c478bd9Sstevel@tonic-gate disk_t *diskp; 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate (void) snprintf(kernel_name, sizeof (kernel_name), "%s%d", 577*7c478bd9Sstevel@tonic-gate di_node_name(node), di_instance(node)); 578*7c478bd9Sstevel@tonic-gate devidstr = get_str_prop(DEVICE_ID_PROP, node); 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate args->node = node; 581*7c478bd9Sstevel@tonic-gate args->minor = minor; 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate /* Check if we already got this disk and this is another slice */ 584*7c478bd9Sstevel@tonic-gate if (!have_disk(args, devidstr, kernel_name, &diskp)) { 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate args->dev_walk_status = 0; 587*7c478bd9Sstevel@tonic-gate /* This is a newly found disk, create the disk structure. */ 588*7c478bd9Sstevel@tonic-gate diskp = create_disk(devidstr, kernel_name, args); 589*7c478bd9Sstevel@tonic-gate if (diskp == NULL) { 590*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate if (diskp->drv_type != DM_DT_FLOPPY) { 594*7c478bd9Sstevel@tonic-gate /* add the controller relationship */ 595*7c478bd9Sstevel@tonic-gate if (args->dev_walk_status == 0) { 596*7c478bd9Sstevel@tonic-gate if (add_disk2controller(diskp, args) != 0) { 597*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate /* Add the devpaths for the drive. */ 604*7c478bd9Sstevel@tonic-gate if (args->dev_walk_status == 0) { 605*7c478bd9Sstevel@tonic-gate char *devpath; 606*7c478bd9Sstevel@tonic-gate char slice_path[MAXPATHLEN]; 607*7c478bd9Sstevel@tonic-gate char *pattern; 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate /* 610*7c478bd9Sstevel@tonic-gate * We will come through here once for each of the raw slice 611*7c478bd9Sstevel@tonic-gate * device names. 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(node); 614*7c478bd9Sstevel@tonic-gate (void) snprintf(slice_path, sizeof (slice_path), "%s:%s", 615*7c478bd9Sstevel@tonic-gate devpath, di_minor_name(minor)); 616*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(di_minor_nodetype(minor), DDI_NT_FD)) { 619*7c478bd9Sstevel@tonic-gate pattern = DEVLINK_FLOPPY_REGEX; 620*7c478bd9Sstevel@tonic-gate } else { 621*7c478bd9Sstevel@tonic-gate pattern = DEVLINK_REGEX; 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate /* Walk the /dev tree to get the devlinks. */ 625*7c478bd9Sstevel@tonic-gate (void) di_devlink_walk(args->handle, pattern, slice_path, 626*7c478bd9Sstevel@tonic-gate DI_PRIMARY_LINK, arg, add_devpath); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate if (args->dev_walk_status != 0) { 630*7c478bd9Sstevel@tonic-gate result = DI_WALK_TERMINATE; 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate } 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate return (result); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate static int 638*7c478bd9Sstevel@tonic-gate add_disk2controller(disk_t *diskp, struct search_args *args) 639*7c478bd9Sstevel@tonic-gate { 640*7c478bd9Sstevel@tonic-gate di_node_t pnode; 641*7c478bd9Sstevel@tonic-gate controller_t *cp; 642*7c478bd9Sstevel@tonic-gate di_minor_t minor; 643*7c478bd9Sstevel@tonic-gate di_node_t node; 644*7c478bd9Sstevel@tonic-gate int i; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate node = args->node; 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate pnode = di_parent_node(node); 649*7c478bd9Sstevel@tonic-gate if (pnode == DI_NODE_NIL) { 650*7c478bd9Sstevel@tonic-gate return (0); 651*7c478bd9Sstevel@tonic-gate } 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate minor = di_minor_next(pnode, NULL); 654*7c478bd9Sstevel@tonic-gate if (minor == NULL) { 655*7c478bd9Sstevel@tonic-gate return (0); 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if ((cp = add_controller(args, pnode, minor)) == NULL) { 659*7c478bd9Sstevel@tonic-gate return (ENOMEM); 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* check if the disk <-> ctrl assoc is already there */ 663*7c478bd9Sstevel@tonic-gate for (i = 0; diskp->controllers[i]; i++) { 664*7c478bd9Sstevel@tonic-gate if (cp == diskp->controllers[i]) { 665*7c478bd9Sstevel@tonic-gate return (0); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate /* this is a new controller for this disk */ 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate /* add the disk to the controlller */ 672*7c478bd9Sstevel@tonic-gate if (add_ptr2array(diskp, (void ***)&cp->disks) != 0) { 673*7c478bd9Sstevel@tonic-gate return (ENOMEM); 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate /* add the controlller to the disk */ 677*7c478bd9Sstevel@tonic-gate if (add_ptr2array(cp, (void ***)&diskp->controllers) != 0) { 678*7c478bd9Sstevel@tonic-gate return (ENOMEM); 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate /* 682*7c478bd9Sstevel@tonic-gate * Set up paths for mpxio controlled drives. 683*7c478bd9Sstevel@tonic-gate */ 684*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(di_node_name(pnode), "scsi_vhci")) { 685*7c478bd9Sstevel@tonic-gate /* note: mpxio di_path stuff is all consolidation private */ 686*7c478bd9Sstevel@tonic-gate di_path_t pi = DI_PATH_NIL; 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate while ((pi = di_path_next_phci(node, pi)) != DI_PATH_NIL) { 689*7c478bd9Sstevel@tonic-gate int cnt; 690*7c478bd9Sstevel@tonic-gate uchar_t *bytes; 691*7c478bd9Sstevel@tonic-gate char str[MAXPATHLEN]; 692*7c478bd9Sstevel@tonic-gate char *wwn; 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate di_node_t phci_node = di_path_phci_node(pi); 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate /* get the node wwn */ 697*7c478bd9Sstevel@tonic-gate cnt = di_path_prop_lookup_bytes(pi, WWN_PROP, &bytes); 698*7c478bd9Sstevel@tonic-gate wwn = NULL; 699*7c478bd9Sstevel@tonic-gate if (cnt > 0) { 700*7c478bd9Sstevel@tonic-gate int i; 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate str[0] = 0; 703*7c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 704*7c478bd9Sstevel@tonic-gate char bstr[8]; /* a byte is only 2 hex chars + null */ 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate (void) snprintf(bstr, sizeof (bstr), "%.2x", bytes[i]); 707*7c478bd9Sstevel@tonic-gate (void) strlcat(str, bstr, sizeof (str)); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate wwn = str; 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate if (new_path(cp, diskp, phci_node, di_path_state(pi), wwn) 713*7c478bd9Sstevel@tonic-gate == NULL) { 714*7c478bd9Sstevel@tonic-gate return (ENOMEM); 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate return (0); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate static int 723*7c478bd9Sstevel@tonic-gate add_disk2path(disk_t *dp, path_t *pp, di_path_state_t st, char *wwn) 724*7c478bd9Sstevel@tonic-gate { 725*7c478bd9Sstevel@tonic-gate /* add the disk to the path */ 726*7c478bd9Sstevel@tonic-gate if (add_ptr2array(dp, (void ***)&pp->disks) != 0) { 727*7c478bd9Sstevel@tonic-gate cache_free_path(pp); 728*7c478bd9Sstevel@tonic-gate return (0); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate /* add the path to the disk */ 732*7c478bd9Sstevel@tonic-gate if (add_ptr2array(pp, (void ***)&dp->paths) != 0) { 733*7c478bd9Sstevel@tonic-gate cache_free_path(pp); 734*7c478bd9Sstevel@tonic-gate return (0); 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate /* add the path state for this disk */ 738*7c478bd9Sstevel@tonic-gate if (add_int2array(st, &pp->states) != 0) { 739*7c478bd9Sstevel@tonic-gate cache_free_path(pp); 740*7c478bd9Sstevel@tonic-gate return (0); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate /* add the path state for this disk */ 744*7c478bd9Sstevel@tonic-gate if (wwn != NULL) { 745*7c478bd9Sstevel@tonic-gate char *wp; 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate if ((wp = strdup(wwn)) != NULL) { 748*7c478bd9Sstevel@tonic-gate if (add_ptr2array(wp, (void ***)(&pp->wwns)) != 0) { 749*7c478bd9Sstevel@tonic-gate cache_free_path(pp); 750*7c478bd9Sstevel@tonic-gate return (0); 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate return (1); 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate static int 759*7c478bd9Sstevel@tonic-gate add_int2array(int p, int **parray) 760*7c478bd9Sstevel@tonic-gate { 761*7c478bd9Sstevel@tonic-gate int i; 762*7c478bd9Sstevel@tonic-gate int cnt; 763*7c478bd9Sstevel@tonic-gate int *pa; 764*7c478bd9Sstevel@tonic-gate int *new_array; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate pa = *parray; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate cnt = 0; 769*7c478bd9Sstevel@tonic-gate if (pa != NULL) { 770*7c478bd9Sstevel@tonic-gate for (; pa[cnt] != -1; cnt++); 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate new_array = (int *)calloc(cnt + 2, sizeof (int *)); 774*7c478bd9Sstevel@tonic-gate if (new_array == NULL) { 775*7c478bd9Sstevel@tonic-gate return (ENOMEM); 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate /* copy the existing array */ 779*7c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 780*7c478bd9Sstevel@tonic-gate new_array[i] = pa[i]; 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate new_array[i] = p; 784*7c478bd9Sstevel@tonic-gate new_array[i + 1] = -1; 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate free(pa); 787*7c478bd9Sstevel@tonic-gate *parray = new_array; 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate return (0); 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate static int 793*7c478bd9Sstevel@tonic-gate add_ptr2array(void *p, void ***parray) 794*7c478bd9Sstevel@tonic-gate { 795*7c478bd9Sstevel@tonic-gate int i; 796*7c478bd9Sstevel@tonic-gate int cnt; 797*7c478bd9Sstevel@tonic-gate void **pa; 798*7c478bd9Sstevel@tonic-gate void **new_array; 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate pa = *parray; 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate cnt = 0; 803*7c478bd9Sstevel@tonic-gate if (pa != NULL) { 804*7c478bd9Sstevel@tonic-gate for (; pa[cnt]; cnt++); 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate new_array = (void **)calloc(cnt + 2, sizeof (void *)); 808*7c478bd9Sstevel@tonic-gate if (new_array == NULL) { 809*7c478bd9Sstevel@tonic-gate return (ENOMEM); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate /* copy the existing array */ 813*7c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 814*7c478bd9Sstevel@tonic-gate new_array[i] = pa[i]; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate new_array[i] = p; 818*7c478bd9Sstevel@tonic-gate new_array[i + 1] = NULL; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate free(pa); 821*7c478bd9Sstevel@tonic-gate *parray = new_array; 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate return (0); 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate /* 827*7c478bd9Sstevel@tonic-gate * This double checks that we aren't going to get into a bad situation. 828*7c478bd9Sstevel@tonic-gate * This function should never fail, but I just want to double check things. 829*7c478bd9Sstevel@tonic-gate */ 830*7c478bd9Sstevel@tonic-gate static int 831*7c478bd9Sstevel@tonic-gate can_remove_controller(controller_t *cp, controller_t *currp) 832*7c478bd9Sstevel@tonic-gate { 833*7c478bd9Sstevel@tonic-gate if (dm_debug) { 834*7c478bd9Sstevel@tonic-gate if (cp == currp) { 835*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ERROR: remove current controller\n"); 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if (cp->disks != NULL && cp->disks[0] != NULL) { 839*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 840*7c478bd9Sstevel@tonic-gate "ERROR: remove controller with disk ptrs\n"); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate if (cp->paths != NULL && cp->paths[0] != NULL) { 844*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 845*7c478bd9Sstevel@tonic-gate "ERROR: remove controller with path ptrs\n"); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate return (1); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * If we have a controller in the list that is really a path then we need to 854*7c478bd9Sstevel@tonic-gate * take that controller out of the list since nodes that are paths are not 855*7c478bd9Sstevel@tonic-gate * considered to be controllers. 856*7c478bd9Sstevel@tonic-gate */ 857*7c478bd9Sstevel@tonic-gate static void 858*7c478bd9Sstevel@tonic-gate clean_paths(struct search_args *args) 859*7c478bd9Sstevel@tonic-gate { 860*7c478bd9Sstevel@tonic-gate controller_t *cp; 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate cp = args->controller_listp; 863*7c478bd9Sstevel@tonic-gate while (cp != NULL) { 864*7c478bd9Sstevel@tonic-gate path_t **pp; 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate pp = cp->paths; 867*7c478bd9Sstevel@tonic-gate if (pp != NULL) { 868*7c478bd9Sstevel@tonic-gate int i; 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate for (i = 0; pp[i]; i++) { 871*7c478bd9Sstevel@tonic-gate remove_invalid_controller(pp[i]->name, cp, args); 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate cp = cp->next; 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate static disk_t * 879*7c478bd9Sstevel@tonic-gate create_disk(char *deviceid, char *kernel_name, struct search_args *args) 880*7c478bd9Sstevel@tonic-gate { 881*7c478bd9Sstevel@tonic-gate disk_t *diskp; 882*7c478bd9Sstevel@tonic-gate char *type; 883*7c478bd9Sstevel@tonic-gate char *prod_id; 884*7c478bd9Sstevel@tonic-gate char *vendor_id; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate if (dm_debug) { 887*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "INFO: create_disk %s\n", kernel_name); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate diskp = calloc(1, sizeof (disk_t)); 891*7c478bd9Sstevel@tonic-gate if (diskp == NULL) { 892*7c478bd9Sstevel@tonic-gate return (NULL); 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate diskp->controllers = (controller_t **) 896*7c478bd9Sstevel@tonic-gate calloc(1, sizeof (controller_t *)); 897*7c478bd9Sstevel@tonic-gate if (diskp->controllers == NULL) { 898*7c478bd9Sstevel@tonic-gate cache_free_disk(diskp); 899*7c478bd9Sstevel@tonic-gate return (NULL); 900*7c478bd9Sstevel@tonic-gate } 901*7c478bd9Sstevel@tonic-gate diskp->controllers[0] = NULL; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate diskp->devid = NULL; 904*7c478bd9Sstevel@tonic-gate if (deviceid != NULL) { 905*7c478bd9Sstevel@tonic-gate if ((diskp->device_id = strdup(deviceid)) == NULL) { 906*7c478bd9Sstevel@tonic-gate cache_free_disk(diskp); 907*7c478bd9Sstevel@tonic-gate return (NULL); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate (void) devid_str_decode(deviceid, &(diskp->devid), NULL); 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate if (kernel_name != NULL) { 914*7c478bd9Sstevel@tonic-gate diskp->kernel_name = strdup(kernel_name); 915*7c478bd9Sstevel@tonic-gate if (diskp->kernel_name == NULL) { 916*7c478bd9Sstevel@tonic-gate cache_free_disk(diskp); 917*7c478bd9Sstevel@tonic-gate return (NULL); 918*7c478bd9Sstevel@tonic-gate } 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate diskp->paths = NULL; 922*7c478bd9Sstevel@tonic-gate diskp->aliases = NULL; 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate diskp->cd_rom = 0; 925*7c478bd9Sstevel@tonic-gate diskp->rpm = 0; 926*7c478bd9Sstevel@tonic-gate type = di_minor_nodetype(args->minor); 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate prod_id = get_str_prop(PROD_ID_PROP, args->node); 929*7c478bd9Sstevel@tonic-gate if (prod_id != NULL) { 930*7c478bd9Sstevel@tonic-gate if ((diskp->product_id = strdup(prod_id)) == NULL) { 931*7c478bd9Sstevel@tonic-gate cache_free_disk(diskp); 932*7c478bd9Sstevel@tonic-gate return (NULL); 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate } else { 935*7c478bd9Sstevel@tonic-gate prod_id = get_str_prop(PROD_ID_USB_PROP, args->node); 936*7c478bd9Sstevel@tonic-gate if (prod_id != NULL) { 937*7c478bd9Sstevel@tonic-gate if ((diskp->product_id = strdup(prod_id)) == NULL) { 938*7c478bd9Sstevel@tonic-gate cache_free_disk(diskp); 939*7c478bd9Sstevel@tonic-gate return (NULL); 940*7c478bd9Sstevel@tonic-gate } 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate vendor_id = get_str_prop(VENDOR_ID_PROP, args->node); 945*7c478bd9Sstevel@tonic-gate if (vendor_id != NULL) { 946*7c478bd9Sstevel@tonic-gate if ((diskp->vendor_id = strdup(vendor_id)) == NULL) { 947*7c478bd9Sstevel@tonic-gate cache_free_disk(diskp); 948*7c478bd9Sstevel@tonic-gate return (NULL); 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate } else { 951*7c478bd9Sstevel@tonic-gate vendor_id = get_str_prop(VENDOR_ID_PROP, args->node); 952*7c478bd9Sstevel@tonic-gate if (vendor_id != NULL) { 953*7c478bd9Sstevel@tonic-gate if ((diskp->vendor_id = strdup(vendor_id)) == NULL) { 954*7c478bd9Sstevel@tonic-gate cache_free_disk(diskp); 955*7c478bd9Sstevel@tonic-gate return (NULL); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate } 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate /* 961*7c478bd9Sstevel@tonic-gate * DVD, CD-ROM, CD-RW, MO, etc. are all reported as CD-ROMS. 962*7c478bd9Sstevel@tonic-gate * We try to use uscsi later to determine the real type. 963*7c478bd9Sstevel@tonic-gate * The cd_rom flag tells us that the kernel categorized the drive 964*7c478bd9Sstevel@tonic-gate * as a CD-ROM. We leave the drv_type as UKNOWN for now. 965*7c478bd9Sstevel@tonic-gate * The combination of the cd_rom flag being set with the drv_type of 966*7c478bd9Sstevel@tonic-gate * unknown is what triggers the uscsi probe in drive.c. 967*7c478bd9Sstevel@tonic-gate */ 968*7c478bd9Sstevel@tonic-gate if (disk_is_cdrom(type)) { 969*7c478bd9Sstevel@tonic-gate diskp->drv_type = DM_DT_UNKNOWN; 970*7c478bd9Sstevel@tonic-gate diskp->cd_rom = 1; 971*7c478bd9Sstevel@tonic-gate diskp->removable = 1; 972*7c478bd9Sstevel@tonic-gate } else if (libdiskmgt_str_eq(type, DDI_NT_FD)) { 973*7c478bd9Sstevel@tonic-gate diskp->drv_type = DM_DT_FLOPPY; 974*7c478bd9Sstevel@tonic-gate diskp->removable = 1; 975*7c478bd9Sstevel@tonic-gate } else { 976*7c478bd9Sstevel@tonic-gate /* not a "CD-ROM" or Floppy */ 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate diskp->removable = get_prop(REMOVABLE_PROP, args->node); 979*7c478bd9Sstevel@tonic-gate if (diskp->removable == -1) { 980*7c478bd9Sstevel@tonic-gate diskp->removable = 0; 981*7c478bd9Sstevel@tonic-gate #ifdef i386 982*7c478bd9Sstevel@tonic-gate /* 983*7c478bd9Sstevel@tonic-gate * x86 does not have removable property. Check for common 984*7c478bd9Sstevel@tonic-gate * removable drives, zip & jaz, and mark those correctly. 985*7c478bd9Sstevel@tonic-gate */ 986*7c478bd9Sstevel@tonic-gate if (vendor_id != NULL && prod_id != NULL) { 987*7c478bd9Sstevel@tonic-gate if (str_case_index(vendor_id, "iomega") != NULL) { 988*7c478bd9Sstevel@tonic-gate if (str_case_index(prod_id, "jaz") != NULL) { 989*7c478bd9Sstevel@tonic-gate diskp->removable = 1; 990*7c478bd9Sstevel@tonic-gate } else if (str_case_index(prod_id, "zip") != NULL) { 991*7c478bd9Sstevel@tonic-gate diskp->removable = 1; 992*7c478bd9Sstevel@tonic-gate } 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate #endif 996*7c478bd9Sstevel@tonic-gate } 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate if (diskp->removable) { 999*7c478bd9Sstevel@tonic-gate /* 1000*7c478bd9Sstevel@tonic-gate * For removable jaz or zip drives there is no way 1001*7c478bd9Sstevel@tonic-gate * to get the drive type unless media is inserted, so we 1002*7c478bd9Sstevel@tonic-gate * look at the product-id for a hint. 1003*7c478bd9Sstevel@tonic-gate */ 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate diskp->drv_type = DM_DT_UNKNOWN; 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate if (prod_id != NULL) { 1008*7c478bd9Sstevel@tonic-gate if (str_case_index(prod_id, "jaz") != NULL) { 1009*7c478bd9Sstevel@tonic-gate diskp->drv_type = DM_DT_JAZ; 1010*7c478bd9Sstevel@tonic-gate } else if (str_case_index(prod_id, "zip") != NULL) { 1011*7c478bd9Sstevel@tonic-gate diskp->drv_type = DM_DT_ZIP; 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate } else { 1015*7c478bd9Sstevel@tonic-gate diskp->drv_type = DM_DT_FIXED; 1016*7c478bd9Sstevel@tonic-gate } 1017*7c478bd9Sstevel@tonic-gate } 1018*7c478bd9Sstevel@tonic-gate diskp->volm_path_set = 0; 1019*7c478bd9Sstevel@tonic-gate diskp->volm_path = NULL; 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate diskp->next = args->disk_listp; 1022*7c478bd9Sstevel@tonic-gate args->disk_listp = diskp; 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate return (diskp); 1025*7c478bd9Sstevel@tonic-gate } 1026*7c478bd9Sstevel@tonic-gate 1027*7c478bd9Sstevel@tonic-gate static char * 1028*7c478bd9Sstevel@tonic-gate ctype(di_node_t node, di_minor_t minor) 1029*7c478bd9Sstevel@tonic-gate { 1030*7c478bd9Sstevel@tonic-gate char *type; 1031*7c478bd9Sstevel@tonic-gate char *name; 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate type = di_minor_nodetype(minor); 1034*7c478bd9Sstevel@tonic-gate name = di_node_name(node); 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate /* IDE disks use SCSI nexus as the type, so handle this special case */ 1037*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(name, "ide")) { 1038*7c478bd9Sstevel@tonic-gate return (DM_CTYPE_ATA); 1039*7c478bd9Sstevel@tonic-gate } 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(di_minor_name(minor), "scsa2usb")) { 1042*7c478bd9Sstevel@tonic-gate return (DM_CTYPE_USB); 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, DDI_NT_SCSI_NEXUS) || 1046*7c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(type, DDI_NT_SCSI_ATTACHMENT_POINT)) { 1047*7c478bd9Sstevel@tonic-gate return (DM_CTYPE_SCSI); 1048*7c478bd9Sstevel@tonic-gate } 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, DDI_NT_FC_ATTACHMENT_POINT)) { 1051*7c478bd9Sstevel@tonic-gate return (DM_CTYPE_FIBRE); 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, DDI_NT_NEXUS) && 1055*7c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(name, "fp")) { 1056*7c478bd9Sstevel@tonic-gate return (DM_CTYPE_FIBRE); 1057*7c478bd9Sstevel@tonic-gate } 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, DDI_PSEUDO) && 1060*7c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(name, "ide")) { 1061*7c478bd9Sstevel@tonic-gate return (DM_CTYPE_ATA); 1062*7c478bd9Sstevel@tonic-gate } 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate return (DM_CTYPE_UNKNOWN); 1065*7c478bd9Sstevel@tonic-gate } 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate static boolean_t 1068*7c478bd9Sstevel@tonic-gate disk_is_cdrom(char *type) 1069*7c478bd9Sstevel@tonic-gate { 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate int type_index; 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate for (type_index = 0; cdromtypes[type_index] != NULL; type_index++) { 1074*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, cdromtypes[type_index])) { 1075*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1076*7c478bd9Sstevel@tonic-gate } 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1080*7c478bd9Sstevel@tonic-gate } 1081*7c478bd9Sstevel@tonic-gate 1082*7c478bd9Sstevel@tonic-gate static alias_t * 1083*7c478bd9Sstevel@tonic-gate find_alias(disk_t *diskp, char *kernel_name) 1084*7c478bd9Sstevel@tonic-gate { 1085*7c478bd9Sstevel@tonic-gate alias_t *ap; 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate ap = diskp->aliases; 1088*7c478bd9Sstevel@tonic-gate while (ap != NULL) { 1089*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(ap->kstat_name, kernel_name)) { 1090*7c478bd9Sstevel@tonic-gate return (ap); 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate ap = ap->next; 1093*7c478bd9Sstevel@tonic-gate } 1094*7c478bd9Sstevel@tonic-gate 1095*7c478bd9Sstevel@tonic-gate return (NULL); 1096*7c478bd9Sstevel@tonic-gate } 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate static bus_t * 1099*7c478bd9Sstevel@tonic-gate find_bus(struct search_args *args, char *name) 1100*7c478bd9Sstevel@tonic-gate { 1101*7c478bd9Sstevel@tonic-gate bus_t *listp; 1102*7c478bd9Sstevel@tonic-gate 1103*7c478bd9Sstevel@tonic-gate listp = args->bus_listp; 1104*7c478bd9Sstevel@tonic-gate while (listp != NULL) { 1105*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(listp->name, name)) { 1106*7c478bd9Sstevel@tonic-gate return (listp); 1107*7c478bd9Sstevel@tonic-gate } 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate listp = listp->next; 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate return (NULL); 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate static controller_t * 1116*7c478bd9Sstevel@tonic-gate find_controller(struct search_args *args, char *name) 1117*7c478bd9Sstevel@tonic-gate { 1118*7c478bd9Sstevel@tonic-gate controller_t *listp; 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate listp = args->controller_listp; 1121*7c478bd9Sstevel@tonic-gate while (listp != NULL) { 1122*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(listp->name, name)) { 1123*7c478bd9Sstevel@tonic-gate return (listp); 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate listp = listp->next; 1127*7c478bd9Sstevel@tonic-gate } 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate return (NULL); 1130*7c478bd9Sstevel@tonic-gate } 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate static int 1133*7c478bd9Sstevel@tonic-gate fix_cluster_devpath(di_devlink_t devlink, void *arg) 1134*7c478bd9Sstevel@tonic-gate { 1135*7c478bd9Sstevel@tonic-gate int fd; 1136*7c478bd9Sstevel@tonic-gate struct search_args *args; 1137*7c478bd9Sstevel@tonic-gate char *devlink_path; 1138*7c478bd9Sstevel@tonic-gate disk_t *diskp = NULL; 1139*7c478bd9Sstevel@tonic-gate alias_t *ap = NULL; 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate /* 1142*7c478bd9Sstevel@tonic-gate * The devlink_path is of the form /dev/did/rdsk/d1s0. 1143*7c478bd9Sstevel@tonic-gate */ 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate args = (struct search_args *)arg; 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate /* Find the disk by the deviceid we read from the cluster disk. */ 1148*7c478bd9Sstevel@tonic-gate devlink_path = (char *)di_devlink_path(devlink); 1149*7c478bd9Sstevel@tonic-gate if (devlink_path == NULL) { 1150*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1151*7c478bd9Sstevel@tonic-gate } 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate if ((fd = open(devlink_path, O_RDONLY|O_NDELAY)) >= 0) { 1154*7c478bd9Sstevel@tonic-gate ddi_devid_t devid; 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate if (dm_debug > 1) { 1157*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "INFO: cluster devpath %s\n", 1158*7c478bd9Sstevel@tonic-gate devlink_path); 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate if (devid_get(fd, &devid) == 0) { 1162*7c478bd9Sstevel@tonic-gate char *minor; 1163*7c478bd9Sstevel@tonic-gate char *devidstr; 1164*7c478bd9Sstevel@tonic-gate 1165*7c478bd9Sstevel@tonic-gate minor = di_minor_name(args->minor); 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate if ((devidstr = devid_str_encode(devid, minor)) != NULL) { 1168*7c478bd9Sstevel@tonic-gate diskp = get_disk_by_deviceid(args->disk_listp, devidstr); 1169*7c478bd9Sstevel@tonic-gate 1170*7c478bd9Sstevel@tonic-gate /* 1171*7c478bd9Sstevel@tonic-gate * This really shouldn't happen, since we should have 1172*7c478bd9Sstevel@tonic-gate * found all of the disks during our first pass through 1173*7c478bd9Sstevel@tonic-gate * the dev tree, but just in case... 1174*7c478bd9Sstevel@tonic-gate */ 1175*7c478bd9Sstevel@tonic-gate if (diskp == NULL) { 1176*7c478bd9Sstevel@tonic-gate if (dm_debug > 1) { 1177*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1178*7c478bd9Sstevel@tonic-gate "INFO: cluster create disk\n"); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate diskp = create_disk(devidstr, NULL, args); 1182*7c478bd9Sstevel@tonic-gate if (diskp == NULL) { 1183*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate /* add the controller relationship */ 1187*7c478bd9Sstevel@tonic-gate if (args->dev_walk_status == 0) { 1188*7c478bd9Sstevel@tonic-gate if (add_disk2controller(diskp, args) != 0) { 1189*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate if (new_alias(diskp, NULL, devlink_path, args) 1194*7c478bd9Sstevel@tonic-gate != 0) { 1195*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate } 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate devid_str_free(devidstr); 1200*7c478bd9Sstevel@tonic-gate } 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate devid_free(devid); 1203*7c478bd9Sstevel@tonic-gate } 1204*7c478bd9Sstevel@tonic-gate (void) close(fd); 1205*7c478bd9Sstevel@tonic-gate } 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate if (diskp != NULL) { 1209*7c478bd9Sstevel@tonic-gate if (dm_debug > 1) { 1210*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "INFO: cluster found disk\n"); 1211*7c478bd9Sstevel@tonic-gate } 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate ap = diskp->aliases; 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate if (ap != NULL) { 1217*7c478bd9Sstevel@tonic-gate /* NOTE: if ap->next != NULL have cluster disks w/ multiple paths */ 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate if (!ap->cluster) { 1220*7c478bd9Sstevel@tonic-gate char *basep; 1221*7c478bd9Sstevel@tonic-gate char *namep; 1222*7c478bd9Sstevel@tonic-gate int cnt = 0; 1223*7c478bd9Sstevel@tonic-gate int size; 1224*7c478bd9Sstevel@tonic-gate char alias[MAXPATHLEN]; 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate /* 1227*7c478bd9Sstevel@tonic-gate * First time; save the /dev/rdsk devpaths and update the 1228*7c478bd9Sstevel@tonic-gate * alias info with the new alias name. 1229*7c478bd9Sstevel@tonic-gate */ 1230*7c478bd9Sstevel@tonic-gate ap->orig_paths = ap->devpaths; 1231*7c478bd9Sstevel@tonic-gate ap->devpaths = NULL; 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate free(ap->alias); 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate /* get the new cluster alias name */ 1236*7c478bd9Sstevel@tonic-gate basep = strrchr(devlink_path, '/'); 1237*7c478bd9Sstevel@tonic-gate if (basep == NULL) { 1238*7c478bd9Sstevel@tonic-gate basep = devlink_path; 1239*7c478bd9Sstevel@tonic-gate } else { 1240*7c478bd9Sstevel@tonic-gate basep++; 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate size = sizeof (alias) - 1; 1244*7c478bd9Sstevel@tonic-gate namep = alias; 1245*7c478bd9Sstevel@tonic-gate while (*basep != 0 && *basep != 's' && cnt < size) { 1246*7c478bd9Sstevel@tonic-gate *namep++ = *basep++; 1247*7c478bd9Sstevel@tonic-gate cnt++; 1248*7c478bd9Sstevel@tonic-gate } 1249*7c478bd9Sstevel@tonic-gate *namep = 0; 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate if ((ap->alias = strdup(alias)) == NULL) { 1252*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate ap->cluster = 1; 1256*7c478bd9Sstevel@tonic-gate } 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate if (new_devpath(ap, devlink_path) != 0) { 1259*7c478bd9Sstevel@tonic-gate args->dev_walk_status = ENOMEM; 1260*7c478bd9Sstevel@tonic-gate } 1261*7c478bd9Sstevel@tonic-gate } 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate /* 1267*7c478bd9Sstevel@tonic-gate * Check if we have the drive in our list, based upon the device id. 1268*7c478bd9Sstevel@tonic-gate * We got the device id from the dev tree walk. This is encoded 1269*7c478bd9Sstevel@tonic-gate * using devid_str_encode(3DEVID). In order to check the device ids we need 1270*7c478bd9Sstevel@tonic-gate * to use the devid_compare(3DEVID) function, so we need to decode the 1271*7c478bd9Sstevel@tonic-gate * string representation of the device id. 1272*7c478bd9Sstevel@tonic-gate */ 1273*7c478bd9Sstevel@tonic-gate static disk_t * 1274*7c478bd9Sstevel@tonic-gate get_disk_by_deviceid(disk_t *listp, char *devidstr) 1275*7c478bd9Sstevel@tonic-gate { 1276*7c478bd9Sstevel@tonic-gate ddi_devid_t devid; 1277*7c478bd9Sstevel@tonic-gate 1278*7c478bd9Sstevel@tonic-gate if (devidstr == NULL || devid_str_decode(devidstr, &devid, NULL) != 0) { 1279*7c478bd9Sstevel@tonic-gate return (NULL); 1280*7c478bd9Sstevel@tonic-gate } 1281*7c478bd9Sstevel@tonic-gate 1282*7c478bd9Sstevel@tonic-gate while (listp != NULL) { 1283*7c478bd9Sstevel@tonic-gate if (listp->devid != NULL && 1284*7c478bd9Sstevel@tonic-gate devid_compare(listp->devid, devid) == 0) { 1285*7c478bd9Sstevel@tonic-gate break; 1286*7c478bd9Sstevel@tonic-gate } 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate listp = listp->next; 1289*7c478bd9Sstevel@tonic-gate } 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate devid_free(devid); 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate return (listp); 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate /* 1297*7c478bd9Sstevel@tonic-gate * Get the base disk name with no path prefix and no slice (if there is one). 1298*7c478bd9Sstevel@tonic-gate * The name parameter should be big enough to hold the name. 1299*7c478bd9Sstevel@tonic-gate * This handles diskette names ok (/dev/rdiskette0) since there is no slice, 1300*7c478bd9Sstevel@tonic-gate * and converts the raw diskette name. 1301*7c478bd9Sstevel@tonic-gate * But, we don't know how to strip off the slice from third party drive 1302*7c478bd9Sstevel@tonic-gate * names. That just means that their drive name will include a slice on 1303*7c478bd9Sstevel@tonic-gate * it. 1304*7c478bd9Sstevel@tonic-gate */ 1305*7c478bd9Sstevel@tonic-gate static void 1306*7c478bd9Sstevel@tonic-gate get_disk_name_from_path(char *path, char *name, int size) 1307*7c478bd9Sstevel@tonic-gate { 1308*7c478bd9Sstevel@tonic-gate char *basep; 1309*7c478bd9Sstevel@tonic-gate int cnt = 0; 1310*7c478bd9Sstevel@tonic-gate 1311*7c478bd9Sstevel@tonic-gate basep = strrchr(path, '/'); 1312*7c478bd9Sstevel@tonic-gate if (basep == NULL) { 1313*7c478bd9Sstevel@tonic-gate basep = path; 1314*7c478bd9Sstevel@tonic-gate } else { 1315*7c478bd9Sstevel@tonic-gate basep++; 1316*7c478bd9Sstevel@tonic-gate } 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate size = size - 1; /* leave room for terminating 0 */ 1319*7c478bd9Sstevel@tonic-gate 1320*7c478bd9Sstevel@tonic-gate if (is_ctds(basep)) { 1321*7c478bd9Sstevel@tonic-gate while (*basep != 0 && *basep != 's' && cnt < size) { 1322*7c478bd9Sstevel@tonic-gate *name++ = *basep++; 1323*7c478bd9Sstevel@tonic-gate cnt++; 1324*7c478bd9Sstevel@tonic-gate } 1325*7c478bd9Sstevel@tonic-gate *name = 0; 1326*7c478bd9Sstevel@tonic-gate } else { 1327*7c478bd9Sstevel@tonic-gate if (strncmp(basep, FLOPPY_NAME, sizeof (FLOPPY_NAME) - 1) == 0) { 1328*7c478bd9Sstevel@tonic-gate /* 1329*7c478bd9Sstevel@tonic-gate * a floppy, convert rdiskette name to diskette name, 1330*7c478bd9Sstevel@tonic-gate * by skipping over the 'r' for raw diskette 1331*7c478bd9Sstevel@tonic-gate */ 1332*7c478bd9Sstevel@tonic-gate basep++; 1333*7c478bd9Sstevel@tonic-gate } 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate /* not a ctds name, just copy it */ 1336*7c478bd9Sstevel@tonic-gate (void) strlcpy(name, basep, size); 1337*7c478bd9Sstevel@tonic-gate } 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate 1340*7c478bd9Sstevel@tonic-gate static char * 1341*7c478bd9Sstevel@tonic-gate get_byte_prop(char *prop_name, di_node_t node) 1342*7c478bd9Sstevel@tonic-gate { 1343*7c478bd9Sstevel@tonic-gate int cnt; 1344*7c478bd9Sstevel@tonic-gate uchar_t *bytes; 1345*7c478bd9Sstevel@tonic-gate int i; 1346*7c478bd9Sstevel@tonic-gate char str[MAXPATHLEN]; 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate cnt = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, prop_name, &bytes); 1349*7c478bd9Sstevel@tonic-gate if (cnt < 1) { 1350*7c478bd9Sstevel@tonic-gate return (NULL); 1351*7c478bd9Sstevel@tonic-gate } 1352*7c478bd9Sstevel@tonic-gate 1353*7c478bd9Sstevel@tonic-gate str[0] = 0; 1354*7c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 1355*7c478bd9Sstevel@tonic-gate char bstr[8]; /* a byte is only 2 hex chars + null */ 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate (void) snprintf(bstr, sizeof (bstr), "%.2x", bytes[i]); 1358*7c478bd9Sstevel@tonic-gate (void) strlcat(str, bstr, sizeof (str)); 1359*7c478bd9Sstevel@tonic-gate } 1360*7c478bd9Sstevel@tonic-gate return (strdup(str)); 1361*7c478bd9Sstevel@tonic-gate } 1362*7c478bd9Sstevel@tonic-gate 1363*7c478bd9Sstevel@tonic-gate static di_node_t 1364*7c478bd9Sstevel@tonic-gate get_parent_bus(di_node_t node, struct search_args *args) 1365*7c478bd9Sstevel@tonic-gate { 1366*7c478bd9Sstevel@tonic-gate di_node_t pnode; 1367*7c478bd9Sstevel@tonic-gate 1368*7c478bd9Sstevel@tonic-gate pnode = di_parent_node(node); 1369*7c478bd9Sstevel@tonic-gate if (pnode == DI_NODE_NIL) { 1370*7c478bd9Sstevel@tonic-gate return (NULL); 1371*7c478bd9Sstevel@tonic-gate } 1372*7c478bd9Sstevel@tonic-gate 1373*7c478bd9Sstevel@tonic-gate if (bus_type(pnode, di_minor_next(pnode, NULL), args->ph) != NULL) { 1374*7c478bd9Sstevel@tonic-gate return (pnode); 1375*7c478bd9Sstevel@tonic-gate } 1376*7c478bd9Sstevel@tonic-gate 1377*7c478bd9Sstevel@tonic-gate return (get_parent_bus(pnode, args)); 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate 1380*7c478bd9Sstevel@tonic-gate static int 1381*7c478bd9Sstevel@tonic-gate get_prom_int(char *prop_name, di_node_t node, di_prom_handle_t ph) 1382*7c478bd9Sstevel@tonic-gate { 1383*7c478bd9Sstevel@tonic-gate int *n; 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate if (di_prom_prop_lookup_ints(ph, node, prop_name, &n) == 1) { 1386*7c478bd9Sstevel@tonic-gate return (*n); 1387*7c478bd9Sstevel@tonic-gate } 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate return (0); 1390*7c478bd9Sstevel@tonic-gate } 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate static char * 1393*7c478bd9Sstevel@tonic-gate get_prom_str(char *prop_name, di_node_t node, di_prom_handle_t ph) 1394*7c478bd9Sstevel@tonic-gate { 1395*7c478bd9Sstevel@tonic-gate char *str; 1396*7c478bd9Sstevel@tonic-gate 1397*7c478bd9Sstevel@tonic-gate if (di_prom_prop_lookup_strings(ph, node, prop_name, &str) == 1) { 1398*7c478bd9Sstevel@tonic-gate return (str); 1399*7c478bd9Sstevel@tonic-gate } 1400*7c478bd9Sstevel@tonic-gate 1401*7c478bd9Sstevel@tonic-gate return (NULL); 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate /* 1405*7c478bd9Sstevel@tonic-gate * Get one of the positive int or boolean properties. 1406*7c478bd9Sstevel@tonic-gate */ 1407*7c478bd9Sstevel@tonic-gate static int 1408*7c478bd9Sstevel@tonic-gate get_prop(char *prop_name, di_node_t node) 1409*7c478bd9Sstevel@tonic-gate { 1410*7c478bd9Sstevel@tonic-gate int num; 1411*7c478bd9Sstevel@tonic-gate int *ip; 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate if ((num = di_prop_lookup_ints(DDI_DEV_T_ANY, node, prop_name, &ip)) 1414*7c478bd9Sstevel@tonic-gate >= 0) { 1415*7c478bd9Sstevel@tonic-gate if (num == 0) { 1416*7c478bd9Sstevel@tonic-gate /* boolean */ 1417*7c478bd9Sstevel@tonic-gate return (1); 1418*7c478bd9Sstevel@tonic-gate } else if (num == 1) { 1419*7c478bd9Sstevel@tonic-gate /* single int */ 1420*7c478bd9Sstevel@tonic-gate return (*ip); 1421*7c478bd9Sstevel@tonic-gate } 1422*7c478bd9Sstevel@tonic-gate } 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate return (-1); 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate static char * 1428*7c478bd9Sstevel@tonic-gate get_str_prop(char *prop_name, di_node_t node) 1429*7c478bd9Sstevel@tonic-gate { 1430*7c478bd9Sstevel@tonic-gate char *str; 1431*7c478bd9Sstevel@tonic-gate 1432*7c478bd9Sstevel@tonic-gate if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, prop_name, &str) == 1) { 1433*7c478bd9Sstevel@tonic-gate return (str); 1434*7c478bd9Sstevel@tonic-gate } 1435*7c478bd9Sstevel@tonic-gate 1436*7c478bd9Sstevel@tonic-gate return (NULL); 1437*7c478bd9Sstevel@tonic-gate } 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate /* 1440*7c478bd9Sstevel@tonic-gate * Check if we have the drive in our list, based upon the device id, if the 1441*7c478bd9Sstevel@tonic-gate * drive has a device id, or the kernel name, if it doesn't have a device id. 1442*7c478bd9Sstevel@tonic-gate */ 1443*7c478bd9Sstevel@tonic-gate static int 1444*7c478bd9Sstevel@tonic-gate have_disk(struct search_args *args, char *devidstr, char *kernel_name, 1445*7c478bd9Sstevel@tonic-gate disk_t **diskp) 1446*7c478bd9Sstevel@tonic-gate { 1447*7c478bd9Sstevel@tonic-gate disk_t *listp; 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate *diskp = NULL; 1450*7c478bd9Sstevel@tonic-gate listp = args->disk_listp; 1451*7c478bd9Sstevel@tonic-gate if (devidstr != NULL) { 1452*7c478bd9Sstevel@tonic-gate if ((*diskp = get_disk_by_deviceid(listp, devidstr)) != NULL) { 1453*7c478bd9Sstevel@tonic-gate return (1); 1454*7c478bd9Sstevel@tonic-gate } 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate } else { 1457*7c478bd9Sstevel@tonic-gate /* no devid, try matching the kernel names on the drives */ 1458*7c478bd9Sstevel@tonic-gate while (listp != NULL) { 1459*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(kernel_name, listp->kernel_name)) { 1460*7c478bd9Sstevel@tonic-gate *diskp = listp; 1461*7c478bd9Sstevel@tonic-gate return (1); 1462*7c478bd9Sstevel@tonic-gate } 1463*7c478bd9Sstevel@tonic-gate listp = listp->next; 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate } 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate return (0); 1468*7c478bd9Sstevel@tonic-gate } 1469*7c478bd9Sstevel@tonic-gate 1470*7c478bd9Sstevel@tonic-gate static char * 1471*7c478bd9Sstevel@tonic-gate bus_type(di_node_t node, di_minor_t minor, di_prom_handle_t ph) 1472*7c478bd9Sstevel@tonic-gate { 1473*7c478bd9Sstevel@tonic-gate char *type; 1474*7c478bd9Sstevel@tonic-gate int i; 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate type = get_prom_str("device_type", node, ph); 1477*7c478bd9Sstevel@tonic-gate if (type == NULL) { 1478*7c478bd9Sstevel@tonic-gate type = di_node_name(node); 1479*7c478bd9Sstevel@tonic-gate } 1480*7c478bd9Sstevel@tonic-gate 1481*7c478bd9Sstevel@tonic-gate for (i = 0; bustypes[i]; i++) { 1482*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, bustypes[i])) { 1483*7c478bd9Sstevel@tonic-gate return (type); 1484*7c478bd9Sstevel@tonic-gate } 1485*7c478bd9Sstevel@tonic-gate } 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate if (minor != NULL && strcmp(di_minor_nodetype(minor), 1488*7c478bd9Sstevel@tonic-gate DDI_NT_USB_ATTACHMENT_POINT) == 0) { 1489*7c478bd9Sstevel@tonic-gate return ("usb"); 1490*7c478bd9Sstevel@tonic-gate } 1491*7c478bd9Sstevel@tonic-gate 1492*7c478bd9Sstevel@tonic-gate return (NULL); 1493*7c478bd9Sstevel@tonic-gate } 1494*7c478bd9Sstevel@tonic-gate 1495*7c478bd9Sstevel@tonic-gate static int 1496*7c478bd9Sstevel@tonic-gate is_cluster_disk(di_node_t node, di_minor_t minor) 1497*7c478bd9Sstevel@tonic-gate { 1498*7c478bd9Sstevel@tonic-gate if (di_minor_spectype(minor) == S_IFCHR && 1499*7c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(di_minor_nodetype(minor), DDI_PSEUDO) && 1500*7c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(di_node_name(node), CLUSTER_DEV)) { 1501*7c478bd9Sstevel@tonic-gate return (1); 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate 1504*7c478bd9Sstevel@tonic-gate return (0); 1505*7c478bd9Sstevel@tonic-gate } 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate /* 1508*7c478bd9Sstevel@tonic-gate * If the input name is in c[t]ds format then return 1, otherwise return 0. 1509*7c478bd9Sstevel@tonic-gate */ 1510*7c478bd9Sstevel@tonic-gate static int 1511*7c478bd9Sstevel@tonic-gate is_ctds(char *name) 1512*7c478bd9Sstevel@tonic-gate { 1513*7c478bd9Sstevel@tonic-gate char *p; 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate p = name; 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate if (*p++ != 'c') { 1518*7c478bd9Sstevel@tonic-gate return (0); 1519*7c478bd9Sstevel@tonic-gate } 1520*7c478bd9Sstevel@tonic-gate /* skip controller digits */ 1521*7c478bd9Sstevel@tonic-gate while (isdigit(*p)) { 1522*7c478bd9Sstevel@tonic-gate p++; 1523*7c478bd9Sstevel@tonic-gate } 1524*7c478bd9Sstevel@tonic-gate 1525*7c478bd9Sstevel@tonic-gate /* handle optional target */ 1526*7c478bd9Sstevel@tonic-gate if (*p == 't') { 1527*7c478bd9Sstevel@tonic-gate p++; 1528*7c478bd9Sstevel@tonic-gate /* skip over target */ 1529*7c478bd9Sstevel@tonic-gate while (isdigit(*p) || isupper(*p)) { 1530*7c478bd9Sstevel@tonic-gate p++; 1531*7c478bd9Sstevel@tonic-gate } 1532*7c478bd9Sstevel@tonic-gate } 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate if (*p++ != 'd') { 1535*7c478bd9Sstevel@tonic-gate return (0); 1536*7c478bd9Sstevel@tonic-gate } 1537*7c478bd9Sstevel@tonic-gate while (isdigit(*p)) { 1538*7c478bd9Sstevel@tonic-gate p++; 1539*7c478bd9Sstevel@tonic-gate } 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate if (*p++ != 's') { 1542*7c478bd9Sstevel@tonic-gate return (0); 1543*7c478bd9Sstevel@tonic-gate } 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate /* check the slice number */ 1546*7c478bd9Sstevel@tonic-gate while (isdigit(*p)) { 1547*7c478bd9Sstevel@tonic-gate p++; 1548*7c478bd9Sstevel@tonic-gate } 1549*7c478bd9Sstevel@tonic-gate 1550*7c478bd9Sstevel@tonic-gate if (*p != 0) { 1551*7c478bd9Sstevel@tonic-gate return (0); 1552*7c478bd9Sstevel@tonic-gate } 1553*7c478bd9Sstevel@tonic-gate 1554*7c478bd9Sstevel@tonic-gate return (1); 1555*7c478bd9Sstevel@tonic-gate } 1556*7c478bd9Sstevel@tonic-gate 1557*7c478bd9Sstevel@tonic-gate static int 1558*7c478bd9Sstevel@tonic-gate is_drive(di_minor_t minor) 1559*7c478bd9Sstevel@tonic-gate { 1560*7c478bd9Sstevel@tonic-gate char *type; 1561*7c478bd9Sstevel@tonic-gate int type_index; 1562*7c478bd9Sstevel@tonic-gate 1563*7c478bd9Sstevel@tonic-gate type = di_minor_nodetype(minor); 1564*7c478bd9Sstevel@tonic-gate type_index = 0; 1565*7c478bd9Sstevel@tonic-gate 1566*7c478bd9Sstevel@tonic-gate while (disktypes[type_index] != NULL) { 1567*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, disktypes[type_index])) { 1568*7c478bd9Sstevel@tonic-gate return (1); 1569*7c478bd9Sstevel@tonic-gate } 1570*7c478bd9Sstevel@tonic-gate type_index++; 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate return (0); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate 1576*7c478bd9Sstevel@tonic-gate static int 1577*7c478bd9Sstevel@tonic-gate is_HBA(di_node_t node, di_minor_t minor) 1578*7c478bd9Sstevel@tonic-gate { 1579*7c478bd9Sstevel@tonic-gate char *type; 1580*7c478bd9Sstevel@tonic-gate char *name; 1581*7c478bd9Sstevel@tonic-gate int type_index; 1582*7c478bd9Sstevel@tonic-gate 1583*7c478bd9Sstevel@tonic-gate type = di_minor_nodetype(minor); 1584*7c478bd9Sstevel@tonic-gate type_index = 0; 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate while (ctrltypes[type_index] != NULL) { 1587*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, ctrltypes[type_index])) { 1588*7c478bd9Sstevel@tonic-gate return (1); 1589*7c478bd9Sstevel@tonic-gate } 1590*7c478bd9Sstevel@tonic-gate type_index++; 1591*7c478bd9Sstevel@tonic-gate } 1592*7c478bd9Sstevel@tonic-gate 1593*7c478bd9Sstevel@tonic-gate name = di_node_name(node); 1594*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(type, DDI_PSEUDO) && 1595*7c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(name, "ide")) { 1596*7c478bd9Sstevel@tonic-gate return (1); 1597*7c478bd9Sstevel@tonic-gate } 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate return (0); 1600*7c478bd9Sstevel@tonic-gate } 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate static int 1603*7c478bd9Sstevel@tonic-gate new_alias(disk_t *diskp, char *kernel_name, char *devlink_path, 1604*7c478bd9Sstevel@tonic-gate struct search_args *args) 1605*7c478bd9Sstevel@tonic-gate { 1606*7c478bd9Sstevel@tonic-gate alias_t *aliasp; 1607*7c478bd9Sstevel@tonic-gate char alias[MAXPATHLEN]; 1608*7c478bd9Sstevel@tonic-gate di_node_t pnode; 1609*7c478bd9Sstevel@tonic-gate 1610*7c478bd9Sstevel@tonic-gate aliasp = malloc(sizeof (alias_t)); 1611*7c478bd9Sstevel@tonic-gate if (aliasp == NULL) { 1612*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1613*7c478bd9Sstevel@tonic-gate } 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate aliasp->alias = NULL; 1616*7c478bd9Sstevel@tonic-gate aliasp->kstat_name = NULL; 1617*7c478bd9Sstevel@tonic-gate aliasp->wwn = NULL; 1618*7c478bd9Sstevel@tonic-gate aliasp->devpaths = NULL; 1619*7c478bd9Sstevel@tonic-gate aliasp->orig_paths = NULL; 1620*7c478bd9Sstevel@tonic-gate 1621*7c478bd9Sstevel@tonic-gate get_disk_name_from_path(devlink_path, alias, sizeof (alias)); 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate aliasp->alias = strdup(alias); 1624*7c478bd9Sstevel@tonic-gate if (aliasp->alias == NULL) { 1625*7c478bd9Sstevel@tonic-gate cache_free_alias(aliasp); 1626*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1627*7c478bd9Sstevel@tonic-gate } 1628*7c478bd9Sstevel@tonic-gate 1629*7c478bd9Sstevel@tonic-gate if (kernel_name != NULL) { 1630*7c478bd9Sstevel@tonic-gate aliasp->kstat_name = strdup(kernel_name); 1631*7c478bd9Sstevel@tonic-gate if (aliasp->kstat_name == NULL) { 1632*7c478bd9Sstevel@tonic-gate cache_free_alias(aliasp); 1633*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1634*7c478bd9Sstevel@tonic-gate } 1635*7c478bd9Sstevel@tonic-gate } else { 1636*7c478bd9Sstevel@tonic-gate aliasp->kstat_name = NULL; 1637*7c478bd9Sstevel@tonic-gate } 1638*7c478bd9Sstevel@tonic-gate 1639*7c478bd9Sstevel@tonic-gate aliasp->cluster = 0; 1640*7c478bd9Sstevel@tonic-gate aliasp->lun = get_prop(DM_LUN, args->node); 1641*7c478bd9Sstevel@tonic-gate aliasp->target = get_prop(DM_TARGET, args->node); 1642*7c478bd9Sstevel@tonic-gate aliasp->wwn = get_byte_prop(WWN_PROP, args->node); 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate pnode = di_parent_node(args->node); 1645*7c478bd9Sstevel@tonic-gate if (pnode != DI_NODE_NIL) { 1646*7c478bd9Sstevel@tonic-gate char prop_name[MAXPROPLEN]; 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate (void) snprintf(prop_name, sizeof (prop_name), 1649*7c478bd9Sstevel@tonic-gate "target%d-sync-speed", aliasp->target); 1650*7c478bd9Sstevel@tonic-gate diskp->sync_speed = get_prop(prop_name, pnode); 1651*7c478bd9Sstevel@tonic-gate (void) snprintf(prop_name, sizeof (prop_name), "target%d-wide", 1652*7c478bd9Sstevel@tonic-gate aliasp->target); 1653*7c478bd9Sstevel@tonic-gate diskp->wide = get_prop(prop_name, pnode); 1654*7c478bd9Sstevel@tonic-gate } 1655*7c478bd9Sstevel@tonic-gate 1656*7c478bd9Sstevel@tonic-gate if (new_devpath(aliasp, devlink_path) != 0) { 1657*7c478bd9Sstevel@tonic-gate cache_free_alias(aliasp); 1658*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1659*7c478bd9Sstevel@tonic-gate } 1660*7c478bd9Sstevel@tonic-gate 1661*7c478bd9Sstevel@tonic-gate aliasp->next = diskp->aliases; 1662*7c478bd9Sstevel@tonic-gate diskp->aliases = aliasp; 1663*7c478bd9Sstevel@tonic-gate 1664*7c478bd9Sstevel@tonic-gate return (0); 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate /* 1668*7c478bd9Sstevel@tonic-gate * Append the new devpath to the end of the devpath list. This is important 1669*7c478bd9Sstevel@tonic-gate * since we may want to use the order of the devpaths to match up the vtoc 1670*7c478bd9Sstevel@tonic-gate * entries. 1671*7c478bd9Sstevel@tonic-gate */ 1672*7c478bd9Sstevel@tonic-gate static int 1673*7c478bd9Sstevel@tonic-gate new_devpath(alias_t *ap, char *devpath) 1674*7c478bd9Sstevel@tonic-gate { 1675*7c478bd9Sstevel@tonic-gate slice_t *newdp; 1676*7c478bd9Sstevel@tonic-gate slice_t *alistp; 1677*7c478bd9Sstevel@tonic-gate 1678*7c478bd9Sstevel@tonic-gate /* 1679*7c478bd9Sstevel@tonic-gate * First, search the alias list to be sure that this devpath is 1680*7c478bd9Sstevel@tonic-gate * not already there. 1681*7c478bd9Sstevel@tonic-gate */ 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate for (alistp = ap->devpaths; alistp != NULL; alistp = alistp->next) { 1684*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(alistp->devpath, devpath)) { 1685*7c478bd9Sstevel@tonic-gate return (0); 1686*7c478bd9Sstevel@tonic-gate } 1687*7c478bd9Sstevel@tonic-gate } 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate /* 1690*7c478bd9Sstevel@tonic-gate * Otherwise, not found so add this new devpath to the list. 1691*7c478bd9Sstevel@tonic-gate */ 1692*7c478bd9Sstevel@tonic-gate 1693*7c478bd9Sstevel@tonic-gate newdp = malloc(sizeof (slice_t)); 1694*7c478bd9Sstevel@tonic-gate if (newdp == NULL) { 1695*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1696*7c478bd9Sstevel@tonic-gate } 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate newdp->devpath = strdup(devpath); 1699*7c478bd9Sstevel@tonic-gate if (newdp->devpath == NULL) { 1700*7c478bd9Sstevel@tonic-gate free(newdp); 1701*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1702*7c478bd9Sstevel@tonic-gate } 1703*7c478bd9Sstevel@tonic-gate newdp->slice_num = -1; 1704*7c478bd9Sstevel@tonic-gate newdp->next = NULL; 1705*7c478bd9Sstevel@tonic-gate 1706*7c478bd9Sstevel@tonic-gate if (ap->devpaths == NULL) { 1707*7c478bd9Sstevel@tonic-gate ap->devpaths = newdp; 1708*7c478bd9Sstevel@tonic-gate } else { 1709*7c478bd9Sstevel@tonic-gate /* append the devpath to the end of the list */ 1710*7c478bd9Sstevel@tonic-gate slice_t *dp; 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate dp = ap->devpaths; 1713*7c478bd9Sstevel@tonic-gate while (dp->next != NULL) { 1714*7c478bd9Sstevel@tonic-gate dp = dp->next; 1715*7c478bd9Sstevel@tonic-gate } 1716*7c478bd9Sstevel@tonic-gate 1717*7c478bd9Sstevel@tonic-gate dp->next = newdp; 1718*7c478bd9Sstevel@tonic-gate } 1719*7c478bd9Sstevel@tonic-gate 1720*7c478bd9Sstevel@tonic-gate return (0); 1721*7c478bd9Sstevel@tonic-gate } 1722*7c478bd9Sstevel@tonic-gate 1723*7c478bd9Sstevel@tonic-gate static path_t * 1724*7c478bd9Sstevel@tonic-gate new_path(controller_t *cp, disk_t *dp, di_node_t node, di_path_state_t st, 1725*7c478bd9Sstevel@tonic-gate char *wwn) 1726*7c478bd9Sstevel@tonic-gate { 1727*7c478bd9Sstevel@tonic-gate char *devpath; 1728*7c478bd9Sstevel@tonic-gate path_t *pp; 1729*7c478bd9Sstevel@tonic-gate di_minor_t minor; 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate /* Special handling for fp attachment node. */ 1732*7c478bd9Sstevel@tonic-gate if (strcmp(di_node_name(node), "fp") == 0) { 1733*7c478bd9Sstevel@tonic-gate di_node_t pnode; 1734*7c478bd9Sstevel@tonic-gate 1735*7c478bd9Sstevel@tonic-gate pnode = di_parent_node(node); 1736*7c478bd9Sstevel@tonic-gate if (pnode != DI_NODE_NIL) { 1737*7c478bd9Sstevel@tonic-gate node = pnode; 1738*7c478bd9Sstevel@tonic-gate } 1739*7c478bd9Sstevel@tonic-gate } 1740*7c478bd9Sstevel@tonic-gate 1741*7c478bd9Sstevel@tonic-gate devpath = di_devfs_path(node); 1742*7c478bd9Sstevel@tonic-gate 1743*7c478bd9Sstevel@tonic-gate /* check if the path is already there */ 1744*7c478bd9Sstevel@tonic-gate pp = NULL; 1745*7c478bd9Sstevel@tonic-gate if (cp->paths != NULL) { 1746*7c478bd9Sstevel@tonic-gate int i; 1747*7c478bd9Sstevel@tonic-gate 1748*7c478bd9Sstevel@tonic-gate for (i = 0; cp->paths[i]; i++) { 1749*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(devpath, cp->paths[i]->name)) { 1750*7c478bd9Sstevel@tonic-gate pp = cp->paths[i]; 1751*7c478bd9Sstevel@tonic-gate break; 1752*7c478bd9Sstevel@tonic-gate } 1753*7c478bd9Sstevel@tonic-gate } 1754*7c478bd9Sstevel@tonic-gate } 1755*7c478bd9Sstevel@tonic-gate 1756*7c478bd9Sstevel@tonic-gate if (pp != NULL) { 1757*7c478bd9Sstevel@tonic-gate /* the path exists, add this disk to it */ 1758*7c478bd9Sstevel@tonic-gate 1759*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 1760*7c478bd9Sstevel@tonic-gate 1761*7c478bd9Sstevel@tonic-gate if (!add_disk2path(dp, pp, st, wwn)) { 1762*7c478bd9Sstevel@tonic-gate return (NULL); 1763*7c478bd9Sstevel@tonic-gate } 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate return (pp); 1766*7c478bd9Sstevel@tonic-gate } 1767*7c478bd9Sstevel@tonic-gate 1768*7c478bd9Sstevel@tonic-gate /* create a new path */ 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate pp = calloc(1, sizeof (path_t)); 1771*7c478bd9Sstevel@tonic-gate if (pp == NULL) { 1772*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 1773*7c478bd9Sstevel@tonic-gate return (NULL); 1774*7c478bd9Sstevel@tonic-gate } 1775*7c478bd9Sstevel@tonic-gate 1776*7c478bd9Sstevel@tonic-gate pp->name = strdup(devpath); 1777*7c478bd9Sstevel@tonic-gate di_devfs_path_free((void *) devpath); 1778*7c478bd9Sstevel@tonic-gate if (pp->name == NULL) { 1779*7c478bd9Sstevel@tonic-gate cache_free_path(pp); 1780*7c478bd9Sstevel@tonic-gate return (NULL); 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate /* add the disk to the path */ 1784*7c478bd9Sstevel@tonic-gate if (!add_disk2path(dp, pp, st, wwn)) { 1785*7c478bd9Sstevel@tonic-gate return (NULL); 1786*7c478bd9Sstevel@tonic-gate } 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate /* add the path to the controller */ 1789*7c478bd9Sstevel@tonic-gate if (add_ptr2array(pp, (void ***)&cp->paths) != 0) { 1790*7c478bd9Sstevel@tonic-gate cache_free_path(pp); 1791*7c478bd9Sstevel@tonic-gate return (NULL); 1792*7c478bd9Sstevel@tonic-gate } 1793*7c478bd9Sstevel@tonic-gate 1794*7c478bd9Sstevel@tonic-gate /* add the controller to the path */ 1795*7c478bd9Sstevel@tonic-gate pp->controller = cp; 1796*7c478bd9Sstevel@tonic-gate 1797*7c478bd9Sstevel@tonic-gate minor = di_minor_next(node, NULL); 1798*7c478bd9Sstevel@tonic-gate if (minor != NULL) { 1799*7c478bd9Sstevel@tonic-gate pp->ctype = ctype(node, minor); 1800*7c478bd9Sstevel@tonic-gate } else { 1801*7c478bd9Sstevel@tonic-gate pp->ctype = DM_CTYPE_UNKNOWN; 1802*7c478bd9Sstevel@tonic-gate } 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate return (pp); 1805*7c478bd9Sstevel@tonic-gate } 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate /* 1808*7c478bd9Sstevel@tonic-gate * We pass in the current controller pointer (currp) so we can double check 1809*7c478bd9Sstevel@tonic-gate * that we aren't corrupting the list by removing the element we are on. This 1810*7c478bd9Sstevel@tonic-gate * should never happen, but it doesn't hurt to double check. 1811*7c478bd9Sstevel@tonic-gate */ 1812*7c478bd9Sstevel@tonic-gate static void 1813*7c478bd9Sstevel@tonic-gate remove_invalid_controller(char *name, controller_t *currp, 1814*7c478bd9Sstevel@tonic-gate struct search_args *args) 1815*7c478bd9Sstevel@tonic-gate { 1816*7c478bd9Sstevel@tonic-gate controller_t *cp; 1817*7c478bd9Sstevel@tonic-gate bus_t *bp; 1818*7c478bd9Sstevel@tonic-gate controller_t *prevp; 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate bp = args->bus_listp; 1821*7c478bd9Sstevel@tonic-gate while (bp != NULL) { 1822*7c478bd9Sstevel@tonic-gate int i; 1823*7c478bd9Sstevel@tonic-gate 1824*7c478bd9Sstevel@tonic-gate for (i = 0; bp->controllers[i]; i++) { 1825*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(bp->controllers[i]->name, name)) { 1826*7c478bd9Sstevel@tonic-gate int j; 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate /* remove pointer to invalid controller (it is a path) */ 1829*7c478bd9Sstevel@tonic-gate for (j = i; bp->controllers[j]; j++) { 1830*7c478bd9Sstevel@tonic-gate bp->controllers[j] = bp->controllers[j + 1]; 1831*7c478bd9Sstevel@tonic-gate } 1832*7c478bd9Sstevel@tonic-gate } 1833*7c478bd9Sstevel@tonic-gate } 1834*7c478bd9Sstevel@tonic-gate bp = bp->next; 1835*7c478bd9Sstevel@tonic-gate } 1836*7c478bd9Sstevel@tonic-gate 1837*7c478bd9Sstevel@tonic-gate if (args->controller_listp == NULL) { 1838*7c478bd9Sstevel@tonic-gate return; 1839*7c478bd9Sstevel@tonic-gate } 1840*7c478bd9Sstevel@tonic-gate 1841*7c478bd9Sstevel@tonic-gate cp = args->controller_listp; 1842*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(cp->name, name)) { 1843*7c478bd9Sstevel@tonic-gate if (can_remove_controller(cp, currp)) { 1844*7c478bd9Sstevel@tonic-gate args->controller_listp = cp->next; 1845*7c478bd9Sstevel@tonic-gate cache_free_controller(cp); 1846*7c478bd9Sstevel@tonic-gate } 1847*7c478bd9Sstevel@tonic-gate return; 1848*7c478bd9Sstevel@tonic-gate } 1849*7c478bd9Sstevel@tonic-gate 1850*7c478bd9Sstevel@tonic-gate prevp = cp; 1851*7c478bd9Sstevel@tonic-gate cp = cp->next; 1852*7c478bd9Sstevel@tonic-gate while (cp != NULL) { 1853*7c478bd9Sstevel@tonic-gate if (libdiskmgt_str_eq(cp->name, name)) { 1854*7c478bd9Sstevel@tonic-gate if (can_remove_controller(cp, currp)) { 1855*7c478bd9Sstevel@tonic-gate prevp->next = cp->next; 1856*7c478bd9Sstevel@tonic-gate cache_free_controller(cp); 1857*7c478bd9Sstevel@tonic-gate } 1858*7c478bd9Sstevel@tonic-gate return; 1859*7c478bd9Sstevel@tonic-gate } 1860*7c478bd9Sstevel@tonic-gate prevp = cp; 1861*7c478bd9Sstevel@tonic-gate cp = cp->next; 1862*7c478bd9Sstevel@tonic-gate } 1863*7c478bd9Sstevel@tonic-gate } 1864*7c478bd9Sstevel@tonic-gate 1865*7c478bd9Sstevel@tonic-gate /* 1866*7c478bd9Sstevel@tonic-gate * This is the standard strstr code modified for case independence. 1867*7c478bd9Sstevel@tonic-gate */ 1868*7c478bd9Sstevel@tonic-gate static char * 1869*7c478bd9Sstevel@tonic-gate str_case_index(register char *s1, register char *s2) 1870*7c478bd9Sstevel@tonic-gate { 1871*7c478bd9Sstevel@tonic-gate uint_t s2len = strlen(s2); /* length of the second string */ 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate /* If the length of the second string is 0, return the first arg. */ 1874*7c478bd9Sstevel@tonic-gate if (s2len == 0) { 1875*7c478bd9Sstevel@tonic-gate return (s1); 1876*7c478bd9Sstevel@tonic-gate } 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate while (strlen(s1) >= s2len) { 1879*7c478bd9Sstevel@tonic-gate if (strncasecmp(s1, s2, s2len) == 0) { 1880*7c478bd9Sstevel@tonic-gate return (s1); 1881*7c478bd9Sstevel@tonic-gate } 1882*7c478bd9Sstevel@tonic-gate s1++; 1883*7c478bd9Sstevel@tonic-gate } 1884*7c478bd9Sstevel@tonic-gate return (NULL); 1885*7c478bd9Sstevel@tonic-gate } 1886