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 2005 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 #include "mdescplugin.h"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate static char *device_format_disk_name(char *devfs_path);
30*7c478bd9Sstevel@tonic-gate static char *device_get_disk_name_from_dir(char *basedir, char *path);
31*7c478bd9Sstevel@tonic-gate static cfga_list_data_t *device_get_disk_cfga_info(char *cfgpath);
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /* These 3 variable are defined and set in mdescplugin.c */
34*7c478bd9Sstevel@tonic-gate extern picl_nodehdl_t	root_node;
35*7c478bd9Sstevel@tonic-gate extern md_t		*mdp;
36*7c478bd9Sstevel@tonic-gate extern mde_cookie_t	rootnode;
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate /* This routine is defined in cpu_prop_update.c */
39*7c478bd9Sstevel@tonic-gate extern void set_prop_info(ptree_propinfo_t *propinfo, int size, char *name,
40*7c478bd9Sstevel@tonic-gate     int type);
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate int
disk_discovery(void)43*7c478bd9Sstevel@tonic-gate disk_discovery(void)
44*7c478bd9Sstevel@tonic-gate {
45*7c478bd9Sstevel@tonic-gate 	int			status = PICL_FAILURE;
46*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		discovery_node;
47*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		new_node;
48*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
49*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		proph;
50*7c478bd9Sstevel@tonic-gate 	char			*cfgpath, *dev_path, *nac;
51*7c478bd9Sstevel@tonic-gate 	cfga_list_data_t	*disk_data;
52*7c478bd9Sstevel@tonic-gate 	int			x, num_nodes, ndisks;
53*7c478bd9Sstevel@tonic-gate 	mde_cookie_t		*disklistp;
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate 	num_nodes = md_node_count(mdp);
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate 	disklistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes);
58*7c478bd9Sstevel@tonic-gate 	if (disklistp == NULL) {
59*7c478bd9Sstevel@tonic-gate 		return (status);
60*7c478bd9Sstevel@tonic-gate 	}
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate 	/*
63*7c478bd9Sstevel@tonic-gate 	 * Starting at the root node, scan the "fwd" dag for
64*7c478bd9Sstevel@tonic-gate 	 * all the disks in this description.
65*7c478bd9Sstevel@tonic-gate 	 */
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate 	ndisks = md_scan_dag(mdp, rootnode, md_find_name(mdp, "disk_nac"),
68*7c478bd9Sstevel@tonic-gate 	    md_find_name(mdp, "fwd"), disklistp);
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate 	if (ndisks <= 0) {
71*7c478bd9Sstevel@tonic-gate 		return (status);
72*7c478bd9Sstevel@tonic-gate 	}
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate 	status = ptree_create_and_add_node(root_node, DISK_DISCOVERY_NAME,
75*7c478bd9Sstevel@tonic-gate 	    PICL_CLASS_PICL, &discovery_node);
76*7c478bd9Sstevel@tonic-gate 	if (status != PICL_SUCCESS)
77*7c478bd9Sstevel@tonic-gate 		return (status);
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 	for (x = 0; x < ndisks; x++) {
80*7c478bd9Sstevel@tonic-gate 		if (md_get_prop_str(mdp, disklistp[x], "phys_path",
81*7c478bd9Sstevel@tonic-gate 			&dev_path) != 0) {
82*7c478bd9Sstevel@tonic-gate 			continue;
83*7c478bd9Sstevel@tonic-gate 		}
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 		if (md_get_prop_str(mdp, disklistp[x], "nac_name",
86*7c478bd9Sstevel@tonic-gate 			&nac) != 0) {
87*7c478bd9Sstevel@tonic-gate 			continue;
88*7c478bd9Sstevel@tonic-gate 		}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 		(void) ptree_create_and_add_node(discovery_node, "disk",
91*7c478bd9Sstevel@tonic-gate 		    PICL_CLASS_DISK, &new_node);
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 		set_prop_info(&propinfo, PICL_PROPNAMELEN_MAX, "Path",
94*7c478bd9Sstevel@tonic-gate 		    PICL_PTYPE_CHARSTRING);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 		(void) ptree_create_and_add_prop(new_node, &propinfo,
97*7c478bd9Sstevel@tonic-gate 		    (void *)dev_path, &proph);
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 		set_prop_info(&propinfo, PICL_PROPNAMELEN_MAX, "Location",
100*7c478bd9Sstevel@tonic-gate 		    PICL_PTYPE_CHARSTRING);
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 		(void) ptree_create_and_add_prop(new_node, &propinfo,
103*7c478bd9Sstevel@tonic-gate 		    (void *)nac, &proph);
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 		set_prop_info(&propinfo, PICL_PROPNAMELEN_MAX, "State",
106*7c478bd9Sstevel@tonic-gate 		    PICL_PTYPE_CHARSTRING);
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 		cfgpath = device_format_disk_name(dev_path);
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate 		if (cfgpath == NULL) {
111*7c478bd9Sstevel@tonic-gate 			(void) ptree_create_and_add_prop(new_node, &propinfo,
112*7c478bd9Sstevel@tonic-gate 			    (void *)strdup(UNCONFIGURED), &proph);
113*7c478bd9Sstevel@tonic-gate 			continue;
114*7c478bd9Sstevel@tonic-gate 		}
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 		disk_data = device_get_disk_cfga_info(cfgpath);
117*7c478bd9Sstevel@tonic-gate 		if (disk_data == NULL) {
118*7c478bd9Sstevel@tonic-gate 			continue;
119*7c478bd9Sstevel@tonic-gate 		}
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 		switch (disk_data->ap_o_state) {
122*7c478bd9Sstevel@tonic-gate 		case CFGA_STAT_UNCONFIGURED:
123*7c478bd9Sstevel@tonic-gate 			(void) ptree_create_and_add_prop(new_node, &propinfo,
124*7c478bd9Sstevel@tonic-gate 			    (void *)strdup(UNCONFIGURED), &proph);
125*7c478bd9Sstevel@tonic-gate 			break;
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 		case CFGA_STAT_CONFIGURED:
128*7c478bd9Sstevel@tonic-gate 			(void) ptree_create_and_add_prop(new_node, &propinfo,
129*7c478bd9Sstevel@tonic-gate 			    (void *)strdup(CONFIGURED), &proph);
130*7c478bd9Sstevel@tonic-gate 			break;
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 		default:
133*7c478bd9Sstevel@tonic-gate 			break;
134*7c478bd9Sstevel@tonic-gate 		}
135*7c478bd9Sstevel@tonic-gate 	}
136*7c478bd9Sstevel@tonic-gate 	return (status);
137*7c478bd9Sstevel@tonic-gate }
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate static cfga_list_data_t *
device_get_disk_cfga_info(char * cfgpath)140*7c478bd9Sstevel@tonic-gate device_get_disk_cfga_info(char *cfgpath)
141*7c478bd9Sstevel@tonic-gate {
142*7c478bd9Sstevel@tonic-gate 	char			**apid_names;
143*7c478bd9Sstevel@tonic-gate 	char			apid_name[CFGA_AP_LOG_ID_LEN];
144*7c478bd9Sstevel@tonic-gate 	cfga_err_t		cfga_err;
145*7c478bd9Sstevel@tonic-gate 	struct cfga_list_data	*list_data;
146*7c478bd9Sstevel@tonic-gate 	int			list_len, count;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	(void) strcpy(apid_name, cfgpath);
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	apid_names = (char **)malloc(2 * sizeof (char *));
151*7c478bd9Sstevel@tonic-gate 	apid_names[0] = apid_name;
152*7c478bd9Sstevel@tonic-gate 	apid_names[1] = NULL;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	cfga_err = config_list_ext(1, (char * const *)apid_names, &list_data,
155*7c478bd9Sstevel@tonic-gate 	    &list_len, NULL, NULL, NULL, CFGA_FLAG_LIST_ALL);
156*7c478bd9Sstevel@tonic-gate 	free(apid_names);
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	if (cfga_err != CFGA_OK || list_len == 0) {
159*7c478bd9Sstevel@tonic-gate 		return (NULL);
160*7c478bd9Sstevel@tonic-gate 	}
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	/* free any extra entries if this is not unique */
163*7c478bd9Sstevel@tonic-gate 	if (list_len > 1) {
164*7c478bd9Sstevel@tonic-gate 		for (count = 1; count < list_len; count++) {
165*7c478bd9Sstevel@tonic-gate 			free(&list_data[count]);
166*7c478bd9Sstevel@tonic-gate 		}
167*7c478bd9Sstevel@tonic-gate 	}
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	return (&list_data[0]);
170*7c478bd9Sstevel@tonic-gate }
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate static char *
device_format_disk_name(char * devfs_path)174*7c478bd9Sstevel@tonic-gate device_format_disk_name(char *devfs_path)
175*7c478bd9Sstevel@tonic-gate {
176*7c478bd9Sstevel@tonic-gate 	char	devname[256];
177*7c478bd9Sstevel@tonic-gate 	char	*diskname, *dev_cpy;
178*7c478bd9Sstevel@tonic-gate 	char	apid_name[CFGA_AP_LOG_ID_LEN];
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	(void) snprintf(devname, sizeof (devname), "/devices%s:a,raw",
181*7c478bd9Sstevel@tonic-gate 	    devfs_path);
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	diskname = device_get_disk_name_from_dir("/dev/rdsk", devname);
184*7c478bd9Sstevel@tonic-gate 	if (diskname != NULL) {
185*7c478bd9Sstevel@tonic-gate 		*strrchr(diskname, 's') = '\0';
186*7c478bd9Sstevel@tonic-gate 		dev_cpy = strdup(diskname);
187*7c478bd9Sstevel@tonic-gate 		*strchr(dev_cpy, 't') = '\0';
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 		(void) snprintf(apid_name, sizeof (apid_name), "%s::dsk/%s",
190*7c478bd9Sstevel@tonic-gate 			dev_cpy, diskname);
191*7c478bd9Sstevel@tonic-gate 		return (strdup(apid_name));
192*7c478bd9Sstevel@tonic-gate 	}
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	return (NULL);
195*7c478bd9Sstevel@tonic-gate }
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate /*
198*7c478bd9Sstevel@tonic-gate  * Getting a disk name is annoying.  Walking controllers
199*7c478bd9Sstevel@tonic-gate  * doesn't work if disks were added out of order (ie a new
200*7c478bd9Sstevel@tonic-gate  * controller card was installed), and DKIO controller numbers
201*7c478bd9Sstevel@tonic-gate  * seem to always be 0.  So we do it the old fashioned way:
202*7c478bd9Sstevel@tonic-gate  *
203*7c478bd9Sstevel@tonic-gate  * We get a target name (in the /devices tree), and we want
204*7c478bd9Sstevel@tonic-gate  * the node in /dev/rdsk that is a symlink to it.  So we walk
205*7c478bd9Sstevel@tonic-gate  * /dev/rdsk, stating each entry.  Since stat follows the symlink
206*7c478bd9Sstevel@tonic-gate  * automatically, we just compare the device and inode numbers
207*7c478bd9Sstevel@tonic-gate  * to the device and inode numbers of the target.  According to
208*7c478bd9Sstevel@tonic-gate  * the stat man page, this constitues a unique match.  The only
209*7c478bd9Sstevel@tonic-gate  * little cleanup is that this includes a slice #, which we take
210*7c478bd9Sstevel@tonic-gate  *  off.
211*7c478bd9Sstevel@tonic-gate  */
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate static char *
device_get_disk_name_from_dir(char * basedir,char * path)214*7c478bd9Sstevel@tonic-gate device_get_disk_name_from_dir(char *basedir, char *path)
215*7c478bd9Sstevel@tonic-gate {
216*7c478bd9Sstevel@tonic-gate 	DIR		*dir;
217*7c478bd9Sstevel@tonic-gate 	struct dirent	*dirent;
218*7c478bd9Sstevel@tonic-gate 	struct stat	srcstat, targstat;
219*7c478bd9Sstevel@tonic-gate 	int		loc_err;
220*7c478bd9Sstevel@tonic-gate 	char		fullname[256 + MAXNAMLEN];
221*7c478bd9Sstevel@tonic-gate 	char		*ptr;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	loc_err = stat(path, &srcstat);
224*7c478bd9Sstevel@tonic-gate 	if (loc_err < 0) {
225*7c478bd9Sstevel@tonic-gate 		return (NULL);
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	dir = opendir(basedir);
229*7c478bd9Sstevel@tonic-gate 	if (dir == NULL) {
230*7c478bd9Sstevel@tonic-gate 		return (NULL);
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	while ((dirent = readdir(dir)) != NULL) {
234*7c478bd9Sstevel@tonic-gate 		(void) snprintf(fullname, sizeof (fullname),
235*7c478bd9Sstevel@tonic-gate 			"%s/%s", basedir, dirent->d_name);
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 		loc_err = stat(fullname, &targstat);
238*7c478bd9Sstevel@tonic-gate 		if (loc_err == 0) {
239*7c478bd9Sstevel@tonic-gate 			if ((memcmp((void *)&(targstat.st_ino),
240*7c478bd9Sstevel@tonic-gate 				(void *)&(srcstat.st_ino),
241*7c478bd9Sstevel@tonic-gate 				sizeof (ino_t)) == 0) &&
242*7c478bd9Sstevel@tonic-gate 				(memcmp((void *)&(targstat.st_dev),
243*7c478bd9Sstevel@tonic-gate 				(void *)&(srcstat.st_dev),
244*7c478bd9Sstevel@tonic-gate 				sizeof (dev_t)) == 0)) {
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 				ptr = strdup(dirent->d_name);
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 				(void) closedir(dir);
249*7c478bd9Sstevel@tonic-gate 				return (ptr);
250*7c478bd9Sstevel@tonic-gate 			}
251*7c478bd9Sstevel@tonic-gate 		}
252*7c478bd9Sstevel@tonic-gate 	}
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	(void) closedir(dir);
255*7c478bd9Sstevel@tonic-gate 	return (NULL);
256*7c478bd9Sstevel@tonic-gate }
257