1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#ifndef _CFGA_FP_H 27#define _CFGA_FP_H 28 29 30 31#ifdef __cplusplus 32extern "C" { 33#endif 34 35#include <sys/types.h> 36#include <sys/mkdev.h> 37#include <stddef.h> 38#include <locale.h> 39#include <ctype.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43#include <fcntl.h> 44#include <unistd.h> 45#include <errno.h> 46#include <locale.h> 47#include <langinfo.h> 48#include <time.h> 49#include <stdarg.h> 50#include <sys/mman.h> 51#include <sys/ioctl.h> 52#include <sys/dditypes.h> 53#include <sys/modctl.h> 54#include <libdevinfo.h> 55#include <libdevice.h> 56#include <librcm.h> 57#include <dirent.h> 58#include <strings.h> 59 60 61#include <sys/ioctl.h> 62#include <sys/byteorder.h> 63#include <sys/scsi/scsi.h> 64#include <strings.h> 65#include <sys/vfstab.h> 66#include <sys/stat.h> 67#include <setjmp.h> 68#include <signal.h> 69#include <hbaapi.h> 70#include <sys/fibre-channel/fcio.h> 71#include <sys/fibre-channel/ulp/fcp_util.h> 72 73#include <sys/uio.h> 74#include <sys/param.h> 75 76#include <synch.h> 77#include <thread.h> 78 79#include <limits.h> 80#include <ftw.h> 81 82#define CFGA_PLUGIN_LIB 83#include <config_admin.h> 84 85#if !defined(DEBUG) 86#define NDEBUG 1 87#else 88#undef NDEBUG 89#endif 90 91#include <assert.h> 92 93/* Return/error codes */ 94typedef enum { 95 FPCFGA_ERR = -2, 96 FPCFGA_LIB_ERR = -1, 97 FPCFGA_OK = 0, 98 FPCFGA_ACCESS_OK, 99 FPCFGA_NACK, 100 FPCFGA_BUSY, 101 FPCFGA_SYSTEM_BUSY, 102 FPCFGA_APID_NOCONFIGURE, 103 FPCFGA_APID_NOACCESS, 104 FPCFGA_APID_NOEXIST, 105 FPCFGA_OPNOTSUPP, 106 FPCFGA_PRIV, 107 FPCFGA_UNLOCKED, 108 FPCFGA_NO_REC, 109 FPCFGA_OP_INTR, 110 FPCFGA_DB_INVAL, 111 FPCFGA_CONF_OK_UPD_REP_FAILED, 112 FPCFGA_UNCONF_OK_UPD_REP_FAILED, 113 FPCFGA_INVALID_PATH, 114 FPCFGA_VHCI_GET_PATHLIST_FAILED, 115 FPCFGA_XPORT_NOT_IN_PHCI_LIST, 116 FPCFGA_UNKNOWN_ERR, 117 FPCFGA_FCP_TGT_SEND_SCSI_FAILED, 118 FPCFGA_FCP_SEND_SCSI_DEV_NOT_TGT 119} fpcfga_ret_t; 120 121/* Commands used internally */ 122typedef enum { 123 FPCFGA_INVAL_CMD = -1, 124 FPCFGA_DEV_OP = 0, 125 FPCFGA_BUS_OP, 126 FPCFGA_STAT_FC_DEV, 127 FPCFGA_STAT_FCA_PORT, 128 FPCFGA_STAT_ALL, 129 FPCFGA_GET_DEVPATH, 130 FPCFGA_INSERT_DEV, 131 FPCFGA_REMOVE_DEV, 132 FPCFGA_REPLACE_DEV, 133 FPCFGA_WALK_NODE, 134 FPCFGA_WALK_MINOR, 135 FPCFGA_BUS_QUIESCE, 136 FPCFGA_BUS_UNQUIESCE, 137 FPCFGA_BUS_GETSTATE, 138 FPCFGA_DEV_GETSTATE, 139 FPCFGA_BUS_CONFIGURE, 140 FPCFGA_BUS_UNCONFIGURE, 141 FPCFGA_DEV_CONFIGURE, 142 FPCFGA_DEV_UNCONFIGURE, 143 FPCFGA_DEV_REMOVE, 144 FPCFGA_RESET_DEV, 145 FPCFGA_RESET_BUS, 146 FPCFGA_RESET_ALL, 147 FPCFGA_READ, 148 FPCFGA_WRITE 149} fpcfga_cmd_t; 150 151typedef enum { 152 FPCFGA_TERMINATE = 0, 153 FPCFGA_CONTINUE 154} fpcfga_recur_t; 155 156 157/* Structures for tree walking code */ 158 159typedef struct { 160 uint_t flags; 161 int (*fcn)(di_node_t node, void *argp); 162} walk_node_t; 163 164typedef struct { 165 const char *nodetype; 166 int (*fcn)(di_node_t node, di_minor_t minor, void *argp); 167} walk_minor_t; 168 169typedef union { 170 walk_node_t node_args; 171 walk_minor_t minor_args; 172} walkmode_t; 173 174typedef struct { 175 uint_t flags; 176 walkmode_t walkmode; 177} walkarg_t; 178 179typedef struct { 180 char *phys; 181 char *log; 182 fpcfga_ret_t ret; 183 int match_minor; 184 int l_errno; 185} pathm_t; 186 187typedef struct ldata_list { 188 cfga_list_data_t ldata; 189 struct ldata_list *next; 190} ldata_list_t; 191 192typedef struct { 193 struct cfga_confirm *confp; 194 struct cfga_msg *msgp; 195} prompt_t; 196 197typedef struct luninfo_list { 198 int lunnum; 199 uint_t node_state; 200 uint_t lun_flag; 201 char *path; 202 struct luninfo_list *next; 203} luninfo_list_t; 204 205typedef struct { 206 char *xport_phys; 207 char *dyncomp; 208 uint_t flags; 209 luninfo_list_t *lunlist; /* Singly linked list */ 210} apid_t; 211 212/* Report luns names */ 213#define FP_SCMD_REPORT_LUN 0xA0 214#define DEFAULT_NUM_LUN 1024 215#define REPORT_LUN_HDR_SIZE 8 216#define SAM_LUN_SIZE 8 217 218#ifdef _BIG_ENDIAN 219#define htonll(x) (x) 220#define ntohll(x) (x) 221#else 222#define htonll(x) ((((unsigned long long)htonl(x)) << 32) + htonl(x >> 32)) 223#define ntohll(x) ((((unsigned long long)ntohl(x)) << 32) + ntohl(x >> 32)) 224#endif 225 226typedef struct report_lun_resp { 227 uint32_t num_lun; 228 uint32_t reserved; 229 longlong_t lun_string[DEFAULT_NUM_LUN]; 230} report_lun_resp_t; 231 232/* 233 * Hardware options acceptable for fp plugin. 234 * list related options are handled by getsupopts() and set to 235 * index of array. 236 */ 237#define OPT_DEVINFO_FORCE 0 238#define OPT_SHOW_SCSI_LUN 1 239#define OPT_FCP_DEV 2 240#define OPT_DISABLE_RCM 0 241#define OPT_FORCE_UPDATE_REP 1 242#define OPT_NO_UPDATE_REP 2 243#define OPT_REMOVE_UNUSABLE_SCSI_LUN 3 244#define OPT_REMOVE_UNUSABLE_FCP_DEV 4 245 246/* walk tree flag */ 247#define FLAG_PATH_INFO_WALK 0x00000001 248 249/* apid_t flags */ 250#define FLAG_DISABLE_RCM 0x00000001 251#define FLAG_FORCE_UPDATE_REP 0x00000010 252#define FLAG_NO_UPDATE_REP 0x00000100 253#define FLAG_DYN_AP_CONFIGURED 0x00001000 254#define FLAG_DEVINFO_FORCE 0x00010000 255#define FLAG_FCP_DEV 0x00100000 256#define FLAG_REMOVE_UNUSABLE_FCP_DEV 0x01000000 257 258/* apid_t lun flags */ 259#define FLAG_SKIP_RCMOFFLINE 0x00000001 260#define FLAG_SKIP_RCMREMOVE 0x00000010 261#define FLAG_SKIP_ONLINEOTHERS 0x00000100 262 263/* define for peripheral qualifier mask */ 264#define FP_PERI_QUAL_MASK 0xE0 265 266/* Message ids */ 267typedef enum { 268 269/* ERRORS */ 270ERR_UNKNOWN = -1, 271ERR_OP_FAILED, 272ERR_CMD_INVAL, 273ERR_NOT_BUSAPID, 274ERR_APID_INVAL, 275ERR_NOT_BUSOP, 276ERR_NOT_DEVOP, 277ERR_UNAVAILABLE, 278ERR_CTRLR_CRIT, 279ERR_BUS_GETSTATE, 280ERR_BUS_NOTCONNECTED, 281ERR_BUS_CONNECTED, 282ERR_BUS_QUIESCE, 283ERR_BUS_UNQUIESCE, 284ERR_BUS_CONFIGURE, 285ERR_BUS_UNCONFIGURE, 286ERR_DEV_CONFIGURE, 287ERR_DEV_UNCONFIGURE, 288ERR_FCA_CONFIGURE, 289ERR_FCA_UNCONFIGURE, 290ERR_DEV_REPLACE, 291ERR_DEV_INSERT, 292ERR_DEV_GETSTATE, 293ERR_RESET, 294ERR_LIST, 295ERR_FC, 296ERR_FC_GET_DEVLIST, 297ERR_FC_GET_FIRST_DEV, 298ERR_FC_GET_NEXT_DEV, 299ERRARG_FC_DEV_MAP_INIT, 300ERRARG_FC_PROP_LOOKUP_BYTES, 301ERRARG_FC_INQUIRY, 302ERRARG_FC_REP_LUNS, 303ERRARG_FC_TOPOLOGY, 304ERRARG_PATH_TOO_LONG, 305ERRARG_INVALID_PATH, 306ERRARG_OPENDIR, 307ERRARG_VHCI_GET_PATHLIST, 308ERRARG_XPORT_NOT_IN_PHCI_LIST, 309ERR_SIG_STATE, 310ERR_MAYBE_BUSY, 311ERR_BUS_DEV_MISMATCH, 312ERR_GET_DEVLIST, 313ERR_MEM_ALLOC, 314ERR_DEVCTL_OFFLINE, 315ERR_UPD_REP, 316ERR_CONF_OK_UPD_REP, 317ERR_UNCONF_OK_UPD_REP, 318ERR_PARTIAL_SUCCESS, 319ERR_HBA_LOAD_LIBRARY, 320ERR_MATCHING_HBA_PORT, 321ERR_NO_ADAPTER_FOUND, 322 323/* Errors with arguments */ 324ERRARG_OPT_INVAL, 325ERRARG_HWCMD_INVAL, 326ERRARG_DEVINFO, 327ERRARG_NOT_IN_DEVLIST, 328ERRARG_NOT_IN_DEVINFO, 329ERRARG_DI_GET_PROP, 330ERRARG_DC_DDEF_ALLOC, 331ERRARG_DC_BYTE_ARRAY, 332ERRARG_DC_BUS_ACQUIRE, 333ERRARG_BUS_DEV_CREATE, 334ERRARG_BUS_DEV_CREATE_UNKNOWN, 335ERRARG_DEV_ACQUIRE, 336ERRARG_DEV_REMOVE, 337 338/* RCM Errors */ 339ERR_RCM_HANDLE, 340ERRARG_RCM_SUSPEND, 341ERRARG_RCM_RESUME, 342ERRARG_RCM_OFFLINE, 343ERRARG_RCM_ONLINE, 344ERRARG_RCM_REMOVE, 345ERRARG_RCM_INFO, 346 347/* Commands */ 348CMD_INSERT_DEV, 349CMD_REMOVE_DEV, 350CMD_REPLACE_DEV, 351CMD_RESET_DEV, 352CMD_RESET_BUS, 353CMD_RESET_ALL, 354 355/* help messages */ 356MSG_HELP_HDR, 357MSG_HELP_USAGE, 358 359/* Hotplug messages */ 360MSG_INSDEV, 361MSG_RMDEV, 362MSG_REPLDEV, 363 364/* Hotplugging confirmation prompts */ 365CONF_QUIESCE_1, 366CONF_QUIESCE_2, 367CONF_UNQUIESCE, 368 369/* Misc. */ 370WARN_DISCONNECT 371} msgid_t; 372 373typedef struct { 374 msgid_t str_id; 375 fpcfga_cmd_t cmd; 376 fpcfga_ret_t (*fcn)(fpcfga_cmd_t, apid_t *, prompt_t *, char **); 377} hw_cmd_t; 378 379typedef struct { 380 msgid_t msgid; 381 int nargs; /* Number of arguments following msgid */ 382 int intl; /* Flag: if 1, internationalize */ 383 const char *msgstr; 384} msgcvt_t; 385 386 387#define SLASH "/" 388#define CFGA_DEV_DIR "/dev/cfg" 389#define DEV_DIR "/dev" 390#define DEVICES_DIR "/devices" 391#define DEV_DSK "/dev/dsk" 392#define DEV_RDSK "/dev/rdsk" 393#define DEV_RMT "/dev/rmt" 394#define DSK_DIR "dsk" 395#define RDSK_DIR "rdsk" 396#define RMT_DIR "rmt" 397 398 399#define DYN_SEP "::" 400#define LUN_COMP_SEP "," 401#define MINOR_SEP ":" 402 403#define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0) 404#define S_STR(x) (((x) == NULL) ? "" : (x)) 405 406 407#define IS_STUB_NODE(s) (di_instance(s) == -1 && \ 408 di_nodeid(s) == (DI_PROM_NODEID)) 409 410#define GET_MSG_STR(i) (str_tbl[msg_idx(i)].msgstr) 411 412#define GET_DYN(a) (((a) != NULL) ? strstr((a), DYN_SEP) : (void *)0) 413#define GET_LUN_DYN(a) (((a) != NULL) ? strstr((a), LUN_COMP_SEP) : (void *)0) 414 415/* 416 * The following macro removes the separator from the dynamic component. 417 */ 418#define DYN_TO_DYNCOMP(a) ((a) + strlen(DYN_SEP)) 419#define LUN_DYN_TO_LUNCOMP(a) ((a) + strlen(LUN_COMP_SEP)) 420 421/* 422 * Property names 423 */ 424#define PORT_WWN_PROP "port-wwn" 425#define LUN_GUID_PROP "client-guid" 426#define LUN_PROP "lun" 427 428#define WWN_S_LEN 17 /* NULL terminated string */ 429#define WWN_SIZE 8 430/* Constants used for repository updates */ 431#define ADD_ENTRY 0 432#define REMOVE_ENTRY 1 433 434#define FAB_REPOSITORY_DIR "/etc/cfg/fp" 435#define FAB_REPOSITORY "/etc/cfg/fp/fabric_WWN_map" 436#define TMP_FAB_REPOSITORY "/etc/cfg/fp/fabric_WWN_map.tmp" 437#define OLD_FAB_REPOSITORY "/etc/cfg/fp/fabric_WWN_map.old" 438 439/* MPXIO VHCI root dir */ 440#define SCSI_VHCI_ROOT "/devices/scsi_vhci/" 441#define SCSI_VHCI_DRVR "scsi_vhci" 442#define HBA_MAX_RETRIES 10 443 444/* Function prototypes */ 445 446fpcfga_ret_t get_report_lun_data(const char *xport_phys, 447 const char *dyncomp, int *num_luns, report_lun_resp_t **resp_buf, 448 struct scsi_extended_sense *sense, int *l_errnop); 449/* Functions in cfga_cs.c */ 450fpcfga_ret_t 451dev_change_state(cfga_cmd_t, apid_t *, la_wwn_t *, cfga_flags_t, char **, 452 HBA_HANDLE handle, HBA_PORTATTRIBUTES portAttrs); 453fpcfga_ret_t 454fca_change_state(cfga_cmd_t, apid_t *, cfga_flags_t, char **); 455 456/* Functions in cfga_rep.c */ 457int update_fabric_wwn_list(int, const char *, char **); 458 459fpcfga_ret_t dev_insert(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp, 460 char **errstring); 461fpcfga_ret_t dev_replace(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp, 462 char **errstring); 463fpcfga_ret_t dev_remove(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp, 464 char **errstring); 465fpcfga_ret_t reset_common(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp, 466 char **errstring); 467 468 469/* List related routines */ 470fpcfga_ret_t do_list(apid_t *apidp, fpcfga_cmd_t cmd, 471 ldata_list_t **ldatalistp, int *nelem, char **errstring); 472fpcfga_ret_t do_list_FCP_dev(const char *ap_id, uint_t flags, fpcfga_cmd_t cmd, 473 ldata_list_t **llpp, int *nelemp, char **errstring); 474fpcfga_ret_t list_ext_postprocess(ldata_list_t **ldatalistp, int nelem, 475 cfga_list_data_t **ap_id_list, int *nlistp, char **errstring); 476int stat_path_info_node(di_node_t root, void *arg, int *l_errnop); 477 478/* Conversion routines */ 479fpcfga_ret_t make_xport_logid(const char *xport_phys, char **xport_logpp, 480 int *l_errnop); 481fpcfga_ret_t dyn_apid_to_path(const char *xport_phys, const char *dyncomp, 482 struct luninfo_list **lunlistpp, int *l_errnop); 483void cvt_lawwn_to_dyncomp(const la_wwn_t *pwwn, char **dyncomp, int *l_errnop); 484int cvt_dyncomp_to_lawwn(const char *dyncomp, la_wwn_t *port_wwn); 485fpcfga_ret_t make_dyncomp_from_dinode(const di_node_t node, char **dyncompp, 486 int *l_errnop); 487fpcfga_ret_t make_portwwn_luncomp_from_dinode(const di_node_t node, 488 char **dyncompp, int **luncompp, int *l_errnop); 489fpcfga_ret_t make_portwwn_luncomp_from_pinode(const di_path_t pinode, 490 char **dyncompp, int **luncompp, int *l_errnop); 491fpcfga_ret_t construct_nodepath_from_dinode(const di_node_t node, 492 char **node_pathp, int *l_errnop); 493u_longlong_t wwnConversion(uchar_t *wwn); 494 495 496/* Functions in cfga_rcm.c */ 497fpcfga_ret_t fp_rcm_offline(char *, char **, cfga_flags_t); 498fpcfga_ret_t fp_rcm_online(char *, char **, cfga_flags_t); 499fpcfga_ret_t fp_rcm_remove(char *, char **, cfga_flags_t); 500fpcfga_ret_t fp_rcm_suspend(char *, char *, char **, cfga_flags_t); 501fpcfga_ret_t fp_rcm_resume(char *, char *, char **, cfga_flags_t); 502fpcfga_ret_t fp_rcm_info(char *, char **, char **); 503 504/* Utility routines */ 505fpcfga_ret_t physpath_to_devlink(const char *basedir, char *xport_phys, 506 char **xport_logpp, int *l_errnop, int match_minor); 507fpcfga_ret_t recurse_dev(const char *basedir, void *arg, 508 fpcfga_recur_t (*fcn)(const char *lpath, void *arg)); 509fpcfga_ret_t apidt_create(const char *ap_id, apid_t *apidp, 510 char **errstring); 511void apidt_free(apid_t *apidp); 512cfga_err_t err_cvt(fpcfga_ret_t err); 513void list_free(ldata_list_t **llpp); 514int known_state(di_node_t node); 515 516fpcfga_ret_t devctl_cmd(const char *ap_id, fpcfga_cmd_t cmd, 517 uint_t *statep, int *l_errnop); 518fpcfga_ret_t invoke_cmd(const char *func, apid_t *apidt, prompt_t *prp, 519 char **errstring); 520 521void cfga_err(char **errstring, int use_errno, ...); 522void cfga_msg(struct cfga_msg *msgp, ...); 523char *cfga_str(int append_newline, ...); 524int msg_idx(msgid_t msgid); 525fpcfga_ret_t walk_tree(const char *physpath, void *arg, uint_t init_flags, 526 walkarg_t *up, fpcfga_cmd_t cmd, int *l_errnop); 527int hba_dev_cmp(const char *hba, const char *dev); 528int dev_cmp(const char *dev1, const char *dev2, int match_minor); 529char *pathdup(const char *path, int *l_errnop); 530int getPortAttrsByWWN(HBA_HANDLE handle, HBA_WWN wwn, 531 HBA_PORTATTRIBUTES *attrs); 532int getDiscPortAttrs(HBA_HANDLE handle, int portIndex, 533 int discIndex, HBA_PORTATTRIBUTES *attrs); 534int getAdapterPortAttrs(HBA_HANDLE handle, int portIndex, 535 HBA_PORTATTRIBUTES *attrs); 536int getAdapterAttrs(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES *attrs); 537fpcfga_ret_t findMatchingAdapterPort(char *portPath, 538 HBA_HANDLE *matchingHandle, int *matchingPortIndex, 539 HBA_PORTATTRIBUTES *matchingPortAttrs, char **errstring); 540 541extern msgcvt_t str_tbl[]; 542 543#ifdef __cplusplus 544} 545#endif 546 547#endif /* _CFGA_FP_H */ 548