cfga_list.c revision 4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6
/*
* 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"
/* Structure for walking the tree */
typedef struct {
char *hba_logp;
int l_errno;
} scfga_list_t;
typedef struct {
const char *ntype;
const char *name;
const char *pathname;
/* The TYPE field is parseable and should not contain spaces */
#define SCFGA_BUS_TYPE "scsi-bus"
/* Function prototypes */
int *l_errnop);
static scfga_devtype_t device_list[] = {
};
ldata_list_t **llpp,
int *nelemp,
char **errstring)
{
walkarg_t u;
int init_flag;
return (SCFGA_ERR);
}
/* Create the HBA logid (also base component of logical ap_id) */
return (SCFGA_ERR);
}
/*
* For all list commands, the bus and 1 or more devices
* needs to be stat'ed
*/
/*
* By default we use DINFOCACHE to get a "full" snapshot
* This much faster than DINFOFORCE which actually
* attaches devices. DINFOFORCE used only if caller
* explicitly requests it via a private option.
*/
limited_bus_stat = 0;
case SCFGA_STAT_DEV:
/*FALLTHRU*/
case SCFGA_STAT_ALL:
break;
case SCFGA_STAT_BUS:
/* limited_bus_stat = 0 and no DINFOCACHE/DINFOFORCE */
init_flag = 0;
break;
default:
goto out;
}
/*
* DINFOCACHE implies DINFOCPYALL. DINFOCPYALL shouldn't
* be ORed with DINFOCACHE, else libdevinfo will return
* error
*/
if (init_flag != DINFOCACHE)
init_flag |= DINFOCPYALL;
goto out;
}
#ifdef DEBUG
if (limited_bus_stat) {
} else {
}
#endif
/* Assume that the bus has no configured children */
/*
* If stat'ing a specific device, we don't know if it exists yet.
* If stat'ing a bus or a bus and child devices, we have at least the
* bus stat data at this point.
*/
} else {
}
/* we need to stat at least 1 device for all commands */
/*
* When cmd is SCFGA_STAT_DEV and the ap id is pathinfo
* related.
*/
} else {
/* we need to stat at least 1 device for all commands */
/*
* Subtree is ALWAYS rooted at the HBA (not at the device) as
* otherwise deadlock may occur if bus is disconnected.
*/
/*
* Check path info on the following conditions.
*
* - chld_config is still set to CFGA_STAT_UNCONFIGURED for
* SCFGA_STAT_BUS cmd after walking any child node.
* - walking node succeeded for SCFGA_STAT_ALL cmd(Continue on
* stating path info node).
* - apid is pathinfo associated and larg.ret is still set to
* SCFGA_APID_NOEXIST for SCFGA_STAT_DEV cmd.
*/
if (((cmd == SCFGA_STAT_BUS) &&
}
}
if (ret != SCFGA_APID_NOEXIST) {
}
goto out;
}
n = 0;
ret = SCFGA_LIB_ERR;
goto out;
}
*nelemp = n;
/* FALLTHROUGH */
out:
return (ret);
}
static scfga_ret_t
const ldata_list_t *listp,
int *np)
{
int i;
*np = 0;
return (SCFGA_ERR);
}
hba_ldatap = NULL;
i++;
/* A bus stat data */
#ifdef DEBUG
} else {
#endif
}
}
switch (cmd) {
case SCFGA_STAT_DEV:
return (SCFGA_LIB_ERR);
}
break;
case SCFGA_STAT_BUS:
return (SCFGA_LIB_ERR);
}
break;
case SCFGA_STAT_ALL:
return (SCFGA_LIB_ERR);
}
break;
default:
return (SCFGA_LIB_ERR);
}
*np = i;
/* Fill in the occupant (child) state. */
if (hba_ldatap != NULL) {
}
return (SCFGA_OK);
}
static int
{
/* Skip stub nodes */
if (IS_STUB_NODE(node)) {
return (DI_WALK_CONTINUE);
}
/* Skip partial nodes */
if (!known_state(node)) {
return (DI_WALK_CONTINUE);
}
goto out;
}
goto out;
}
/* Skip node if it is HBA */
match_minor = 0;
goto out;
}
/* If stat'ing a specific device, is this that device */
goto out;
}
}
/*
* If stat'ing a bus only, we look at device nodes only to get
* bus configuration status. So a limited stat will suffice.
*/
limited_dev_stat = 1;
} else {
limited_dev_stat = 0;
}
/*
* Ignore errors if stat'ing a bus or listing all
*/
} else {
}
goto out;
}
/* Are we done ? */
/*
* If stat'ing a specific device, we are done at this point.
*/
}
/*FALLTHRU*/
out:
return (rv);
}
/*
* Create list date entry and add to ldata list.
*/
static scfga_ret_t
{
int match_minor;
return (SCFGA_LIB_ERR);
}
return (ret);
}
if (client_node == DI_NODE_NIL) {
return (SCFGA_LIB_ERR);
}
/* Create logical and physical ap_id */
/* ap class filled in by libcfgadm */
/* path info exist so set to configured. */
/* now fill up ap_info field with client dev link and instance #. */
if (client_path) {
/* get first minor node. */
if (minor == DI_MINOR_NIL) {
match_minor = 0;
} else {
match_minor = 1;
}
}
if (client_devlink) {
}
}
if (pi_state == DI_PATH_STATE_FAULT) {
} else {
}
/* no way to determine state change */
/* Link it in */
return (SCFGA_OK);
}
/*
* Routine to stat pathinfo nodes.
*
* No pathinfo founds returns a success.
* When cmd is SCFGA_STAT_DEV, finds a matching pathinfo node and
* and create ldata if found.
* When cmd is SCFGA_STAT_ALL, create ldata for each pathinfo node.
* When cmd is SCFGA_STAT_BUS, checks if any pathinfo exist.
*
* Return:
* 0 for success
* -1 for failure.
*/
int
void *arg,
int *l_errnop)
{
if (root == DI_NODE_NIL) {
return (-1);
}
/*
* when there is no path_info node return SCFGA_OK.
*/
return (0);
}
return (0);
/*
* NOTE: apidt_create() validated pathinfo apid so
* the apid should have a valid format.
*/
/* check the length first. */
continue;
}
/* check for full match. */
continue;
}
/* found match, record information */
return (0);
} else {
return (-1);
}
}
} else { /* cmd = STAT_ALL */
/* set child config to configured */
/* continue on even if there is an error on one path. */
}
}
return (0);
}
struct bus_state {
int b_state;
int b_retired;
char iconnect_type[16];
};
static scfga_ret_t
{
int l_errno = 0;
walkarg_t u;
int i;
char itypelower[MAXNAMELEN];
/* Get bus state */
} else {
}
if (limited_bus_stat) {
/* We only want to know bus(receptacle) connect status */
return (SCFGA_OK);
}
return (SCFGA_LIB_ERR);
}
if (bstate.iconnect_type) {
/*
* For SPI type, keep the existing SCFGA_BUS_TYPE.
* For other types, the ap type will be scsi-'interconnct-type'.
*/
"%s", SCFGA_BUS_TYPE);
} else {
itypelower[i] =
}
itypelower[i] = '\0';
}
}
/* Link it in */
return (SCFGA_OK);
}
static int
{
(void) di_prop_lookup_strings(DDI_DEV_T_ANY,
} else {
}
return (DI_WALK_TERMINATE);
}
static scfga_ret_t
const char *nodepath,
int limited_dev_stat)
{
uint_t devinfo_state = 0;
/* If child device is configured, record it */
if (ostate == CFGA_STAT_CONFIGURED) {
}
if (limited_dev_stat) {
/* We only want to know device config state */
return (SCFGA_OK);
}
return (SCFGA_LIB_ERR);
}
/* Create the dynamic component */
return (ret);
}
/* Create logical and physical ap_id */
/* Link it in */
return (SCFGA_OK);
}
/* fill in device type, vid, pid from properties */
static void
{
char client_inst[MAXNAMELEN];
/*
* Fill in type information
*/
}
/*
* Fill in vendor and product ID.
*/
}
} else {
di_instance(node));
"Client Device: %s", client_inst);
} else {
di_instance(node));
}
}
}
}
/*
* Get dtype from "inquiry-device-type" property. If not present,
* derive it from minor node type
*/
static char *
{
int *inq_dtype;
int i;
return ("smp");
}
/* first, derive type based on inquiry property */
&inq_dtype) == 1) {
for (i = 0; i < N_DEVICE_TYPES; i++) {
continue;
(char *)device_list[i].name :
(char *)device_list[i].pathname;
break;
}
}
}
/* if property fails, use minor nodetype */
char *nodetype;
if ((minor != DI_MINOR_NIL) &&
for (i = 0; i < N_DEVICE_TYPES; i++) {
if (device_list[i].ntype &&
== 0)) {
(char *)device_list[i].name :
(char *)device_list[i].pathname;
break;
}
}
}
}
name = "unknown";
return (name);
}
/* Transform linked list into an array */
ldata_list_t **llpp,
int nelem,
int *nlistp,
char **errstring)
{
int i = -1;
*ap_id_list = NULL;
*nlistp = 0;
return (SCFGA_LIB_ERR);
}
if (nelem == 0) {
return (SCFGA_APID_NOEXIST);
}
return (SCFGA_LIB_ERR);
}
/* Extract the list_data structures from the linked list */
}
return (SCFGA_LIB_ERR);
}
*ap_id_list = ldatap;
return (SCFGA_OK);
}
/*
* Convert bus state to receptacle state
*/
static cfga_stat_t
{
return (CFGA_STAT_DISCONNECTED);
return (CFGA_STAT_CONNECTED);
}
/*
* Convert device state to occupant state
*/
static cfga_stat_t
{
return (CFGA_STAT_UNCONFIGURED);
if (!(dev_di_state & DI_DRIVER_DETACHED))
return (CFGA_STAT_CONFIGURED);
return (CFGA_STAT_NONE);
}