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