piclscsi.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* implementation specific to scsi nodes probing */
#include <stdio.h>
#include <unistd.h>
#include <syslog.h>
#include <stdlib.h>
#include <config_admin.h>
#include <string.h>
#include <strings.h>
#include <picl.h>
#include <picltree.h>
#include <libintl.h>
#include <libdevinfo.h>
#include <picldefs.h>
#include "piclfrutree.h"
#define SCSI_SLOT "scsi-bus"
#define SCSI_LOC_FORMAT "t%dd0"
#define TARGET "target"
#define CLASS "class"
#define BUF_SIZE 256
#define SCSI_INITIATOR_ID 7
#define DRV_TYPE_DSK 1
#define DRV_TYPE_TAPE 2
#define NUM_DSK_TARGS 15
/*
* No support for wide tapes for now.
* If required wide support, set this to 8
* See st.conf.
*/
#define NUM_TAPE_TARGS 7
#define DIRLINK_DSK "dsk"
#define DIRLINK_RMT "rmt"
#define DRV_SCSI_DSK "sd"
#define DRV_SCSI_TAPE "st"
#define NULL_ENTRY 0
/* currently supported directory strings for SCSI FRUs in cfgadm APs */
/* currently supported SCSI FRU drivers */
static struct scsi_drv_info {
char *drv_name;
} scsi_drv[] = {
};
/* the following defs are based on defines in scsi cfgadm plugin */
#define CDROM "CD-ROM"
#define RMM "tape"
#define DISK "disk"
const char *, const char *);
int, char *, boolean_t);
extern boolean_t frutree_connects_initiated;
extern int frutree_debug;
typedef struct node {
} node_t;
typedef struct linked_list {
int num_nodes;
} list_t;
typedef struct scsi_info {
int num_list;
int geo_addr;
} scsi_info_t;
static int nlist = 0;
static void
{
return;
}
}
/*
* This routine gets the list of scsi controllers present
*/
static cfga_err_t
{
int i;
return (CFGA_ATTR_INVAL);
}
cntrl_list->num_nodes = 0;
if (num == 0) {
return (CFGA_OK);
}
for (i = 0; i < num; i++) {
continue;
}
/* scsi controller */
return (CFGA_ERROR);
}
return (CFGA_ERROR);
}
/* append to the list */
cntrl_list->num_nodes++;
} else {
cntrl_list->num_nodes++;
}
}
return (CFGA_OK);
}
{
if (ap_list_err != CFGA_OK) {
if (ap_list_err == CFGA_NOTSUPP) {
return (PICL_SUCCESS);
} else {
return (PICL_FAILURE);
}
}
return (PICL_NOSPACE);
}
if (ap_list_err != CFGA_OK) {
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
void
{
}
/*
* This routine searches the controllers list to find the mapping based
* on given devfs_path.
* caller should allocate memory for ap_id
*/
static picl_errno_t
{
char path[MAXPATHLEN];
return (PICL_INVALIDARG);
}
(char **)&lasts);
continue;
}
sizeof (ap_id));
return (PICL_SUCCESS);
}
}
return (PICL_NODENOTFOUND);
}
/*
* This routine dynamically determines the cfgadm attachment point
* for a given devfspath and target id.
* memory for name should be allocated by the caller.
*/
{
int target_id = 0;
int numlist;
char controller[MAXPATHLEN];
if (ap_list_err != CFGA_OK) {
return (PICL_NODENOTFOUND);
}
numlist);
if (ap_list_err != CFGA_OK) {
return (PICL_NODENOTFOUND);
}
return (PICL_NODENOTFOUND);
}
controller)) != PICL_SUCCESS) {
return (rc);
}
return (PICL_SUCCESS);
}
/*
* Arg scsi_loc can be any of the following forms appearing in cfgadm output
* c1::sd56
* c2::rmt/0
* c3::st41
* rmt/1
*
* On return, bus_addr contains the target id of the device.
* Please note that currently the target id is computed. It is better
* to eventually change this to getting from libdevinfo.
* Also, please note that SCSI_INITIATOR_ID should not
* be hardcoded, but should be dynamically retrieved from an OBP property.
*/
static void
{
int len = 0, i = 0;
char parse_link = 0;
if (!ap)
else
while (scsi_dirlink_names[i] && !len) {
/*
* strspn may return positive len even when there is no
* complete string matches!!! hence the following check is
* necessary. So ensure the string match.
*/
break;
len = 0;
}
if (len)
parse_link = 1;
else {
i = 0;
break;
len = 0;
}
}
/* slice 0 must be present in the system */
}
/* get the devlink and read the target id from minor node */
ap_idp);
return;
if (!fileinfo[0])
return;
ap++;
}
if (!parse_link) {
}
return;
}
}
/*
* This routine determines all the scsi nodes under a FRU and
* creates a subtree of all the scsi nodes with basic properties.
*/
static picl_errno_t
{
int i, geo_addr = 0;
char path[MAXPATHLEN];
char controller_name[MAXPATHLEN];
/* compare the path */
continue;
}
for (i = 0; i < numlist; i++) {
continue;
}
controller_name) == NULL) {
continue;
}
/* check if device is under fru */
continue;
}
/* we found a scsi fru */
geo_addr++;
/* check if the device is present in subtree */
continue;
}
continue;
}
if (rc != PICL_SUCCESS) {
"Error in creating node %s under %s(error=%d)",
}
}
}
return (PICL_SUCCESS);
}
/*
* data used here is cached information (cfglist, nlist)
*/
static picl_errno_t
{
int i, geo_addr = 0;
char path[MAXPATHLEN];
char controller_name[MAXPATHLEN];
return (PICL_SUCCESS);
}
/* compare the path */
continue;
}
for (i = 0; i < nlist; i++) {
continue;
}
controller_name) == NULL) {
continue;
}
/* check if the device is under fru */
continue;
}
/* we found a scsi fru */
geo_addr++;
/* check if the device is present in subtree */
continue;
}
continue;
}
if (rc != PICL_SUCCESS) {
"Error in creating node %s under %s(error=%d)",
}
}
}
return (PICL_SUCCESS);
}
/*
* This routine checks if the node (scsi device) is present in cfgadm data
* Algorithm:
* 1. traverse thru list of controllers and find
* the controller of interest
* 2. go thru list of devices under controller and compare if the target is same
* 3. if yes
* - device is already represented
* 4. if No
* - The node must be repreented in PICL tree.
*/
static boolean_t
{
char path[MAXPATHLEN];
char controller[MAXPATHLEN];
int i = 0;
return (B_FALSE);
}
return (B_FALSE);
}
(char **)&lasts);
continue;
}
/* this controller is not of interest */
continue;
}
SCSI_SLOT) == 0) {
continue;
}
controller) == NULL) {
continue;
}
&bus_addr);
/*
* compare with target value
*/
return (B_TRUE);
}
/*
* this device is already represented
* in fru tree
*/
return (B_TRUE);
}
}
}
return (B_FALSE);
}
static di_prop_t
{
while (prop != DI_PROP_NIL) {
return (prop);
}
}
}
return (DI_PROP_NIL);
}
static int
{
char slot_type[PICL_PROPNAMELEN_MAX];
return (PICL_INVALIDARG);
return (rc);
}
}
return (PICL_WALK_CONTINUE);
}
static int
{
int geo_addr = 1;
return (geo_addr);
}
return (geo_addr);
}
static int
{
int *target_val = NULL;
char *devfs_path = NULL;
char slot_type[PICL_PROPNAMELEN_MAX];
return (DI_WALK_TERMINATE);
return (DI_WALK_TERMINATE);
}
/* initialize the geo_addr value */
} else {
}
}
continue;
}
} else {
continue;
}
if (devfs_path == NULL) {
continue;
}
continue;
}
if (prop != DI_PROP_NIL) {
if (data->compare_cfgadm) {
/* check if node is present in cfgadm data */
*target_val) == B_TRUE) {
return (DI_WALK_CONTINUE);
}
}
if (prop != DI_PROP_NIL) {
}
/* determine the slot type based on class code */
sizeof (slot_type));
DEVICE_CLASS_IDE) == 0) {
sizeof (slot_type));
} else {
sizeof (slot_type));
}
} else {
sizeof (slot_type));
}
B_FALSE)) != PICL_SUCCESS) {
return (rc);
}
/* increment the geo_addr */
} else {
continue;
}
return (DI_WALK_CONTINUE);
}
return (DI_WALK_CONTINUE);
}
static picl_errno_t
{
return (PICL_FAILURE);
}
if (rnode == DI_NODE_NIL) {
return (PICL_FAILURE);
}
return (PICL_NOSPACE);
}
probe_disks) != 0) {
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
{
int numlist;
if (ap_list_err != CFGA_OK) {
0, B_FALSE);
return (rc);
}
/* get list of all controllers in the system */
numlist);
if (ap_list_err != CFGA_OK) {
0, B_FALSE);
return (rc);
}
/* no controllers found */
0, B_FALSE);
return (rc);
}
/*
* we have to fetch cfgadm, look for scsi controllers
* dynamically
*/
return (rc);
} else {
/* during initialization */
/* use the cached cfgadm data */
} else {
}
return (rc);
}
}