4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include "mdescplugin.h"
31 static char *device_format_disk_name(char *devfs_path
);
32 static char *device_get_disk_name_from_dir(char *basedir
, char *path
);
33 static cfga_list_data_t
*device_get_disk_cfga_info(char *cfgpath
);
35 /* These 3 variable are defined and set in mdescplugin.c */
36 extern picl_nodehdl_t root_node
;
38 extern mde_cookie_t rootnode
;
40 /* This routine is defined in cpu_prop_update.c */
41 extern void set_prop_info(ptree_propinfo_t
*propinfo
, int size
, char *name
,
47 int status
= PICL_FAILURE
;
48 picl_nodehdl_t discovery_node
;
49 picl_nodehdl_t new_node
;
50 ptree_propinfo_t propinfo
;
52 char *cfgpath
, *dev_path
, *nac
;
53 cfga_list_data_t
*disk_data
;
54 int x
, num_nodes
, ndisks
;
55 mde_cookie_t
*disklistp
;
57 num_nodes
= md_node_count(mdp
);
59 disklistp
= (mde_cookie_t
*) alloca(sizeof (mde_cookie_t
) *num_nodes
);
60 if (disklistp
== NULL
) {
65 * Starting at the root node, scan the "fwd" dag for
66 * all the disks in this description.
69 ndisks
= md_scan_dag(mdp
, rootnode
, md_find_name(mdp
, "disk_nac"),
70 md_find_name(mdp
, "fwd"), disklistp
);
76 status
= ptree_create_and_add_node(root_node
, DISK_DISCOVERY_NAME
,
77 PICL_CLASS_PICL
, &discovery_node
);
78 if (status
!= PICL_SUCCESS
)
81 for (x
= 0; x
< ndisks
; x
++) {
82 if (md_get_prop_str(mdp
, disklistp
[x
], "phys_path",
87 if (md_get_prop_str(mdp
, disklistp
[x
], "nac_name",
92 (void) ptree_create_and_add_node(discovery_node
, "disk",
93 PICL_CLASS_DISK
, &new_node
);
95 set_prop_info(&propinfo
, PICL_PROPNAMELEN_MAX
, "Path",
96 PICL_PTYPE_CHARSTRING
);
98 (void) ptree_create_and_add_prop(new_node
, &propinfo
,
99 (void *)dev_path
, &proph
);
101 set_prop_info(&propinfo
, PICL_PROPNAMELEN_MAX
, "Location",
102 PICL_PTYPE_CHARSTRING
);
104 (void) ptree_create_and_add_prop(new_node
, &propinfo
,
105 (void *)nac
, &proph
);
107 set_prop_info(&propinfo
, PICL_PROPNAMELEN_MAX
, "State",
108 PICL_PTYPE_CHARSTRING
);
110 cfgpath
= device_format_disk_name(dev_path
);
112 if (cfgpath
== NULL
) {
113 (void) ptree_create_and_add_prop(new_node
, &propinfo
,
114 (void *)strdup(UNCONFIGURED
), &proph
);
118 disk_data
= device_get_disk_cfga_info(cfgpath
);
119 if (disk_data
== NULL
) {
123 switch (disk_data
->ap_o_state
) {
124 case CFGA_STAT_UNCONFIGURED
:
125 (void) ptree_create_and_add_prop(new_node
, &propinfo
,
126 (void *)strdup(UNCONFIGURED
), &proph
);
129 case CFGA_STAT_CONFIGURED
:
130 (void) ptree_create_and_add_prop(new_node
, &propinfo
,
131 (void *)strdup(CONFIGURED
), &proph
);
141 static cfga_list_data_t
*
142 device_get_disk_cfga_info(char *cfgpath
)
145 char apid_name
[CFGA_AP_LOG_ID_LEN
];
147 struct cfga_list_data
*list_data
;
150 (void) strcpy(apid_name
, cfgpath
);
152 apid_names
= (char **)malloc(2 * sizeof (char *));
153 apid_names
[0] = apid_name
;
154 apid_names
[1] = NULL
;
156 cfga_err
= config_list_ext(1, (char * const *)apid_names
, &list_data
,
157 &list_len
, NULL
, NULL
, NULL
, CFGA_FLAG_LIST_ALL
);
160 if (cfga_err
!= CFGA_OK
|| list_len
== 0) {
164 /* free any extra entries if this is not unique */
166 for (count
= 1; count
< list_len
; count
++) {
167 free(&list_data
[count
]);
171 return (&list_data
[0]);
176 device_format_disk_name(char *devfs_path
)
179 char *diskname
, *dev_cpy
;
180 char apid_name
[CFGA_AP_LOG_ID_LEN
];
182 (void) snprintf(devname
, sizeof (devname
), "/devices%s:a,raw",
185 diskname
= device_get_disk_name_from_dir("/dev/rdsk", devname
);
186 if (diskname
!= NULL
) {
187 *strrchr(diskname
, 's') = '\0';
188 dev_cpy
= strdup(diskname
);
189 *strchr(dev_cpy
, 't') = '\0';
191 (void) snprintf(apid_name
, sizeof (apid_name
), "%s::dsk/%s",
193 return (strdup(apid_name
));
200 * Getting a disk name is annoying. Walking controllers
201 * doesn't work if disks were added out of order (ie a new
202 * controller card was installed), and DKIO controller numbers
203 * seem to always be 0. So we do it the old fashioned way:
205 * We get a target name (in the /devices tree), and we want
206 * the node in /dev/rdsk that is a symlink to it. So we walk
207 * /dev/rdsk, stating each entry. Since stat follows the symlink
208 * automatically, we just compare the device and inode numbers
209 * to the device and inode numbers of the target. According to
210 * the stat man page, this constitues a unique match. The only
211 * little cleanup is that this includes a slice #, which we take
216 device_get_disk_name_from_dir(char *basedir
, char *path
)
219 struct dirent
*dirent
;
220 struct stat srcstat
, targstat
;
222 char fullname
[256 + MAXNAMLEN
];
225 loc_err
= stat(path
, &srcstat
);
230 dir
= opendir(basedir
);
235 while ((dirent
= readdir(dir
)) != NULL
) {
236 (void) snprintf(fullname
, sizeof (fullname
),
237 "%s/%s", basedir
, dirent
->d_name
);
239 loc_err
= stat(fullname
, &targstat
);
241 if ((memcmp((void *)&(targstat
.st_ino
),
242 (void *)&(srcstat
.st_ino
),
243 sizeof (ino_t
)) == 0) &&
244 (memcmp((void *)&(targstat
.st_dev
),
245 (void *)&(srcstat
.st_dev
),
246 sizeof (dev_t
)) == 0)) {
248 ptr
= strdup(dirent
->d_name
);
250 (void) closedir(dir
);
256 (void) closedir(dir
);