disk.c revision 184cd04c26b064536977dfbb913a1240eaf6f708
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <strings.h>
#include <devid.h>
#include <pthread.h>
#include <inttypes.h>
#include <fm/topo_mod.h>
#include <fm/topo_list.h>
#include <fm/libdiskstatus.h>
#include "disk.h"
/*
* Given a /devices path for a whole disk, appending this extension gives the
* path to a raw device that can be opened.
*/
#define PHYS_EXTN ":q,raw"
#define PHYS_EXTN ":c,raw"
#else
#endif
topo_instance_t, topo_instance_t, void *, void *);
static const topo_modops_t disk_ops =
const topo_modinfo_t disk_info =
static const topo_pgroup_info_t io_pgroup =
static const topo_pgroup_info_t disk_auth_pgroup = {
};
static const topo_pgroup_info_t storage_pgroup = {
1
};
/*
* Methods for disks. This is used by the disk-transport module to
* generate ereports based off SCSI disk status.
*/
static const topo_method_t disk_methods[] = {
disk_status },
{ NULL }
};
/* disk node information */
typedef struct disk_di_node {
int ddn_instance;
char *ddn_devid;
char *ddn_lpath; /* logical path */
char *ddn_dpath; /* device path */
typedef struct disk_di_nodes {
/* list of devices */
static disk_di_nodes_t disk_di_nodes;
/* given a device find it in the global device list */
static disk_di_node_t *
disk_di_node_match_device(char *device)
{
(void) pthread_mutex_unlock(
return (dnode);
}
}
return (NULL);
}
/* get the disk storage group information */
static void
{
char *entry;
int *dblksizep;
char lentry[MAXPATHLEN];
INQUIRY_VENDOR_ID, &entry) > 0) {
}
INQUIRY_PRODUCT_ID, &entry) > 0) {
}
INQUIRY_REVISION_ID, &entry) > 0) {
}
INQUIRY_SERIAL_NO, &entry) > 0) {
}
"device-nblocks", &nblocksp) > 0) {
/*
* To save kernel memory, the driver may not
* define "device-dblksize" when its value is
* the default DEV_BSIZE value.
*/
"device-dblksize", &dblksizep) > 0)
else
}
}
/* populate the protocol group properties */
static void
{
int err;
char label[32];
char *func = "disk_set_proto_props";
/* set the asru */
"%s: topo_node_asru_set error %d\n",
return;
}
topo_strerror(err));
return;
}
/* get the resource property */
"%s: topo_node_resource error: %s\n", func,
topo_strerror(err));
return;
}
/* set the child fru to the same as the resource */
"%s: topo_node_fru_set error: %s\n", func,
topo_strerror(err));
return;
}
}
/*
* Set the properties of the disk node which include:
* group: protocol properties: resource, asru, label, fru
* group: authority properties: product-id, chasis-id, server-id
* group: io properties: devfs-path
* group: storage properties:
* - logical-disk, disk-model, disk-manufacturer, serial-number
* - firmware-revision, capacity-in-bytes
*/
static void
{
char *device;
/* set the protocol group properties */
}
/* create the storage group */
/* set the storage group properties */
if (ptr1)
*ptr1 = '\0';
if (ptr1)
*ptr1 = 's';
/* populate the storage group properties */
if (model) {
}
if (manuf) {
err);
}
if (serial) {
}
if (firm) {
}
if (cap) {
}
}
/* create the disk topo node */
/*ARGSUSED*/
static tnode_t *
{
char *s;
*s = '-';
}
else
else if (*s != NULL)
*s = ' ';
"Unable to make nvlist for %s bind: %s.\n",
return (NULL);
}
"topo_node_bind (%s%d/%s%d) failed: %s\n",
name, i,
return (NULL);
}
/* add the properties of the disk */
return (dtn);
}
/*ARGSUSED*/
static tnode_t *
{
int err;
char *func = "disk_declare";
/* create the node */
return (NULL);
}
/* set the parent fru */
"%s: topo_node_resource error: %s\n", func,
topo_strerror(err));
return (NULL);
}
return (NULL);
}
"topo_method_register failed: %s\n",
return (NULL);
}
return (dtn);
}
/*ARGSUSED*/
static int
{
char *device;
int err;
"Currently only know how to enumerate %s components.\n",
DISK);
return (-1);
}
"No occupant found for bay=%d.\n",
return (-1);
}
return (-1); /* mod_errno already set */
}
return (0);
}
/*
* Query the current disk status. If successful, the disk status is returned as
* an nvlist consisting of at least the following members:
*
* protocol string Supported protocol (currently "scsi")
*
* status nvlist Arbitrary protocol-specific information
* about the current state of the disk.
*
* faults nvlist A list of supported faults. Each
* element of this list is a boolean value.
* An element's existence indicates that
* the drive supports detecting this fault,
* and the value indicates the current
* state of the fault.
*
* <fault-name> nvlist For each fault named in 'faults', a
* nvlist describing protocol-specific
* attributes of the fault.
*
* This method relies on the libdiskstatus library to query this information.
*/
static int
{
int err;
if (vers != TOPO_METH_DISK_STATUS_VERSION)
/*
* If the caller specifies the "path" parameter, then this indicates
* that we should use this instead of deriving it from the topo node
* itself.
*/
} else {
/*
* Get the /devices path and attempt to open the disk status
* handle.
*/
/*
* Note that sizeof(string) includes the terminating NULL byte
*/
sizeof (PHYS_EXTN) - 1;
}
if (devpath)
}
if (devpath)
}
return (0);
}
/* di_devlink callback for disk_drvinst2devpath */
static int
{
return (DI_WALK_TERMINATE);
}
static disk_di_node_t *
{
int mlen;
char *extn = ":a";
"disk_node_add - already there %s\n", devid);
(void) pthread_mutex_unlock(
return (dnode); /* return existing node */
}
}
"disk_node_add - topo_mod_alloc failed\n");
return (NULL); /* return existing node */
}
extn);
/* walk devlink looking for node that maps to /device path */
(void *)&devpath, disk_drvinst2devpath_devlink_callback);
"disk_node_add - adding %s inst: %d\n",
return (dnode);
}
/*ARGSUSED*/
static int
{
char *devidstr;
static int instance_devid = 0;
/* only interested in nodes that have devids */
return (DI_WALK_CONTINUE);
/* ... with a string representation of the devid */
return (DI_WALK_CONTINUE);
return (DI_WALK_CONTINUE);
}
/*ARGSUSED*/
int
{
/*
* Turn on module debugging output
*/
return (-1); /* mod errno already set */
}
/* we don't get all the nodes with topo_mod_devinfo */
return (-1);
}
/* walk the tree to get the devids */
if (devlink_hdl == DI_NODE_NIL) {
return (-1);
}
if (devlink_hdl != NULL)
(void) di_devlink_fini(&devlink_hdl);
return (0);
}
void
{
!= NULL) {
(void *)dnode);
}
}