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 <devfsadm.h> 30*7c478bd9Sstevel@tonic-gate #include <stdio.h> 31*7c478bd9Sstevel@tonic-gate #include <strings.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <limits.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #define DISK_SUBPATH_MAX 100 37*7c478bd9Sstevel@tonic-gate #define RM_STALE 0x01 38*7c478bd9Sstevel@tonic-gate #define DISK_LINK_RE "^r?dsk/c[0-9]+(t[0-9A-F]+)?d[0-9]+(((s|p))[0-9]+)?$" 39*7c478bd9Sstevel@tonic-gate #define DISK_LINK_TO_UPPER(ch)\ 40*7c478bd9Sstevel@tonic-gate (((ch) >= 'a' && (ch) <= 'z') ? (ch - 'a' + 'A') : ch) 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #define SLICE_SMI "s7" 43*7c478bd9Sstevel@tonic-gate #define SLICE_EFI "" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #define MN_SMI "h" 46*7c478bd9Sstevel@tonic-gate #define MN_EFI "wd" 47*7c478bd9Sstevel@tonic-gate #define ASCIIWWNSIZE 255 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate static int disk_callback_chan(di_minor_t minor, di_node_t node); 50*7c478bd9Sstevel@tonic-gate static int disk_callback_nchan(di_minor_t minor, di_node_t node); 51*7c478bd9Sstevel@tonic-gate static int disk_callback_wwn(di_minor_t minor, di_node_t node); 52*7c478bd9Sstevel@tonic-gate static int disk_callback_fabric(di_minor_t minor, di_node_t node); 53*7c478bd9Sstevel@tonic-gate static void disk_common(di_minor_t minor, di_node_t node, char *disk, 54*7c478bd9Sstevel@tonic-gate int flags); 55*7c478bd9Sstevel@tonic-gate static char *diskctrl(di_node_t node, di_minor_t minor); 56*7c478bd9Sstevel@tonic-gate extern void rm_link_from_cache(char *devlink, char *physpath); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate static devfsadm_create_t disk_cbt[] = { 60*7c478bd9Sstevel@tonic-gate { "disk", "ddi_block", NULL, 61*7c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, disk_callback_nchan 62*7c478bd9Sstevel@tonic-gate }, 63*7c478bd9Sstevel@tonic-gate { "disk", "ddi_block:channel", NULL, 64*7c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, disk_callback_chan 65*7c478bd9Sstevel@tonic-gate }, 66*7c478bd9Sstevel@tonic-gate { "disk", "ddi_block:fabric", NULL, 67*7c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, disk_callback_fabric 68*7c478bd9Sstevel@tonic-gate }, 69*7c478bd9Sstevel@tonic-gate { "disk", "ddi_block:wwn", NULL, 70*7c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, disk_callback_wwn 71*7c478bd9Sstevel@tonic-gate }, 72*7c478bd9Sstevel@tonic-gate { "disk", "ddi_block:cdrom", NULL, 73*7c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, disk_callback_nchan 74*7c478bd9Sstevel@tonic-gate }, 75*7c478bd9Sstevel@tonic-gate { "disk", "ddi_block:cdrom:channel", NULL, 76*7c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, disk_callback_chan 77*7c478bd9Sstevel@tonic-gate }, 78*7c478bd9Sstevel@tonic-gate }; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(disk_cbt); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate /* 83*7c478bd9Sstevel@tonic-gate * HOT auto cleanup of disks not desired. 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate static devfsadm_remove_t disk_remove_cbt[] = { 86*7c478bd9Sstevel@tonic-gate { "disk", DISK_LINK_RE, RM_POST, 87*7c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate }; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(disk_remove_cbt); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate static int 94*7c478bd9Sstevel@tonic-gate disk_callback_chan(di_minor_t minor, di_node_t node) 95*7c478bd9Sstevel@tonic-gate { 96*7c478bd9Sstevel@tonic-gate char *addr; 97*7c478bd9Sstevel@tonic-gate char disk[20]; 98*7c478bd9Sstevel@tonic-gate uint_t targ; 99*7c478bd9Sstevel@tonic-gate uint_t lun; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate addr = di_bus_addr(node); 102*7c478bd9Sstevel@tonic-gate (void) sscanf(addr, "%X,%X", &targ, &lun); 103*7c478bd9Sstevel@tonic-gate (void) sprintf(disk, "t%dd%d", targ, lun); 104*7c478bd9Sstevel@tonic-gate disk_common(minor, node, disk, 0); 105*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate static int 110*7c478bd9Sstevel@tonic-gate disk_callback_nchan(di_minor_t minor, di_node_t node) 111*7c478bd9Sstevel@tonic-gate { 112*7c478bd9Sstevel@tonic-gate char *addr; 113*7c478bd9Sstevel@tonic-gate char disk[10]; 114*7c478bd9Sstevel@tonic-gate uint_t lun; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate addr = di_bus_addr(node); 117*7c478bd9Sstevel@tonic-gate (void) sscanf(addr, "%X", &lun); 118*7c478bd9Sstevel@tonic-gate (void) sprintf(disk, "d%d", lun); 119*7c478bd9Sstevel@tonic-gate disk_common(minor, node, disk, 0); 120*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate static int 125*7c478bd9Sstevel@tonic-gate disk_callback_wwn(di_minor_t minor, di_node_t node) 126*7c478bd9Sstevel@tonic-gate { 127*7c478bd9Sstevel@tonic-gate char disk[10]; 128*7c478bd9Sstevel@tonic-gate int lun; 129*7c478bd9Sstevel@tonic-gate int targ; 130*7c478bd9Sstevel@tonic-gate int *intp; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, 133*7c478bd9Sstevel@tonic-gate "target", &intp) <= 0) { 134*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate targ = *intp; 137*7c478bd9Sstevel@tonic-gate if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, 138*7c478bd9Sstevel@tonic-gate "lun", &intp) <= 0) { 139*7c478bd9Sstevel@tonic-gate lun = 0; 140*7c478bd9Sstevel@tonic-gate } else { 141*7c478bd9Sstevel@tonic-gate lun = *intp; 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate (void) sprintf(disk, "t%dd%d", targ, lun); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate disk_common(minor, node, disk, RM_STALE); 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate static int 151*7c478bd9Sstevel@tonic-gate disk_callback_fabric(di_minor_t minor, di_node_t node) 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate char disk[DISK_SUBPATH_MAX]; 154*7c478bd9Sstevel@tonic-gate int lun; 155*7c478bd9Sstevel@tonic-gate int count; 156*7c478bd9Sstevel@tonic-gate int *intp; 157*7c478bd9Sstevel@tonic-gate uchar_t *str; 158*7c478bd9Sstevel@tonic-gate uchar_t *wwn; 159*7c478bd9Sstevel@tonic-gate uchar_t ascii_wwn[ASCIIWWNSIZE]; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, 162*7c478bd9Sstevel@tonic-gate "client-guid", (char **)&wwn) > 0) { 163*7c478bd9Sstevel@tonic-gate if (strlcpy((char *)ascii_wwn, (char *)wwn, sizeof (ascii_wwn)) 164*7c478bd9Sstevel@tonic-gate >= sizeof (ascii_wwn)) { 165*7c478bd9Sstevel@tonic-gate devfsadm_errprint("SUNW_disk_link: GUID too long:%d", 166*7c478bd9Sstevel@tonic-gate strlen((char *)wwn)); 167*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate lun = 0; 170*7c478bd9Sstevel@tonic-gate } else if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, 171*7c478bd9Sstevel@tonic-gate "port-wwn", &wwn) > 0) { 172*7c478bd9Sstevel@tonic-gate if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, 173*7c478bd9Sstevel@tonic-gate "lun", &intp) > 0) { 174*7c478bd9Sstevel@tonic-gate lun = *intp; 175*7c478bd9Sstevel@tonic-gate } else { 176*7c478bd9Sstevel@tonic-gate lun = 0; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate for (count = 0, str = ascii_wwn; count < 8; count++, str += 2) { 180*7c478bd9Sstevel@tonic-gate (void) sprintf((caddr_t)str, "%02x", wwn[count]); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate *str = '\0'; 183*7c478bd9Sstevel@tonic-gate } else { 184*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate for (str = ascii_wwn; *str != '\0'; str++) { 188*7c478bd9Sstevel@tonic-gate *str = DISK_LINK_TO_UPPER(*str); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate (void) snprintf(disk, DISK_SUBPATH_MAX, "t%sd%d", ascii_wwn, lun); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate disk_common(minor, node, disk, RM_STALE); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * This function is called for every disk minor node. 200*7c478bd9Sstevel@tonic-gate * Calls enumerate to assign a logical controller number, and 201*7c478bd9Sstevel@tonic-gate * then devfsadm_mklink to make the link. 202*7c478bd9Sstevel@tonic-gate */ 203*7c478bd9Sstevel@tonic-gate static void 204*7c478bd9Sstevel@tonic-gate disk_common(di_minor_t minor, di_node_t node, char *disk, int flags) 205*7c478bd9Sstevel@tonic-gate { 206*7c478bd9Sstevel@tonic-gate char l_path[PATH_MAX + 1]; 207*7c478bd9Sstevel@tonic-gate char stale_re[DISK_SUBPATH_MAX]; 208*7c478bd9Sstevel@tonic-gate char *dir; 209*7c478bd9Sstevel@tonic-gate char slice[4]; 210*7c478bd9Sstevel@tonic-gate char *mn; 211*7c478bd9Sstevel@tonic-gate char *ctrl; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (strstr(mn = di_minor_name(minor), ",raw")) { 214*7c478bd9Sstevel@tonic-gate dir = "rdsk"; 215*7c478bd9Sstevel@tonic-gate } else { 216*7c478bd9Sstevel@tonic-gate dir = "dsk"; 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate if (mn[0] < 113) { 220*7c478bd9Sstevel@tonic-gate (void) sprintf(slice, "s%d", mn[0] - 'a'); 221*7c478bd9Sstevel@tonic-gate } else if (strncmp(mn, MN_EFI, 2) != 0) { 222*7c478bd9Sstevel@tonic-gate (void) sprintf(slice, "p%d", mn[0] - 'q'); 223*7c478bd9Sstevel@tonic-gate } else { 224*7c478bd9Sstevel@tonic-gate /* For EFI label */ 225*7c478bd9Sstevel@tonic-gate (void) sprintf(slice, SLICE_EFI); 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate if (NULL == (ctrl = diskctrl(node, minor))) 229*7c478bd9Sstevel@tonic-gate return; 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate (void) strcpy(l_path, dir); 232*7c478bd9Sstevel@tonic-gate (void) strcat(l_path, "/c"); 233*7c478bd9Sstevel@tonic-gate (void) strcat(l_path, ctrl); 234*7c478bd9Sstevel@tonic-gate (void) strcat(l_path, disk); 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * If switching between SMI and EFI label or vice versa 238*7c478bd9Sstevel@tonic-gate * cleanup the previous label's devlinks. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate if (*mn == *(MN_SMI) || (strncmp(mn, MN_EFI, 2) == 0)) { 241*7c478bd9Sstevel@tonic-gate char *s, tpath[PATH_MAX + 1]; 242*7c478bd9Sstevel@tonic-gate struct stat sb; 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate s = l_path + strlen(l_path); 245*7c478bd9Sstevel@tonic-gate (void) strcat(l_path, (*mn == *(MN_SMI)) 246*7c478bd9Sstevel@tonic-gate ? SLICE_EFI : SLICE_SMI); 247*7c478bd9Sstevel@tonic-gate /* 248*7c478bd9Sstevel@tonic-gate * Attempt the remove only if the stale link exists 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate (void) snprintf(tpath, sizeof (tpath), "%s/dev/%s", 251*7c478bd9Sstevel@tonic-gate devfsadm_root_path(), l_path); 252*7c478bd9Sstevel@tonic-gate if (lstat(tpath, &sb) != -1) 253*7c478bd9Sstevel@tonic-gate devfsadm_rm_all(l_path); 254*7c478bd9Sstevel@tonic-gate *s = '\0'; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate (void) strcat(l_path, slice); 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate if ((flags & RM_STALE) == RM_STALE) { 261*7c478bd9Sstevel@tonic-gate (void) strcpy(stale_re, "^"); 262*7c478bd9Sstevel@tonic-gate (void) strcat(stale_re, dir); 263*7c478bd9Sstevel@tonic-gate (void) strcat(stale_re, "/c"); 264*7c478bd9Sstevel@tonic-gate (void) strcat(stale_re, ctrl); 265*7c478bd9Sstevel@tonic-gate (void) strcat(stale_re, "t[0-9A-F]+d[0-9]+(s[0-9]+)?$"); 266*7c478bd9Sstevel@tonic-gate /* 267*7c478bd9Sstevel@tonic-gate * optimizations are made inside of devfsadm_rm_stale_links 268*7c478bd9Sstevel@tonic-gate * instead of before calling the function, as it always 269*7c478bd9Sstevel@tonic-gate * needs to add the valid link to the cache. 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate devfsadm_rm_stale_links(stale_re, l_path, node, minor); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate free(ctrl); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* index of enumeration rule applicable to this module */ 279*7c478bd9Sstevel@tonic-gate #define RULE_INDEX 0 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate static char * 282*7c478bd9Sstevel@tonic-gate diskctrl(di_node_t node, di_minor_t minor) 283*7c478bd9Sstevel@tonic-gate { 284*7c478bd9Sstevel@tonic-gate char path[PATH_MAX + 1]; 285*7c478bd9Sstevel@tonic-gate char *devfspath; 286*7c478bd9Sstevel@tonic-gate char *buf, *mn; 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate devfsadm_enumerate_t rules[3] = { 289*7c478bd9Sstevel@tonic-gate {"^r?dsk$/^c([0-9]+)", 1, MATCH_PARENT}, 290*7c478bd9Sstevel@tonic-gate {"^cfg$/^c([0-9]+)$", 1, MATCH_ADDR}, 291*7c478bd9Sstevel@tonic-gate {"^scsi$/^.+$/^c([0-9]+)", 1, MATCH_PARENT} 292*7c478bd9Sstevel@tonic-gate }; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate mn = di_minor_name(minor); 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate if ((devfspath = di_devfs_path(node)) == NULL) { 297*7c478bd9Sstevel@tonic-gate return (NULL); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate (void) strcpy(path, devfspath); 300*7c478bd9Sstevel@tonic-gate (void) strcat(path, ":"); 301*7c478bd9Sstevel@tonic-gate (void) strcat(path, mn); 302*7c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * Use controller component of disk path 306*7c478bd9Sstevel@tonic-gate */ 307*7c478bd9Sstevel@tonic-gate if (disk_enumerate_int(path, RULE_INDEX, &buf, rules, 3) == 308*7c478bd9Sstevel@tonic-gate DEVFSADM_MULTIPLE) { 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * We failed because there are multiple logical controller 312*7c478bd9Sstevel@tonic-gate * numbers for a single physical controller. If we use node 313*7c478bd9Sstevel@tonic-gate * name also in the match it should fix this and only find one 314*7c478bd9Sstevel@tonic-gate * logical controller. (See 4045879). 315*7c478bd9Sstevel@tonic-gate * NOTE: Rules for controllers are not changed, as there is 316*7c478bd9Sstevel@tonic-gate * no unique controller number for them in this case. 317*7c478bd9Sstevel@tonic-gate * 318*7c478bd9Sstevel@tonic-gate * MATCH_UNCACHED flag is private to the "disks" and "sgen" 319*7c478bd9Sstevel@tonic-gate * modules. NOT to be used by other modules. 320*7c478bd9Sstevel@tonic-gate */ 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate rules[0].flags = MATCH_NODE | MATCH_UNCACHED; /* disks */ 323*7c478bd9Sstevel@tonic-gate rules[2].flags = MATCH_NODE | MATCH_UNCACHED; /* generic scsi */ 324*7c478bd9Sstevel@tonic-gate if (devfsadm_enumerate_int(path, RULE_INDEX, &buf, rules, 3)) { 325*7c478bd9Sstevel@tonic-gate return (NULL); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate return (buf); 330*7c478bd9Sstevel@tonic-gate } 331