17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*66f9d5cbSmlf * Common Development and Distribution License (the "License"). 6*66f9d5cbSmlf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*66f9d5cbSmlf 227c478bd9Sstevel@tonic-gate /* 23*66f9d5cbSmlf * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <devfsadm.h> 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <limits.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #define SCSI_CFG_LINK_RE "^cfg/c[0-9]+$" 367c478bd9Sstevel@tonic-gate #define SBD_CFG_LINK_RE "^cfg/((((N[0-9]+[.])?(SB|IB))?[0-9]+)|[abcd])$" 377c478bd9Sstevel@tonic-gate #define USB_CFG_LINK_RE "^cfg/((usb[0-9]+)/([0-9]+)([.]([0-9])+)*)$" 387c478bd9Sstevel@tonic-gate #define PCI_CFG_LINK_RE "^cfg/[:alnum:]$" 397c478bd9Sstevel@tonic-gate #define IB_CFG_LINK_RE "^cfg/(hca[0-9A-F]+)$" 40*66f9d5cbSmlf #define SATA_CFG_LINK_RE "^cfg/((sata[0-9]+)/([0-9]+)([.]([0-9])+)*)$" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #define CFG_DIRNAME "cfg" 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static int scsi_cfg_creat_cb(di_minor_t minor, di_node_t node); 457c478bd9Sstevel@tonic-gate static int sbd_cfg_creat_cb(di_minor_t minor, di_node_t node); 467c478bd9Sstevel@tonic-gate static int usb_cfg_creat_cb(di_minor_t minor, di_node_t node); 477c478bd9Sstevel@tonic-gate static char *get_roothub(const char *path, void *cb_arg); 487c478bd9Sstevel@tonic-gate static int pci_cfg_creat_cb(di_minor_t minor, di_node_t node); 497c478bd9Sstevel@tonic-gate static int ib_cfg_creat_cb(di_minor_t minor, di_node_t node); 50*66f9d5cbSmlf static int sata_cfg_creat_cb(di_minor_t minor, di_node_t node); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate /* 537c478bd9Sstevel@tonic-gate * NOTE: The CREATE_DEFER flag is private to this module. 547c478bd9Sstevel@tonic-gate * NOT to be used by other modules 557c478bd9Sstevel@tonic-gate */ 567c478bd9Sstevel@tonic-gate static devfsadm_create_t cfg_create_cbt[] = { 577c478bd9Sstevel@tonic-gate { "attachment-point", "ddi_ctl:attachment_point:scsi", NULL, 587c478bd9Sstevel@tonic-gate TYPE_EXACT | CREATE_DEFER, ILEVEL_0, scsi_cfg_creat_cb 597c478bd9Sstevel@tonic-gate }, 607c478bd9Sstevel@tonic-gate { "attachment-point", "ddi_ctl:attachment_point:sbd", NULL, 617c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, sbd_cfg_creat_cb 627c478bd9Sstevel@tonic-gate }, 637c478bd9Sstevel@tonic-gate { "fc-attachment-point", "ddi_ctl:attachment_point:fc", NULL, 647c478bd9Sstevel@tonic-gate TYPE_EXACT | CREATE_DEFER, ILEVEL_0, scsi_cfg_creat_cb 657c478bd9Sstevel@tonic-gate }, 667c478bd9Sstevel@tonic-gate { "attachment-point", "ddi_ctl:attachment_point:usb", NULL, 677c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, usb_cfg_creat_cb 687c478bd9Sstevel@tonic-gate }, 697c478bd9Sstevel@tonic-gate { "attachment-point", "ddi_ctl:attachment_point:pci", NULL, 707c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, pci_cfg_creat_cb 717c478bd9Sstevel@tonic-gate }, 727c478bd9Sstevel@tonic-gate { "attachment-point", "ddi_ctl:attachment_point:ib", NULL, 737c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, ib_cfg_creat_cb 74*66f9d5cbSmlf }, 75*66f9d5cbSmlf { "attachment-point", "ddi_ctl:attachment_point:sata", NULL, 76*66f9d5cbSmlf TYPE_EXACT, ILEVEL_0, sata_cfg_creat_cb 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate }; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(cfg_create_cbt); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static devfsadm_remove_t cfg_remove_cbt[] = { 837c478bd9Sstevel@tonic-gate { "attachment-point", SCSI_CFG_LINK_RE, RM_POST, 847c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all 857c478bd9Sstevel@tonic-gate }, 867c478bd9Sstevel@tonic-gate { "attachment-point", SBD_CFG_LINK_RE, RM_POST, 877c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all 887c478bd9Sstevel@tonic-gate }, 897c478bd9Sstevel@tonic-gate { "fc-attachment-point", SCSI_CFG_LINK_RE, RM_POST, 907c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all 917c478bd9Sstevel@tonic-gate }, 927c478bd9Sstevel@tonic-gate { "attachment-point", USB_CFG_LINK_RE, RM_POST|RM_HOT|RM_ALWAYS, 937c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all 947c478bd9Sstevel@tonic-gate }, 957c478bd9Sstevel@tonic-gate { "attachment-point", PCI_CFG_LINK_RE, RM_POST, 967c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all 977c478bd9Sstevel@tonic-gate }, 987c478bd9Sstevel@tonic-gate { "attachment-point", IB_CFG_LINK_RE, RM_POST|RM_HOT|RM_ALWAYS, 997c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all 100*66f9d5cbSmlf }, 101*66f9d5cbSmlf { "attachment-point", SATA_CFG_LINK_RE, RM_POST|RM_HOT|RM_ALWAYS, 102*66f9d5cbSmlf ILEVEL_0, devfsadm_rm_all 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate }; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(cfg_remove_cbt); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static int 1097c478bd9Sstevel@tonic-gate scsi_cfg_creat_cb(di_minor_t minor, di_node_t node) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate char path[PATH_MAX + 1]; 1127c478bd9Sstevel@tonic-gate char *c_num = NULL, *devfs_path, *mn; 1137c478bd9Sstevel@tonic-gate devfsadm_enumerate_t rules[3] = { 1147c478bd9Sstevel@tonic-gate {"^r?dsk$/^c([0-9]+)", 1, MATCH_PARENT}, 1157c478bd9Sstevel@tonic-gate {"^cfg$/^c([0-9]+)$", 1, MATCH_ADDR}, 1167c478bd9Sstevel@tonic-gate {"^scsi$/^.+$/^c([0-9]+)", 1, MATCH_PARENT} 1177c478bd9Sstevel@tonic-gate }; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate mn = di_minor_name(minor); 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if ((devfs_path = di_devfs_path(node)) == NULL) { 1227c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate (void) strcpy(path, devfs_path); 1257c478bd9Sstevel@tonic-gate (void) strcat(path, ":"); 1267c478bd9Sstevel@tonic-gate (void) strcat(path, mn); 1277c478bd9Sstevel@tonic-gate di_devfs_path_free(devfs_path); 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if (devfsadm_enumerate_int(path, 1, &c_num, rules, 3) 1307c478bd9Sstevel@tonic-gate == DEVFSADM_FAILURE) { 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Unlike the disks module we don't retry on failure. 1337c478bd9Sstevel@tonic-gate * If we have multiple "c" numbers for a single physical 1347c478bd9Sstevel@tonic-gate * controller due to bug 4045879, we will not assign a 1357c478bd9Sstevel@tonic-gate * c-number/symlink for the controller. 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate (void) strcpy(path, CFG_DIRNAME); 1417c478bd9Sstevel@tonic-gate (void) strcat(path, "/c"); 1427c478bd9Sstevel@tonic-gate (void) strcat(path, c_num); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate free(c_num); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(path, node, minor, 0); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate static int 1527c478bd9Sstevel@tonic-gate sbd_cfg_creat_cb(di_minor_t minor, di_node_t node) 1537c478bd9Sstevel@tonic-gate { 1547c478bd9Sstevel@tonic-gate char path[PATH_MAX + 1]; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate (void) strcpy(path, CFG_DIRNAME); 1577c478bd9Sstevel@tonic-gate (void) strcat(path, "/"); 1587c478bd9Sstevel@tonic-gate (void) strcat(path, di_minor_name(minor)); 1597c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(path, node, minor, 0); 1607c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate static int 1657c478bd9Sstevel@tonic-gate usb_cfg_creat_cb(di_minor_t minor, di_node_t node) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate char *cp, path[PATH_MAX + 1]; 1687c478bd9Sstevel@tonic-gate devfsadm_enumerate_t rules[1] = 1697c478bd9Sstevel@tonic-gate {"^cfg$/^usb([0-9]+)$", 1, MATCH_CALLBACK, NULL, get_roothub}; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if ((cp = di_devfs_path(node)) == NULL) { 1727c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s:%s", cp, di_minor_name(minor)); 1767c478bd9Sstevel@tonic-gate di_devfs_path_free(cp); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (devfsadm_enumerate_int(path, 0, &cp, rules, 1)) { 1797c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* create usbN and the symlink */ 1837c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s/usb%s/%s", CFG_DIRNAME, cp, 1847c478bd9Sstevel@tonic-gate di_minor_name(minor)); 1857c478bd9Sstevel@tonic-gate free(cp); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(path, node, minor, 0); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate 193*66f9d5cbSmlf static int 194*66f9d5cbSmlf sata_cfg_creat_cb(di_minor_t minor, di_node_t node) 195*66f9d5cbSmlf { 196*66f9d5cbSmlf char path[PATH_MAX + 1], l_path[PATH_MAX], *buf, *devfspath; 197*66f9d5cbSmlf char *minor_nm; 198*66f9d5cbSmlf devfsadm_enumerate_t rules[1] = 199*66f9d5cbSmlf {"^cfg$/^sata([0-9]+)$", 1, MATCH_ADDR}; 200*66f9d5cbSmlf 201*66f9d5cbSmlf minor_nm = di_minor_name(minor); 202*66f9d5cbSmlf if (minor_nm == NULL) 203*66f9d5cbSmlf return (DEVFSADM_CONTINUE); 204*66f9d5cbSmlf 205*66f9d5cbSmlf devfspath = di_devfs_path(node); 206*66f9d5cbSmlf if (devfspath == NULL) 207*66f9d5cbSmlf return (DEVFSADM_CONTINUE); 208*66f9d5cbSmlf 209*66f9d5cbSmlf (void) strlcpy(path, devfspath, sizeof (path)); 210*66f9d5cbSmlf (void) strlcat(path, ":", sizeof (path)); 211*66f9d5cbSmlf (void) strlcat(path, minor_nm, sizeof (path)); 212*66f9d5cbSmlf di_devfs_path_free(devfspath); 213*66f9d5cbSmlf 214*66f9d5cbSmlf /* build the physical path from the components */ 215*66f9d5cbSmlf if (devfsadm_enumerate_int(path, 0, &buf, rules, 1) == 216*66f9d5cbSmlf DEVFSADM_FAILURE) { 217*66f9d5cbSmlf return (DEVFSADM_CONTINUE); 218*66f9d5cbSmlf } 219*66f9d5cbSmlf 220*66f9d5cbSmlf (void) snprintf(l_path, sizeof (l_path), "%s/sata%s/%s", CFG_DIRNAME, 221*66f9d5cbSmlf buf, minor_nm); 222*66f9d5cbSmlf free(buf); 223*66f9d5cbSmlf 224*66f9d5cbSmlf (void) devfsadm_mklink(l_path, node, minor, 0); 225*66f9d5cbSmlf 226*66f9d5cbSmlf return (DEVFSADM_CONTINUE); 227*66f9d5cbSmlf } 228*66f9d5cbSmlf 229*66f9d5cbSmlf 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * get_roothub: 2327c478bd9Sstevel@tonic-gate * figure out the root hub path to calculate /dev/cfg/usbN 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2357c478bd9Sstevel@tonic-gate static char * 2367c478bd9Sstevel@tonic-gate get_roothub(const char *path, void *cb_arg) 2377c478bd9Sstevel@tonic-gate { 2387c478bd9Sstevel@tonic-gate int i, count = 0; 2397c478bd9Sstevel@tonic-gate char *physpath, *cp; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* make a copy */ 2427c478bd9Sstevel@tonic-gate if ((physpath = strdup(path)) == NULL) { 2437c478bd9Sstevel@tonic-gate return (NULL); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * physpath must always have a minor name component 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate if ((cp = strrchr(physpath, ':')) == NULL) { 2507c478bd9Sstevel@tonic-gate free(physpath); 2517c478bd9Sstevel@tonic-gate return (NULL); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate *cp++ = '\0'; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* 2567c478bd9Sstevel@tonic-gate * No '.' in the minor name indicates a roothub port. 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate if (strchr(cp, '.') == NULL) { 2597c478bd9Sstevel@tonic-gate /* roothub device */ 2607c478bd9Sstevel@tonic-gate return (physpath); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate while (*cp) { 2647c478bd9Sstevel@tonic-gate if (*cp == '.') 2657c478bd9Sstevel@tonic-gate count++; 2667c478bd9Sstevel@tonic-gate cp++; 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* Remove as many trailing path components as there are '.'s */ 2707c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 2717c478bd9Sstevel@tonic-gate if ((cp = strrchr(physpath, '/')) == NULL || (cp == physpath)) { 2727c478bd9Sstevel@tonic-gate free(physpath); 2737c478bd9Sstevel@tonic-gate return (NULL); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate *cp = '\0'; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate return (physpath); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* 2837c478bd9Sstevel@tonic-gate * pci_cfg_creat_cb() search the <device mask> data from 2847c478bd9Sstevel@tonic-gate * "slot-names" PROM property for the match device number, 2857c478bd9Sstevel@tonic-gate * then create device link with the right slot label. 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate static int 2887c478bd9Sstevel@tonic-gate pci_cfg_creat_cb(di_minor_t minor, di_node_t node) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate char *minor_name, *dev_path; 2917c478bd9Sstevel@tonic-gate char path[PATH_MAX + 1]; 2927c478bd9Sstevel@tonic-gate int *devlink_flags; 2937c478bd9Sstevel@tonic-gate minor_t pci_dev; 2947c478bd9Sstevel@tonic-gate di_node_t dev_node; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate minor_name = di_minor_name(minor); 2977c478bd9Sstevel@tonic-gate pci_dev = (minor->dev_minor) & 0xFF; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate dev_path = di_devfs_path(node); 3007c478bd9Sstevel@tonic-gate dev_node = di_init(dev_path, DINFOCPYALL); 3017c478bd9Sstevel@tonic-gate if ((di_prop_lookup_ints(DDI_DEV_T_ANY, dev_node, 3027c478bd9Sstevel@tonic-gate "ap-names", &devlink_flags)) > 0) { 3037c478bd9Sstevel@tonic-gate if ((*devlink_flags) & (1 << pci_dev)) { 3047c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s/%s", 3057c478bd9Sstevel@tonic-gate CFG_DIRNAME, minor_name); 3067c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(path, node, minor, 0); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate di_fini(dev_node); 3107c478bd9Sstevel@tonic-gate (void) di_devfs_path_free(dev_path); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * ib_cfg_creat_cb() creates two types of links 3187c478bd9Sstevel@tonic-gate * One for the fabric as /dev/cfg/ib 3197c478bd9Sstevel@tonic-gate * Another for each HCA seen in the fabric as /dev/cfg/hca:<HCA-GUID> 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate static int 3227c478bd9Sstevel@tonic-gate ib_cfg_creat_cb(di_minor_t minor, di_node_t node) 3237c478bd9Sstevel@tonic-gate { 3247c478bd9Sstevel@tonic-gate char *cp; 3257c478bd9Sstevel@tonic-gate char path[PATH_MAX + 1]; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate if ((cp = di_devfs_path(node)) == NULL) { 3287c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s:%s", cp, di_minor_name(minor)); 3327c478bd9Sstevel@tonic-gate di_devfs_path_free(cp); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* create fabric or hca:GUID and the symlink */ 3357c478bd9Sstevel@tonic-gate if (strstr(path, "ib:fabric") != NULL) { 3367c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s/ib", CFG_DIRNAME); 3377c478bd9Sstevel@tonic-gate } else { 3387c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s/hca:%s", CFG_DIRNAME, 3397c478bd9Sstevel@tonic-gate di_minor_name(minor)); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(path, node, minor, 0); 3437c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3447c478bd9Sstevel@tonic-gate } 345