disk.c revision 184cd04c26b064536977dfbb913a1240eaf6f708
184cd04c26b064536977dfbb913a1240eaf6f708cth/*
184cd04c26b064536977dfbb913a1240eaf6f708cth * CDDL HEADER START
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * The contents of this file are subject to the terms of the
184cd04c26b064536977dfbb913a1240eaf6f708cth * Common Development and Distribution License (the "License").
184cd04c26b064536977dfbb913a1240eaf6f708cth * You may not use this file except in compliance with the License.
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
184cd04c26b064536977dfbb913a1240eaf6f708cth * or http://www.opensolaris.org/os/licensing.
184cd04c26b064536977dfbb913a1240eaf6f708cth * See the License for the specific language governing permissions
184cd04c26b064536977dfbb913a1240eaf6f708cth * and limitations under the License.
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * When distributing Covered Code, include this CDDL HEADER in each
184cd04c26b064536977dfbb913a1240eaf6f708cth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
184cd04c26b064536977dfbb913a1240eaf6f708cth * If applicable, add the following below this CDDL HEADER, with the
184cd04c26b064536977dfbb913a1240eaf6f708cth * fields enclosed by brackets "[]" replaced with your own identifying
184cd04c26b064536977dfbb913a1240eaf6f708cth * information: Portions Copyright [yyyy] [name of copyright owner]
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * CDDL HEADER END
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
184cd04c26b064536977dfbb913a1240eaf6f708cth * Use is subject to license terms.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth#pragma ident "%Z%%M% %I% %E% SMI"
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <strings.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <devid.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <pthread.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <inttypes.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <sys/dkio.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <sys/scsi/scsi_types.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <fm/topo_mod.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <fm/topo_list.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <fm/libdiskstatus.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include <sys/fm/protocol.h>
184cd04c26b064536977dfbb913a1240eaf6f708cth#include "disk.h"
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int disk_status(topo_mod_t *, tnode_t *, topo_version_t,
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *, nvlist_t **);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Given a /devices path for a whole disk, appending this extension gives the
184cd04c26b064536977dfbb913a1240eaf6f708cth * path to a raw device that can be opened.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth#if defined(__i386) || defined(__amd64)
184cd04c26b064536977dfbb913a1240eaf6f708cth#define PHYS_EXTN ":q,raw"
184cd04c26b064536977dfbb913a1240eaf6f708cth#elif defined(__sparc) || defined(__sparcv9)
184cd04c26b064536977dfbb913a1240eaf6f708cth#define PHYS_EXTN ":c,raw"
184cd04c26b064536977dfbb913a1240eaf6f708cth#else
184cd04c26b064536977dfbb913a1240eaf6f708cth#error Unknown architecture
184cd04c26b064536977dfbb913a1240eaf6f708cth#endif
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int disk_enum(topo_mod_t *, tnode_t *, const char *,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_instance_t, topo_instance_t, void *, void *);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic const topo_modops_t disk_ops =
184cd04c26b064536977dfbb913a1240eaf6f708cth { disk_enum, NULL };
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthconst topo_modinfo_t disk_info =
184cd04c26b064536977dfbb913a1240eaf6f708cth {DISK, FM_FMRI_SCHEME_HC, DISK_VERSION, &disk_ops};
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic const topo_pgroup_info_t io_pgroup =
184cd04c26b064536977dfbb913a1240eaf6f708cth { TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic const topo_pgroup_info_t disk_auth_pgroup = {
184cd04c26b064536977dfbb913a1240eaf6f708cth FM_FMRI_AUTHORITY,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STABILITY_PRIVATE,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STABILITY_PRIVATE,
184cd04c26b064536977dfbb913a1240eaf6f708cth};
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic const topo_pgroup_info_t storage_pgroup = {
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_PGROUP,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STABILITY_PRIVATE,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STABILITY_PRIVATE,
184cd04c26b064536977dfbb913a1240eaf6f708cth 1
184cd04c26b064536977dfbb913a1240eaf6f708cth};
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Methods for disks. This is used by the disk-transport module to
184cd04c26b064536977dfbb913a1240eaf6f708cth * generate ereports based off SCSI disk status.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic const topo_method_t disk_methods[] = {
184cd04c26b064536977dfbb913a1240eaf6f708cth { TOPO_METH_DISK_STATUS, TOPO_METH_DISK_STATUS_DESC,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_METH_DISK_STATUS_VERSION, TOPO_STABILITY_INTERNAL,
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_status },
184cd04c26b064536977dfbb913a1240eaf6f708cth { NULL }
184cd04c26b064536977dfbb913a1240eaf6f708cth};
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic di_devlink_handle_t devlink_hdl = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/* disk node information */
184cd04c26b064536977dfbb913a1240eaf6f708cthtypedef struct disk_di_node {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_list_t ddn_list;
184cd04c26b064536977dfbb913a1240eaf6f708cth int ddn_instance;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *ddn_devid;
184cd04c26b064536977dfbb913a1240eaf6f708cth di_node_t ddn_node;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *ddn_lpath; /* logical path */
184cd04c26b064536977dfbb913a1240eaf6f708cth char *ddn_dpath; /* device path */
184cd04c26b064536977dfbb913a1240eaf6f708cth}disk_di_node_t;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthtypedef struct disk_di_nodes {
184cd04c26b064536977dfbb913a1240eaf6f708cth pthread_mutex_t disk_di_nodes_lock;
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_list_t disk_di_nodes_list;
184cd04c26b064536977dfbb913a1240eaf6f708cth}disk_di_nodes_t;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/* list of devices */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic disk_di_nodes_t disk_di_nodes;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/* given a device find it in the global device list */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic disk_di_node_t *
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_di_node_match_device(char *device)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_node_t *dnode;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_lock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth for (dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list));
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode != NULL; dnode = topo_list_next(dnode)) {
184cd04c26b064536977dfbb913a1240eaf6f708cth if (dnode->ddn_devid != NULL &&
184cd04c26b064536977dfbb913a1240eaf6f708cth strcmp(device,
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_dpath) == 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(
184cd04c26b064536977dfbb913a1240eaf6f708cth &disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (dnode);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/* get the disk storage group information */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic void
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_storage_info(topo_mod_t *mod, disk_di_node_t *dnode,
184cd04c26b064536977dfbb913a1240eaf6f708cth char **model, char **manuf, char **serial, char **firm, char **cap)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth char *entry;
184cd04c26b064536977dfbb913a1240eaf6f708cth di_node_t node = dnode->ddn_node;
184cd04c26b064536977dfbb913a1240eaf6f708cth int64_t *nblocksp;
184cd04c26b064536977dfbb913a1240eaf6f708cth uint64_t nblocks;
184cd04c26b064536977dfbb913a1240eaf6f708cth int *dblksizep;
184cd04c26b064536977dfbb913a1240eaf6f708cth uint_t dblksize;
184cd04c26b064536977dfbb913a1240eaf6f708cth char lentry[MAXPATHLEN];
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
184cd04c26b064536977dfbb913a1240eaf6f708cth INQUIRY_VENDOR_ID, &entry) > 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth *manuf = topo_mod_strdup(mod, entry);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
184cd04c26b064536977dfbb913a1240eaf6f708cth INQUIRY_PRODUCT_ID, &entry) > 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth *model = topo_mod_strdup(mod, entry);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
184cd04c26b064536977dfbb913a1240eaf6f708cth INQUIRY_REVISION_ID, &entry) > 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth *firm = topo_mod_strdup(mod, entry);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
184cd04c26b064536977dfbb913a1240eaf6f708cth INQUIRY_SERIAL_NO, &entry) > 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth *serial = topo_mod_strdup(mod, entry);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (di_prop_lookup_int64(DDI_DEV_T_ANY, node,
184cd04c26b064536977dfbb913a1240eaf6f708cth "device-nblocks", &nblocksp) > 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth nblocks = (uint64_t)*nblocksp;
184cd04c26b064536977dfbb913a1240eaf6f708cth /*
184cd04c26b064536977dfbb913a1240eaf6f708cth * To save kernel memory, the driver may not
184cd04c26b064536977dfbb913a1240eaf6f708cth * define "device-dblksize" when its value is
184cd04c26b064536977dfbb913a1240eaf6f708cth * the default DEV_BSIZE value.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
184cd04c26b064536977dfbb913a1240eaf6f708cth "device-dblksize", &dblksizep) > 0)
184cd04c26b064536977dfbb913a1240eaf6f708cth dblksize = (uint_t)*dblksizep;
184cd04c26b064536977dfbb913a1240eaf6f708cth else
184cd04c26b064536977dfbb913a1240eaf6f708cth dblksize = DEV_BSIZE; /* default value */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) snprintf(lentry, sizeof (lentry),
184cd04c26b064536977dfbb913a1240eaf6f708cth "%" PRIu64, nblocks * dblksize);
184cd04c26b064536977dfbb913a1240eaf6f708cth *cap = topo_mod_strdup(mod, lentry);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/* populate the protocol group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic void
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_set_proto_props(topo_mod_t *mod, tnode_t *dtn, int pinst)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth int err;
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *asru = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth char label[32];
184cd04c26b064536977dfbb913a1240eaf6f708cth char *func = "disk_set_proto_props";
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *fmri;
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_node_t *dnode;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the asru */
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode = topo_node_getspecific(dtn);
184cd04c26b064536977dfbb913a1240eaf6f708cth asru = topo_mod_devfmri(mod, FM_DEV_SCHEME_VERSION,
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_dpath, dnode->ddn_devid);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_node_asru_set(dtn, asru, 0, &err) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "%s: topo_node_asru_set error %d\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth func, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(asru);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_mod_seterrno(mod, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth return;
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(asru);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth snprintf(label, sizeof (label), "HD_ID_%d", pinst);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_node_label_set(dtn, label, &err) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "%s: label error %s\n", func,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_strerror(err));
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_mod_seterrno(mod, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth return;
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* get the resource property */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_node_resource(dtn, &fmri, &err) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "%s: topo_node_resource error: %s\n", func,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_strerror(err));
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_mod_seterrno(mod, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth return;
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the child fru to the same as the resource */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_node_fru_set(dtn, fmri, 0, &err) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "%s: topo_node_fru_set error: %s\n", func,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_strerror(err));
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_mod_seterrno(mod, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(fmri);
184cd04c26b064536977dfbb913a1240eaf6f708cth return;
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(fmri);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Set the properties of the disk node which include:
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: protocol properties: resource, asru, label, fru
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: authority properties: product-id, chasis-id, server-id
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: io properties: devfs-path
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: storage properties:
184cd04c26b064536977dfbb913a1240eaf6f708cth * - logical-disk, disk-model, disk-manufacturer, serial-number
184cd04c26b064536977dfbb913a1240eaf6f708cth * - firmware-revision, capacity-in-bytes
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic void
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_set_props(tnode_t *dtn, tnode_t *parent, char *model, char *manuf,
184cd04c26b064536977dfbb913a1240eaf6f708cth char *serial, char *firm, char *cap, int *err, topo_mod_t *mod)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth char *device;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *ptr, *ptr1;
184cd04c26b064536977dfbb913a1240eaf6f708cth int inst = topo_node_instance(parent);
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_node_t *dnode;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_prop_get_string(parent, TOPO_BINDING_PGROUP, TOPO_BINDING_OCCUPANT,
184cd04c26b064536977dfbb913a1240eaf6f708cth &device, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode = topo_node_getspecific(dtn);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the protocol group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_set_proto_props(mod, dtn, inst);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create/set the authority group */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_pgroup_create(dtn, &disk_auth_pgroup, err) == 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_inherit(dtn, FM_FMRI_AUTHORITY,
184cd04c26b064536977dfbb913a1240eaf6f708cth FM_FMRI_AUTH_PRODUCT, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_inherit(dtn, FM_FMRI_AUTHORITY,
184cd04c26b064536977dfbb913a1240eaf6f708cth FM_FMRI_AUTH_CHASSIS, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_inherit(dtn, FM_FMRI_AUTHORITY,
184cd04c26b064536977dfbb913a1240eaf6f708cth FM_FMRI_AUTH_SERVER, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create/set the devfs-path in the io group */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_pgroup_create(dtn, &io_pgroup, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_set_string(dtn, TOPO_PGROUP_IO,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_IO_DEV_PATH, TOPO_PROP_IMMUTABLE, device, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, device);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create the storage group */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_pgroup_create(dtn, &storage_pgroup, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the storage group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cth ptr = strrchr(dnode->ddn_lpath, '/');
184cd04c26b064536977dfbb913a1240eaf6f708cth ptr1 = strchr(ptr, 's');
184cd04c26b064536977dfbb913a1240eaf6f708cth if (ptr1)
184cd04c26b064536977dfbb913a1240eaf6f708cth *ptr1 = '\0';
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_LOGICAL_DISK_NAME, TOPO_PROP_IMMUTABLE,
184cd04c26b064536977dfbb913a1240eaf6f708cth ptr+1, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (ptr1)
184cd04c26b064536977dfbb913a1240eaf6f708cth *ptr1 = 's';
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* populate the storage group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (model) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_MODEL, TOPO_PROP_IMMUTABLE, model, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (manuf) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_MANUFACTURER, TOPO_PROP_IMMUTABLE, manuf,
184cd04c26b064536977dfbb913a1240eaf6f708cth err);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (serial) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_SERIAL_NUM, TOPO_PROP_IMMUTABLE, serial, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (firm) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_FIRMWARE_REV, TOPO_PROP_IMMUTABLE, firm, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (cap) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_CAPACITY, TOPO_PROP_IMMUTABLE, cap, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/* create the disk topo node */
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic tnode_t *
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_tnode_create(topo_mod_t *mod, tnode_t *parent,
184cd04c26b064536977dfbb913a1240eaf6f708cth const char *name, topo_instance_t i, char *model, char *manuf,
184cd04c26b064536977dfbb913a1240eaf6f708cth char *serial, char *firm, char *cap, void *priv)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth int err, len = 0;
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *fmri;
184cd04c26b064536977dfbb913a1240eaf6f708cth tnode_t *dtn;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *mm = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *s;
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *auth = topo_mod_auth(mod, parent);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((s = strchr(model, ' ')) != NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth *s = '-';
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth len = strlen(manuf) + strlen(model) + 2;
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((mm = topo_mod_alloc(mod, len)) != NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) snprintf(mm, len, "%s-%s", manuf, model);
184cd04c26b064536977dfbb913a1240eaf6f708cth else
184cd04c26b064536977dfbb913a1240eaf6f708cth mm = model;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
184cd04c26b064536977dfbb913a1240eaf6f708cth NULL, auth, mm, firm, serial);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(auth);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (mm != model)
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_free(mod, mm, len);
184cd04c26b064536977dfbb913a1240eaf6f708cth else if (*s != NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth *s = ' ';
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (fmri == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "Unable to make nvlist for %s bind: %s.\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth name, topo_mod_errmsg(mod));
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((dtn = topo_node_bind(mod, parent, name, i, fmri)) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "topo_node_bind (%s%d/%s%d) failed: %s\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_node_name(parent), topo_node_instance(parent),
184cd04c26b064536977dfbb913a1240eaf6f708cth name, i,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_strerror(topo_mod_errno(mod)));
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(fmri);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(fmri);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_node_setspecific(dtn, priv);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* add the properties of the disk */
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_set_props(dtn, parent, model, manuf, serial, firm, cap,
184cd04c26b064536977dfbb913a1240eaf6f708cth &err, mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth return (dtn);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic tnode_t *
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_declare(tnode_t *parent, const char *name, topo_instance_t i,
184cd04c26b064536977dfbb913a1240eaf6f708cth void *priv, topo_mod_t *mod)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth tnode_t *dtn;
184cd04c26b064536977dfbb913a1240eaf6f708cth int err;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *func = "disk_declare";
184cd04c26b064536977dfbb913a1240eaf6f708cth char *model = NULL, *manuf = NULL, *serial = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *cap = NULL, *firm = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_node_t *dnode = (disk_di_node_t *)priv;
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *fmri;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_storage_info(mod, dnode,
184cd04c26b064536977dfbb913a1240eaf6f708cth &model, &manuf, &serial, &firm, &cap);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create the node */
184cd04c26b064536977dfbb913a1240eaf6f708cth dtn = disk_tnode_create(mod, parent,
184cd04c26b064536977dfbb913a1240eaf6f708cth name, i, model, manuf, serial, firm, cap, priv);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, model);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, manuf);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, serial);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, firm);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, cap);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (dtn == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the parent fru */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_node_resource(parent, &fmri, &err) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "%s: topo_node_resource error: %s\n", func,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_strerror(err));
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_node_unbind(dtn);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_node_fru_set(parent, fmri, 0, &err) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "%s topo_node_fru error: %s\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth func, topo_strerror(err));
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(fmri);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_node_unbind(dtn);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_method_register(mod, dtn, disk_methods) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "topo_method_register failed: %s\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_strerror(topo_mod_errno(mod)));
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(fmri);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_node_unbind(dtn);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_free(fmri);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth return (dtn);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_instance_t min, topo_instance_t max, void *arg, void *notused)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth tnode_t *diskn;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *device;
184cd04c26b064536977dfbb913a1240eaf6f708cth int err;
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_node_t *dnode;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (strcmp(name, DISK) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "Currently only know how to enumerate %s components.\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth DISK);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_prop_get_string(rnode, TOPO_BINDING_PGROUP, TOPO_BINDING_OCCUPANT,
184cd04c26b064536977dfbb913a1240eaf6f708cth &device, &err);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((dnode = disk_di_node_match_device(device)) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "No occupant found for bay=%d.\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_node_instance(rnode));
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, device);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth diskn = disk_declare(rnode, name, 0, dnode, mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (diskn == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "Enumeration of %s failed: %s\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth DISK, topo_strerror(topo_mod_errno(mod)));
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, device);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1); /* mod_errno already set */
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, device);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (0);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Query the current disk status. If successful, the disk status is returned as
184cd04c26b064536977dfbb913a1240eaf6f708cth * an nvlist consisting of at least the following members:
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * protocol string Supported protocol (currently "scsi")
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * status nvlist Arbitrary protocol-specific information
184cd04c26b064536977dfbb913a1240eaf6f708cth * about the current state of the disk.
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * faults nvlist A list of supported faults. Each
184cd04c26b064536977dfbb913a1240eaf6f708cth * element of this list is a boolean value.
184cd04c26b064536977dfbb913a1240eaf6f708cth * An element's existence indicates that
184cd04c26b064536977dfbb913a1240eaf6f708cth * the drive supports detecting this fault,
184cd04c26b064536977dfbb913a1240eaf6f708cth * and the value indicates the current
184cd04c26b064536977dfbb913a1240eaf6f708cth * state of the fault.
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * <fault-name> nvlist For each fault named in 'faults', a
184cd04c26b064536977dfbb913a1240eaf6f708cth * nvlist describing protocol-specific
184cd04c26b064536977dfbb913a1240eaf6f708cth * attributes of the fault.
184cd04c26b064536977dfbb913a1240eaf6f708cth *
184cd04c26b064536977dfbb913a1240eaf6f708cth * This method relies on the libdiskstatus library to query this information.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_status(topo_mod_t *mod, tnode_t *nodep, topo_version_t vers,
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *in_nvl, nvlist_t **out_nvl)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_status_t *dsp;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *devpath, *fullpath;
184cd04c26b064536977dfbb913a1240eaf6f708cth size_t pathlen;
184cd04c26b064536977dfbb913a1240eaf6f708cth int err;
184cd04c26b064536977dfbb913a1240eaf6f708cth nvlist_t *status;
184cd04c26b064536977dfbb913a1240eaf6f708cth *out_nvl = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (vers != TOPO_METH_DISK_STATUS_VERSION)
184cd04c26b064536977dfbb913a1240eaf6f708cth return (topo_mod_seterrno(mod, EMOD_VER_NEW));
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /*
184cd04c26b064536977dfbb913a1240eaf6f708cth * If the caller specifies the "path" parameter, then this indicates
184cd04c26b064536977dfbb913a1240eaf6f708cth * that we should use this instead of deriving it from the topo node
184cd04c26b064536977dfbb913a1240eaf6f708cth * itself.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (nvlist_lookup_string(in_nvl, "path", &fullpath) == 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth devpath = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth } else {
184cd04c26b064536977dfbb913a1240eaf6f708cth /*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Get the /devices path and attempt to open the disk status
184cd04c26b064536977dfbb913a1240eaf6f708cth * handle.
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_prop_get_string(nodep, TOPO_PGROUP_IO,
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_IO_DEV_PATH, &devpath, &err) != 0)
184cd04c26b064536977dfbb913a1240eaf6f708cth return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP));
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Note that sizeof(string) includes the terminating NULL byte
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth pathlen = strlen(devpath) + sizeof ("/devices") +
184cd04c26b064536977dfbb913a1240eaf6f708cth sizeof (PHYS_EXTN) - 1;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((fullpath = topo_mod_alloc(mod, pathlen)) == NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth return (topo_mod_seterrno(mod, EMOD_NOMEM));
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) snprintf(fullpath, pathlen, "/devices%s%s", devpath,
184cd04c26b064536977dfbb913a1240eaf6f708cth PHYS_EXTN);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_strfree(mod, devpath);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((dsp = disk_status_open(fullpath, &err)) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth if (devpath)
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_free(mod, fullpath, pathlen);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (topo_mod_seterrno(mod, err == EDS_NOMEM ?
184cd04c26b064536977dfbb913a1240eaf6f708cth EMOD_NOMEM : EMOD_METHOD_NOTSUP));
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (devpath)
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_free(mod, fullpath, pathlen);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((status = disk_status_get(dsp)) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth err = (disk_status_errno(dsp) == EDS_NOMEM ?
184cd04c26b064536977dfbb913a1240eaf6f708cth EMOD_NOMEM : EMOD_METHOD_NOTSUP);
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_status_close(dsp);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (topo_mod_seterrno(mod, err));
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth *out_nvl = status;
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_status_close(dsp);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (0);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/* di_devlink callback for disk_drvinst2devpath */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_drvinst2devpath_devlink_callback(di_devlink_t dl, void *arg)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth char **devpathp = (char **)arg;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *devpath = (char *)di_devlink_path(dl);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth *devpathp = strdup(devpath);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (DI_WALK_TERMINATE);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic disk_di_node_t *
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_di_node_add(int *instancep, char *devid, di_node_t node, topo_mod_t *mod)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth int mlen;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *devpath, *minorpath;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *extn = ":a";
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_node_t *dnode;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_lock(&(disk_di_nodes.disk_di_nodes_lock));
184cd04c26b064536977dfbb913a1240eaf6f708cth for (dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list));
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode != NULL; dnode = topo_list_next(dnode)) {
184cd04c26b064536977dfbb913a1240eaf6f708cth if (strcmp(dnode->ddn_devid, devid) == 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "disk_node_add - already there %s\n", devid);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(
184cd04c26b064536977dfbb913a1240eaf6f708cth &disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (dnode); /* return existing node */
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((dnode = topo_mod_alloc(mod, sizeof (disk_di_node_t))) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "disk_node_add - topo_mod_alloc failed\n");
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (NULL); /* return existing node */
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_devid = strdup(devid);
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_instance = *instancep;
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_node = node;
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_dpath = di_devfs_path(node);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth mlen = strlen(dnode->ddn_dpath) + strlen(extn) + 1;
184cd04c26b064536977dfbb913a1240eaf6f708cth minorpath = topo_mod_alloc(mod, mlen);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) snprintf(minorpath, mlen, "%s%s", dnode->ddn_dpath,
184cd04c26b064536977dfbb913a1240eaf6f708cth extn);
184cd04c26b064536977dfbb913a1240eaf6f708cth /* walk devlink looking for node that maps to /device path */
184cd04c26b064536977dfbb913a1240eaf6f708cth devpath = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) di_devlink_walk(devlink_hdl, "^dsk/",
184cd04c26b064536977dfbb913a1240eaf6f708cth minorpath, DI_PRIMARY_LINK,
184cd04c26b064536977dfbb913a1240eaf6f708cth (void *)&devpath, disk_drvinst2devpath_devlink_callback);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_free(mod, minorpath, mlen);
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_lpath = devpath;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_list_append(&disk_di_nodes.disk_di_nodes_list, (void *)dnode);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth "disk_node_add - adding %s inst: %d\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth dnode->ddn_devid, *instancep);
184cd04c26b064536977dfbb913a1240eaf6f708cth *instancep = (*instancep) + 1;
184cd04c26b064536977dfbb913a1240eaf6f708cth return (dnode);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_walk_di_nodes(di_node_t node, void *arg)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth ddi_devid_t devid = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth char *devidstr;
184cd04c26b064536977dfbb913a1240eaf6f708cth static int instance_devid = 0;
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_t *mod = (topo_mod_t *)arg;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* only interested in nodes that have devids */
184cd04c26b064536977dfbb913a1240eaf6f708cth devid = (ddi_devid_t)di_devid(node);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (devid == NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth return (DI_WALK_CONTINUE);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* ... with a string representation of the devid */
184cd04c26b064536977dfbb913a1240eaf6f708cth devidstr = devid_str_encode(devid, NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (devidstr == NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth return (DI_WALK_CONTINUE);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create/find the devid scsi topology node */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) disk_di_node_add(&instance_devid, devidstr, node, mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth devid_str_free(devidstr);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (DI_WALK_CONTINUE);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cthint
184cd04c26b064536977dfbb913a1240eaf6f708cth_topo_init(topo_mod_t *mod, topo_version_t version)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth di_node_t devtree;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth /*
184cd04c26b064536977dfbb913a1240eaf6f708cth * Turn on module debugging output
184cd04c26b064536977dfbb913a1240eaf6f708cth */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (getenv("TOPODISKDEBUG") != NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_setdebug(mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "initializing %s enumerator\n", DISK);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_mod_register(mod, &disk_info, TOPO_VERSION) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "%s registration failed: %s\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth DISK, topo_mod_errmsg(mod));
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1); /* mod errno already set */
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_init(&disk_di_nodes.disk_di_nodes_lock, NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_nodes.disk_di_nodes_list.l_next = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_nodes.disk_di_nodes_list.l_prev = NULL;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth devtree = di_init("/", DINFOCACHE);
184cd04c26b064536977dfbb913a1240eaf6f708cth /* we don't get all the nodes with topo_mod_devinfo */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (devtree == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_unregister(mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "topo_mod_devinfo init failed.");
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth /* walk the tree to get the devids */
184cd04c26b064536977dfbb913a1240eaf6f708cth devlink_hdl = di_devlink_init(NULL, 0);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (devlink_hdl == DI_NODE_NIL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_unregister(mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "di_devlink init failed.");
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) di_walk_node(devtree, DI_WALK_CLDFIRST, mod,
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_walk_di_nodes);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth if (devlink_hdl != NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) di_devlink_fini(&devlink_hdl);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "%s enumerator initialized\n", DISK);
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth return (0);
184cd04c26b064536977dfbb913a1240eaf6f708cth}
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cthvoid
184cd04c26b064536977dfbb913a1240eaf6f708cth_topo_fini(topo_mod_t *mod)
184cd04c26b064536977dfbb913a1240eaf6f708cth{
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_di_node_t *dnode;
184cd04c26b064536977dfbb913a1240eaf6f708cth
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_lock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth while ((dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list)))
184cd04c26b064536977dfbb913a1240eaf6f708cth != NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth free(dnode->ddn_lpath);
184cd04c26b064536977dfbb913a1240eaf6f708cth free(dnode->ddn_dpath);
184cd04c26b064536977dfbb913a1240eaf6f708cth free(dnode->ddn_devid);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_list_delete(&(disk_di_nodes.disk_di_nodes_list),
184cd04c26b064536977dfbb913a1240eaf6f708cth (void *)dnode);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_free(mod, dnode, sizeof (disk_di_node_t));
184cd04c26b064536977dfbb913a1240eaf6f708cth }
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_unregister(mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth}