10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*789Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /* implementation specific to scsi nodes probing */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <syslog.h>
340Sstevel@tonic-gate #include <stdlib.h>
350Sstevel@tonic-gate #include <sys/param.h>
360Sstevel@tonic-gate #include <config_admin.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <strings.h>
390Sstevel@tonic-gate #include <picl.h>
400Sstevel@tonic-gate #include <picltree.h>
410Sstevel@tonic-gate #include <libintl.h>
420Sstevel@tonic-gate #include <libdevinfo.h>
430Sstevel@tonic-gate #include <sys/types.h>
440Sstevel@tonic-gate #include <picldefs.h>
450Sstevel@tonic-gate #include "piclfrutree.h"
460Sstevel@tonic-gate
470Sstevel@tonic-gate #define SCSI_SLOT "scsi-bus"
480Sstevel@tonic-gate #define SCSI_LOC_FORMAT "t%dd0"
490Sstevel@tonic-gate #define TARGET "target"
500Sstevel@tonic-gate #define CLASS "class"
510Sstevel@tonic-gate #define BUF_SIZE 256
520Sstevel@tonic-gate
530Sstevel@tonic-gate #define SCSI_INITIATOR_ID 7
540Sstevel@tonic-gate #define DRV_TYPE_DSK 1
550Sstevel@tonic-gate #define DRV_TYPE_TAPE 2
560Sstevel@tonic-gate #define NUM_DSK_TARGS 15
570Sstevel@tonic-gate /*
580Sstevel@tonic-gate * No support for wide tapes for now.
590Sstevel@tonic-gate * If required wide support, set this to 8
600Sstevel@tonic-gate * See st.conf.
610Sstevel@tonic-gate */
620Sstevel@tonic-gate #define NUM_TAPE_TARGS 7
630Sstevel@tonic-gate
640Sstevel@tonic-gate #define DIRLINK_DSK "dsk"
650Sstevel@tonic-gate #define DIRLINK_RMT "rmt"
660Sstevel@tonic-gate #define DRV_SCSI_DSK "sd"
670Sstevel@tonic-gate #define DRV_SCSI_TAPE "st"
680Sstevel@tonic-gate #define NULL_ENTRY 0
690Sstevel@tonic-gate
700Sstevel@tonic-gate /* currently supported directory strings for SCSI FRUs in cfgadm APs */
710Sstevel@tonic-gate static char *scsi_dirlink_names[] = { DIRLINK_DSK, DIRLINK_RMT, NULL_ENTRY};
720Sstevel@tonic-gate /* currently supported SCSI FRU drivers */
730Sstevel@tonic-gate static struct scsi_drv_info {
740Sstevel@tonic-gate char *drv_name;
750Sstevel@tonic-gate uint8_t num_targets;
760Sstevel@tonic-gate uint8_t drv_type;
770Sstevel@tonic-gate } scsi_drv[] = {
780Sstevel@tonic-gate DRV_SCSI_DSK, NUM_DSK_TARGS, DRV_TYPE_DSK,
790Sstevel@tonic-gate DRV_SCSI_TAPE, NUM_TAPE_TARGS, DRV_TYPE_TAPE,
800Sstevel@tonic-gate NULL_ENTRY, NULL_ENTRY, NULL_ENTRY
810Sstevel@tonic-gate };
820Sstevel@tonic-gate
830Sstevel@tonic-gate /* the following defs are based on defines in scsi cfgadm plugin */
840Sstevel@tonic-gate #define CDROM "CD-ROM"
850Sstevel@tonic-gate #define RMM "tape"
860Sstevel@tonic-gate #define DISK "disk"
870Sstevel@tonic-gate
880Sstevel@tonic-gate extern boolean_t is_location_present_in_subtree(frutree_frunode_t *,
890Sstevel@tonic-gate const char *, const char *);
900Sstevel@tonic-gate extern picl_errno_t create_children(frutree_frunode_t *, char *, char *,
910Sstevel@tonic-gate int, char *, boolean_t);
920Sstevel@tonic-gate extern char *strtok_r(char *s1, const char *s2, char **lasts);
930Sstevel@tonic-gate extern boolean_t frutree_connects_initiated;
940Sstevel@tonic-gate extern int frutree_debug;
950Sstevel@tonic-gate
960Sstevel@tonic-gate typedef struct node {
970Sstevel@tonic-gate struct node *next;
980Sstevel@tonic-gate cfga_list_data_t *data;
990Sstevel@tonic-gate } node_t;
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate typedef struct linked_list {
1020Sstevel@tonic-gate node_t *first;
1030Sstevel@tonic-gate int num_nodes;
104*789Sahrens } plist_t;
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate typedef struct scsi_info {
1070Sstevel@tonic-gate frutree_frunode_t *frup;
1080Sstevel@tonic-gate cfga_list_data_t *cfgalist;
109*789Sahrens plist_t *list;
1100Sstevel@tonic-gate int num_list;
1110Sstevel@tonic-gate boolean_t compare_cfgadm;
1120Sstevel@tonic-gate int geo_addr;
1130Sstevel@tonic-gate } scsi_info_t;
1140Sstevel@tonic-gate
115*789Sahrens static plist_t *scsi_list = NULL;
1160Sstevel@tonic-gate static cfga_list_data_t *cfglist = NULL;
1170Sstevel@tonic-gate static int nlist = 0;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate static void
free_list(plist_t * list)120*789Sahrens free_list(plist_t *list)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate node_t *tmp = NULL, *tmp1 = NULL;
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate if (list == NULL)
1250Sstevel@tonic-gate return;
1260Sstevel@tonic-gate tmp = list->first;
1270Sstevel@tonic-gate while (tmp != NULL) {
1280Sstevel@tonic-gate free(tmp->data);
1290Sstevel@tonic-gate tmp1 = tmp->next;
1300Sstevel@tonic-gate free(tmp);
1310Sstevel@tonic-gate tmp = tmp1;
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate /*
1360Sstevel@tonic-gate * This routine gets the list of scsi controllers present
1370Sstevel@tonic-gate */
1380Sstevel@tonic-gate static cfga_err_t
populate_controllers_list(plist_t * cntrl_list,cfga_list_data_t * list,int num)139*789Sahrens populate_controllers_list(plist_t *cntrl_list, cfga_list_data_t *list, int num)
1400Sstevel@tonic-gate {
1410Sstevel@tonic-gate int i;
1420Sstevel@tonic-gate node_t *nodeptr = NULL;
1430Sstevel@tonic-gate cfga_list_data_t *temp = NULL;
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate if (cntrl_list == NULL || list == NULL) {
1460Sstevel@tonic-gate return (CFGA_ATTR_INVAL);
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate cntrl_list->first = NULL;
1500Sstevel@tonic-gate cntrl_list->num_nodes = 0;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate if (num == 0) {
1530Sstevel@tonic-gate return (CFGA_OK);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate for (i = 0; i < num; i++) {
1570Sstevel@tonic-gate if (strcmp(list[i].ap_type, SCSI_SLOT) != 0) {
1580Sstevel@tonic-gate continue;
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /* scsi controller */
1620Sstevel@tonic-gate temp = (cfga_list_data_t *)malloc(sizeof (cfga_list_data_t));
1630Sstevel@tonic-gate if (temp == NULL) {
1640Sstevel@tonic-gate return (CFGA_ERROR);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate (void) memcpy(temp, &list[i], sizeof (cfga_list_data_t));
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate nodeptr = (node_t *)malloc(sizeof (node_t));
1690Sstevel@tonic-gate if (nodeptr == NULL) {
1700Sstevel@tonic-gate free(temp);
1710Sstevel@tonic-gate return (CFGA_ERROR);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate nodeptr->data = temp;
1740Sstevel@tonic-gate nodeptr->next = NULL;
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate /* append to the list */
1770Sstevel@tonic-gate if (cntrl_list->first == NULL) {
1780Sstevel@tonic-gate cntrl_list->first = nodeptr;
1790Sstevel@tonic-gate cntrl_list->num_nodes++;
1800Sstevel@tonic-gate } else {
1810Sstevel@tonic-gate nodeptr->next = cntrl_list->first;
1820Sstevel@tonic-gate cntrl_list->first = nodeptr;
1830Sstevel@tonic-gate cntrl_list->num_nodes++;
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate return (CFGA_OK);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate picl_errno_t
scsi_info_init()1900Sstevel@tonic-gate scsi_info_init()
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate cfga_err_t ap_list_err;
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate ap_list_err = config_list_ext(0, NULL, &cfglist, &nlist, NULL,
1950Sstevel@tonic-gate NULL, NULL, CFGA_FLAG_LIST_ALL);
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate if (ap_list_err != CFGA_OK) {
1980Sstevel@tonic-gate if (ap_list_err == CFGA_NOTSUPP) {
1990Sstevel@tonic-gate return (PICL_SUCCESS);
2000Sstevel@tonic-gate } else {
2010Sstevel@tonic-gate return (PICL_FAILURE);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate
205*789Sahrens scsi_list = (plist_t *)malloc(sizeof (plist_t));
2060Sstevel@tonic-gate if (scsi_list == NULL) {
2070Sstevel@tonic-gate free(cfglist);
2080Sstevel@tonic-gate return (PICL_NOSPACE);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate ap_list_err = populate_controllers_list(scsi_list, cfglist, nlist);
2120Sstevel@tonic-gate if (ap_list_err != CFGA_OK) {
2130Sstevel@tonic-gate free(cfglist);
2140Sstevel@tonic-gate free(scsi_list);
2150Sstevel@tonic-gate return (PICL_FAILURE);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate return (PICL_SUCCESS);
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate void
scsi_info_fini()2210Sstevel@tonic-gate scsi_info_fini()
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate free(cfglist);
2240Sstevel@tonic-gate free_list(scsi_list);
2250Sstevel@tonic-gate free(scsi_list);
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate /*
2290Sstevel@tonic-gate * This routine searches the controllers list to find the mapping based
2300Sstevel@tonic-gate * on given devfs_path.
2310Sstevel@tonic-gate * caller should allocate memory for ap_id
2320Sstevel@tonic-gate */
2330Sstevel@tonic-gate static picl_errno_t
find_scsi_controller(char * devfs_path,plist_t * list,char * ap_id)234*789Sahrens find_scsi_controller(char *devfs_path, plist_t *list, char *ap_id)
2350Sstevel@tonic-gate {
2360Sstevel@tonic-gate node_t *tmp = NULL;
2370Sstevel@tonic-gate char *lasts = NULL;
2380Sstevel@tonic-gate char *token = NULL;
2390Sstevel@tonic-gate char path[MAXPATHLEN];
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate if (devfs_path == NULL || ap_id == NULL) {
2420Sstevel@tonic-gate return (PICL_INVALIDARG);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate (void) snprintf((char *)path, sizeof (path), "/devices%s", devfs_path);
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate tmp = list->first;
2470Sstevel@tonic-gate while (tmp != NULL) {
2480Sstevel@tonic-gate lasts = tmp->data->ap_phys_id;
2490Sstevel@tonic-gate token = (char *)strtok_r(lasts, (const char *)":",
2500Sstevel@tonic-gate (char **)&lasts);
2510Sstevel@tonic-gate if (token == NULL) {
2520Sstevel@tonic-gate tmp = tmp->next;
2530Sstevel@tonic-gate continue;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate if (strcmp(path, token) == 0) { /* match found */
2570Sstevel@tonic-gate (void) strncpy(ap_id, tmp->data->ap_log_id,
2580Sstevel@tonic-gate sizeof (ap_id));
2590Sstevel@tonic-gate return (PICL_SUCCESS);
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate tmp = tmp->next;
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate return (PICL_NODENOTFOUND);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate /*
2670Sstevel@tonic-gate * This routine dynamically determines the cfgadm attachment point
2680Sstevel@tonic-gate * for a given devfspath and target id.
2690Sstevel@tonic-gate * memory for name should be allocated by the caller.
2700Sstevel@tonic-gate */
2710Sstevel@tonic-gate picl_errno_t
get_scsislot_name(char * devfs_path,char * bus_addr,char * name)2720Sstevel@tonic-gate get_scsislot_name(char *devfs_path, char *bus_addr, char *name)
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate picl_errno_t rc;
2750Sstevel@tonic-gate int target_id = 0;
2760Sstevel@tonic-gate int numlist;
277*789Sahrens plist_t list;
2780Sstevel@tonic-gate cfga_err_t ap_list_err;
2790Sstevel@tonic-gate cfga_list_data_t *cfgalist = NULL;
2800Sstevel@tonic-gate char controller[MAXPATHLEN];
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate ap_list_err = config_list_ext(0, NULL, &cfgalist,
2830Sstevel@tonic-gate &numlist, NULL, NULL, NULL, CFGA_FLAG_LIST_ALL);
2840Sstevel@tonic-gate if (ap_list_err != CFGA_OK) {
2850Sstevel@tonic-gate return (PICL_NODENOTFOUND);
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate ap_list_err = populate_controllers_list(&list, cfgalist,
2890Sstevel@tonic-gate numlist);
2900Sstevel@tonic-gate if (ap_list_err != CFGA_OK) {
2910Sstevel@tonic-gate free_list(&list);
2920Sstevel@tonic-gate free(cfgalist);
2930Sstevel@tonic-gate return (PICL_NODENOTFOUND);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate if (list.num_nodes <= 0) {
2970Sstevel@tonic-gate free(cfgalist);
2980Sstevel@tonic-gate return (PICL_NODENOTFOUND);
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate if ((rc = find_scsi_controller(devfs_path, &list,
3020Sstevel@tonic-gate controller)) != PICL_SUCCESS) {
3030Sstevel@tonic-gate free(cfgalist);
3040Sstevel@tonic-gate free_list(&list);
3050Sstevel@tonic-gate return (rc);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate target_id = strtol(bus_addr, (char **)NULL, 16);
3080Sstevel@tonic-gate (void) sprintf(name, "%s::dsk/%st%dd0", controller,
3090Sstevel@tonic-gate controller, target_id);
3100Sstevel@tonic-gate free(cfgalist);
3110Sstevel@tonic-gate free_list(&list);
3120Sstevel@tonic-gate return (PICL_SUCCESS);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate /*
3160Sstevel@tonic-gate * Arg scsi_loc can be any of the following forms appearing in cfgadm output
3170Sstevel@tonic-gate * c0::dsk/c0t0d0
3180Sstevel@tonic-gate * c1::sd56
3190Sstevel@tonic-gate * c2::rmt/0
3200Sstevel@tonic-gate * c3::st41
3210Sstevel@tonic-gate * dsk/c1t1d0
3220Sstevel@tonic-gate * rmt/1
3230Sstevel@tonic-gate * /devices/pci@1f,0/pci@1,1/scsi@2:scsi::dsk/c0t0d0
3240Sstevel@tonic-gate *
3250Sstevel@tonic-gate * On return, bus_addr contains the target id of the device.
3260Sstevel@tonic-gate * Please note that currently the target id is computed. It is better
3270Sstevel@tonic-gate * to eventually change this to getting from libdevinfo.
3280Sstevel@tonic-gate * Also, please note that SCSI_INITIATOR_ID should not
3290Sstevel@tonic-gate * be hardcoded, but should be dynamically retrieved from an OBP property.
3300Sstevel@tonic-gate */
3310Sstevel@tonic-gate static void
get_bus_addr(char * scsi_loc,char ** bus_addr)3320Sstevel@tonic-gate get_bus_addr(char *scsi_loc, char **bus_addr)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate char *ap, *token, *p, *ap_idp;
3350Sstevel@tonic-gate int len = 0, i = 0;
3360Sstevel@tonic-gate char parse_link = 0;
3370Sstevel@tonic-gate char addr[BUF_SIZE], ap_id[BUF_SIZE];
3380Sstevel@tonic-gate char fileinfo[BUF_SIZE], ap_id_link[BUF_SIZE];
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate (void) strncpy(ap_id, scsi_loc, sizeof (ap_id));
3410Sstevel@tonic-gate ap = strrchr(ap_id, ':');
3420Sstevel@tonic-gate if (!ap)
3430Sstevel@tonic-gate ap = ap_idp = ap_id;
3440Sstevel@tonic-gate else
3450Sstevel@tonic-gate ap_idp = ++ap;
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate while (scsi_dirlink_names[i] && !len) {
3480Sstevel@tonic-gate len = strspn(ap, scsi_dirlink_names[i++]);
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate * strspn may return positive len even when there is no
3510Sstevel@tonic-gate * complete string matches!!! hence the following check is
3520Sstevel@tonic-gate * necessary. So ensure the string match.
3530Sstevel@tonic-gate */
3540Sstevel@tonic-gate if (len && strstr(ap, scsi_dirlink_names[i-1]))
3550Sstevel@tonic-gate break;
3560Sstevel@tonic-gate len = 0;
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate if (len)
3590Sstevel@tonic-gate parse_link = 1;
3600Sstevel@tonic-gate else {
3610Sstevel@tonic-gate i = 0;
3620Sstevel@tonic-gate while (scsi_drv[i].drv_name && !len) {
3630Sstevel@tonic-gate len = strspn(ap, scsi_drv[i++].drv_name);
3640Sstevel@tonic-gate if (len && strstr(ap, scsi_drv[i-1].drv_name))
3650Sstevel@tonic-gate break;
3660Sstevel@tonic-gate len = 0;
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate ap += len;
3700Sstevel@tonic-gate if (strlen(ap) && parse_link) {
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate /* slice 0 must be present in the system */
3730Sstevel@tonic-gate if (strstr(ap, "/c")) {
3740Sstevel@tonic-gate if (strstr(ap, "s0") == NULL)
3750Sstevel@tonic-gate (void) strcat(ap, "s0");
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate /* get the devlink and read the target id from minor node */
3780Sstevel@tonic-gate (void) snprintf(ap_id_link, sizeof (ap_id_link), "/dev/%s",
3790Sstevel@tonic-gate ap_idp);
3800Sstevel@tonic-gate (void) bzero(fileinfo, sizeof (fileinfo));
3810Sstevel@tonic-gate if (readlink(ap_id_link, fileinfo, sizeof (fileinfo)) < 0)
3820Sstevel@tonic-gate return;
3830Sstevel@tonic-gate if (!fileinfo[0])
3840Sstevel@tonic-gate return;
3850Sstevel@tonic-gate ap = strrchr(fileinfo, '@');
3860Sstevel@tonic-gate ap++;
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate token = (char *)strtok_r(ap, ",", &p);
3890Sstevel@tonic-gate (void) strncpy(addr, token, sizeof (addr));
3900Sstevel@tonic-gate if (!parse_link) {
3910Sstevel@tonic-gate int drv_inst = atoi(token);
3920Sstevel@tonic-gate int tmp_targ_id = drv_inst % scsi_drv[i-1].num_targets;
3930Sstevel@tonic-gate int targ_id = scsi_drv[i-1].drv_type == DRV_TYPE_DSK ?
3940Sstevel@tonic-gate (tmp_targ_id < SCSI_INITIATOR_ID ?
3950Sstevel@tonic-gate tmp_targ_id : tmp_targ_id+1):
3960Sstevel@tonic-gate DRV_TYPE_TAPE ? tmp_targ_id : drv_inst;
3970Sstevel@tonic-gate (void) snprintf(addr, sizeof (addr), "%d", targ_id);
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate if (strlen(addr)) {
4000Sstevel@tonic-gate *bus_addr = (char *)malloc(strlen(addr)+1);
4010Sstevel@tonic-gate if ((*bus_addr) == NULL)
4020Sstevel@tonic-gate return;
4030Sstevel@tonic-gate (void) strcpy((char *)*bus_addr, addr);
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate /*
4080Sstevel@tonic-gate * This routine determines all the scsi nodes under a FRU and
4090Sstevel@tonic-gate * creates a subtree of all the scsi nodes with basic properties.
4100Sstevel@tonic-gate */
4110Sstevel@tonic-gate static picl_errno_t
dyn_probe_for_scsi_frus(frutree_frunode_t * frup,cfga_list_data_t * cfgalist,plist_t * list,int numlist)4120Sstevel@tonic-gate dyn_probe_for_scsi_frus(frutree_frunode_t *frup, cfga_list_data_t *cfgalist,
413*789Sahrens plist_t *list, int numlist)
4140Sstevel@tonic-gate {
4150Sstevel@tonic-gate picl_errno_t rc;
4160Sstevel@tonic-gate int i, geo_addr = 0;
4170Sstevel@tonic-gate node_t *curr = NULL;
4180Sstevel@tonic-gate char *bus_addr = NULL;
4190Sstevel@tonic-gate char path[MAXPATHLEN];
4200Sstevel@tonic-gate char controller_name[MAXPATHLEN];
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate /* for each controller in the list, find if disk/fru is present */
4230Sstevel@tonic-gate curr = list->first;
4240Sstevel@tonic-gate while (curr != NULL) {
4250Sstevel@tonic-gate /* compare the path */
4260Sstevel@tonic-gate (void) snprintf((char *)path, sizeof (path), "/devices%s",
4270Sstevel@tonic-gate frup->fru_path);
4280Sstevel@tonic-gate if (strstr(curr->data->ap_phys_id, path) == NULL) {
4290Sstevel@tonic-gate curr = curr->next;
4300Sstevel@tonic-gate continue;
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate (void) snprintf(controller_name, sizeof (controller_name),
4340Sstevel@tonic-gate "%s::", curr->data->ap_log_id);
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate for (i = 0; i < numlist; i++) {
4370Sstevel@tonic-gate if (strcmp(cfgalist[i].ap_type, SCSI_SLOT) == 0) {
4380Sstevel@tonic-gate continue;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate if (strstr(cfgalist[i].ap_log_id,
4410Sstevel@tonic-gate controller_name) == NULL) {
4420Sstevel@tonic-gate continue;
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate /* check if device is under fru */
4450Sstevel@tonic-gate if (strstr(cfgalist[i].ap_phys_id, path) == NULL) {
4460Sstevel@tonic-gate continue;
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate
4490Sstevel@tonic-gate /* we found a scsi fru */
4500Sstevel@tonic-gate geo_addr++;
4510Sstevel@tonic-gate /* check if the device is present in subtree */
4520Sstevel@tonic-gate if (is_location_present_in_subtree(frup,
4530Sstevel@tonic-gate cfgalist[i].ap_log_id, path) == B_TRUE) {
4540Sstevel@tonic-gate continue;
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate get_bus_addr(cfgalist[i].ap_log_id, &bus_addr);
4570Sstevel@tonic-gate if (bus_addr == NULL) {
4580Sstevel@tonic-gate continue;
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate rc = create_children(frup, cfgalist[i].ap_log_id,
4610Sstevel@tonic-gate bus_addr, geo_addr, SANIBEL_SCSI_SLOT, B_TRUE);
4620Sstevel@tonic-gate free(bus_addr);
4630Sstevel@tonic-gate if (rc != PICL_SUCCESS) {
4640Sstevel@tonic-gate FRUTREE_DEBUG3(FRUTREE_INIT, "SUNW_frutree:"
4650Sstevel@tonic-gate "Error in creating node %s under %s(error=%d)",
4660Sstevel@tonic-gate cfgalist[i].ap_log_id, frup->name, rc);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate curr = curr->next;
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate return (PICL_SUCCESS);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate * data used here is cached information (cfglist, nlist)
4760Sstevel@tonic-gate */
4770Sstevel@tonic-gate static picl_errno_t
cache_probe_for_scsi_frus(frutree_frunode_t * frup)4780Sstevel@tonic-gate cache_probe_for_scsi_frus(frutree_frunode_t *frup)
4790Sstevel@tonic-gate {
4800Sstevel@tonic-gate int i, geo_addr = 0;
4810Sstevel@tonic-gate picl_errno_t rc;
4820Sstevel@tonic-gate node_t *curr = NULL;
4830Sstevel@tonic-gate char path[MAXPATHLEN];
4840Sstevel@tonic-gate char controller_name[MAXPATHLEN];
4850Sstevel@tonic-gate char *bus_addr = NULL;
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate /* for each controller in the list, find if disk/fru is present */
4880Sstevel@tonic-gate if (scsi_list == NULL) {
4890Sstevel@tonic-gate return (PICL_SUCCESS);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate curr = scsi_list->first;
4920Sstevel@tonic-gate while (curr != NULL) {
4930Sstevel@tonic-gate /* compare the path */
4940Sstevel@tonic-gate (void) snprintf((char *)path, sizeof (path), "/devices%s",
4950Sstevel@tonic-gate frup->fru_path);
4960Sstevel@tonic-gate if (strstr(curr->data->ap_phys_id, path) == NULL) {
4970Sstevel@tonic-gate curr = curr->next;
4980Sstevel@tonic-gate continue;
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate (void) snprintf(controller_name, sizeof (controller_name),
5010Sstevel@tonic-gate "%s::", curr->data->ap_log_id);
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate for (i = 0; i < nlist; i++) {
5040Sstevel@tonic-gate if (strcmp(cfglist[i].ap_type, SCSI_SLOT) == 0) {
5050Sstevel@tonic-gate continue;
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate if (strstr(cfglist[i].ap_log_id,
5080Sstevel@tonic-gate controller_name) == NULL) {
5090Sstevel@tonic-gate continue;
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate /* check if the device is under fru */
5120Sstevel@tonic-gate if (strstr(cfglist[i].ap_phys_id, path) == NULL) {
5130Sstevel@tonic-gate continue;
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate /* we found a scsi fru */
5170Sstevel@tonic-gate geo_addr++;
5180Sstevel@tonic-gate /* check if the device is present in subtree */
5190Sstevel@tonic-gate if (is_location_present_in_subtree(frup,
5200Sstevel@tonic-gate cfglist[i].ap_log_id, path) == B_TRUE) {
5210Sstevel@tonic-gate continue;
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate get_bus_addr(cfglist[i].ap_log_id, &bus_addr);
5240Sstevel@tonic-gate if (bus_addr == NULL) {
5250Sstevel@tonic-gate continue;
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate rc = create_children(frup, cfglist[i].ap_log_id,
5280Sstevel@tonic-gate bus_addr, geo_addr, SANIBEL_SCSI_SLOT, B_TRUE);
5290Sstevel@tonic-gate free(bus_addr);
5300Sstevel@tonic-gate if (rc != PICL_SUCCESS) {
5310Sstevel@tonic-gate FRUTREE_DEBUG3(FRUTREE_INIT, "SUNW_frutree:"
5320Sstevel@tonic-gate "Error in creating node %s under %s(error=%d)",
5330Sstevel@tonic-gate cfglist[i].ap_log_id, frup->name, rc);
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate curr = curr->next;
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate return (PICL_SUCCESS);
5390Sstevel@tonic-gate }
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate /*
5420Sstevel@tonic-gate * This routine checks if the node (scsi device) is present in cfgadm data
5430Sstevel@tonic-gate * Algorithm:
5440Sstevel@tonic-gate * 1. traverse thru list of controllers and find
5450Sstevel@tonic-gate * the controller of interest
5460Sstevel@tonic-gate * 2. go thru list of devices under controller and compare if the target is same
5470Sstevel@tonic-gate * 3. if yes
5480Sstevel@tonic-gate * - device is already represented
5490Sstevel@tonic-gate * 4. if No
5500Sstevel@tonic-gate * - The node must be repreented in PICL tree.
5510Sstevel@tonic-gate */
5520Sstevel@tonic-gate static boolean_t
is_node_present(scsi_info_t * scsi_info,char * devfs_path,int target)5530Sstevel@tonic-gate is_node_present(scsi_info_t *scsi_info, char *devfs_path, int target)
5540Sstevel@tonic-gate {
5550Sstevel@tonic-gate node_t *curr = NULL;
5560Sstevel@tonic-gate char path[MAXPATHLEN];
5570Sstevel@tonic-gate char controller[MAXPATHLEN];
5580Sstevel@tonic-gate char *bus_addr = NULL;
5590Sstevel@tonic-gate char *lasts = NULL, *token = NULL;
5600Sstevel@tonic-gate int i = 0;
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate if (scsi_info == NULL) {
5630Sstevel@tonic-gate return (B_FALSE);
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate if (scsi_info->list == NULL) {
5670Sstevel@tonic-gate return (B_FALSE);
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "/devices%s", devfs_path);
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate curr = scsi_info->list->first;
5730Sstevel@tonic-gate while (curr != NULL) {
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate lasts = curr->data->ap_phys_id;
5760Sstevel@tonic-gate token = (char *)strtok_r(lasts, (const char *)":",
5770Sstevel@tonic-gate (char **)&lasts);
5780Sstevel@tonic-gate if (token == NULL) {
5790Sstevel@tonic-gate curr = curr->next;
5800Sstevel@tonic-gate continue;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate if (strstr(path, token) == NULL) {
5840Sstevel@tonic-gate /* this controller is not of interest */
5850Sstevel@tonic-gate curr = curr->next;
5860Sstevel@tonic-gate continue;
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate (void) snprintf(controller, sizeof (controller), "%s::",
5900Sstevel@tonic-gate curr->data->ap_log_id);
5910Sstevel@tonic-gate for (i = 0; i < scsi_info->num_list; i++) {
5920Sstevel@tonic-gate if (strcmp(scsi_info->cfgalist[i].ap_type,
5930Sstevel@tonic-gate SCSI_SLOT) == 0) {
5940Sstevel@tonic-gate continue;
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate if (strstr(scsi_info->cfgalist[i].ap_log_id,
5980Sstevel@tonic-gate controller) == NULL) {
5990Sstevel@tonic-gate continue;
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate get_bus_addr(scsi_info->cfgalist[i].ap_phys_id,
6030Sstevel@tonic-gate &bus_addr);
6040Sstevel@tonic-gate /*
6050Sstevel@tonic-gate * compare with target value
6060Sstevel@tonic-gate */
6070Sstevel@tonic-gate if (bus_addr == NULL) {
6080Sstevel@tonic-gate return (B_TRUE);
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate if (strtoul(bus_addr, NULL, 16) == target) {
6110Sstevel@tonic-gate /*
6120Sstevel@tonic-gate * this device is already represented
6130Sstevel@tonic-gate * in fru tree
6140Sstevel@tonic-gate */
6150Sstevel@tonic-gate free(bus_addr);
6160Sstevel@tonic-gate return (B_TRUE);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate free(bus_addr);
6190Sstevel@tonic-gate }
6200Sstevel@tonic-gate curr = curr->next;
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate return (B_FALSE);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate static di_prop_t
get_prop_by_name(di_node_t node,char * name)6260Sstevel@tonic-gate get_prop_by_name(di_node_t node, char *name)
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate di_prop_t prop = DI_PROP_NIL;
6290Sstevel@tonic-gate char *prop_name = NULL;
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate prop = di_prop_next(node, DI_PROP_NIL);
6320Sstevel@tonic-gate while (prop != DI_PROP_NIL) {
6330Sstevel@tonic-gate prop_name = di_prop_name(prop);
6340Sstevel@tonic-gate if (prop_name != NULL) {
6350Sstevel@tonic-gate if (strcmp(prop_name, name) == 0) {
6360Sstevel@tonic-gate return (prop);
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate prop = di_prop_next(node, prop);
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate return (DI_PROP_NIL);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate static int
get_geoaddr(picl_nodehdl_t nodeh,void * c_args)6450Sstevel@tonic-gate get_geoaddr(picl_nodehdl_t nodeh, void *c_args)
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate picl_errno_t rc;
6480Sstevel@tonic-gate uint8_t *geo_addr = NULL;
6490Sstevel@tonic-gate char slot_type[PICL_PROPNAMELEN_MAX];
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate if (c_args == NULL)
6520Sstevel@tonic-gate return (PICL_INVALIDARG);
6530Sstevel@tonic-gate geo_addr = (uint8_t *)c_args;
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_SLOT_TYPE,
6560Sstevel@tonic-gate slot_type, sizeof (slot_type))) != PICL_SUCCESS) {
6570Sstevel@tonic-gate return (rc);
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate
6600Sstevel@tonic-gate if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 ||
6610Sstevel@tonic-gate strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) {
6620Sstevel@tonic-gate *geo_addr = *geo_addr + 1;
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate return (PICL_WALK_CONTINUE);
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate static int
frutree_get_geoaddr(frutree_frunode_t * frup)6680Sstevel@tonic-gate frutree_get_geoaddr(frutree_frunode_t *frup)
6690Sstevel@tonic-gate {
6700Sstevel@tonic-gate int geo_addr = 1;
6710Sstevel@tonic-gate if (ptree_walk_tree_by_class(frup->frunodeh, PICL_CLASS_LOCATION,
6720Sstevel@tonic-gate &geo_addr, get_geoaddr) != PICL_SUCCESS) {
6730Sstevel@tonic-gate return (geo_addr);
6740Sstevel@tonic-gate }
6750Sstevel@tonic-gate return (geo_addr);
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate static int
probe_disks(di_node_t node,void * arg)6790Sstevel@tonic-gate probe_disks(di_node_t node, void *arg)
6800Sstevel@tonic-gate {
6810Sstevel@tonic-gate di_prop_t prop;
6820Sstevel@tonic-gate picl_errno_t rc;
6830Sstevel@tonic-gate int *target_val = NULL;
6840Sstevel@tonic-gate char *nodetype = NULL;
6850Sstevel@tonic-gate char *devfs_path = NULL;
6860Sstevel@tonic-gate char *bus_addr = NULL;
6870Sstevel@tonic-gate char *drv_name = NULL;
6880Sstevel@tonic-gate scsi_info_t *data = NULL;
6890Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL;
6900Sstevel@tonic-gate char *class = NULL;
6910Sstevel@tonic-gate char node_name[BUF_SIZE];
6920Sstevel@tonic-gate char slot_type[PICL_PROPNAMELEN_MAX];
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate if (arg == NULL)
6950Sstevel@tonic-gate return (DI_WALK_TERMINATE);
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate data = *(scsi_info_t **)arg;
6980Sstevel@tonic-gate if (data == NULL) {
6990Sstevel@tonic-gate return (DI_WALK_TERMINATE);
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate /* initialize the geo_addr value */
7030Sstevel@tonic-gate if (data->geo_addr == 0) {
7040Sstevel@tonic-gate if (data->compare_cfgadm == B_FALSE) {
7050Sstevel@tonic-gate data->geo_addr = 1;
7060Sstevel@tonic-gate } else {
7070Sstevel@tonic-gate data->geo_addr = frutree_get_geoaddr(data->frup);
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
7120Sstevel@tonic-gate nodetype = di_minor_nodetype(minor);
7130Sstevel@tonic-gate if (nodetype == NULL) {
7140Sstevel@tonic-gate continue;
7150Sstevel@tonic-gate }
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate if (strcmp(nodetype, DDI_NT_BLOCK_CHAN) == 0 ||
7180Sstevel@tonic-gate strcmp(nodetype, DDI_NT_BLOCK_WWN) == 0) {
7190Sstevel@tonic-gate (void) snprintf(node_name, sizeof (node_name),
7200Sstevel@tonic-gate "%s%d", DISK, data->geo_addr);
7210Sstevel@tonic-gate } else if (strcmp(nodetype, DDI_NT_TAPE) == 0) {
7220Sstevel@tonic-gate (void) snprintf(node_name, sizeof (node_name),
7230Sstevel@tonic-gate "%s%d", RMM, data->geo_addr);
7240Sstevel@tonic-gate } else if (strcmp(nodetype, DDI_NT_CD) == 0 ||
7250Sstevel@tonic-gate strcmp(nodetype, DDI_NT_CD_CHAN) == 0) {
7260Sstevel@tonic-gate (void) snprintf(node_name, sizeof (node_name),
7270Sstevel@tonic-gate "%s%d", CDROM, data->geo_addr);
7280Sstevel@tonic-gate } else {
7290Sstevel@tonic-gate continue;
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate devfs_path = di_devfs_path(node);
7330Sstevel@tonic-gate drv_name = di_driver_name(node);
7340Sstevel@tonic-gate bus_addr = di_bus_addr(node);
7350Sstevel@tonic-gate if (devfs_path == NULL) {
7360Sstevel@tonic-gate continue;
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate if (drv_name == NULL || bus_addr == NULL) {
7390Sstevel@tonic-gate di_devfs_path_free(devfs_path);
7400Sstevel@tonic-gate continue;
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate prop = get_prop_by_name(node, TARGET);
7430Sstevel@tonic-gate if (prop != DI_PROP_NIL) {
7440Sstevel@tonic-gate di_prop_ints(prop, &target_val);
7450Sstevel@tonic-gate if (data->compare_cfgadm) {
7460Sstevel@tonic-gate /* check if node is present in cfgadm data */
7470Sstevel@tonic-gate if (is_node_present(data, devfs_path,
7480Sstevel@tonic-gate *target_val) == B_TRUE) {
7490Sstevel@tonic-gate di_devfs_path_free(devfs_path);
7500Sstevel@tonic-gate return (DI_WALK_CONTINUE);
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate
7540Sstevel@tonic-gate di_devfs_path_free(devfs_path);
7550Sstevel@tonic-gate prop = get_prop_by_name(node, CLASS);
7560Sstevel@tonic-gate if (prop != DI_PROP_NIL) {
7570Sstevel@tonic-gate di_prop_strings(prop, &class);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate /* determine the slot type based on class code */
7610Sstevel@tonic-gate if (class != NULL) {
7620Sstevel@tonic-gate if (strcmp(class, DEVICE_CLASS_SCSI) == 0) {
7630Sstevel@tonic-gate (void) strncpy(slot_type,
7640Sstevel@tonic-gate SANIBEL_SCSI_SLOT,
7650Sstevel@tonic-gate sizeof (slot_type));
7660Sstevel@tonic-gate } else if (strcmp(class,
7670Sstevel@tonic-gate DEVICE_CLASS_IDE) == 0) {
7680Sstevel@tonic-gate (void) strncpy(slot_type,
7690Sstevel@tonic-gate SANIBEL_IDE_SLOT,
7700Sstevel@tonic-gate sizeof (slot_type));
7710Sstevel@tonic-gate } else {
7720Sstevel@tonic-gate (void) strncpy(slot_type,
7730Sstevel@tonic-gate SANIBEL_UNKNOWN_SLOT,
7740Sstevel@tonic-gate sizeof (slot_type));
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate } else {
7780Sstevel@tonic-gate (void) strncpy(slot_type, SANIBEL_UNKNOWN_SLOT,
7790Sstevel@tonic-gate sizeof (slot_type));
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate if ((rc = create_children(data->frup, node_name,
7830Sstevel@tonic-gate bus_addr, data->geo_addr, slot_type,
7840Sstevel@tonic-gate B_FALSE)) != PICL_SUCCESS) {
7850Sstevel@tonic-gate return (rc);
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate /* increment the geo_addr */
7880Sstevel@tonic-gate data->geo_addr++;
7890Sstevel@tonic-gate } else {
7900Sstevel@tonic-gate di_devfs_path_free(devfs_path);
7910Sstevel@tonic-gate continue;
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate return (DI_WALK_CONTINUE);
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate return (DI_WALK_CONTINUE);
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate static picl_errno_t
probe_scsi_in_libdevinfo(frutree_frunode_t * frup,cfga_list_data_t * cfgalist,plist_t * list,int num_list,boolean_t compare_cfgadm)7990Sstevel@tonic-gate probe_scsi_in_libdevinfo(frutree_frunode_t *frup, cfga_list_data_t *cfgalist,
800*789Sahrens plist_t *list, int num_list, boolean_t compare_cfgadm)
8010Sstevel@tonic-gate {
8020Sstevel@tonic-gate di_node_t rnode;
8030Sstevel@tonic-gate scsi_info_t *scsi_data = NULL;
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate if (frup == NULL) {
8060Sstevel@tonic-gate return (PICL_FAILURE);
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate rnode = di_init(frup->fru_path, DINFOCPYALL);
8100Sstevel@tonic-gate if (rnode == DI_NODE_NIL) {
8110Sstevel@tonic-gate return (PICL_FAILURE);
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate scsi_data = (scsi_info_t *)malloc(sizeof (scsi_info_t));
8150Sstevel@tonic-gate if (scsi_data == NULL) {
8160Sstevel@tonic-gate di_fini(rnode);
8170Sstevel@tonic-gate return (PICL_NOSPACE);
8180Sstevel@tonic-gate }
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate scsi_data->frup = frup;
8210Sstevel@tonic-gate scsi_data->cfgalist = cfgalist;
8220Sstevel@tonic-gate scsi_data->list = list;
8230Sstevel@tonic-gate scsi_data->num_list = num_list;
8240Sstevel@tonic-gate scsi_data->compare_cfgadm = compare_cfgadm;
8250Sstevel@tonic-gate scsi_data->geo_addr = 0;
8260Sstevel@tonic-gate if (di_walk_node(rnode, DI_WALK_CLDFIRST, &scsi_data,
8270Sstevel@tonic-gate probe_disks) != 0) {
8280Sstevel@tonic-gate free(scsi_data);
8290Sstevel@tonic-gate di_fini(rnode);
8300Sstevel@tonic-gate return (PICL_FAILURE);
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate free(scsi_data);
8340Sstevel@tonic-gate di_fini(rnode);
8350Sstevel@tonic-gate return (PICL_SUCCESS);
8360Sstevel@tonic-gate }
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate picl_errno_t
probe_for_scsi_frus(frutree_frunode_t * frup)8390Sstevel@tonic-gate probe_for_scsi_frus(frutree_frunode_t *frup)
8400Sstevel@tonic-gate {
8410Sstevel@tonic-gate int numlist;
8420Sstevel@tonic-gate picl_errno_t rc;
843*789Sahrens plist_t list;
8440Sstevel@tonic-gate cfga_err_t ap_list_err;
8450Sstevel@tonic-gate cfga_list_data_t *cfgalist = NULL;
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate if (frutree_connects_initiated == B_TRUE) { /* probing after hotswap */
8480Sstevel@tonic-gate ap_list_err = config_list_ext(0, NULL, &cfgalist,
8490Sstevel@tonic-gate &numlist, NULL, NULL, NULL, CFGA_FLAG_LIST_ALL);
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate if (ap_list_err != CFGA_OK) {
8520Sstevel@tonic-gate rc = probe_scsi_in_libdevinfo(frup, NULL, NULL,
8530Sstevel@tonic-gate 0, B_FALSE);
8540Sstevel@tonic-gate return (rc);
8550Sstevel@tonic-gate }
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate /* get list of all controllers in the system */
8580Sstevel@tonic-gate ap_list_err = populate_controllers_list(&list, cfgalist,
8590Sstevel@tonic-gate numlist);
8600Sstevel@tonic-gate if (ap_list_err != CFGA_OK) {
8610Sstevel@tonic-gate free_list(&list);
8620Sstevel@tonic-gate free(cfgalist);
8630Sstevel@tonic-gate rc = probe_scsi_in_libdevinfo(frup, NULL, NULL,
8640Sstevel@tonic-gate 0, B_FALSE);
8650Sstevel@tonic-gate return (rc);
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate /* no controllers found */
8690Sstevel@tonic-gate if (list.num_nodes <= 0) {
8700Sstevel@tonic-gate free_list(&list);
8710Sstevel@tonic-gate free(cfgalist);
8720Sstevel@tonic-gate rc = probe_scsi_in_libdevinfo(frup, NULL, NULL,
8730Sstevel@tonic-gate 0, B_FALSE);
8740Sstevel@tonic-gate return (rc);
8750Sstevel@tonic-gate }
8760Sstevel@tonic-gate /*
8770Sstevel@tonic-gate * we have to fetch cfgadm, look for scsi controllers
8780Sstevel@tonic-gate * dynamically
8790Sstevel@tonic-gate */
8800Sstevel@tonic-gate (void) dyn_probe_for_scsi_frus(frup, cfgalist, &list, numlist);
8810Sstevel@tonic-gate rc = probe_scsi_in_libdevinfo(frup, cfgalist, &list,
8820Sstevel@tonic-gate numlist, B_TRUE);
8830Sstevel@tonic-gate free_list(&list);
8840Sstevel@tonic-gate free(cfgalist);
8850Sstevel@tonic-gate return (rc);
8860Sstevel@tonic-gate } else {
8870Sstevel@tonic-gate /* during initialization */
8880Sstevel@tonic-gate /* use the cached cfgadm data */
8890Sstevel@tonic-gate rc = cache_probe_for_scsi_frus(frup);
8900Sstevel@tonic-gate if (scsi_list && scsi_list->num_nodes > 0) {
8910Sstevel@tonic-gate rc = probe_scsi_in_libdevinfo(frup, cfglist,
8920Sstevel@tonic-gate scsi_list, nlist, B_TRUE);
8930Sstevel@tonic-gate } else {
8940Sstevel@tonic-gate rc = probe_scsi_in_libdevinfo(frup, NULL,
8950Sstevel@tonic-gate NULL, 0, B_FALSE);
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate return (rc);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate }
900