/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include "cfga_scsi.h"
typedef struct {
char *dyncomp;
char *devlink;
int l_errno;
} dyn_t;
typedef struct {
} dynrules_t;
typedef struct {
int nrules;
} dyncvt_t;
typedef struct {
const char *hba_phys;
const char *dyncomp;
char *path;
int l_errno;
} devpath_t;
/* Function prototypes */
/* Globals */
/*
* Rules for converting between a devlink and logical ap_id and vice-versa
* The default rules must be the last entry.
*/
};
/*
* Numbering of disk slices is assumed to be 0 through n - 1
*/
typedef struct {
char *prefix;
int nslices;
} slice_t;
{"s", 16},
{"p", 5},
};
static const char *tape_modes[] = {
"",
"b", "bn",
"c", "cb", "cbn", "cn",
"h", "hb", "hbn", "hn",
"l", "lb", "lbn", "ln",
"m", "mb", "mbn", "mn",
"n",
"u", "ub", "ubn", "un"
};
/* Various conversions routines */
/*
* Generates the HBA logical ap_id from physical ap_id.
*/
{
walkarg_t u;
return (SCFGA_ERR);
}
/* A devlink for the HBA may or may not exist */
return (SCFGA_OK);
}
/*
* No devlink based logical ap_id.
* Try driver name and instance number.
*/
errno = 0;
return (SCFGA_OK);
}
/* failed to create logical ap_id */
}
return (ret);
}
static scfga_ret_t
{
return (ret);
}
return (SCFGA_OK);
}
/* Make logical name for HBA based on driver and instance */
static int
{
int inst;
errno = 0;
/* Count does not include terminating NULL */
return (DI_WALK_TERMINATE);
}
}
return (DI_WALK_CONTINUE);
}
/*
* Given a bus or device ap_id <hba_phys, dyncomp>, returns the physical
* path in pathpp.
* Returns: SCFGA_APID_NOEXIST if the path does not exist.
*/
const char *hba_phys,
const char *dyncomp,
char **pathpp,
int *l_errnop)
{
return (SCFGA_LIB_ERR);
}
/* If a bus, the physical ap_id is the physical path */
return (SCFGA_LIB_ERR);
}
return (SCFGA_OK);
}
/* Dynamic component exists, we have a device */
/*
* If the dynamic component has a '/', it was derived from a devlink
* Else it was derived from driver name and instance number.
* If it is pathinfo instance number based ap id, it will have a format
* path#.???.
*/
l_errnop);
l_errnop);
} else {
}
return (ret);
}
/*
* Get the devfs path of pathinfo node that is associated with
* the given dynamic component.
*
* input
* hba_phys: physical path of HBA
* dyn : bus address of pathinfo node
* output:
* pathpp: devfs path of the pathinfo node.
*/
static scfga_ret_t
const char *hba_phys,
const char *dyn,
char **pathpp,
int *l_errnop)
{
int len;
*l_errnop = 0;
/* *pathpp should be NULL if pathpp is not NULL. */
return (SCFGA_LIB_ERR);
}
return (SCFGA_LIB_ERR);
}
/* Fix up path for di_init() */
} else if (*root_path != '/') {
*l_errnop = 0;
return (SCFGA_ERR);
}
/* Remove dynamic component if any */
*cp = '\0';
}
/* Remove minor name if any */
*cp = '\0';
}
/*
* Cached snapshots are always rooted at "/"
*/
/* Get a snapshot */
return (SCFGA_ERR);
}
/*
* Lookup the subtree of interest
*/
if (walk_root == DI_NODE_NIL) {
return (SCFGA_LIB_ERR);
}
DI_PATH_NIL) {
return (SCFGA_APID_NOEXIST);
}
/*
* now parse the path info node.
*/
do {
/* check the length first. */
continue;
}
/* get the devfspath of pathinfo node. */
return (SCFGA_ERR);
}
return (SCFGA_ERR);
} else {
return (SCFGA_OK);
}
}
} while (pi_node != DI_PATH_NIL);
return (SCFGA_APID_NOEXIST);
}
static scfga_ret_t
const char *hba_phys,
const char *dyncomp,
char **pathpp,
int *l_errnop)
{
walkarg_t u;
/* A device MUST have a dynamic component */
return (SCFGA_LIB_ERR);
}
return (SCFGA_OK);
}
}
return (ret);
}
/* Converts a driver and instance number based logid into a physical path */
static int
{
/*
* Skip stub nodes
*/
if (IS_STUB_NODE(node)) {
return (DI_WALK_CONTINUE);
}
errno = 0;
goto out;
}
goto out;
}
/* Create the physical path */
/* Skip node if it is the HBA */
match_minor = 0;
goto out;
}
/* Compare the base and dynamic components */
} else {
}
/*FALLTHRU*/
out:
return (rv);
}
/* readlink wrapper to ensure proper null termination of the results */
static int
{
int count;
if (count != -1)
return (count);
}
/* Converts a devlink based dynamic component to a path */
static scfga_ret_t
const char *hba_phys,
const char *dyncomp,
char **pathpp,
int *l_errnop)
{
int i;
return (SCFGA_LIB_ERR);
}
/* Convert the dynamic component to the corresponding devlink */
for (i = 0; i < N_DYNRULES; i++) {
!= SCFGA_CONTINUE) {
break;
}
}
if (i >= N_DYNRULES) {
}
/* No symlink or error */
}
/*
* Follow devlink to get the physical path
* Note: Do not use realpath(). It will stat() device
* and stat() fails under devfs if device is offline.
*/
errno = 0;
ret = SCFGA_LIB_ERR;
goto out;
}
/* Compare base components as well */
} else {
/* Mismatched base and dynamic component */
*l_errnop = 0;
}
/*FALLTHRU*/
out:
return (ret);
}
const char *physpath,
char **dyncompp,
int *l_errnop)
{
char *path;
int match_minor;
return (SCFGA_LIB_ERR);
}
/* tag on minor name */
if (minor == DI_MINOR_NIL) {
match_minor = 0;
} else {
match_minor = 1;
}
/* Get the corresponding devlink from the physical path */
/* Create dynamic component. */
return (SCFGA_OK);
}
/*
* Failed to get devlink based dynamic component.
* Try driver and instance
*/
}
return (ret);
}
/*
* Create a dynamic component of path ap_id for the given path info node.
* The caller should free the buffer for the dynamic component.
*/
char **dyncompp,
int *l_errnop)
{
char *pi_addr;
return (SCFGA_LIB_ERR);
}
return (SCFGA_LIB_ERR);
}
} else {
return (SCFGA_LIB_ERR);
}
return (SCFGA_OK);
}
/*ARGSUSED*/
static scfga_ret_t
{
char *drv;
int inst;
*l_errnop = 0;
return (SCFGA_LIB_ERR);
}
return (SCFGA_OK);
} else {
ret = SCFGA_LIB_ERR;
}
} else {
}
return (ret);
}
/* Get a dynamic component from a physical path if possible */
static scfga_ret_t
{
int i;
*l_errnop = 0;
return (SCFGA_LIB_ERR);
}
/* Convert devlink to dynamic component */
for (i = 0; i < N_DYNRULES; i++) {
!= SCFGA_CONTINUE) {
break;
}
}
if (i >= N_DYNRULES) {
}
}
}
/* For disks remove partition information, (s or p) */
static scfga_recur_t
{
goto lib_err;
}
/* Check if a disk devlink */
return (SCFGA_CONTINUE);
}
goto lib_err;
}
/* Blank out partition information */
*cp = '\0';
*cp = '\0';
} else {
}
return (SCFGA_TERMINATE);
return (SCFGA_TERMINATE);
}
static scfga_recur_t
{
int i, j;
return (SCFGA_TERMINATE);
}
return (SCFGA_CONTINUE); /* not a disk link */
for (i = 0; i < N_SLICE_TYPES; i++) {
for (j = 0; j < disk_slices[i].nslices; j++) {
>= len) {
continue;
}
return (SCFGA_TERMINATE);
}
return (SCFGA_TERMINATE);
}
}
}
return (SCFGA_TERMINATE);
}
/* For tapes, remove mode(minor) information from link */
static scfga_recur_t
{
goto lib_err;
}
return (SCFGA_CONTINUE); /* not a tape */
}
goto lib_err;
}
/* Remove the mode part */
};
*cp = '\0';
return (SCFGA_TERMINATE);
return (SCFGA_TERMINATE);
}
static scfga_recur_t
{
int i;
goto lib_err;
}
return (SCFGA_CONTINUE); /* not a tape */
}
/* A tape device */
for (i = 0; i < N_TAPE_MODES; i++) {
goto lib_err;
}
return (SCFGA_TERMINATE);
}
}
return (SCFGA_TERMINATE);
return (SCFGA_TERMINATE);
}
/*
* Default rules
*/
static scfga_recur_t
{
return (SCFGA_TERMINATE);
}
/* Is it a link in DEV_DIR directory ? */
return (SCFGA_CONTINUE);
}
/* Check if this is a top level devlink */
/* not top level - Remove DEV_DIR SLASH prefix */
} else {
/* top level, leave DEV_DIR SLASH part in */
}
} else {
}
return (SCFGA_TERMINATE);
}
static scfga_recur_t
{
int top;
goto lib_err;
}
/*
* Check if the dynamic component was derived from a top level entry
* in "/dev"
*/
top = 1;
top = 0;
} else {
/* Not a dynamic component we handle */
return (SCFGA_CONTINUE);
}
goto lib_err;
}
if (!top) {
}
return (SCFGA_TERMINATE);
}
return (SCFGA_CONTINUE);
return (SCFGA_TERMINATE);
}