1*a08731ecScth /* 2*a08731ecScth * CDDL HEADER START 3*a08731ecScth * 4*a08731ecScth * The contents of this file are subject to the terms of the 5*a08731ecScth * Common Development and Distribution License (the "License"). 6*a08731ecScth * You may not use this file except in compliance with the License. 7*a08731ecScth * 8*a08731ecScth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*a08731ecScth * or http://www.opensolaris.org/os/licensing. 10*a08731ecScth * See the License for the specific language governing permissions 11*a08731ecScth * and limitations under the License. 12*a08731ecScth * 13*a08731ecScth * When distributing Covered Code, include this CDDL HEADER in each 14*a08731ecScth * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*a08731ecScth * If applicable, add the following below this CDDL HEADER, with the 16*a08731ecScth * fields enclosed by brackets "[]" replaced with your own identifying 17*a08731ecScth * information: Portions Copyright [yyyy] [name of copyright owner] 18*a08731ecScth * 19*a08731ecScth * CDDL HEADER END 20*a08731ecScth */ 21*a08731ecScth /* 22*a08731ecScth * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*a08731ecScth * Use is subject to license terms. 24*a08731ecScth */ 25*a08731ecScth 26*a08731ecScth #pragma ident "%Z%%M% %I% %E% SMI" 27*a08731ecScth 28*a08731ecScth #include "libdevinfo.h" 29*a08731ecScth #include <strings.h> 30*a08731ecScth #include <sys/modctl.h> 31*a08731ecScth 32*a08731ecScth /* 33*a08731ecScth * 34*a08731ecScth * This file contains interfaces to translate <driver><instance><minorname> 35*a08731ecScth * information into /devices and /dev paths. It does this using interfaces to 36*a08731ecScth * the kernel instance tree so that it can provide translations for devices 37*a08731ecScth * which are no longer present. An example consumer of these interfaces is 38*a08731ecScth * iostat(1M) - which shows, in its first iteration, activity since reboot. 39*a08731ecScth * With persistant kstats, a device which was busy a long time ago can still 40*a08731ecScth * have a decaying presence in iostat output, and that output, when '-n' is 41*a08731ecScth * used, should show the public name. 42*a08731ecScth */ 43*a08731ecScth 44*a08731ecScth typedef struct { 45*a08731ecScth di_devlink_handle_t i_devlink_hdl; 46*a08731ecScth } *idim_t; 47*a08731ecScth 48*a08731ecScth di_dim_t 49*a08731ecScth di_dim_init() 50*a08731ecScth { 51*a08731ecScth idim_t idim; 52*a08731ecScth 53*a08731ecScth if ((idim = (idim_t)malloc(sizeof (*idim))) == NULL) 54*a08731ecScth return (NULL); 55*a08731ecScth idim->i_devlink_hdl = di_devlink_init(NULL, 0); 56*a08731ecScth if (idim->i_devlink_hdl == NULL) { 57*a08731ecScth free(idim); 58*a08731ecScth return (NULL); 59*a08731ecScth } 60*a08731ecScth return ((di_dim_t)idim); 61*a08731ecScth } 62*a08731ecScth 63*a08731ecScth void 64*a08731ecScth di_dim_fini(di_dim_t dim) 65*a08731ecScth { 66*a08731ecScth idim_t idim = (idim_t)dim; 67*a08731ecScth 68*a08731ecScth if (idim->i_devlink_hdl) { 69*a08731ecScth (void) di_devlink_fini(&idim->i_devlink_hdl); 70*a08731ecScth } 71*a08731ecScth free(idim); 72*a08731ecScth } 73*a08731ecScth 74*a08731ecScth /*ARGSUSED*/ 75*a08731ecScth char * 76*a08731ecScth di_dim_path_devices(di_dim_t dim, char *drv_name, int instance, 77*a08731ecScth char *minor_name) 78*a08731ecScth { 79*a08731ecScth major_t major; 80*a08731ecScth int len; 81*a08731ecScth int mlen; 82*a08731ecScth char *devices; 83*a08731ecScth 84*a08731ecScth /* convert drv_name to major_t */ 85*a08731ecScth if (modctl(MODGETMAJBIND, drv_name, strlen(drv_name) + 1, &major) < 0) 86*a08731ecScth return (NULL); 87*a08731ecScth 88*a08731ecScth /* find the length of the devices path given major,instance */ 89*a08731ecScth if (modctl(MODGETDEVFSPATH_MI_LEN, major, instance, &len) != 0) 90*a08731ecScth return (NULL); 91*a08731ecScth 92*a08731ecScth /* 93*a08731ecScth * MODGETDEVFSPATH_MI_LEN result includes '\0' termination, but we 94*a08731ecScth * may need to add space for ":<minor_name>" 95*a08731ecScth */ 96*a08731ecScth if (minor_name) 97*a08731ecScth mlen = len + 1 + strlen(minor_name); 98*a08731ecScth else 99*a08731ecScth mlen = len; 100*a08731ecScth if ((devices = (char *)malloc(mlen)) == NULL) 101*a08731ecScth return (NULL); 102*a08731ecScth 103*a08731ecScth if (modctl(MODGETDEVFSPATH_MI, major, instance, len, devices) != 0) { 104*a08731ecScth free(devices); 105*a08731ecScth return (NULL); 106*a08731ecScth } 107*a08731ecScth 108*a08731ecScth if (minor_name) { 109*a08731ecScth /* add ':<minot_name>' to the end of /devices path */ 110*a08731ecScth (void) strcat(devices, ":"); 111*a08731ecScth (void) strcat(devices, minor_name); 112*a08731ecScth } 113*a08731ecScth return (devices); 114*a08731ecScth } 115*a08731ecScth 116*a08731ecScth /* di_dim_path_dev di_devlink callback */ 117*a08731ecScth static int 118*a08731ecScth di_dim_path_dev_callback(di_devlink_t dl, void *arg) 119*a08731ecScth { 120*a08731ecScth char **devp = (char **)arg; 121*a08731ecScth char *devpath = (char *)di_devlink_path(dl); 122*a08731ecScth 123*a08731ecScth if (devpath) 124*a08731ecScth *devp = strdup(devpath); 125*a08731ecScth return (DI_WALK_TERMINATE); 126*a08731ecScth } 127*a08731ecScth 128*a08731ecScth char * 129*a08731ecScth di_dim_path_dev(di_dim_t dim, char *drv_name, int instance, char *minor_name) 130*a08731ecScth { 131*a08731ecScth idim_t idim = (idim_t)dim; 132*a08731ecScth char *devices; 133*a08731ecScth char *dev = NULL; 134*a08731ecScth 135*a08731ecScth /* we must have a minor_name to resolve to a public name */ 136*a08731ecScth if (minor_name == NULL) 137*a08731ecScth return (NULL); 138*a08731ecScth 139*a08731ecScth /* convert <driver><instance><minor_name> to /devices path */ 140*a08731ecScth devices = di_dim_path_devices(dim, drv_name, instance, minor_name); 141*a08731ecScth if (devices == NULL) 142*a08731ecScth return (NULL); 143*a08731ecScth 144*a08731ecScth /* convert /devices path to /dev path */ 145*a08731ecScth (void) di_devlink_walk(idim->i_devlink_hdl, NULL, 146*a08731ecScth devices, DI_PRIMARY_LINK, (void *)&dev, di_dim_path_dev_callback); 147*a08731ecScth free(devices); 148*a08731ecScth return (dev); 149*a08731ecScth } 150