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
   9  * http://www.opensource.org/licenses/cddl1.txt.
  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 /*
  23  * Copyright (c) 2004-2012 Emulex. All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <emlxs.h>
  28 
  29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
  30 EMLXS_MSG_DEF(EMLXS_DFC_C);
  31 
  32 static int32_t          emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc,
  33                                 int32_t mode);
  34 static int32_t          emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc,
  35                                 int32_t mode);
  36 static int32_t          emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc,
  37                                 int32_t mode);
  38 static int32_t          emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc,
  39                                 int32_t mode);
  40 static int32_t          emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc,
  41                                 int32_t mode);
  42 static int32_t          emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc,
  43                                 int32_t mode);
  44 static int32_t          emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc,
  45                                 int32_t mode);
  46 static int32_t          emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc,
  47                                 int32_t mode);
  48 static int32_t          emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc,
  49                                 int32_t mode);
  50 static int32_t          emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc,
  51                                 int32_t mode);
  52 static int32_t          emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc,
  53                                 int32_t mode);
  54 static int32_t          emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc,
  55                                 int32_t mode);
  56 static int32_t          emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc,
  57                                 int32_t mode);
  58 static int32_t          emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc,
  59                                 int32_t mode);
  60 static int32_t          emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc,
  61                                 int32_t mode);
  62 static int32_t          emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc,
  63                                 int32_t mode);
  64 static int32_t          emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc,
  65                                 int32_t mode);
  66 static int32_t          emlxs_dfc_reset_port(emlxs_hba_t *hba, dfc_t *dfc,
  67                                 int32_t mode);
  68 static int32_t          emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc,
  69                                 int32_t mode);
  70 static int32_t          emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc,
  71                                 int32_t mode);
  72 static int32_t          emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc,
  73                                 int32_t mode);
  74 static int32_t          emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc,
  75                                 int32_t mode);
  76 static int32_t          emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc,
  77                                 int32_t mode);
  78 static int32_t          emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc,
  79                                 int32_t mode);
  80 static int32_t          emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc,
  81                                 int32_t mode);
  82 static int32_t          emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc,
  83                                 int32_t mode);
  84 static int32_t          emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc,
  85                                 int32_t mode);
  86 static int32_t          emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc,
  87                                 int32_t mode);
  88 static int32_t          emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc,
  89                                 int32_t mode);
  90 static int32_t          emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc,
  91                                 int32_t mode);
  92 
  93 #ifdef SFCT_SUPPORT
  94 static int32_t          emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc,
  95                                 int32_t mode);
  96 #endif /* SFCT_SUPPORT */
  97 
  98 static int32_t          emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc,
  99                                 int32_t mode);
 100 static int32_t          emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc,
 101                                 int32_t mode);
 102 static int32_t          emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc,
 103                                 int32_t mode);
 104 static int32_t          emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc,
 105                                 int32_t mode);
 106 static int32_t          emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc,
 107                                 int32_t mode);
 108 static emlxs_port_t     *emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn);
 109 
 110 #ifdef DHCHAP_SUPPORT
 111 static int32_t          emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc,
 112                                 int32_t mode);
 113 static int32_t          emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc,
 114                                 int32_t mode);
 115 static int32_t          emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc,
 116                                 int32_t mode);
 117 static int32_t          emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc,
 118                                 int32_t mode);
 119 static int32_t          emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc,
 120                                 int32_t mode);
 121 static int32_t          emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc,
 122                                 int32_t mode);
 123 static int32_t          emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba,
 124                                 dfc_t *dfc, int32_t mode);
 125 static int32_t          emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba,
 126                                 dfc_t *dfc, int32_t mode);
 127 #endif  /* DHCHAP_SUPPORT */
 128 
 129 #ifdef SAN_DIAG_SUPPORT
 130 static int32_t          emlxs_dfc_sd_set_bucket(emlxs_hba_t *hba, dfc_t *dfc,
 131                                 int32_t mode);
 132 static int32_t          emlxs_dfc_sd_destroy_bucket(emlxs_hba_t *hba,
 133                                 dfc_t *dfc, int32_t mode);
 134 static int32_t          emlxs_dfc_sd_get_bucket(emlxs_hba_t *hba, dfc_t *dfc,
 135                                 int32_t mode);
 136 static int32_t          emlxs_dfc_sd_start_collection(emlxs_hba_t *hba,
 137                                 dfc_t *dfc, int32_t mode);
 138 static int32_t          emlxs_dfc_sd_stop_collection(emlxs_hba_t *hba,
 139                                 dfc_t *dfc, int32_t mode);
 140 static int32_t          emlxs_dfc_sd_reset_collection(emlxs_hba_t *hba,
 141                                 dfc_t *dfc, int32_t mode);
 142 static int32_t          emlxs_dfc_sd_get_data(emlxs_hba_t *hba, dfc_t *dfc,
 143                                 int32_t mode);
 144 static int32_t          emlxs_dfc_sd_set_event(emlxs_hba_t *hba, dfc_t *dfc,
 145                                 int32_t mode);
 146 static int32_t          emlxs_dfc_sd_get_event(emlxs_hba_t *hba, dfc_t *dfc,
 147                                 int32_t mode);
 148 #endif  /* SAN_DIAG_SUPPORT */
 149 
 150 static int32_t          emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc,
 151                                 int32_t mode);
 152 #ifdef FCIO_SUPPORT
 153 static int32_t          emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc,
 154                                 int32_t mode);
 155 static int32_t          emlxs_fcio_get_num_devs(emlxs_port_t *port,
 156                                 fcio_t *fcio, int32_t mode);
 157 static int32_t          emlxs_fcio_get_dev_list(emlxs_port_t *port,
 158                                 fcio_t *fcio, int32_t mode);
 159 static int32_t          emlxs_fcio_get_sym_pname(emlxs_port_t *port,
 160                                 fcio_t *fcio, int32_t mode);
 161 static int32_t          emlxs_fcio_get_sym_nname(emlxs_port_t *port,
 162                                 fcio_t *fcio, int32_t mode);
 163 static int32_t          emlxs_fcio_unsupported(emlxs_port_t *port,
 164                                 fcio_t *fcio, int32_t mode);
 165 static int32_t          emlxs_fcio_get_logi_params(emlxs_port_t *port,
 166                                 fcio_t *fcio, int32_t mode);
 167 static int32_t          emlxs_fcio_get_state(emlxs_port_t *port,
 168                                 fcio_t *fcio, int32_t mode);
 169 static int32_t          emlxs_fcio_get_fcode_rev(emlxs_port_t *port,
 170                                 fcio_t *fcio, int32_t mode);
 171 static int32_t          emlxs_fcio_get_fw_rev(emlxs_port_t *port,
 172                                 fcio_t *fcio, int32_t mode);
 173 static int32_t          emlxs_fcio_get_dump_size(emlxs_port_t *port,
 174                                 fcio_t *fcio, int32_t mode);
 175 static int32_t          emlxs_fcio_force_dump(emlxs_port_t *port,
 176                                 fcio_t *fcio, int32_t mode);
 177 static int32_t          emlxs_fcio_get_dump(emlxs_port_t *port,
 178                                 fcio_t *fcio, int32_t mode);
 179 static int32_t          emlxs_fcio_get_topology(emlxs_port_t *port,
 180                                 fcio_t *fcio, int32_t mode);
 181 static int32_t          emlxs_fcio_reset_link(emlxs_port_t *port,
 182                                 fcio_t *fcio, int32_t mode);
 183 static int32_t          emlxs_fcio_reset_hard(emlxs_port_t *port,
 184                                 fcio_t *fcio, int32_t mode);
 185 static int32_t          emlxs_fcio_diag(emlxs_port_t *port,
 186                                 fcio_t *fcio, int32_t mode);
 187 static int32_t          emlxs_fcio_download_fw(emlxs_port_t *port,
 188                                 fcio_t *fcio, int32_t mode);
 189 static int32_t          emlxs_fcio_get_host_params(emlxs_port_t *port,
 190                                 fcio_t *fcio, int32_t mode);
 191 static int32_t          emlxs_fcio_get_link_status(emlxs_port_t *port,
 192                                 fcio_t *fcio, int32_t mode);
 193 static int32_t          emlxs_fcio_download_fcode(emlxs_port_t *port,
 194                                 fcio_t *fcio, int32_t mode);
 195 static int32_t          emlxs_fcio_get_node_id(emlxs_port_t *port,
 196                                 fcio_t *fcio, int32_t mode);
 197 static int32_t          emlxs_fcio_set_node_id(emlxs_port_t *port,
 198                                 fcio_t *fcio, int32_t mode);
 199 static int32_t          emlxs_fcio_get_adapter_attrs(emlxs_port_t *port,
 200                                 fcio_t *fcio, int32_t mode);
 201 static int32_t          emlxs_fcio_get_other_adapter_ports(emlxs_port_t *port,
 202                                 fcio_t *fcio, int32_t mode);
 203 static int32_t          emlxs_fcio_get_adapter_port_attrs(emlxs_port_t *port,
 204                                 fcio_t *fcio, int32_t mode);
 205 static int32_t          emlxs_fcio_get_disc_port_attrs(emlxs_port_t *port,
 206                                 fcio_t *fcio, int32_t mode);
 207 static int32_t          emlxs_fcio_get_port_attrs(emlxs_port_t *port,
 208                                 fcio_t *fcio, int32_t mode);
 209 #endif  /* FCIO_SUPPORT */
 210 
 211 static int32_t          emlxs_dfc_get_persist_linkdown(emlxs_hba_t *hba,
 212                                 dfc_t *dfc, int32_t mode);
 213 static int32_t          emlxs_dfc_set_persist_linkdown(emlxs_hba_t *hba,
 214                                 dfc_t *dfc, int32_t mode);
 215 
 216 /* SLI-4 ioctls */
 217 static int32_t          emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc,
 218                                 int32_t mode);
 219 static int32_t          emlxs_dfc_send_mbox4(emlxs_hba_t *hba, dfc_t *dfc,
 220                                 int32_t mode);
 221 static int              emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc,
 222                             int32_t mode);
 223 static int              emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc,
 224                             int32_t mode);
 225 static int              emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc,
 226                             int32_t mode);
 227 static int              emlxs_dfc_get_qos(emlxs_hba_t *hba, dfc_t *dfc,
 228                             int32_t mode);
 229 
 230 uint32_t        emlxs_loopback_tmo = 60;
 231 
 232 typedef struct
 233 {
 234         uint32_t        code;
 235         char            string[32];
 236         int             (*func)(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode);
 237 } emlxs_dfc_table_t;
 238 
 239 emlxs_dfc_table_t emlxs_dfc_table[] = {
 240         {EMLXS_GET_HBAINFO, "GET_HBAINFO", emlxs_dfc_get_hbainfo},
 241         {EMLXS_GET_REV, "GET_REV", emlxs_dfc_get_rev},
 242         {EMLXS_SET_DIAG, "SET_DIAG", emlxs_dfc_set_diag},
 243         {EMLXS_SEND_MBOX, "SEND_MBOX", emlxs_dfc_send_mbox},
 244         {EMLXS_READ_PCI, "READ_PCI", emlxs_dfc_read_pci},
 245         {EMLXS_WRITE_PCI, "WRITE_PCI", emlxs_dfc_write_pci},
 246         {EMLXS_GET_CFG, "GET_CFG", emlxs_dfc_get_cfg},
 247         {EMLXS_SET_CFG, "SET_CFG", emlxs_dfc_set_cfg},
 248         {EMLXS_SEND_CT, "SEND_CT", emlxs_dfc_send_ct},
 249         {EMLXS_SEND_CT_RSP, "SEND_CT_RSP", emlxs_dfc_send_ct_rsp},
 250         {EMLXS_WRITE_FLASH, "WRITE_FLASH", emlxs_dfc_write_flash},
 251         {EMLXS_READ_FLASH, "READ_FLASH", emlxs_dfc_read_flash},
 252         {EMLXS_SEND_ELS, "SEND_ELS", emlxs_dfc_send_els},
 253         {EMLXS_LOOPBACK_TEST, "LOOPBACK_TEST", emlxs_dfc_loopback_test},
 254         {EMLXS_RESET_PORT, "RESET_PORT", emlxs_dfc_reset_port},
 255         {EMLXS_GET_DUMPREGION, "GET_DUMPREGION", emlxs_dfc_get_dump_region},
 256         {EMLXS_LOOPBACK_MODE, "LOOPBACK_MODE", emlxs_dfc_loopback_mode},
 257         {EMLXS_GET_IOINFO, "GET_IOINFO", emlxs_dfc_get_ioinfo},
 258         {EMLXS_GET_LINKINFO, "GET_LINKINFO", emlxs_dfc_get_linkinfo},
 259         {EMLXS_GET_NODEINFO, "GET_NODEINFO", emlxs_dfc_get_nodeinfo},
 260         {EMLXS_READ_MEM, "READ_MEM", emlxs_dfc_read_mem},
 261         {EMLXS_WRITE_MEM, "WRITE_MEM", emlxs_dfc_write_mem},
 262         {EMLXS_WRITE_CTLREG, "WRITE_CTLREG", emlxs_dfc_write_ctlreg},
 263         {EMLXS_READ_CTLREG, "READ_CTLREG", emlxs_dfc_read_ctlreg},
 264         {EMLXS_SEND_SCSI, "SEND_SCSI", emlxs_dfc_send_scsi_fcp},
 265         {EMLXS_GET_EVENT, "GET_EVENT", emlxs_dfc_get_event},
 266         {EMLXS_SET_EVENT, "SET_EVENT", emlxs_dfc_set_event},
 267         {EMLXS_GET_EVENTINFO, "GET_EVENTINFO", emlxs_dfc_get_eventinfo},
 268         {EMLXS_GET_HBASTATS, "GET_HBASTATS", emlxs_dfc_get_hbastats},
 269         {EMLXS_GET_DRVSTATS, "GET_DRVSTATS", emlxs_dfc_get_drvstats},
 270         {EMLXS_CREATE_VPORT, "CREATE_VPORT", emlxs_dfc_create_vport},
 271         {EMLXS_DESTROY_VPORT, "DESTROY_VPORT", emlxs_dfc_destroy_vport},
 272         {EMLXS_GET_VPORTINFO, "GET_VPORTINFO", emlxs_dfc_get_vportinfo},
 273         {EMLXS_NPIV_RESOURCE, "NPIV_RESOURCE", emlxs_dfc_npiv_resource},
 274         {EMLXS_NPIV_TEST, "NPIV_TEST", emlxs_dfc_npiv_test},
 275         {EMLXS_GET_PERSIST_LINKDOWN, "GET_PERSIST_LINKDOWN",
 276             emlxs_dfc_get_persist_linkdown},
 277         {EMLXS_SET_PERSIST_LINKDOWN, "SET_PERSIST_LINKDOWN",
 278             emlxs_dfc_set_persist_linkdown},
 279         {EMLXS_GET_FCOE_FCFLIST, "GET_FCOE_FCFLIST", emlxs_dfc_get_fcflist},
 280         {EMLXS_SEND_MBOX4, "SEND_MBOX4", emlxs_dfc_send_mbox4},
 281         {EMLXS_RD_BE_FCF, "RD_BE_FCF", emlxs_dfc_rd_be_fcf},
 282         {EMLXS_SET_BE_DCBX, "SET_BE_DCBX", emlxs_dfc_set_be_dcbx},
 283         {EMLXS_GET_BE_DCBX, "GET_BE_DCBX", emlxs_dfc_get_be_dcbx},
 284         {EMLXS_GET_QOS, "GET_QOS", emlxs_dfc_get_qos},
 285 #ifdef MENLO_SUPPORT
 286         {EMLXS_SEND_MENLO, "SEND_MENLO", emlxs_dfc_send_menlo},
 287 #endif /* MENLO_SUPPORT */
 288 #ifdef DHCHAP_SUPPORT
 289         {EMLXS_INIT_AUTH, "INIT_AUTH", emlxs_dfc_init_auth},
 290         {EMLXS_GET_AUTH_CFG, "GET_AUTH_CFG", emlxs_dfc_get_auth_cfg},
 291         {EMLXS_SET_AUTH_CFG, "SET_AUTH_CFG", emlxs_dfc_set_auth_cfg},
 292         {EMLXS_GET_AUTH_PASSWORD, "GET_AUTH_PASSWORD", emlxs_dfc_get_auth_pwd},
 293         {EMLXS_SET_AUTH_PASSWORD, "SET_AUTH_PASSWORD", emlxs_dfc_set_auth_pwd},
 294         {EMLXS_GET_AUTH_STATUS, "GET_AUTH_STATUS", emlxs_dfc_get_auth_status},
 295         {EMLXS_GET_AUTH_CFG_TABLE, "GET_AUTH_CFG_TABLE",
 296             emlxs_dfc_get_auth_cfg_table},
 297         {EMLXS_GET_AUTH_KEY_TABLE, "GET_AUTH_KEY_TABLE",
 298             emlxs_dfc_get_auth_key_table},
 299 #endif  /* DHCHAP_SUPPORT */
 300 #ifdef FCIO_SUPPORT
 301         {EMLXS_FCIO_CMD, "FCIO_CMD", emlxs_fcio_manage},
 302 #endif /* FCIO_SUPPORT */
 303 #ifdef SFCT_SUPPORT
 304         {EMLXS_GET_FCTSTAT, "GET_FCTSTAT", emlxs_dfc_get_fctstat},
 305 #endif /* SFCT_SUPPORT */
 306 #ifdef SAN_DIAG_SUPPORT
 307         {EMLXS_SD_SET_BUCKET, "SD_SET_BUCKET", emlxs_dfc_sd_set_bucket},
 308         {EMLXS_SD_DESTROY_BUCKET, "SD_DESTROY_BUCKET",
 309             emlxs_dfc_sd_destroy_bucket},
 310         {EMLXS_SD_GET_BUCKET, "SD_GET_BUCKET", emlxs_dfc_sd_get_bucket},
 311         {EMLXS_SD_START_DATA_COLLECTION, "SD_START_DATA_COLLECTION",
 312             emlxs_dfc_sd_start_collection},
 313         {EMLXS_SD_STOP_DATA_COLLECTION, "SD_STOP_DATA_COLLECTION",
 314             emlxs_dfc_sd_stop_collection},
 315         {EMLXS_SD_RESET_DATA_COLLECTION, "SD_RESET_DATA_COLLECTION",
 316             emlxs_dfc_sd_reset_collection},
 317         {EMLXS_SD_GET_DATA, "SD_GET_DATA", emlxs_dfc_sd_get_data},
 318         {EMLXS_SD_SET_EVENT, "SD_SET_EVENT", emlxs_dfc_sd_set_event},
 319         {EMLXS_SD_GET_EVENT, "SD_GET_EVENT", emlxs_dfc_sd_get_event},
 320 #endif  /* SAN_DIAG_SUPPORT */
 321 };      /* emlxs_dfc_table */
 322 
 323 
 324 emlxs_table_t emlxs_dfc_event_table[] = {
 325         {FC_REG_LINK_EVENT,             "LINK_EVENT"},
 326         {FC_REG_RSCN_EVENT,             "RSCN_EVENT"},
 327         {FC_REG_CT_EVENT,               "CT_EVENT"},
 328         {FC_REG_DUMP_EVENT,             "DUMP_EVENT"},
 329         {FC_REG_TEMP_EVENT,             "TEMP_EVENT"},
 330         {FC_REG_VPORTRSCN_EVENT,        "VPORTRSCN_EVENT"},
 331         {FC_REG_FCOE_EVENT,             "FCOE_EVENT"},
 332 
 333 };      /* emlxs_dfc_event_table */
 334 
 335 
 336 #ifdef SAN_DIAG_SUPPORT
 337 kmutex_t                emlxs_sd_bucket_mutex;
 338 sd_bucket_info_t        emlxs_sd_bucket;
 339 #endif  /* SAN_DIAG_SUPPORT */
 340 
 341 extern char    *
 342 emlxs_dfc_xlate(uint16_t cmd)
 343 {
 344         static char     buffer[32];
 345         uint32_t        i;
 346         uint32_t        count;
 347 
 348         count = sizeof (emlxs_dfc_table) / sizeof (emlxs_dfc_table_t);
 349         for (i = 0; i < count; i++) {
 350                 if (cmd == emlxs_dfc_table[i].code) {
 351                         return (emlxs_dfc_table[i].string);
 352                 }
 353         }
 354 
 355         (void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", cmd);
 356         return (buffer);
 357 
 358 } /* emlxs_dfc_xlate() */
 359 
 360 
 361 static int
 362 emlxs_dfc_func(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
 363 {
 364         emlxs_port_t *port = &PPORT;
 365         uint32_t        i;
 366         uint32_t        count;
 367         int             rval;
 368 
 369         count = sizeof (emlxs_dfc_table) / sizeof (emlxs_dfc_table_t);
 370         for (i = 0; i < count; i++) {
 371                 if (dfc->cmd == emlxs_dfc_table[i].code) {
 372                         if ((dfc->cmd != EMLXS_FCIO_CMD) ||
 373                             (dfc->data1 != FCIO_DIAG) ||
 374                             (dfc->data2 != EMLXS_LOG_GET)) {
 375                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
 376                                     "%s requested.",
 377                                     emlxs_dfc_table[i].string);
 378                         }
 379 
 380                         rval = emlxs_dfc_table[i].func(hba, dfc, mode);
 381                         return (rval);
 382                 }
 383         }
 384 
 385         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
 386             "Unknown DFC command. (0x%x)", dfc->cmd);
 387 
 388         return (DFC_ARG_INVALID);
 389 
 390 } /* emlxs_dfc_func() */
 391 
 392 
 393 extern char    *
 394 emlxs_dfc_event_xlate(uint32_t event)
 395 {
 396         static char     buffer[32];
 397         uint32_t        i;
 398         uint32_t        count;
 399 
 400         count = sizeof (emlxs_dfc_event_table) / sizeof (emlxs_table_t);
 401         for (i = 0; i < count; i++) {
 402                 if (event == emlxs_dfc_event_table[i].code) {
 403                         return (emlxs_dfc_event_table[i].string);
 404                 }
 405         }
 406 
 407         (void) snprintf(buffer, sizeof (buffer), "Event=0x%x", event);
 408         return (buffer);
 409 
 410 } /* emlxs_dfc_event_xlate() */
 411 
 412 
 413 static int32_t
 414 emlxs_dfc_copyin(emlxs_hba_t *hba, void *arg, dfc_t *dfc1, dfc_t *dfc2,
 415     int32_t mode)
 416 {
 417         emlxs_port_t    *port = &PPORT;
 418         int             rval = 0;
 419         uint32_t        use32 = 0;
 420 
 421 #ifdef  _MULTI_DATAMODEL
 422         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
 423                 use32 = 1;
 424         }
 425 #endif  /* _MULTI_DATAMODEL */
 426 
 427         if (use32) {
 428                 dfc32_t dfc32;
 429 
 430                 if (ddi_copyin((void *)arg, (void *)&dfc32,
 431                     sizeof (dfc32_t), mode)) {
 432                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 433                             "ddi_copyin32 failed.");
 434 
 435                         rval = DFC_COPYIN_ERROR;
 436                         goto done;
 437                 }
 438 
 439                 dfc1->cmd = dfc32.cmd;
 440                 dfc1->flag = dfc32.flag;
 441                 dfc1->buf1 = (void *)((uintptr_t)dfc32.buf1);
 442                 dfc1->buf1_size = dfc32.buf1_size;
 443                 dfc1->data1 = dfc32.data1;
 444                 dfc1->buf2 = (void *)((uintptr_t)dfc32.buf2);
 445                 dfc1->buf2_size = dfc32.buf2_size;
 446                 dfc1->data2 = dfc32.data2;
 447                 dfc1->buf3 = (void *)((uintptr_t)dfc32.buf3);
 448                 dfc1->buf3_size = dfc32.buf3_size;
 449                 dfc1->data3 = dfc32.data3;
 450                 dfc1->buf4 = (void *)((uintptr_t)dfc32.buf4);
 451                 dfc1->buf4_size = dfc32.buf4_size;
 452                 dfc1->data4 = dfc32.data4;
 453 
 454         } else {
 455                 if (ddi_copyin((void *)arg, (void *)dfc1, sizeof (dfc_t),
 456                     mode)) {
 457                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 458                             "ddi_copyin failed.");
 459 
 460                         rval = DFC_COPYIN_ERROR;
 461                         goto done;
 462                 }
 463         }
 464 
 465         /* Map dfc1 to dfc2 */
 466         dfc2->cmd   = dfc1->cmd;
 467         dfc2->flag  = dfc1->flag;
 468         dfc2->data1 = dfc1->data1;
 469         dfc2->data2 = dfc1->data2;
 470         dfc2->data3 = dfc1->data3;
 471         dfc2->data4 = dfc1->data4;
 472         dfc2->buf1  = 0;
 473         dfc2->buf1_size = 0;
 474         dfc2->buf2  = 0;
 475         dfc2->buf2_size = 0;
 476         dfc2->buf3  = 0;
 477         dfc2->buf3_size = 0;
 478         dfc2->buf4  = 0;
 479         dfc2->buf4_size = 0;
 480 
 481         /* Copyin data buffers */
 482         if (dfc1->buf1_size && dfc1->buf1) {
 483                 dfc2->buf1_size = dfc1->buf1_size;
 484                 dfc2->buf1 = kmem_zalloc(dfc1->buf1_size, KM_SLEEP);
 485 
 486                 if (ddi_copyin(dfc1->buf1, dfc2->buf1, dfc1->buf1_size,
 487                     mode)) {
 488                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 489                             "%s: buf1 ddi_copyin failed. (size=%d)",
 490                             emlxs_dfc_xlate(dfc1->cmd),
 491                             dfc1->buf1_size);
 492 
 493                         rval = DFC_COPYIN_ERROR;
 494                         goto done;
 495                 }
 496         }
 497 
 498         if (dfc1->buf2_size && dfc1->buf2) {
 499                 dfc2->buf2_size = dfc1->buf2_size;
 500                 dfc2->buf2 = kmem_zalloc(dfc1->buf2_size, KM_SLEEP);
 501 
 502                 if (ddi_copyin(dfc1->buf2, dfc2->buf2, dfc1->buf2_size,
 503                     mode)) {
 504                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 505                             "%s: buf2 ddi_copyin failed. (size=%d)",
 506                             emlxs_dfc_xlate(dfc1->cmd),
 507                             dfc1->buf2_size);
 508 
 509                         rval = DFC_COPYIN_ERROR;
 510                         goto done;
 511                 }
 512         }
 513 
 514         if (dfc1->buf3_size && dfc1->buf3) {
 515                 dfc2->buf3_size = dfc1->buf3_size;
 516                 dfc2->buf3 = kmem_zalloc(dfc1->buf3_size, KM_SLEEP);
 517 
 518                 if (ddi_copyin(dfc1->buf3, dfc2->buf3, dfc1->buf3_size,
 519                     mode)) {
 520                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 521                             "%s buf3 ddi_copyin failed. (size=%d)",
 522                             emlxs_dfc_xlate(dfc1->cmd),
 523                             dfc1->buf3_size);
 524 
 525                         rval = DFC_COPYIN_ERROR;
 526                         goto done;
 527                 }
 528         }
 529 
 530         if (dfc1->buf4_size && dfc1->buf4) {
 531                 dfc2->buf4_size = dfc1->buf4_size;
 532                 dfc2->buf4 = kmem_zalloc(dfc1->buf4_size, KM_SLEEP);
 533 
 534                 if (ddi_copyin(dfc1->buf4, dfc2->buf4, dfc1->buf4_size,
 535                     mode)) {
 536                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 537                             "%s: buf4 ddi_copyin failed. (size=%d)",
 538                             emlxs_dfc_xlate(dfc1->cmd),
 539                             dfc1->buf4_size);
 540 
 541                         rval = DFC_COPYIN_ERROR;
 542                         goto done;
 543                 }
 544         }
 545 
 546 done:
 547         return (rval);
 548 
 549 } /* emlxs_dfc_copyin() */
 550 
 551 
 552 static int32_t
 553 emlxs_dfc_copyout(emlxs_hba_t *hba, void *arg, dfc_t *dfc2, dfc_t *dfc1,
 554     int32_t mode)
 555 {
 556         emlxs_port_t    *port = &PPORT;
 557         int             rval = 0;
 558         uint32_t        use32 = 0;
 559 
 560 #ifdef  _MULTI_DATAMODEL
 561         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
 562                 use32 = 1;
 563         }
 564 #endif  /* _MULTI_DATAMODEL */
 565 
 566         /* Copyout data buffers */
 567         if (dfc2->buf1) {
 568                 if (ddi_copyout(dfc2->buf1, dfc1->buf1, dfc1->buf1_size,
 569                     mode)) {
 570                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 571                             "%s: buf1 ddi_copyout failed. (size=%d)",
 572                             emlxs_dfc_xlate(dfc2->cmd),
 573                             dfc2->buf1_size);
 574 
 575                         rval = DFC_COPYOUT_ERROR;
 576                 }
 577                 kmem_free(dfc2->buf1, dfc2->buf1_size);
 578                 dfc2->buf1 = 0;
 579         }
 580 
 581         if (dfc2->buf2) {
 582                 if (ddi_copyout(dfc2->buf2, dfc1->buf2, dfc1->buf2_size,
 583                     mode)) {
 584                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 585                             "%s: buf2 ddi_copyout failed. (size=%d)",
 586                             emlxs_dfc_xlate(dfc2->cmd),
 587                             dfc2->buf2_size);
 588 
 589                         rval = DFC_COPYOUT_ERROR;
 590                 }
 591                 kmem_free(dfc2->buf2, dfc2->buf2_size);
 592                 dfc2->buf2 = 0;
 593         }
 594 
 595         if (dfc2->buf3) {
 596                 if (ddi_copyout(dfc2->buf3, dfc1->buf3, dfc1->buf3_size,
 597                     mode)) {
 598                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 599                             "%s buf3 ddi_copyout failed. (size=%d)",
 600                             emlxs_dfc_xlate(dfc2->cmd),
 601                             dfc2->buf3_size);
 602 
 603                         rval = DFC_COPYOUT_ERROR;
 604                 }
 605                 kmem_free(dfc2->buf3, dfc2->buf3_size);
 606                 dfc2->buf3 = 0;
 607         }
 608 
 609         if (dfc2->buf4) {
 610                 if (ddi_copyout(dfc2->buf4, dfc1->buf4, dfc1->buf4_size,
 611                     mode)) {
 612                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 613                             "%s: buf4 ddi_copyout failed. (size=%d)",
 614                             emlxs_dfc_xlate(dfc2->cmd),
 615                             dfc2->buf4_size);
 616 
 617                         rval = DFC_COPYOUT_ERROR;
 618                 }
 619                 kmem_free(dfc2->buf4, dfc2->buf4_size);
 620                 dfc2->buf4 = 0;
 621         }
 622 
 623         if (use32) {
 624                 dfc32_t dfc32;
 625 
 626                 dfc32.cmd = dfc1->cmd;
 627                 dfc32.flag = dfc1->flag;
 628                 dfc32.buf1 = (uint32_t)((uintptr_t)dfc1->buf1);
 629                 dfc32.buf1_size = dfc1->buf1_size;
 630                 dfc32.data1 = dfc1->data1;
 631                 dfc32.buf2 = (uint32_t)((uintptr_t)dfc1->buf2);
 632                 dfc32.buf2_size = dfc1->buf2_size;
 633                 dfc32.data2 = dfc1->data2;
 634                 dfc32.buf3 = (uint32_t)((uintptr_t)dfc1->buf3);
 635                 dfc32.buf3_size = dfc1->buf3_size;
 636                 dfc32.data3 = dfc1->data3;
 637                 dfc32.buf4 = (uint32_t)((uintptr_t)dfc1->buf4);
 638                 dfc32.buf4_size = dfc1->buf4_size;
 639                 dfc32.data4 = dfc1->data4;
 640 
 641                 if (ddi_copyout((void *)&dfc32, (void *)arg,
 642                     sizeof (dfc32_t), mode)) {
 643                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 644                             "ddi_copyout32 failed.");
 645 
 646                         rval = DFC_COPYOUT_ERROR;
 647                         goto done;
 648                 }
 649         } else {
 650                 if (ddi_copyout((void *)dfc1, (void *)arg, sizeof (dfc_t),
 651                     mode)) {
 652                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
 653                             "ddi_copyout failed.");
 654 
 655                         rval = DFC_COPYOUT_ERROR;
 656                         goto done;
 657                 }
 658         }
 659 
 660 done:
 661         return (rval);
 662 
 663 } /* emlxs_dfc_copyout() */
 664 
 665 
 666 extern int32_t
 667 emlxs_dfc_manage(emlxs_hba_t *hba, void *arg, int32_t mode)
 668 {
 669         dfc_t           dfc1;
 670         dfc_t           dfc2;
 671         int             rval = 0;
 672 
 673         /* This copies arg data to dfc1 space, */
 674         /* then creates local dfc2 buffers */
 675         rval = emlxs_dfc_copyin(hba, arg, &dfc1, &dfc2, mode);
 676 
 677         if (rval) {
 678                 return (rval);
 679         }
 680 
 681         rval = emlxs_dfc_func(hba, &dfc2, mode);
 682 
 683         if (rval) {
 684                 return (rval);
 685         }
 686 
 687         /* This copies dfc2 local buffers back to dfc1 addresses */
 688         rval = emlxs_dfc_copyout(hba, arg, &dfc2, &dfc1, mode);
 689 
 690         return (rval);
 691 
 692 } /* emlxs_dfc_manage() */
 693 
 694 
 695 #ifdef FCIO_SUPPORT
 696 typedef struct
 697 {
 698         uint32_t        code;
 699         char            string[32];
 700         int             (*func)(emlxs_port_t *port, fcio_t *fcio, int32_t mode);
 701 } emlxs_fcio_table_t;
 702 
 703 emlxs_fcio_table_t emlxs_fcio_table[] = {
 704         {FCIO_GET_NUM_DEVS, "GET_NUM_DEVS", emlxs_fcio_get_num_devs},
 705         {FCIO_GET_DEV_LIST, "GET_DEV_LIST", emlxs_fcio_get_dev_list},
 706         {FCIO_GET_SYM_PNAME, "GET_SYM_PNAME", emlxs_fcio_get_sym_pname},
 707         {FCIO_GET_SYM_NNAME, "GET_SYM_NNAME", emlxs_fcio_get_sym_nname},
 708         {FCIO_SET_SYM_PNAME, "SET_SYM_PNAME", emlxs_fcio_unsupported},
 709         {FCIO_SET_SYM_NNAME, "SET_SYM_NNAME", emlxs_fcio_unsupported},
 710         {FCIO_GET_LOGI_PARAMS, "GET_LOGI_PARAMS", emlxs_fcio_get_logi_params},
 711         {FCIO_DEV_LOGIN, "DEV_LOGIN", emlxs_fcio_unsupported},
 712         {FCIO_DEV_LOGOUT, "DEV_LOGOUT", emlxs_fcio_unsupported},
 713         {FCIO_GET_STATE, "GET_STATE", emlxs_fcio_get_state},
 714         {FCIO_DEV_REMOVE, "DEV_REMOVE", emlxs_fcio_unsupported},
 715         {FCIO_GET_FCODE_REV, "GET_FCODE_REV", emlxs_fcio_get_fcode_rev},
 716         {FCIO_GET_FW_REV, "GET_FW_REV", emlxs_fcio_get_fw_rev},
 717         {FCIO_GET_DUMP_SIZE, "GET_DUMP_SIZE", emlxs_fcio_get_dump_size},
 718         {FCIO_FORCE_DUMP, "FORCE_DUMP", emlxs_fcio_force_dump},
 719         {FCIO_GET_DUMP, "GET_DUMP", emlxs_fcio_get_dump},
 720         {FCIO_GET_TOPOLOGY, "GET_TOPOLOGY", emlxs_fcio_get_topology},
 721         {FCIO_RESET_LINK, "RESET_LINK", emlxs_fcio_reset_link},
 722         {FCIO_RESET_HARD, "RESET_HARD", emlxs_fcio_reset_hard},
 723         {FCIO_RESET_HARD_CORE, "RESET_HARD_CORE", emlxs_fcio_reset_hard},
 724         {FCIO_DIAG, "DIAG", emlxs_fcio_diag},
 725         {FCIO_NS, "NS", emlxs_fcio_unsupported},
 726         {FCIO_DOWNLOAD_FW, "DOWNLOAD_FW", emlxs_fcio_download_fw},
 727         {FCIO_GET_HOST_PARAMS, "GET_HOST_PARAMS", emlxs_fcio_get_host_params},
 728         {FCIO_LINK_STATUS, "LINK_STATUS", emlxs_fcio_get_link_status},
 729         {FCIO_DOWNLOAD_FCODE, "DOWNLOAD_FCODE", emlxs_fcio_download_fcode},
 730         {FCIO_GET_NODE_ID, "GET_NODE_ID", emlxs_fcio_get_node_id},
 731         {FCIO_SET_NODE_ID, "SET_NODE_ID", emlxs_fcio_set_node_id},
 732         {FCIO_SEND_NODE_ID, "SEND_NODE_ID", emlxs_fcio_unsupported},
 733         /* {FCIO_GET_P2P_INFO, "GET_P2P_INFO", emlxs_fcio_get_p2p_info}, */
 734         {FCIO_GET_ADAPTER_ATTRIBUTES, "GET_ADAPTER_ATTRIBUTES",
 735             emlxs_fcio_get_adapter_attrs},
 736         {FCIO_GET_OTHER_ADAPTER_PORTS, "GET_OTHER_ADAPTER_PORTS",
 737             emlxs_fcio_get_other_adapter_ports},
 738         {FCIO_GET_ADAPTER_PORT_ATTRIBUTES, "GET_ADAPTER_PORT_ATTRIBUTES",
 739             emlxs_fcio_get_adapter_port_attrs},
 740         {FCIO_GET_DISCOVERED_PORT_ATTRIBUTES, "GET_DISCOVERED_PORT_ATTRIBUTES",
 741             emlxs_fcio_get_disc_port_attrs},
 742         {FCIO_GET_PORT_ATTRIBUTES, "GET_PORT_ATTRIBUTES",
 743             emlxs_fcio_get_port_attrs},
 744         {FCIO_GET_ADAPTER_PORT_STATS, "GET_ADAPTER_PORT_STATS",
 745             emlxs_fcio_unsupported},
 746 };      /* emlxs_fcio_table */
 747 
 748 
 749 extern char *
 750 emlxs_fcio_xlate(uint16_t cmd)
 751 {
 752         static char     buffer[32];
 753         uint32_t        i;
 754         uint32_t        count;
 755 
 756         count = sizeof (emlxs_fcio_table) / sizeof (emlxs_fcio_table_t);
 757         for (i = 0; i < count; i++) {
 758                 if (cmd == emlxs_fcio_table[i].code) {
 759                         return (emlxs_fcio_table[i].string);
 760                 }
 761         }
 762 
 763         (void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", cmd);
 764         return (buffer);
 765 
 766 } /* emlxs_fcio_xlate() */
 767 
 768 
 769 static int
 770 emlxs_fcio_func(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
 771 {
 772         uint32_t        i;
 773         uint32_t        count;
 774         int             rval;
 775 
 776         count = sizeof (emlxs_fcio_table) / sizeof (emlxs_fcio_table_t);
 777         for (i = 0; i < count; i++) {
 778                 if (fcio->fcio_cmd == emlxs_fcio_table[i].code) {
 779                         if ((fcio->fcio_cmd != FCIO_DIAG) ||
 780                             (fcio->fcio_cmd_flags != EMLXS_LOG_GET)) {
 781                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
 782                                     "%s requested.",
 783                                     emlxs_fcio_table[i].string);
 784                         }
 785 
 786                         rval = emlxs_fcio_table[i].func(port, fcio, mode);
 787                         return (rval);
 788                 }
 789         }
 790 
 791         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
 792             "Unknown FCIO command. (0x%x)", fcio->fcio_cmd);
 793 
 794         return (EFAULT);
 795 
 796 } /* emlxs_fcio_func() */
 797 
 798 
 799 /* This is used by FCT ports to mimic SFS ports for FCIO support */
 800 /*ARGSUSED*/
 801 extern int32_t
 802 emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
 803 {
 804         emlxs_port_t    *port = &PPORT;
 805         int32_t         rval = 0;
 806         fcio_t          fcio;
 807         uint32_t        vpi;
 808 
 809         /* Map DFC to FCIO */
 810         vpi = (dfc->data4 < MAX_VPORTS)? dfc->data4:0;
 811         port = &VPORT(vpi);
 812 
 813         bzero(&fcio, sizeof (fcio_t));
 814         fcio.fcio_flags         = dfc->flag;
 815         fcio.fcio_cmd           = dfc->data1;
 816         fcio.fcio_cmd_flags     = dfc->data2;
 817         fcio.fcio_xfer          = dfc->data3;
 818 
 819         if (dfc->buf1_size && dfc->buf1) {
 820                 fcio.fcio_ilen = dfc->buf1_size;
 821                 fcio.fcio_ibuf = dfc->buf1;
 822         }
 823 
 824         if (dfc->buf2_size && dfc->buf2) {
 825                 fcio.fcio_olen = dfc->buf2_size;
 826                 fcio.fcio_obuf = dfc->buf2;
 827         }
 828 
 829         if (dfc->buf3_size && dfc->buf3) {
 830                 fcio.fcio_alen = dfc->buf3_size;
 831                 fcio.fcio_abuf = dfc->buf3;
 832         }
 833 
 834         if (!dfc->buf4 || (dfc->buf4_size < sizeof (uint32_t))) {
 835                 EMLXS_MSGF(EMLXS_CONTEXT,
 836                     &emlxs_dfc_error_msg,
 837                     "%s: %s: buf4 invalid. (buf4=%p size=%d)",
 838                     emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1),
 839                     dfc->buf4, dfc->buf4_size);
 840 
 841                 rval = EFAULT;
 842                 goto done;
 843         }
 844 
 845         rval = emlxs_fcio_func(port, &fcio, mode);
 846 
 847         /* Map FCIO to DFC */
 848         dfc->flag  = fcio.fcio_flags;
 849         dfc->data1 = fcio.fcio_cmd;
 850         dfc->data2 = fcio.fcio_cmd_flags;
 851         dfc->data3 = fcio.fcio_xfer;
 852 
 853 done:
 854         /* Set fcio_errno if needed */
 855         if ((rval != 0) && (fcio.fcio_errno == 0)) {
 856                 fcio.fcio_errno = FC_FAILURE;
 857         }
 858 
 859         bcopy((void *)&fcio.fcio_errno, (void *)dfc->buf4, sizeof (uint32_t));
 860 
 861         return (rval);
 862 
 863 } /* emlxs_fcio_manage() */
 864 
 865 
 866 /*ARGSUSED*/
 867 static int32_t
 868 emlxs_fcio_diag(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
 869 {
 870         fc_fca_pm_t     pm;
 871         int32_t         rval = 0;
 872 
 873         bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
 874 
 875         pm.pm_cmd_len   = fcio->fcio_ilen;
 876         pm.pm_cmd_buf   = fcio->fcio_ibuf;
 877         pm.pm_data_len  = fcio->fcio_alen;
 878         pm.pm_data_buf  = fcio->fcio_abuf;
 879         pm.pm_stat_len  = fcio->fcio_olen;
 880         pm.pm_stat_buf  = fcio->fcio_obuf;
 881         pm.pm_cmd_code  = FC_PORT_DIAG;
 882         pm.pm_cmd_flags = fcio->fcio_cmd_flags;
 883 
 884         rval = emlxs_fca_port_manage(port, &pm);
 885 
 886         if (rval != FC_SUCCESS) {
 887                 fcio->fcio_errno = rval;
 888 
 889                 if (rval == FC_INVALID_REQUEST) {
 890                         rval = ENOTTY;
 891                 } else {
 892                         rval = EIO;
 893                 }
 894         }
 895         if (fcio->fcio_olen > pm.pm_stat_len) {
 896                 fcio->fcio_olen = pm.pm_stat_len;
 897         }
 898 
 899         return (rval);
 900 
 901 } /* emlxs_fcio_diag() */
 902 
 903 
 904 #ifndef _MULTI_DATAMODEL
 905 /* ARGSUSED */
 906 #endif
 907 static int32_t
 908 emlxs_fcio_get_host_params(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
 909 {
 910         emlxs_hba_t     *hba = HBA;
 911         int32_t         rval = 0;
 912         uint32_t        use32 = 0;
 913         emlxs_config_t  *cfg  = &CFG;
 914 
 915 #ifdef  _MULTI_DATAMODEL
 916         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
 917                 use32 = 1;
 918         }
 919 #endif  /* _MULTI_DATAMODEL */
 920 
 921         if (use32) {
 922                 fc_port_dev32_t *port_dev;
 923                 uint32_t i;
 924 
 925                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
 926                     fcio->fcio_olen != sizeof (fc_port_dev32_t)) {
 927                         rval = EINVAL;
 928                         goto done;
 929                 }
 930 
 931                 port_dev = (fc_port_dev32_t *)fcio->fcio_obuf;
 932 
 933                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
 934                     "fcio_get_host_params: fct_flags=%x ulp_statec=%x",
 935                     port->fct_flags, port->ulp_statec);
 936 
 937                 if ((port->mode == MODE_TARGET) &&
 938                     (port->fct_port) &&
 939                     (port->fct_flags & FCT_STATE_PORT_ONLINE)) {
 940                         port_dev->dev_state = port->ulp_statec;
 941                         port_dev->dev_did.port_id = port->did;
 942 
 943                         if (hba->topology == TOPOLOGY_LOOP) {
 944                                 for (i = 0; i < port->alpa_map[0]; i++) {
 945                                 if (port->alpa_map[i + 1] == port->did) {
 946                                         port_dev->dev_did.priv_lilp_posit =
 947                                             (uint8_t)(i & 0xff);
 948                                         goto done;
 949                                 }
 950                                 }
 951                         }
 952 
 953                 } else {
 954                         port_dev->dev_state = FC_STATE_OFFLINE;
 955                         port_dev->dev_did.port_id = 0;
 956                 }
 957 
 958                 port_dev->dev_hard_addr.hard_addr =
 959                     cfg[CFG_ASSIGN_ALPA].current;
 960 
 961                 bcopy((caddr_t)&port->wwpn,
 962                     (caddr_t)&port_dev->dev_pwwn, 8);
 963                 bcopy((caddr_t)&port->wwnn,
 964                     (caddr_t)&port_dev->dev_nwwn, 8);
 965 
 966                 port_dev->dev_type[0] = LE_SWAP32(0x00000120);
 967                 port_dev->dev_type[1] = LE_SWAP32(0x00000001);
 968 
 969         } else {
 970 
 971                 fc_port_dev_t *port_dev;
 972                 uint32_t i;
 973 
 974                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
 975                     fcio->fcio_olen != sizeof (fc_port_dev_t)) {
 976                         rval = EINVAL;
 977                         goto done;
 978                 }
 979 
 980                 port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
 981 
 982                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
 983                     "fcio_get_host_params: fct_flags=%x ulp_statec=%x",
 984                     port->fct_flags, port->ulp_statec);
 985 
 986                 if ((port->mode == MODE_TARGET) &&
 987                     (port->fct_port) &&
 988                     (port->fct_flags & FCT_STATE_PORT_ONLINE)) {
 989                         port_dev->dev_state = port->ulp_statec;
 990                         port_dev->dev_did.port_id = port->did;
 991 
 992                         if (hba->topology == TOPOLOGY_LOOP) {
 993                                 for (i = 0; i < port->alpa_map[0]; i++) {
 994                                 if (port->alpa_map[i + 1] == port->did) {
 995                                         port_dev->dev_did.priv_lilp_posit =
 996                                             (uint8_t)(i & 0xff);
 997                                         goto done;
 998                                 }
 999                                 }
1000                         }
1001 
1002                 } else {
1003                         port_dev->dev_state = FC_STATE_OFFLINE;
1004                         port_dev->dev_did.port_id = 0;
1005                 }
1006 
1007                 port_dev->dev_hard_addr.hard_addr =
1008                     cfg[CFG_ASSIGN_ALPA].current;
1009 
1010                 bcopy((caddr_t)&port->wwpn,
1011                     (caddr_t)&port_dev->dev_pwwn, 8);
1012                 bcopy((caddr_t)&port->wwnn,
1013                     (caddr_t)&port_dev->dev_nwwn, 8);
1014 
1015                 port_dev->dev_type[0] = LE_SWAP32(0x00000120);
1016                 port_dev->dev_type[1] = LE_SWAP32(0x00000001);
1017         }
1018 
1019 done:
1020         return (rval);
1021 
1022 } /* emlxs_fcio_get_host_params() */
1023 
1024 
1025 /*ARGSUSED*/
1026 static int32_t
1027 emlxs_fcio_reset_link(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1028 {
1029         int32_t         rval = 0;
1030         uint8_t         null_wwn[8];
1031 
1032         if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1033             fcio->fcio_ilen != 8) {
1034                 rval = EINVAL;
1035                 goto done;
1036         }
1037 
1038         if (port->mode != MODE_TARGET) {
1039                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1040                     "fcio_reset_link failed. Port is not in target mode.");
1041 
1042                 fcio->fcio_errno = FC_FAILURE;
1043                 rval = EIO;
1044                 goto done;
1045         }
1046 
1047         bzero(null_wwn, 8);
1048 
1049         if (bcmp((uint8_t *)fcio->fcio_ibuf, null_wwn, 8) == 0) {
1050                 rval = emlxs_fca_reset(port, FC_FCA_LINK_RESET);
1051 
1052                 if (rval != FC_SUCCESS) {
1053                         fcio->fcio_errno = rval;
1054                         rval = EIO;
1055                 }
1056         } else {
1057                 rval = ENOTSUP;
1058         }
1059 
1060 done:
1061         return (rval);
1062 
1063 } /* emlxs_fcio_reset_link() */
1064 
1065 
1066 /*ARGSUSED*/
1067 static int32_t
1068 emlxs_fcio_reset_hard(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1069 {
1070         int32_t         rval = 0;
1071 
1072         if (port->mode != MODE_TARGET) {
1073                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1074                     "fcio_reset_hard failed. Port is not in target mode.");
1075 
1076                 fcio->fcio_errno = FC_FAILURE;
1077                 rval = EIO;
1078                 goto done;
1079         }
1080 
1081         rval = emlxs_reset(port, FC_FCA_RESET);
1082 
1083         if (rval != FC_SUCCESS) {
1084                 fcio->fcio_errno = rval;
1085                 rval = EIO;
1086         }
1087 
1088 done:
1089         return (rval);
1090 
1091 } /* emlxs_fcio_reset_hard() */
1092 
1093 
1094 /*ARGSUSED*/
1095 static int32_t
1096 emlxs_fcio_download_fw(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1097 {
1098         int32_t         rval = 0;
1099         fc_fca_pm_t     pm;
1100 
1101         if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1102             fcio->fcio_ilen == 0) {
1103                 rval = EINVAL;
1104                 goto done;
1105         }
1106 
1107         bzero((caddr_t)&pm, sizeof (pm));
1108 
1109         pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1110         pm.pm_cmd_code  = FC_PORT_DOWNLOAD_FW;
1111         pm.pm_data_len  = fcio->fcio_ilen;
1112         pm.pm_data_buf  = fcio->fcio_ibuf;
1113 
1114         rval = emlxs_fca_port_manage(port, &pm);
1115 
1116         if ((rval != FC_SUCCESS) && (rval != EMLXS_REBOOT_REQUIRED)) {
1117                 fcio->fcio_errno = rval;
1118                 rval = EIO;
1119         }
1120 
1121 done:
1122         return (rval);
1123 
1124 } /* emlxs_fcio_download_fw() */
1125 
1126 
1127 /*ARGSUSED*/
1128 static int32_t
1129 emlxs_fcio_get_fw_rev(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1130 {
1131         int32_t         rval = 0;
1132         fc_fca_pm_t     pm;
1133 
1134         if (fcio->fcio_xfer != FCIO_XFER_READ ||
1135             fcio->fcio_olen < FC_FW_REV_SIZE) {
1136                 rval = EINVAL;
1137                 goto done;
1138         }
1139 
1140         bzero((caddr_t)&pm, sizeof (pm));
1141 
1142         pm.pm_cmd_flags = FC_FCA_PM_READ;
1143         pm.pm_cmd_code  = FC_PORT_GET_FW_REV;
1144         pm.pm_data_len  = fcio->fcio_olen;
1145         pm.pm_data_buf  = fcio->fcio_obuf;
1146 
1147         rval = emlxs_fca_port_manage(port, &pm);
1148 
1149         if (rval != FC_SUCCESS) {
1150                 fcio->fcio_errno = rval;
1151                 rval = EIO;
1152         }
1153 
1154 done:
1155         return (rval);
1156 
1157 } /* emlxs_fcio_get_fw_rev() */
1158 
1159 
1160 /*ARGSUSED*/
1161 static int32_t
1162 emlxs_fcio_get_fcode_rev(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1163 {
1164         int32_t         rval = 0;
1165         fc_fca_pm_t     pm;
1166 
1167         if (fcio->fcio_xfer != FCIO_XFER_READ ||
1168             fcio->fcio_olen < FC_FCODE_REV_SIZE) {
1169                 rval = EINVAL;
1170                 goto done;
1171         }
1172 
1173         bzero((caddr_t)&pm, sizeof (pm));
1174 
1175         pm.pm_cmd_flags = FC_FCA_PM_READ;
1176         pm.pm_cmd_code  = FC_PORT_GET_FCODE_REV;
1177         pm.pm_data_len  = fcio->fcio_olen;
1178         pm.pm_data_buf  = fcio->fcio_obuf;
1179 
1180         rval = emlxs_fca_port_manage(port, &pm);
1181 
1182         if (rval != FC_SUCCESS) {
1183                 fcio->fcio_errno = rval;
1184                 rval = EIO;
1185         }
1186 
1187 done:
1188         return (rval);
1189 
1190 } /* emlxs_fcio_get_fcode_rev() */
1191 
1192 
1193 /*ARGSUSED*/
1194 static int32_t
1195 emlxs_fcio_download_fcode(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1196 {
1197         int32_t         rval = 0;
1198         fc_fca_pm_t     pm;
1199 
1200         if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1201             fcio->fcio_ilen == 0) {
1202                 rval = EINVAL;
1203                 goto done;
1204         }
1205 
1206         bzero((caddr_t)&pm, sizeof (pm));
1207 
1208         pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1209         pm.pm_cmd_code  = FC_PORT_DOWNLOAD_FCODE;
1210         pm.pm_data_len  = fcio->fcio_ilen;
1211         pm.pm_data_buf  = fcio->fcio_ibuf;
1212 
1213         rval = emlxs_fca_port_manage(port, &pm);
1214 
1215         if (rval != FC_SUCCESS) {
1216                 fcio->fcio_errno = rval;
1217                 rval = EIO;
1218         }
1219 
1220 done:
1221         return (rval);
1222 
1223 } /* emlxs_fcio_download_fcode() */
1224 
1225 
1226 #ifndef _MULTI_DATAMODEL
1227 /* ARGSUSED */
1228 #endif
1229 static int32_t
1230 emlxs_fcio_get_adapter_attrs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1231 {
1232         emlxs_hba_t     *hba = HBA;
1233         int32_t         rval = 0;
1234         uint32_t        use32 = 0;
1235         emlxs_vpd_t     *vpd = &VPD;
1236 
1237 #ifdef  _MULTI_DATAMODEL
1238         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1239                 use32 = 1;
1240         }
1241 #endif  /* _MULTI_DATAMODEL */
1242 
1243         if (use32) {
1244                 fc_hba_adapter_attributes32_t   *hba_attrs;
1245 
1246                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
1247                     fcio->fcio_olen <
1248                     sizeof (fc_hba_adapter_attributes32_t)) {
1249                         rval = EINVAL;
1250                         goto done;
1251                 }
1252 
1253                 hba_attrs =
1254                     (fc_hba_adapter_attributes32_t *)fcio->fcio_obuf;
1255 
1256                 hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1257                 (void) strncpy(hba_attrs->Manufacturer, "Emulex",
1258                     (sizeof (hba_attrs->Manufacturer)-1));
1259                 (void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1260                     (sizeof (hba_attrs->SerialNumber)-1));
1261                 (void) strncpy(hba_attrs->Model, hba->model_info.model,
1262                     (sizeof (hba_attrs->Model)-1));
1263                 (void) strncpy(hba_attrs->ModelDescription,
1264                     hba->model_info.model_desc,
1265                     (sizeof (hba_attrs->ModelDescription)-1));
1266                 bcopy((caddr_t)&port->wwnn,
1267                     (caddr_t)&hba_attrs->NodeWWN, 8);
1268                 (void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1269                     (caddr_t)port->snn,
1270                     (sizeof (hba_attrs->NodeSymbolicName)-1));
1271                 (void) snprintf(hba_attrs->HardwareVersion,
1272                     (sizeof (hba_attrs->HardwareVersion)-1),
1273                     "%x", vpd->biuRev);
1274                 (void) snprintf(hba_attrs->DriverVersion,
1275                     (sizeof (hba_attrs->DriverVersion)-1),
1276                     "%s (%s)", emlxs_version, emlxs_revision);
1277                 (void) strncpy(hba_attrs->OptionROMVersion,
1278                     vpd->fcode_version,
1279                     (sizeof (hba_attrs->OptionROMVersion)-1));
1280                 (void) snprintf(hba_attrs->FirmwareVersion,
1281                     (sizeof (hba_attrs->FirmwareVersion)-1),
1282                     "%s (%s)", vpd->fw_version, vpd->fw_label);
1283                 (void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1284                     (sizeof (hba_attrs->DriverName)-1));
1285                 hba_attrs->VendorSpecificID =
1286                     ((hba->model_info.device_id << 16) |
1287                     PCI_VENDOR_ID_EMULEX);
1288                 hba_attrs->NumberOfPorts = hba->num_of_ports;
1289         } else {
1290                 fc_hba_adapter_attributes_t     *hba_attrs;
1291 
1292                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
1293                     fcio->fcio_olen <
1294                     sizeof (fc_hba_adapter_attributes_t)) {
1295                         rval = EINVAL;
1296                         goto done;
1297                 }
1298 
1299                 hba_attrs =
1300                     (fc_hba_adapter_attributes_t *)fcio->fcio_obuf;
1301 
1302                 hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1303                 (void) strncpy(hba_attrs->Manufacturer, "Emulex",
1304                     (sizeof (hba_attrs->Manufacturer)-1));
1305                 (void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1306                     (sizeof (hba_attrs->SerialNumber)-1));
1307                 (void) strncpy(hba_attrs->Model, hba->model_info.model,
1308                     (sizeof (hba_attrs->Model)-1));
1309                 (void) strncpy(hba_attrs->ModelDescription,
1310                     hba->model_info.model_desc,
1311                     (sizeof (hba_attrs->ModelDescription)-1));
1312                 bcopy((caddr_t)&port->wwnn,
1313                     (caddr_t)&hba_attrs->NodeWWN, 8);
1314                 (void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1315                     (caddr_t)port->snn,
1316                     (sizeof (hba_attrs->NodeSymbolicName)-1));
1317                 (void) snprintf(hba_attrs->HardwareVersion,
1318                     (sizeof (hba_attrs->HardwareVersion)-1),
1319                     "%x", vpd->biuRev);
1320                 (void) snprintf(hba_attrs->DriverVersion,
1321                     (sizeof (hba_attrs->DriverVersion)-1),
1322                     "%s (%s)", emlxs_version, emlxs_revision);
1323                 (void) strncpy(hba_attrs->OptionROMVersion,
1324                     vpd->fcode_version,
1325                     (sizeof (hba_attrs->OptionROMVersion)-1));
1326                 (void) snprintf(hba_attrs->FirmwareVersion,
1327                     (sizeof (hba_attrs->FirmwareVersion)-1),
1328                     "%s (%s)", vpd->fw_version, vpd->fw_label);
1329                 (void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1330                     (sizeof (hba_attrs->DriverName)-1));
1331                 hba_attrs->VendorSpecificID =
1332                     ((hba->model_info.device_id << 16) |
1333                     PCI_VENDOR_ID_EMULEX);
1334                 hba_attrs->NumberOfPorts = hba->num_of_ports;
1335         }
1336 
1337 done:
1338         return (rval);
1339 
1340 } /* emlxs_fcio_get_adapter_attrs() */
1341 
1342 
1343 #ifndef _MULTI_DATAMODEL
1344 /* ARGSUSED */
1345 #endif
1346 static int32_t
1347 emlxs_fcio_get_adapter_port_attrs(emlxs_port_t *port, fcio_t *fcio,
1348     int32_t mode)
1349 {
1350         emlxs_hba_t     *hba = HBA;
1351         int32_t         rval = 0;
1352         uint32_t        use32 = 0;
1353         emlxs_vpd_t     *vpd = &VPD;
1354 
1355 #ifdef  _MULTI_DATAMODEL
1356         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1357                 use32 = 1;
1358         }
1359 #endif  /* _MULTI_DATAMODEL */
1360 
1361         if (use32) {
1362                 fc_hba_port_attributes32_t  *port_attrs;
1363                 uint32_t value1;
1364                 uint32_t value2;
1365 
1366                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
1367                     fcio->fcio_olen <
1368                     sizeof (fc_hba_port_attributes32_t)) {
1369                         rval = EINVAL;
1370                         goto done;
1371                 }
1372 
1373                 port_attrs =
1374                     (fc_hba_port_attributes32_t *)fcio->fcio_obuf;
1375 
1376                 port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
1377                 port_attrs->lastChange = 0;
1378                 port_attrs->fp_minor   = 0;
1379                 bcopy((caddr_t)&port->wwnn,
1380                     (caddr_t)&port_attrs->NodeWWN, 8);
1381                 bcopy((caddr_t)&port->wwpn,
1382                     (caddr_t)&port_attrs->PortWWN, 8);
1383 
1384                 if ((port->mode != MODE_TARGET) ||
1385                     (port->ulp_statec == FC_STATE_OFFLINE)) {
1386                         /* port_attrs->PortFcId   */
1387                         /* port_attrs->PortType   */
1388                         /* port_attrs->PortSpeed  */
1389                         /* port_attrs->FabricName */
1390                         port_attrs->PortState =
1391                             FC_HBA_PORTSTATE_OFFLINE;
1392                 } else {
1393                         port_attrs->PortFcId  = port->did;
1394                         port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1395 
1396                         if (hba->topology == TOPOLOGY_LOOP) {
1397                                 if (hba->flag & FC_FABRIC_ATTACHED) {
1398                                         port_attrs->PortType =
1399                                             FC_HBA_PORTTYPE_NLPORT;
1400                                 } else {
1401                                         port_attrs->PortType =
1402                                             FC_HBA_PORTTYPE_LPORT;
1403                                 }
1404 
1405                         } else {
1406                                 if (hba->flag & FC_PT_TO_PT) {
1407                                         port_attrs->PortType =
1408                                             FC_HBA_PORTTYPE_PTP;
1409                                 } else {
1410                                         port_attrs->PortType =
1411                                             FC_HBA_PORTTYPE_NPORT;
1412                                 }
1413                         }
1414 
1415                         if (hba->flag & FC_FABRIC_ATTACHED) {
1416                                 bcopy(&port->fabric_sparam.portName,
1417                                     (caddr_t)&port_attrs->FabricName,
1418                                     sizeof (port_attrs->FabricName));
1419                         }
1420 
1421                         switch (hba->linkspeed) {
1422                         case 0:
1423                                 port_attrs->PortSpeed =
1424                                     HBA_PORTSPEED_1GBIT;
1425                                 break;
1426                         case LA_1GHZ_LINK:
1427                                 port_attrs->PortSpeed =
1428                                     HBA_PORTSPEED_1GBIT;
1429                                 break;
1430                         case LA_2GHZ_LINK:
1431                                 port_attrs->PortSpeed =
1432                                     HBA_PORTSPEED_2GBIT;
1433                                 break;
1434                         case LA_4GHZ_LINK:
1435                                 port_attrs->PortSpeed =
1436                                     HBA_PORTSPEED_4GBIT;
1437                                 break;
1438                         case LA_8GHZ_LINK:
1439                                 port_attrs->PortSpeed =
1440                                     HBA_PORTSPEED_8GBIT;
1441                                 break;
1442                         case LA_10GHZ_LINK:
1443                                 port_attrs->PortSpeed =
1444                                     HBA_PORTSPEED_10GBIT;
1445                                 break;
1446                         case LA_16GHZ_LINK:
1447                                 port_attrs->PortSpeed =
1448                                     HBA_PORTSPEED_16GBIT;
1449                                 break;
1450                         default:
1451                                 port_attrs->PortSpeed =
1452                                     HBA_PORTSPEED_UNKNOWN;
1453                         }
1454 
1455                         port_attrs->NumberofDiscoveredPorts =
1456                             emlxs_nport_count(port);
1457                 }
1458 
1459                 port_attrs->PortSupportedClassofService =
1460                     LE_SWAP32(FC_NS_CLASS3);
1461                 (void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1462                     (caddr_t)port->spn,
1463                     (sizeof (port_attrs->PortSymbolicName)-1));
1464 
1465                 /* Set the hba speed limit */
1466                 if (vpd->link_speed & LMT_16GB_CAPABLE) {
1467                         port_attrs->PortSupportedSpeed |=
1468                             FC_HBA_PORTSPEED_16GBIT;
1469                 }
1470                 if (vpd->link_speed & LMT_10GB_CAPABLE) {
1471                         port_attrs->PortSupportedSpeed |=
1472                             FC_HBA_PORTSPEED_10GBIT;
1473                 }
1474                 if (vpd->link_speed & LMT_8GB_CAPABLE) {
1475                         port_attrs->PortSupportedSpeed |=
1476                             FC_HBA_PORTSPEED_8GBIT;
1477                 }
1478                 if (vpd->link_speed & LMT_4GB_CAPABLE) {
1479                         port_attrs->PortSupportedSpeed |=
1480                             FC_HBA_PORTSPEED_4GBIT;
1481                 }
1482                 if (vpd->link_speed & LMT_2GB_CAPABLE) {
1483                         port_attrs->PortSupportedSpeed |=
1484                             FC_HBA_PORTSPEED_2GBIT;
1485                 }
1486                 if (vpd->link_speed & LMT_1GB_CAPABLE) {
1487                         port_attrs->PortSupportedSpeed |=
1488                             FC_HBA_PORTSPEED_1GBIT;
1489                 }
1490 
1491                 value1 = 0x00000120;
1492                 value2 = 0x00000001;
1493 
1494                 bcopy((caddr_t)&value1,
1495                     (caddr_t)&port_attrs->PortSupportedFc4Types[0], 4);
1496                 bcopy((caddr_t)&value2,
1497                     (caddr_t)&port_attrs->PortSupportedFc4Types[4], 4);
1498 
1499                 bcopy((caddr_t)&value1,
1500                     (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1501                 bcopy((caddr_t)&value2,
1502                     (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1503 
1504                 port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1505 
1506         } else {
1507 
1508                 fc_hba_port_attributes_t  *port_attrs;
1509                 uint32_t value1;
1510                 uint32_t value2;
1511 
1512                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
1513                     fcio->fcio_olen <
1514                     sizeof (fc_hba_port_attributes_t)) {
1515                         rval = EINVAL;
1516                         goto done;
1517                 }
1518 
1519                 port_attrs =
1520                     (fc_hba_port_attributes_t *)fcio->fcio_obuf;
1521 
1522                 port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
1523                 port_attrs->lastChange = 0;
1524                 port_attrs->fp_minor   = 0;
1525                 bcopy((caddr_t)&port->wwnn,
1526                     (caddr_t)&port_attrs->NodeWWN, 8);
1527                 bcopy((caddr_t)&port->wwpn,
1528                     (caddr_t)&port_attrs->PortWWN, 8);
1529 
1530                 if (port->mode != MODE_TARGET ||
1531                     (port->ulp_statec == FC_STATE_OFFLINE)) {
1532                         /* port_attrs->PortFcId   */
1533                         /* port_attrs->PortType   */
1534                         /* port_attrs->PortSpeed  */
1535                         /* port_attrs->FabricName */
1536                         port_attrs->PortState =
1537                             FC_HBA_PORTSTATE_OFFLINE;
1538                 } else {
1539                         port_attrs->PortFcId  = port->did;
1540                         port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1541 
1542                         if (hba->topology == TOPOLOGY_LOOP) {
1543                                 if (hba->flag & FC_FABRIC_ATTACHED) {
1544                                         port_attrs->PortType =
1545                                             FC_HBA_PORTTYPE_NLPORT;
1546                                 } else {
1547                                         port_attrs->PortType =
1548                                             FC_HBA_PORTTYPE_LPORT;
1549                                 }
1550 
1551                         } else {
1552                                 if (hba->flag & FC_PT_TO_PT) {
1553                                         port_attrs->PortType =
1554                                             FC_HBA_PORTTYPE_PTP;
1555                                 } else {
1556                                         port_attrs->PortType =
1557                                             FC_HBA_PORTTYPE_NPORT;
1558                                 }
1559                         }
1560 
1561                         if (hba->flag & FC_FABRIC_ATTACHED) {
1562                                 bcopy(&port->fabric_sparam.portName,
1563                                     (caddr_t)&port_attrs->FabricName,
1564                                     sizeof (port_attrs->FabricName));
1565                         }
1566 
1567                         switch (hba->linkspeed) {
1568                         case 0:
1569                                 port_attrs->PortSpeed =
1570                                     HBA_PORTSPEED_1GBIT;
1571                                 break;
1572                         case LA_1GHZ_LINK:
1573                                 port_attrs->PortSpeed =
1574                                     HBA_PORTSPEED_1GBIT;
1575                                 break;
1576                         case LA_2GHZ_LINK:
1577                                 port_attrs->PortSpeed =
1578                                     HBA_PORTSPEED_2GBIT;
1579                                 break;
1580                         case LA_4GHZ_LINK:
1581                                 port_attrs->PortSpeed =
1582                                     HBA_PORTSPEED_4GBIT;
1583                                 break;
1584                         case LA_8GHZ_LINK:
1585                                 port_attrs->PortSpeed =
1586                                     HBA_PORTSPEED_8GBIT;
1587                                 break;
1588                         case LA_10GHZ_LINK:
1589                                 port_attrs->PortSpeed =
1590                                     HBA_PORTSPEED_10GBIT;
1591                                 break;
1592                         case LA_16GHZ_LINK:
1593                                 port_attrs->PortSpeed =
1594                                     HBA_PORTSPEED_16GBIT;
1595                                 break;
1596                         default:
1597                                 port_attrs->PortSpeed =
1598                                     HBA_PORTSPEED_UNKNOWN;
1599                         }
1600 
1601                         port_attrs->NumberofDiscoveredPorts =
1602                             emlxs_nport_count(port);
1603                 }
1604 
1605                 port_attrs->PortSupportedClassofService =
1606                     LE_SWAP32(FC_NS_CLASS3);
1607                 (void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1608                     (caddr_t)port->spn,
1609                     (sizeof (port_attrs->PortSymbolicName)-1));
1610 
1611                 /* Set the hba speed limit */
1612                 if (vpd->link_speed & LMT_16GB_CAPABLE) {
1613                         port_attrs->PortSupportedSpeed |=
1614                             FC_HBA_PORTSPEED_16GBIT;
1615                 }
1616                 if (vpd->link_speed & LMT_10GB_CAPABLE) {
1617                         port_attrs->PortSupportedSpeed |=
1618                             FC_HBA_PORTSPEED_10GBIT;
1619                 }
1620                 if (vpd->link_speed & LMT_8GB_CAPABLE) {
1621                         port_attrs->PortSupportedSpeed |=
1622                             FC_HBA_PORTSPEED_8GBIT;
1623                 }
1624                 if (vpd->link_speed & LMT_4GB_CAPABLE) {
1625                         port_attrs->PortSupportedSpeed |=
1626                             FC_HBA_PORTSPEED_4GBIT;
1627                 }
1628                 if (vpd->link_speed & LMT_2GB_CAPABLE) {
1629                         port_attrs->PortSupportedSpeed |=
1630                             FC_HBA_PORTSPEED_2GBIT;
1631                 }
1632                 if (vpd->link_speed & LMT_1GB_CAPABLE) {
1633                         port_attrs->PortSupportedSpeed |=
1634                             FC_HBA_PORTSPEED_1GBIT;
1635                 }
1636 
1637                 value1 = 0x00000120;
1638                 value2 = 0x00000001;
1639 
1640                 bcopy((caddr_t)&value1,
1641                     (caddr_t)&port_attrs->PortSupportedFc4Types[0], 4);
1642                 bcopy((caddr_t)&value2,
1643                     (caddr_t)&port_attrs->PortSupportedFc4Types[4], 4);
1644 
1645                 bcopy((caddr_t)&value1,
1646                     (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1647                 bcopy((caddr_t)&value2,
1648                     (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1649 
1650                 port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1651         }
1652 
1653 done:
1654         return (rval);
1655 
1656 } /* emlxs_fcio_get_adapter_port_attrs() */
1657 
1658 
1659 /*ARGSUSED*/
1660 static int32_t
1661 emlxs_fcio_get_node_id(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1662 {
1663         int32_t         rval = 0;
1664         fc_fca_pm_t     pm;
1665 
1666         if (fcio->fcio_xfer != FCIO_XFER_READ ||
1667             fcio->fcio_olen < sizeof (fc_rnid_t)) {
1668                 rval = EINVAL;
1669                 goto done;
1670         }
1671 
1672         bzero((caddr_t)&pm, sizeof (pm));
1673 
1674         pm.pm_cmd_flags = FC_FCA_PM_READ;
1675         pm.pm_cmd_code  = FC_PORT_GET_NODE_ID;
1676         pm.pm_data_len  = fcio->fcio_olen;
1677         pm.pm_data_buf  = fcio->fcio_obuf;
1678 
1679         rval = emlxs_fca_port_manage(port, &pm);
1680 
1681         if (rval != FC_SUCCESS) {
1682                 fcio->fcio_errno = rval;
1683                 rval = EIO;
1684         }
1685 
1686 done:
1687         return (rval);
1688 
1689 } /* emlxs_fcio_get_node_id() */
1690 
1691 
1692 /*ARGSUSED*/
1693 static int32_t
1694 emlxs_fcio_set_node_id(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1695 {
1696         int32_t         rval = 0;
1697         fc_fca_pm_t     pm;
1698 
1699         if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1700             fcio->fcio_ilen < sizeof (fc_rnid_t)) {
1701                 rval = EINVAL;
1702                 goto done;
1703         }
1704 
1705         bzero((caddr_t)&pm, sizeof (pm));
1706 
1707         pm.pm_cmd_flags = FC_FCA_PM_READ;
1708         pm.pm_cmd_code  = FC_PORT_SET_NODE_ID;
1709         pm.pm_data_len  = fcio->fcio_ilen;
1710         pm.pm_data_buf  = fcio->fcio_ibuf;
1711 
1712         rval = emlxs_fca_port_manage(port, &pm);
1713 
1714         if (rval != FC_SUCCESS) {
1715                 fcio->fcio_errno = rval;
1716                 rval = EIO;
1717         }
1718 
1719 done:
1720         return (rval);
1721 
1722 } /* emlxs_fcio_set_node_id() */
1723 
1724 
1725 
1726 
1727 /*ARGSUSED*/
1728 static int32_t
1729 emlxs_fcio_get_num_devs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1730 {
1731         int32_t         rval = 0;
1732 
1733         if (fcio->fcio_xfer != FCIO_XFER_READ ||
1734             fcio->fcio_olen < sizeof (uint32_t)) {
1735                 rval = EINVAL;
1736                 goto done;
1737         }
1738 
1739         if (port->mode == MODE_TARGET) {
1740                 *(uint32_t *)fcio->fcio_obuf = emlxs_nport_count(port);
1741         }
1742 
1743 done:
1744         return (rval);
1745 
1746 } /* emlxs_fcio_get_num_devs() */
1747 
1748 
1749 #ifndef _MULTI_DATAMODEL
1750 /* ARGSUSED */
1751 #endif
1752 static int32_t
1753 emlxs_fcio_get_dev_list(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1754 {
1755         emlxs_hba_t     *hba = HBA;
1756         int32_t         rval = 0;
1757         uint32_t        use32 = 0;
1758 
1759 #ifdef  _MULTI_DATAMODEL
1760         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1761                 use32 = 1;
1762         }
1763 #endif  /* _MULTI_DATAMODEL */
1764 
1765         if (use32) {
1766                 fc_port_dev32_t *port_dev;
1767                 uint32_t max_count;
1768                 uint32_t i;
1769                 uint32_t j;
1770                 emlxs_node_t *nlp;
1771                 uint32_t nport_count = 0;
1772 
1773                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
1774                     fcio->fcio_alen < sizeof (uint32_t)) {
1775                         rval = EINVAL;
1776                         goto done;
1777                 }
1778 
1779                 port_dev = (fc_port_dev32_t *)fcio->fcio_obuf;
1780                 max_count = fcio->fcio_olen / sizeof (fc_port_dev32_t);
1781 
1782                 rw_enter(&port->node_rwlock, RW_READER);
1783 
1784                 if (port->mode == MODE_TARGET) {
1785                         nport_count = emlxs_nport_count(port);
1786                 }
1787 
1788                 *(uint32_t *)fcio->fcio_abuf = nport_count;
1789 
1790                 if (nport_count == 0) {
1791                         rw_exit(&port->node_rwlock);
1792 
1793                         fcio->fcio_errno = FC_NO_MAP;
1794                         rval = EIO;
1795                         goto done;
1796                 }
1797 
1798                 if (nport_count > max_count) {
1799                         rw_exit(&port->node_rwlock);
1800 
1801                         fcio->fcio_errno = FC_TOOMANY;
1802                         rval = EIO;
1803                         goto done;
1804                 }
1805 
1806                 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1807                         nlp = port->node_table[i];
1808                         while (nlp != NULL) {
1809                         if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
1810                                 port_dev->dev_dtype = 0;
1811                                 port_dev->dev_type[0] =
1812                                     BE_SWAP32(0x00000100);
1813                                 port_dev->dev_state =
1814                                     PORT_DEVICE_LOGGED_IN;
1815                                 port_dev->dev_did.port_id =
1816                                     nlp->nlp_DID;
1817                                 port_dev->dev_did.priv_lilp_posit = 0;
1818                                 port_dev->dev_hard_addr.hard_addr = 0;
1819 
1820                 if (hba->topology == TOPOLOGY_LOOP) {
1821                         for (j = 1; j < port->alpa_map[0]; j++) {
1822                                 if (nlp->nlp_DID == port->alpa_map[j]) {
1823                                         port_dev->dev_did.priv_lilp_posit = j-1;
1824                                         goto done;
1825                                 }
1826                         }
1827                         port_dev->dev_hard_addr.hard_addr = nlp->nlp_DID;
1828                 }
1829 
1830                                 bcopy((caddr_t)&nlp->nlp_portname,
1831                                     (caddr_t)&port_dev->dev_pwwn, 8);
1832                                 bcopy((caddr_t)&nlp->nlp_nodename,
1833                                     (caddr_t)&port_dev->dev_nwwn, 8);
1834                                 port_dev++;
1835                         }
1836 
1837                         nlp = (NODELIST *) nlp->nlp_list_next;
1838                         }
1839                 }
1840                 rw_exit(&port->node_rwlock);
1841 
1842         } else {
1843 
1844                 fc_port_dev_t *port_dev;
1845                 uint32_t max_count;
1846                 uint32_t i;
1847                 uint32_t j;
1848                 emlxs_node_t *nlp;
1849                 uint32_t nport_count = 0;
1850 
1851                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
1852                     fcio->fcio_alen < sizeof (uint32_t)) {
1853                         rval = EINVAL;
1854                         goto done;
1855                 }
1856 
1857                 port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
1858                 max_count = fcio->fcio_olen / sizeof (fc_port_dev_t);
1859 
1860                 rw_enter(&port->node_rwlock, RW_READER);
1861 
1862                 if (port->mode == MODE_TARGET) {
1863                         nport_count = emlxs_nport_count(port);
1864                 }
1865 
1866                 *(uint32_t *)fcio->fcio_abuf = nport_count;
1867 
1868                 if (nport_count == 0) {
1869                         rw_exit(&port->node_rwlock);
1870 
1871                         fcio->fcio_errno = FC_NO_MAP;
1872                         rval = EIO;
1873                         goto done;
1874                 }
1875 
1876                 if (nport_count > max_count) {
1877                         rw_exit(&port->node_rwlock);
1878 
1879                         fcio->fcio_errno = FC_TOOMANY;
1880                         rval = EIO;
1881                         goto done;
1882                 }
1883 
1884                 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1885                         nlp = port->node_table[i];
1886                         while (nlp != NULL) {
1887                         if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
1888                                 port_dev->dev_dtype = 0;
1889                                 port_dev->dev_type[0] =
1890                                     BE_SWAP32(0x00000100);
1891                                 port_dev->dev_state =
1892                                     PORT_DEVICE_LOGGED_IN;
1893                                 port_dev->dev_did.port_id =
1894                                     nlp->nlp_DID;
1895                                 port_dev->dev_did.priv_lilp_posit = 0;
1896                                 port_dev->dev_hard_addr.hard_addr = 0;
1897 
1898                 if (hba->topology == TOPOLOGY_LOOP) {
1899                         for (j = 1; j < port->alpa_map[0]; j++) {
1900                                 if (nlp->nlp_DID == port->alpa_map[j]) {
1901                                         port_dev->dev_did.priv_lilp_posit = j-1;
1902                                         goto done;
1903                                 }
1904                         }
1905                         port_dev->dev_hard_addr.hard_addr = nlp->nlp_DID;
1906                 }
1907 
1908                                 bcopy((caddr_t)&nlp->nlp_portname,
1909                                     (caddr_t)&port_dev->dev_pwwn, 8);
1910                                 bcopy((caddr_t)&nlp->nlp_nodename,
1911                                     (caddr_t)&port_dev->dev_nwwn, 8);
1912                                 port_dev++;
1913                         }
1914 
1915                         nlp = (NODELIST *) nlp->nlp_list_next;
1916                         }
1917                 }
1918                 rw_exit(&port->node_rwlock);
1919         }
1920 
1921 done:
1922         return (rval);
1923 
1924 } /* emlxs_fcio_get_dev_list() */
1925 
1926 
1927 /*ARGSUSED*/
1928 static int32_t
1929 emlxs_fcio_get_logi_params(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1930 {
1931         int32_t         rval = 0;
1932         uint8_t         null_wwn[8];
1933         uint8_t         *wwpn;
1934         emlxs_node_t    *ndlp;
1935 
1936         if (fcio->fcio_ilen != sizeof (la_wwn_t) ||
1937             (fcio->fcio_xfer & FCIO_XFER_READ) == 0 ||
1938             (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0) {
1939                 rval = EINVAL;
1940                 goto done;
1941         }
1942 
1943         bzero(null_wwn, 8);
1944         wwpn = (uint8_t *)fcio->fcio_ibuf;
1945 
1946         if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1947             (bcmp((caddr_t)wwpn, (caddr_t)&port->wwpn, 8) == 0)) {
1948                 bcopy((caddr_t)&port->sparam,
1949                     (caddr_t)fcio->fcio_obuf, fcio->fcio_olen);
1950         } else {
1951                 ndlp = emlxs_node_find_wwpn(port, wwpn, 1);
1952 
1953                 if (ndlp) {
1954                         bcopy((caddr_t)&ndlp->sparm,
1955                             (caddr_t)fcio->fcio_obuf,
1956                             fcio->fcio_olen);
1957                 } else {
1958                         rval = ENXIO;
1959                 }
1960         }
1961 
1962 done:
1963         return (rval);
1964 
1965 } /* emlxs_fcio_get_logi_params() */
1966 
1967 
1968 /*ARGSUSED*/
1969 static int32_t
1970 emlxs_fcio_get_state(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
1971 {
1972         int32_t         rval = 0;
1973         uint8_t         null_wwn[8];
1974         uint32_t        *statep;
1975         uint8_t         *wwpn;
1976         emlxs_node_t    *ndlp;
1977 
1978         if (fcio->fcio_ilen != 8 ||
1979             fcio->fcio_olen != 4 ||
1980             (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0 ||
1981             (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1982                 rval = EINVAL;
1983                 goto done;
1984         }
1985 
1986         bzero(null_wwn, 8);
1987         wwpn   = (uint8_t *)fcio->fcio_ibuf;
1988         statep = (uint32_t *)fcio->fcio_obuf;
1989 
1990         if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1991             (bcmp((caddr_t)wwpn, (caddr_t)&port->wwpn, 8) == 0)) {
1992                 *statep = PORT_DEVICE_VALID;
1993         } else {
1994                 ndlp = emlxs_node_find_wwpn(port, wwpn, 1);
1995 
1996                 if (ndlp) {
1997                         *statep = PORT_DEVICE_VALID;
1998                 } else {
1999                         *statep = PORT_DEVICE_INVALID;
2000                 }
2001         }
2002 
2003 done:
2004         return (rval);
2005 
2006 } /* emlxs_fcio_get_state() */
2007 
2008 
2009 /*ARGSUSED*/
2010 static int32_t
2011 emlxs_fcio_get_topology(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2012 {
2013         emlxs_hba_t     *hba = HBA;
2014         int32_t         rval = 0;
2015         uint32_t        *tp;
2016         emlxs_node_t    *ndlp;
2017 
2018         if (fcio->fcio_olen != 4 ||
2019             (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2020                 rval = EINVAL;
2021                 goto done;
2022         }
2023 
2024         tp = (uint32_t *)fcio->fcio_obuf;
2025 
2026         if ((port->mode != MODE_TARGET) ||
2027             (port->ulp_statec == FC_STATE_OFFLINE)) {
2028                 *tp = FC_TOP_UNKNOWN;
2029         } else {
2030                 ndlp = emlxs_node_find_did(port, FABRIC_DID, 1);
2031 
2032                 if (hba->topology == TOPOLOGY_LOOP) {
2033                         if (ndlp) {
2034                                 *tp = FC_TOP_PUBLIC_LOOP;
2035                         } else {
2036                                 *tp = FC_TOP_PRIVATE_LOOP;
2037                         }
2038                 } else {
2039                         if (ndlp) {
2040                                 *tp = FC_TOP_FABRIC;
2041                         } else {
2042                                 *tp = FC_TOP_PT_PT;
2043                         }
2044                 }
2045         }
2046 
2047 done:
2048         return (rval);
2049 
2050 } /* emlxs_fcio_get_topology() */
2051 
2052 
2053 /*ARGSUSED*/
2054 static int32_t
2055 emlxs_fcio_get_link_status(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2056 {
2057         int32_t         rval = 0;
2058         fc_portid_t     *portid;
2059         fc_rls_acc_t    *rls;
2060         fc_fca_pm_t     pm;
2061 
2062         if (fcio->fcio_ilen != sizeof (fc_portid_t) ||
2063             fcio->fcio_olen != sizeof (fc_rls_acc_t) ||
2064             fcio->fcio_xfer != FCIO_XFER_RW) {
2065                 rval = EINVAL;
2066                 goto done;
2067         }
2068 
2069         if ((fcio->fcio_cmd_flags != FCIO_CFLAGS_RLS_DEST_FPORT) &&
2070             (fcio->fcio_cmd_flags != FCIO_CFLAGS_RLS_DEST_NPORT)) {
2071                 rval = EINVAL;
2072                 goto done;
2073         }
2074 
2075         portid = (fc_portid_t *)fcio->fcio_ibuf;
2076         rls    = (fc_rls_acc_t *)fcio->fcio_obuf;
2077 
2078         if (portid->port_id == 0 || portid->port_id == port->did) {
2079                 bzero((caddr_t)&pm, sizeof (pm));
2080 
2081                 pm.pm_cmd_flags = FC_FCA_PM_READ;
2082                 pm.pm_cmd_code  = FC_PORT_RLS;
2083                 pm.pm_data_len  = sizeof (fc_rls_acc_t);
2084                 pm.pm_data_buf  = (caddr_t)rls;
2085 
2086                 rval = emlxs_fca_port_manage(port, &pm);
2087 
2088                 if (rval != FC_SUCCESS) {
2089                         fcio->fcio_errno = rval;
2090                         rval = EIO;
2091                 }
2092         } else {
2093                 rval = ENOTSUP;
2094         }
2095 
2096 done:
2097         return (rval);
2098 
2099 } /* emlxs_fcio_get_link_status() */
2100 
2101 
2102 /*ARGSUSED*/
2103 static int32_t
2104 emlxs_fcio_get_other_adapter_ports(emlxs_port_t *port, fcio_t *fcio,
2105     int32_t mode)
2106 {
2107         emlxs_hba_t     *hba = HBA;
2108         int32_t         rval = 0;
2109         uint32_t        index;
2110         char            *path;
2111 
2112         if (fcio->fcio_olen < MAXPATHLEN ||
2113             fcio->fcio_ilen != sizeof (uint32_t)) {
2114                 rval = EINVAL;
2115                 goto done;
2116         }
2117 
2118         index = *(uint32_t *)fcio->fcio_ibuf;
2119         path  = (char *)fcio->fcio_obuf;
2120 
2121         if (index > hba->vpi_max) {
2122                 fcio->fcio_errno = FC_BADPORT;
2123                 rval = EFAULT;
2124                 goto done;
2125         }
2126 
2127         (void) ddi_pathname(hba->dip, path);
2128 
2129 done:
2130         return (rval);
2131 
2132 } /* emlxs_fcio_get_other_adapter_ports() */
2133 
2134 
2135 /*ARGSUSED*/
2136 static int32_t
2137 emlxs_fcio_get_disc_port_attrs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2138 {
2139         emlxs_hba_t     *hba = HBA;
2140         int32_t         rval = 0;
2141         uint32_t        index;
2142         emlxs_node_t    *ndlp;
2143         uint32_t        use32 = 0;
2144 
2145 #ifdef  _MULTI_DATAMODEL
2146         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2147                 use32 = 1;
2148         }
2149 #endif  /* _MULTI_DATAMODEL */
2150 
2151         if (use32) {
2152                 fc_hba_port_attributes32_t  *port_attrs;
2153 
2154                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
2155                     fcio->fcio_ilen < sizeof (uint32_t) ||
2156                     fcio->fcio_olen < sizeof (fc_hba_port_attributes32_t)) {
2157                         rval = EINVAL;
2158                         goto done;
2159                 }
2160 
2161                 index = *(uint32_t *)fcio->fcio_ibuf;
2162                 ndlp  = emlxs_node_find_index(port, index, 1);
2163 
2164                 if (!ndlp) {
2165                         fcio->fcio_errno = FC_OUTOFBOUNDS;
2166                         rval = EINVAL;
2167                         goto done;
2168                 }
2169 
2170                 port_attrs = (fc_hba_port_attributes32_t *)fcio->fcio_obuf;
2171 
2172                 port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2173                 /* port_attrs->lastChange */
2174                 /* port_attrs->fp_minor   */
2175                 bcopy((caddr_t)&ndlp->nlp_nodename,
2176                     (caddr_t)&port_attrs->NodeWWN, 8);
2177                 bcopy((caddr_t)&ndlp->nlp_portname,
2178                     (caddr_t)&port_attrs->PortWWN, 8);
2179 
2180                 port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2181                 port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2182                 port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2183 
2184                 if ((port->mode == MODE_TARGET) &&
2185                     (hba->state >= FC_LINK_UP)) {
2186                         port_attrs->PortFcId  = ndlp->nlp_DID;
2187                         port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2188 
2189                         /* no switch */
2190                         if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2191                                 if (hba->topology == TOPOLOGY_LOOP) {
2192                                         port_attrs->PortType =
2193                                             FC_HBA_PORTTYPE_LPORT;
2194                                 } else {
2195                                         port_attrs->PortType =
2196                                             FC_HBA_PORTTYPE_PTP;
2197                                 }
2198 
2199                                 /* We share a common speed */
2200                                 switch (hba->linkspeed) {
2201                                 case 0:
2202                                         port_attrs->PortSpeed =
2203                                             HBA_PORTSPEED_1GBIT;
2204                                         break;
2205                                 case LA_1GHZ_LINK:
2206                                         port_attrs->PortSpeed =
2207                                             HBA_PORTSPEED_1GBIT;
2208                                         break;
2209                                 case LA_2GHZ_LINK:
2210                                         port_attrs->PortSpeed =
2211                                             HBA_PORTSPEED_2GBIT;
2212                                         break;
2213                                 case LA_4GHZ_LINK:
2214                                         port_attrs->PortSpeed =
2215                                             HBA_PORTSPEED_4GBIT;
2216                                         break;
2217                                 case LA_8GHZ_LINK:
2218                                         port_attrs->PortSpeed =
2219                                             HBA_PORTSPEED_8GBIT;
2220                                         break;
2221                                 case LA_10GHZ_LINK:
2222                                         port_attrs->PortSpeed =
2223                                             HBA_PORTSPEED_10GBIT;
2224                                         break;
2225                                 case LA_16GHZ_LINK:
2226                                         port_attrs->PortSpeed =
2227                                             HBA_PORTSPEED_16GBIT;
2228                                         break;
2229                                 }
2230                         }
2231                         /* public loop */
2232                         else if (hba->topology == TOPOLOGY_LOOP) {
2233                                 /* Check for common area and domain */
2234                                 if ((ndlp->nlp_DID & 0xFFFF00) ==
2235                                     (port->did & 0xFFFF00)) {
2236                                         port_attrs->PortType =
2237                                             FC_HBA_PORTTYPE_NLPORT;
2238 
2239                                         /* We share a common speed */
2240                                         switch (hba->linkspeed) {
2241                                         case 0:
2242                                                 port_attrs->PortSpeed =
2243                                                     HBA_PORTSPEED_1GBIT;
2244                                                 break;
2245                                         case LA_1GHZ_LINK:
2246                                                 port_attrs->PortSpeed =
2247                                                     HBA_PORTSPEED_1GBIT;
2248                                                 break;
2249                                         case LA_2GHZ_LINK:
2250                                                 port_attrs->PortSpeed =
2251                                                     HBA_PORTSPEED_2GBIT;
2252                                                 break;
2253                                         case LA_4GHZ_LINK:
2254                                                 port_attrs->PortSpeed =
2255                                                     HBA_PORTSPEED_4GBIT;
2256                                                 break;
2257                                         case LA_8GHZ_LINK:
2258                                                 port_attrs->PortSpeed =
2259                                                     HBA_PORTSPEED_8GBIT;
2260                                                 break;
2261                                         case LA_10GHZ_LINK:
2262                                                 port_attrs->PortSpeed =
2263                                                     HBA_PORTSPEED_10GBIT;
2264                                                 break;
2265                                         case LA_16GHZ_LINK:
2266                                                 port_attrs->PortSpeed =
2267                                                     HBA_PORTSPEED_16GBIT;
2268                                                 break;
2269                                         }
2270                                 }
2271                         }
2272                 }
2273 
2274                 port_attrs->PortSupportedClassofService =
2275                     LE_SWAP32(FC_NS_CLASS3);
2276                 /* port_attrs->PortSymbolicName              */
2277                 /* port_attrs->PortSupportedSpeed    */
2278                 /* port_attrs->PortSupportedFc4Types */
2279                 /* port_attrs->PortActiveFc4Types    */
2280                 /* port_attrs->PortMaxFrameSize              */
2281                 /* port_attrs->NumberofDiscoveredPorts       */
2282 
2283         } else {
2284                 fc_hba_port_attributes_t  *port_attrs;
2285 
2286                 if (fcio->fcio_xfer != FCIO_XFER_READ ||
2287                     fcio->fcio_ilen < sizeof (uint32_t) ||
2288                     fcio->fcio_olen < sizeof (fc_hba_port_attributes_t)) {
2289                         rval = EINVAL;
2290                         goto done;
2291                 }
2292 
2293                 index = *(uint32_t *)fcio->fcio_ibuf;
2294                 ndlp  = emlxs_node_find_index(port, index, 1);
2295 
2296                 if (!ndlp) {
2297                         fcio->fcio_errno = FC_OUTOFBOUNDS;
2298                         rval = EINVAL;
2299                         goto done;
2300                 }
2301 
2302                 port_attrs = (fc_hba_port_attributes_t *)fcio->fcio_obuf;
2303 
2304                 port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2305                 /* port_attrs->lastChange */
2306                 /* port_attrs->fp_minor   */
2307                 bcopy((caddr_t)&ndlp->nlp_nodename,
2308                     (caddr_t)&port_attrs->NodeWWN, 8);
2309                 bcopy((caddr_t)&ndlp->nlp_portname,
2310                     (caddr_t)&port_attrs->PortWWN, 8);
2311 
2312                 port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2313                 port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2314                 port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2315 
2316                 if ((port->mode == MODE_TARGET) &&
2317                     (hba->state >= FC_LINK_UP)) {
2318                         port_attrs->PortFcId  = ndlp->nlp_DID;
2319                         port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2320 
2321                         /* no switch */
2322                         if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2323                                 if (hba->topology == TOPOLOGY_LOOP) {
2324                                         port_attrs->PortType =
2325                                             FC_HBA_PORTTYPE_LPORT;
2326                                 } else {
2327                                         port_attrs->PortType =
2328                                             FC_HBA_PORTTYPE_PTP;
2329                                 }
2330 
2331                                 /* We share a common speed */
2332                                 switch (hba->linkspeed) {
2333                                 case 0:
2334                                         port_attrs->PortSpeed =
2335                                             HBA_PORTSPEED_1GBIT;
2336                                         break;
2337                                 case LA_1GHZ_LINK:
2338                                         port_attrs->PortSpeed =
2339                                             HBA_PORTSPEED_1GBIT;
2340                                         break;
2341                                 case LA_2GHZ_LINK:
2342                                         port_attrs->PortSpeed =
2343                                             HBA_PORTSPEED_2GBIT;
2344                                         break;
2345                                 case LA_4GHZ_LINK:
2346                                         port_attrs->PortSpeed =
2347                                             HBA_PORTSPEED_4GBIT;
2348                                         break;
2349                                 case LA_8GHZ_LINK:
2350                                         port_attrs->PortSpeed =
2351                                             HBA_PORTSPEED_8GBIT;
2352                                         break;
2353                                 case LA_10GHZ_LINK:
2354                                         port_attrs->PortSpeed =
2355                                             HBA_PORTSPEED_10GBIT;
2356                                         break;
2357                                 case LA_16GHZ_LINK:
2358                                         port_attrs->PortSpeed =
2359                                             HBA_PORTSPEED_16GBIT;
2360                                         break;
2361                                 }
2362                         }
2363                         /* public loop */
2364                         else if (hba->topology == TOPOLOGY_LOOP) {
2365                                 /* Check for common area and domain */
2366                                 if ((ndlp->nlp_DID & 0xFFFF00) ==
2367                                     (port->did & 0xFFFF00)) {
2368                                         port_attrs->PortType =
2369                                             FC_HBA_PORTTYPE_NLPORT;
2370 
2371                                         /* We share a common speed */
2372                                         switch (hba->linkspeed) {
2373                                         case 0:
2374                                                 port_attrs->PortSpeed =
2375                                                     HBA_PORTSPEED_1GBIT;
2376                                                 break;
2377                                         case LA_1GHZ_LINK:
2378                                                 port_attrs->PortSpeed =
2379                                                     HBA_PORTSPEED_1GBIT;
2380                                                 break;
2381                                         case LA_2GHZ_LINK:
2382                                                 port_attrs->PortSpeed =
2383                                                     HBA_PORTSPEED_2GBIT;
2384                                                 break;
2385                                         case LA_4GHZ_LINK:
2386                                                 port_attrs->PortSpeed =
2387                                                     HBA_PORTSPEED_4GBIT;
2388                                                 break;
2389                                         case LA_8GHZ_LINK:
2390                                                 port_attrs->PortSpeed =
2391                                                     HBA_PORTSPEED_8GBIT;
2392                                                 break;
2393                                         case LA_10GHZ_LINK:
2394                                                 port_attrs->PortSpeed =
2395                                                     HBA_PORTSPEED_10GBIT;
2396                                                 break;
2397                                         case LA_16GHZ_LINK:
2398                                                 port_attrs->PortSpeed =
2399                                                     HBA_PORTSPEED_16GBIT;
2400                                                 break;
2401                                         }
2402                                 }
2403                         }
2404                 }
2405 
2406                 port_attrs->PortSupportedClassofService =
2407                     LE_SWAP32(FC_NS_CLASS3);
2408                 /* port_attrs->PortSymbolicName              */
2409                 /* port_attrs->PortSupportedSpeed    */
2410                 /* port_attrs->PortSupportedFc4Types */
2411                 /* port_attrs->PortActiveFc4Types    */
2412                 /* port_attrs->PortMaxFrameSize              */
2413                 /* port_attrs->NumberofDiscoveredPorts       */
2414         }
2415 
2416 done:
2417         return (rval);
2418 
2419 } /* emlxs_fcio_get_disc_port_attrs() */
2420 
2421 
2422 /*ARGSUSED*/
2423 static int32_t
2424 emlxs_fcio_get_port_attrs(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2425 {
2426         emlxs_hba_t     *hba = HBA;
2427         int32_t         rval = 0;
2428         emlxs_node_t    *ndlp;
2429         uint8_t         *wwpn;
2430         uint32_t        use32 = 0;
2431 
2432 #ifdef  _MULTI_DATAMODEL
2433         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2434                 use32 = 1;
2435         }
2436 #endif  /* _MULTI_DATAMODEL */
2437 
2438         if (use32) {
2439                 fc_hba_port_attributes32_t  *port_attrs;
2440 
2441                 if ((fcio->fcio_xfer != FCIO_XFER_READ) ||
2442                     (fcio->fcio_ilen < 8) ||
2443                     (fcio->fcio_olen < sizeof (fc_hba_port_attributes32_t))) {
2444                         rval = EINVAL;
2445                         goto done;
2446                 }
2447 
2448                 wwpn  = (uint8_t *)fcio->fcio_ibuf;
2449                 ndlp  = emlxs_node_find_wwpn(port, wwpn, 1);
2450 
2451                 if (!ndlp) {
2452                         fcio->fcio_errno = FC_NOMAP;
2453                         rval = EINVAL;
2454                         goto done;
2455                 }
2456 
2457                 /* Filter fabric ports */
2458                 if ((ndlp->nlp_DID & 0xFFF000) == 0xFFF000) {
2459                         fcio->fcio_errno = FC_NOMAP;
2460                         rval = EINVAL;
2461                         goto done;
2462                 }
2463 
2464                 port_attrs = (fc_hba_port_attributes32_t *)fcio->fcio_obuf;
2465 
2466                 port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2467                 /* port_attrs->lastChange */
2468                 /* port_attrs->fp_minor   */
2469                 bcopy((caddr_t)&ndlp->nlp_nodename,
2470                     (caddr_t)&port_attrs->NodeWWN, 8);
2471                 bcopy((caddr_t)&ndlp->nlp_portname,
2472                     (caddr_t)&port_attrs->PortWWN, 8);
2473 
2474                 port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2475                 port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2476                 port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2477 
2478                 if ((port->mode == MODE_TARGET) &&
2479                     (hba->state >= FC_LINK_UP)) {
2480                         port_attrs->PortFcId  = ndlp->nlp_DID;
2481                         port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2482 
2483                         /* no switch */
2484                         if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2485                                 if (hba->topology == TOPOLOGY_LOOP) {
2486                                         port_attrs->PortType =
2487                                             FC_HBA_PORTTYPE_LPORT;
2488                                 } else {
2489                                         port_attrs->PortType =
2490                                             FC_HBA_PORTTYPE_PTP;
2491                                 }
2492 
2493                                 /* We share a common speed */
2494                                 switch (hba->linkspeed) {
2495                                 case 0:
2496                                         port_attrs->PortSpeed =
2497                                             HBA_PORTSPEED_1GBIT;
2498                                         break;
2499                                 case LA_1GHZ_LINK:
2500                                         port_attrs->PortSpeed =
2501                                             HBA_PORTSPEED_1GBIT;
2502                                         break;
2503                                 case LA_2GHZ_LINK:
2504                                         port_attrs->PortSpeed =
2505                                             HBA_PORTSPEED_2GBIT;
2506                                         break;
2507                                 case LA_4GHZ_LINK:
2508                                         port_attrs->PortSpeed =
2509                                             HBA_PORTSPEED_4GBIT;
2510                                         break;
2511                                 case LA_8GHZ_LINK:
2512                                         port_attrs->PortSpeed =
2513                                             HBA_PORTSPEED_8GBIT;
2514                                         break;
2515                                 case LA_10GHZ_LINK:
2516                                         port_attrs->PortSpeed =
2517                                             HBA_PORTSPEED_10GBIT;
2518                                         break;
2519                                 case LA_16GHZ_LINK:
2520                                         port_attrs->PortSpeed =
2521                                             HBA_PORTSPEED_16GBIT;
2522                                         break;
2523                                 }
2524                         }
2525                         /* public loop */
2526                         else if (hba->topology == TOPOLOGY_LOOP) {
2527                                 /* Check for common area and domain */
2528                                 if ((ndlp->nlp_DID & 0xFFFF00) ==
2529                                     (port->did & 0xFFFF00)) {
2530                                         port_attrs->PortType =
2531                                             FC_HBA_PORTTYPE_NLPORT;
2532 
2533                                         /* We share a common speed */
2534                                         switch (hba->linkspeed) {
2535                                         case 0:
2536                                                 port_attrs->PortSpeed =
2537                                                     HBA_PORTSPEED_1GBIT;
2538                                                 break;
2539                                         case LA_1GHZ_LINK:
2540                                                 port_attrs->PortSpeed =
2541                                                     HBA_PORTSPEED_1GBIT;
2542                                                 break;
2543                                         case LA_2GHZ_LINK:
2544                                                 port_attrs->PortSpeed =
2545                                                     HBA_PORTSPEED_2GBIT;
2546                                                 break;
2547                                         case LA_4GHZ_LINK:
2548                                                 port_attrs->PortSpeed =
2549                                                     HBA_PORTSPEED_4GBIT;
2550                                                 break;
2551                                         case LA_8GHZ_LINK:
2552                                                 port_attrs->PortSpeed =
2553                                                     HBA_PORTSPEED_8GBIT;
2554                                                 break;
2555                                         case LA_10GHZ_LINK:
2556                                                 port_attrs->PortSpeed =
2557                                                     HBA_PORTSPEED_10GBIT;
2558                                                 break;
2559                                         case LA_16GHZ_LINK:
2560                                                 port_attrs->PortSpeed =
2561                                                     HBA_PORTSPEED_16GBIT;
2562                                                 break;
2563                                         }
2564                                 }
2565                         }
2566                 }
2567 
2568                 port_attrs->PortSupportedClassofService =
2569                     LE_SWAP32(FC_NS_CLASS3);
2570                 /* port_attrs->PortSymbolicName              */
2571                 /* port_attrs->PortSupportedSpeed    */
2572                 /* port_attrs->PortSupportedFc4Types */
2573                 /* port_attrs->PortActiveFc4Types    */
2574                 /* port_attrs->PortMaxFrameSize              */
2575                 /* port_attrs->NumberofDiscoveredPorts       */
2576 
2577         } else {
2578                 fc_hba_port_attributes_t  *port_attrs;
2579 
2580                 if ((fcio->fcio_xfer != FCIO_XFER_READ) ||
2581                     (fcio->fcio_ilen < 8) ||
2582                     (fcio->fcio_olen < sizeof (fc_hba_port_attributes_t))) {
2583                         rval = EINVAL;
2584                         goto done;
2585                 }
2586 
2587                 wwpn  = (uint8_t *)fcio->fcio_ibuf;
2588                 ndlp  = emlxs_node_find_wwpn(port, wwpn, 1);
2589 
2590                 if (!ndlp) {
2591                         fcio->fcio_errno = FC_NOMAP;
2592                         rval = EINVAL;
2593                         goto done;
2594                 }
2595 
2596                 /* Filter fabric ports */
2597                 if ((ndlp->nlp_DID & 0xFFF000) == 0xFFF000) {
2598                         fcio->fcio_errno = FC_NOMAP;
2599                         rval = EINVAL;
2600                         goto done;
2601                 }
2602 
2603                 port_attrs = (fc_hba_port_attributes_t *)fcio->fcio_obuf;
2604 
2605                 port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2606                 /* port_attrs->lastChange */
2607                 /* port_attrs->fp_minor   */
2608                 bcopy((caddr_t)&ndlp->nlp_nodename,
2609                     (caddr_t)&port_attrs->NodeWWN, 8);
2610                 bcopy((caddr_t)&ndlp->nlp_portname,
2611                     (caddr_t)&port_attrs->PortWWN, 8);
2612 
2613                 port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2614                 port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2615                 port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2616 
2617                 if ((port->mode == MODE_TARGET) &&
2618                     (hba->state >= FC_LINK_UP)) {
2619                         port_attrs->PortFcId  = ndlp->nlp_DID;
2620                         port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2621 
2622                         /* no switch */
2623                         if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2624                                 if (hba->topology == TOPOLOGY_LOOP) {
2625                                         port_attrs->PortType =
2626                                             FC_HBA_PORTTYPE_LPORT;
2627                                 } else {
2628                                         port_attrs->PortType =
2629                                             FC_HBA_PORTTYPE_PTP;
2630                                 }
2631 
2632                                 /* We share a common speed */
2633                                 switch (hba->linkspeed) {
2634                                 case 0:
2635                                         port_attrs->PortSpeed =
2636                                             HBA_PORTSPEED_1GBIT;
2637                                         break;
2638                                 case LA_1GHZ_LINK:
2639                                         port_attrs->PortSpeed =
2640                                             HBA_PORTSPEED_1GBIT;
2641                                         break;
2642                                 case LA_2GHZ_LINK:
2643                                         port_attrs->PortSpeed =
2644                                             HBA_PORTSPEED_2GBIT;
2645                                         break;
2646                                 case LA_4GHZ_LINK:
2647                                         port_attrs->PortSpeed =
2648                                             HBA_PORTSPEED_4GBIT;
2649                                         break;
2650                                 case LA_8GHZ_LINK:
2651                                         port_attrs->PortSpeed =
2652                                             HBA_PORTSPEED_8GBIT;
2653                                         break;
2654                                 case LA_10GHZ_LINK:
2655                                         port_attrs->PortSpeed =
2656                                             HBA_PORTSPEED_10GBIT;
2657                                         break;
2658                                 case LA_16GHZ_LINK:
2659                                         port_attrs->PortSpeed =
2660                                             HBA_PORTSPEED_16GBIT;
2661                                         break;
2662                                 }
2663                         }
2664                         /* public loop */
2665                         else if (hba->topology == TOPOLOGY_LOOP) {
2666                                 /* Check for common area and domain */
2667                                 if ((ndlp->nlp_DID & 0xFFFF00) ==
2668                                     (port->did & 0xFFFF00)) {
2669                                         port_attrs->PortType =
2670                                             FC_HBA_PORTTYPE_NLPORT;
2671 
2672                                         /* We share a common speed */
2673                                         switch (hba->linkspeed) {
2674                                         case 0:
2675                                                 port_attrs->PortSpeed =
2676                                                     HBA_PORTSPEED_1GBIT;
2677                                                 break;
2678                                         case LA_1GHZ_LINK:
2679                                                 port_attrs->PortSpeed =
2680                                                     HBA_PORTSPEED_1GBIT;
2681                                                 break;
2682                                         case LA_2GHZ_LINK:
2683                                                 port_attrs->PortSpeed =
2684                                                     HBA_PORTSPEED_2GBIT;
2685                                                 break;
2686                                         case LA_4GHZ_LINK:
2687                                                 port_attrs->PortSpeed =
2688                                                     HBA_PORTSPEED_4GBIT;
2689                                                 break;
2690                                         case LA_8GHZ_LINK:
2691                                                 port_attrs->PortSpeed =
2692                                                     HBA_PORTSPEED_8GBIT;
2693                                                 break;
2694                                         case LA_10GHZ_LINK:
2695                                                 port_attrs->PortSpeed =
2696                                                     HBA_PORTSPEED_10GBIT;
2697                                                 break;
2698                                         case LA_16GHZ_LINK:
2699                                                 port_attrs->PortSpeed =
2700                                                     HBA_PORTSPEED_16GBIT;
2701                                                 break;
2702                                         }
2703                                 }
2704                         }
2705                 }
2706 
2707                 port_attrs->PortSupportedClassofService =
2708                     LE_SWAP32(FC_NS_CLASS3);
2709                 /* port_attrs->PortSymbolicName              */
2710                 /* port_attrs->PortSupportedSpeed    */
2711                 /* port_attrs->PortSupportedFc4Types */
2712                 /* port_attrs->PortActiveFc4Types    */
2713                 /* port_attrs->PortMaxFrameSize              */
2714                 /* port_attrs->NumberofDiscoveredPorts       */
2715         }
2716 
2717 done:
2718         return (rval);
2719 
2720 } /* emlxs_fcio_get_port_attrs() */
2721 
2722 
2723 /*ARGSUSED*/
2724 static int32_t
2725 emlxs_fcio_get_sym_pname(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2726 {
2727         int32_t         rval = 0;
2728 
2729         if (fcio->fcio_olen < (strlen(port->spn)+1) ||
2730             (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2731                 rval = EINVAL;
2732                 goto done;
2733         }
2734 
2735         (void) strlcpy((caddr_t)fcio->fcio_obuf, (caddr_t)port->spn,
2736             fcio->fcio_olen);
2737 
2738 done:
2739         return (rval);
2740 
2741 } /* emlxs_fcio_get_sym_pname() */
2742 
2743 
2744 /*ARGSUSED*/
2745 static int32_t
2746 emlxs_fcio_get_sym_nname(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2747 {
2748         int32_t         rval = 0;
2749 
2750         if (fcio->fcio_olen < (strlen(port->snn)+1) ||
2751             (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2752                 rval = EINVAL;
2753                 goto done;
2754         }
2755 
2756         (void) strlcpy((caddr_t)fcio->fcio_obuf, (caddr_t)port->snn,
2757             fcio->fcio_olen);
2758 
2759 done:
2760         return (rval);
2761 
2762 } /* emlxs_fcio_get_sym_nname() */
2763 
2764 
2765 /*ARGSUSED*/
2766 static int32_t
2767 emlxs_fcio_force_dump(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2768 {
2769         int32_t         rval = 0;
2770 
2771         if (port->mode != MODE_TARGET) {
2772                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
2773                     "fcio_force_dump failed. Port is not in target mode.");
2774 
2775                 fcio->fcio_errno = FC_FAILURE;
2776                 rval = EIO;
2777                 goto done;
2778         }
2779 
2780         rval = emlxs_reset(port, FC_FCA_CORE);
2781 
2782         if (rval != FC_SUCCESS) {
2783                 fcio->fcio_errno = rval;
2784                 rval = EIO;
2785                 goto done;
2786         }
2787 
2788 done:
2789         return (rval);
2790 
2791 } /* emlxs_fcio_force_dump() */
2792 
2793 
2794 /*ARGSUSED*/
2795 static int32_t
2796 emlxs_fcio_get_dump_size(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2797 {
2798         int32_t         rval = 0;
2799         fc_fca_pm_t pm;
2800 
2801         if (fcio->fcio_olen != sizeof (uint32_t) ||
2802             fcio->fcio_xfer != FCIO_XFER_READ) {
2803                 rval = EINVAL;
2804                 goto done;
2805         }
2806 
2807         bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2808 
2809         pm.pm_data_len  = fcio->fcio_olen;
2810         pm.pm_data_buf  = fcio->fcio_obuf;
2811         pm.pm_cmd_code  = FC_PORT_GET_DUMP_SIZE;
2812         pm.pm_cmd_flags = FC_FCA_PM_READ;
2813 
2814         rval = emlxs_fca_port_manage(port, &pm);
2815 
2816         if (rval != FC_SUCCESS) {
2817                 fcio->fcio_errno = rval;
2818 
2819                 if (rval == FC_INVALID_REQUEST) {
2820                         rval = ENOTTY;
2821                 } else {
2822                         rval = EIO;
2823                 }
2824         }
2825 
2826 done:
2827         return (rval);
2828 
2829 } /* emlxs_fcio_get_dump_size() */
2830 
2831 
2832 /*ARGSUSED*/
2833 static int32_t
2834 emlxs_fcio_get_dump(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2835 {
2836         int32_t         rval = 0;
2837         fc_fca_pm_t     pm;
2838         uint32_t        dump_size;
2839 
2840         if (fcio->fcio_xfer != FCIO_XFER_READ) {
2841                 rval = EINVAL;
2842                 goto done;
2843         }
2844 
2845         bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2846 
2847         pm.pm_data_len  = sizeof (uint32_t);
2848         pm.pm_data_buf  = (caddr_t)&dump_size;
2849         pm.pm_cmd_code  = FC_PORT_GET_DUMP_SIZE;
2850         pm.pm_cmd_flags = FC_FCA_PM_READ;
2851 
2852         rval = emlxs_fca_port_manage(port, &pm);
2853 
2854         if (rval != FC_SUCCESS) {
2855                 fcio->fcio_errno = rval;
2856 
2857                 if (rval == FC_INVALID_REQUEST) {
2858                         rval = ENOTTY;
2859                 } else {
2860                         rval = EIO;
2861                 }
2862                 goto done;
2863         }
2864 
2865         if (fcio->fcio_olen != dump_size) {
2866                 fcio->fcio_errno = FC_NOMEM;
2867                 rval = EINVAL;
2868                 goto done;
2869         }
2870 
2871         bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2872 
2873         pm.pm_data_len  = fcio->fcio_olen;
2874         pm.pm_data_buf  = fcio->fcio_obuf;
2875         pm.pm_cmd_code  = FC_PORT_GET_DUMP;
2876         pm.pm_cmd_flags = FC_FCA_PM_READ;
2877 
2878         rval = emlxs_fca_port_manage(port, &pm);
2879 
2880         if (rval != FC_SUCCESS) {
2881                 fcio->fcio_errno = rval;
2882 
2883                 if (rval == FC_INVALID_REQUEST) {
2884                         rval = ENOTTY;
2885                 } else {
2886                         rval = EIO;
2887                 }
2888         }
2889 
2890 done:
2891         return (rval);
2892 
2893 } /* emlxs_fcio_get_dump() */
2894 
2895 
2896 /*ARGSUSED*/
2897 static int32_t
2898 emlxs_fcio_unsupported(emlxs_port_t *port, fcio_t *fcio, int32_t mode)
2899 {
2900         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2901             "%s: Command not supported.",
2902             emlxs_fcio_xlate(fcio->fcio_cmd));
2903 
2904         return (ENOTSUP);
2905 
2906 } /* emlxs_fcio_unsupported() */
2907 #endif /* FCIO_SUPPORT */
2908 
2909 
2910 /*ARGSUSED*/
2911 static int32_t
2912 emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2913 {
2914         emlxs_port_t    *port = &PPORT;
2915         emlxs_config_t  *cfg = &CFG;
2916         emlxs_port_t    *vport;
2917         emlxs_port_t    *tport;
2918         dfc_vportinfo_t *dfc_vport;
2919         uint32_t        vpi;
2920         uint32_t        options;
2921         char            name[256];
2922         uint8_t         wwn[8];
2923 
2924         options = dfc->data1;
2925 
2926         if (!dfc->buf1 || !dfc->buf1_size) {
2927                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2928                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
2929 
2930                 return (DFC_ARG_NULL);
2931         }
2932 
2933         if (dfc->buf1_size < sizeof (dfc_vportinfo_t)) {
2934                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2935                     "%s: Buffer1 too small. (size=%d)",
2936                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2937 
2938                 return (DFC_ARG_TOOSMALL);
2939         }
2940 
2941         dfc_vport = (dfc_vportinfo_t *)dfc->buf1;
2942 
2943         if (!(options & VPORT_OPT_AUTORETRY)) {
2944                 if (!(hba->flag & FC_NPIV_ENABLED)) {
2945                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2946                             "%s: NPIV currently not enabled.",
2947                             emlxs_dfc_xlate(dfc->cmd));
2948 
2949                         return (DFC_NPIV_DISABLED);
2950                 }
2951 
2952                 if (!(hba->flag & FC_NPIV_SUPPORTED)) {
2953                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2954                             "%s: NPIV currently not supported.",
2955                             emlxs_dfc_xlate(dfc->cmd));
2956 
2957                         return (DFC_NPIV_UNSUPPORTED);
2958                 }
2959         }
2960 
2961         /*
2962          * Only the same WWNN and WWPN can be re-created
2963          */
2964         bzero(wwn, 8);
2965         if (bcmp(wwn, dfc_vport->wwpn, 8) || bcmp(wwn, dfc_vport->wwnn, 8)) {
2966                 for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
2967                         vport = &VPORT(vpi);
2968 
2969                         if ((bcmp((caddr_t)&vport->wwnn,
2970                             (caddr_t)dfc_vport->wwnn, 8) == 0) &&
2971                             (bcmp((caddr_t)&vport->wwpn,
2972                             (caddr_t)dfc_vport->wwpn, 8) == 0)) {
2973                                 if (!(vport->flag & EMLXS_PORT_CONFIG) &&
2974                                     (vport->flag & EMLXS_PORT_BOUND)) {
2975                                         dfc_vport->vpi = vpi;
2976                                         break;
2977                                 } else {
2978                                         EMLXS_MSGF(EMLXS_CONTEXT,
2979                                             &emlxs_dfc_error_msg,
2980                                             "%s: VPI already in use.",
2981                                             emlxs_dfc_xlate(dfc->cmd));
2982 
2983                                         return (DFC_ARG_INVALID);
2984                                 }
2985                         }
2986                 }
2987         }
2988 
2989         /* else auto assign */
2990         /* Acquire a VPI */
2991         if (dfc_vport->vpi == 0) {
2992                 /* Auto Assign VPI */
2993                 for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
2994                         vport = &VPORT(vpi);
2995 
2996                         if (!(vport->flag & EMLXS_PORT_CONFIG)) {
2997                                 break;
2998                         }
2999                 }
3000 
3001                 if (vpi > hba->vpi_max) {
3002                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3003                             "%s: Out of resources.",
3004                             emlxs_dfc_xlate(dfc->cmd));
3005 
3006                         return (DFC_DRVRES_ERROR);
3007                 }
3008 
3009                 dfc_vport->vpi = vpi;
3010         }
3011 
3012         /* Establish a WWPN */
3013         bzero(wwn, 8);
3014         if (!(bcmp(wwn, dfc_vport->wwpn, 8))) {
3015                 /* Generate new WWPN */
3016                 bcopy((caddr_t)&hba->wwpn, (caddr_t)dfc_vport->wwpn, 8);
3017                 dfc_vport->wwpn[0] = 0x20;
3018                 dfc_vport->wwpn[1] = (uint8_t)vpi;
3019         } else {        /* use one provided */
3020 
3021                 /* Make sure WWPN is unique */
3022                 if (tport = emlxs_vport_find_wwpn(hba, dfc_vport->wwpn)) {
3023                         if ((tport->flag & EMLXS_PORT_CONFIG) &&
3024                             (tport->flag & EMLXS_PORT_BOUND)) {
3025                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3026                                     "%s: WWPN already exists. vpi=%d",
3027                                     emlxs_dfc_xlate(dfc->cmd), vpi);
3028                                 return (DFC_ARG_INVALID);
3029                         }
3030                 }
3031         }
3032 
3033         /* Establish a WWNN */
3034         bzero(wwn, 8);
3035         if (!(bcmp(wwn, dfc_vport->wwnn, 8))) {
3036                 /* Generate new WWNN */
3037                 bcopy((caddr_t)&hba->wwnn, (caddr_t)dfc_vport->wwnn, 8);
3038                 dfc_vport->wwnn[0] = 0x28;
3039                 dfc_vport->wwnn[1] = (uint8_t)vpi;
3040         }
3041         /* else use WWNN provided */
3042 
3043         /* Generate the symbolic node name */
3044         if (dfc_vport->snn[0]) {
3045                 (void) strncpy(name, dfc_vport->snn,
3046                     (sizeof (name)-1));
3047                 (void) snprintf(dfc_vport->snn, (sizeof (dfc_vport->snn)-1),
3048                     "%s %s", hba->snn, name);
3049         } else {
3050                 (void) strncpy(dfc_vport->snn, hba->snn,
3051                     (sizeof (dfc_vport->snn)-1));
3052         }
3053 
3054         /* Generate the symbolic port name */
3055         if (dfc_vport->spn[0]) {
3056                 (void) strncpy(name, dfc_vport->spn,
3057                     (sizeof (name)-1));
3058                 (void) snprintf(dfc_vport->spn, (sizeof (dfc_vport->spn)-1),
3059                     "%s VPort-%d VName-%s", hba->spn,
3060                     vpi, name);
3061         } else {
3062                 (void) snprintf(dfc_vport->spn, (sizeof (dfc_vport->spn)-1),
3063                     "%s VPort-%d", hba->spn, vpi);
3064         }
3065 
3066         dfc_vport->port_id = 0;
3067         dfc_vport->ulp_statec = FC_STATE_OFFLINE;
3068         dfc_vport->flags = VPORT_CONFIG;
3069 
3070         /* Set the highest configured vpi */
3071         if (dfc_vport->vpi >= hba->vpi_high) {
3072                 hba->vpi_high = dfc_vport->vpi;
3073         }
3074 
3075         /* Configure the port object */
3076         bcopy((caddr_t)dfc_vport->wwnn, (caddr_t)&vport->wwnn, 8);
3077         bcopy((caddr_t)dfc_vport->wwpn, (caddr_t)&vport->wwpn, 8);
3078         (void) strncpy((caddr_t)vport->snn, (caddr_t)dfc_vport->snn,
3079             (sizeof (vport->snn)-1));
3080         (void) strncpy((caddr_t)vport->spn, (caddr_t)dfc_vport->spn,
3081             (sizeof (vport->spn)-1));
3082         vport->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED);
3083 
3084         /* Adjust restricted flags */
3085         vport->options &= ~EMLXS_OPT_RESTRICT_MASK;
3086         vport->flag &= ~EMLXS_PORT_RESTRICTED;
3087         if (options & VPORT_OPT_RESTRICT) {
3088                 vport->options |= EMLXS_OPT_RESTRICT;
3089                 vport->flag |= EMLXS_PORT_RESTRICTED;
3090                 dfc_vport->flags |= VPORT_RESTRICTED;
3091         } else if (options & VPORT_OPT_UNRESTRICT) {
3092                 vport->options |= EMLXS_OPT_UNRESTRICT;
3093         } else if (cfg[CFG_VPORT_RESTRICTED].current) {
3094                 vport->flag |= EMLXS_PORT_RESTRICTED;
3095                 dfc_vport->flags |= VPORT_RESTRICTED;
3096         }
3097 
3098         if (vport->flag & EMLXS_PORT_BOUND) {
3099                 /*
3100                  * The same WWNN, WWPN and VPI has been re-created.
3101                  * Bring up the vport now!
3102                  */
3103                 emlxs_port_online(vport);
3104         }
3105 
3106         return (0);
3107 
3108 } /* emlxs_dfc_create_vport() */
3109 
3110 
3111 /*ARGSUSED*/
3112 static int32_t
3113 emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3114 {
3115         emlxs_port_t    *port = &PPORT;
3116         emlxs_port_t    *vport;
3117         uint8_t         wwpn[8];
3118         fc_packet_t     *pkt = NULL;
3119         uint32_t        rval = 0;
3120         ELS_PKT         *els;
3121         char            buffer[256];
3122 
3123         if (!dfc->buf1 || !dfc->buf1_size) {
3124                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3125                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3126 
3127                 rval = DFC_ARG_NULL;
3128                 goto done;
3129         }
3130 
3131         if (dfc->buf1_size < 8) {
3132                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3133                     "%s: Buffer1 too small. (size=%d)",
3134                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3135 
3136                 rval = DFC_ARG_TOOSMALL;
3137                 goto done;
3138         }
3139 
3140         /* Read the wwn object */
3141         bcopy((void *)dfc->buf1, (void *)wwpn, 8);
3142 
3143         /* Make sure WWPN is unique */
3144         vport = emlxs_vport_find_wwpn(hba, wwpn);
3145 
3146         /* Physical does not have EMLXS_PORT_CONFIG set */
3147         if (!vport || !(vport->flag & EMLXS_PORT_CONFIG)) {
3148                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3149                     "%s: WWPN does not exists. %s", emlxs_dfc_xlate(dfc->cmd),
3150                     emlxs_wwn_xlate(buffer, sizeof (buffer), wwpn));
3151 
3152                 rval = DFC_ARG_INVALID;
3153                 goto done;
3154         }
3155 
3156         if (vport->did) {
3157                 /* Fabric Logout */
3158                 if (!(pkt = emlxs_pkt_alloc(vport,
3159                     sizeof (uint32_t) + sizeof (LOGO),
3160                     sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
3161                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3162                             "%s: Unable to allocate packet.",
3163                             emlxs_dfc_xlate(dfc->cmd));
3164 
3165                         rval = DFC_SYSRES_ERROR;
3166                         goto done;
3167                 }
3168 
3169                 /* Make this a polled IO */
3170                 pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
3171                 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
3172                 pkt->pkt_comp = NULL;
3173 
3174                 pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3175                 pkt->pkt_timeout = 60;
3176 
3177                 /* Build the fc header */
3178                 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3179                 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
3180                 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(vport->did);
3181                 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3182                 pkt->pkt_cmd_fhdr.f_ctl =
3183                     F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3184                 pkt->pkt_cmd_fhdr.seq_id = 0;
3185                 pkt->pkt_cmd_fhdr.df_ctl = 0;
3186                 pkt->pkt_cmd_fhdr.seq_cnt = 0;
3187                 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
3188                 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
3189                 pkt->pkt_cmd_fhdr.ro = 0;
3190 
3191                 /* Build the command */
3192                 els = (ELS_PKT *) pkt->pkt_cmd;
3193                 els->elsCode = 0x05; /* LOGO */
3194                 els->un.logo.un.nPortId32 = LE_SWAP32(vport->did);
3195                 bcopy(&vport->wwpn, &els->un.logo.portName, 8);
3196 
3197                 /*
3198                  * Just send LOGO. Don't worry about result.
3199                  * This is just a courtesy anyway.
3200                  */
3201                 (void) emlxs_pkt_send(pkt, 1);
3202 
3203 
3204                 /* Take the port offline */
3205                 (void) emlxs_port_offline(vport, 0xffffffff);
3206         }
3207 
3208         vport->flag &= ~(EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLED);
3209 
3210         rval = 0;
3211 
3212 done:
3213 
3214         if (pkt) {
3215                 emlxs_pkt_free(pkt);
3216         }
3217 
3218         return (rval);
3219 
3220 } /* emlxs_dfc_destroy_vport() */
3221 
3222 
3223 /*ARGSUSED*/
3224 static int32_t
3225 emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3226 {
3227         emlxs_port_t    *port = &PPORT;
3228         emlxs_port_t    *vport;
3229         dfc_vportinfo_t *dfc_vport;
3230         dfc_vportinfo_t *dfc_vport_list = NULL;
3231         uint32_t        i;
3232         uint32_t        size;
3233         uint32_t        max_count;
3234         uint32_t        rval = DFC_SUCCESS;
3235 
3236         if (!dfc->buf1 || !dfc->buf1_size) {
3237                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3238                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3239 
3240                 return (DFC_ARG_NULL);
3241         }
3242 
3243         size = (sizeof (dfc_vportinfo_t) * MAX_VPORTS);
3244 
3245         if (!(dfc_vport_list =
3246             (dfc_vportinfo_t *)kmem_zalloc(size, KM_NOSLEEP))) {
3247                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3248                     "%s: Unable to allocate memory.",
3249                     emlxs_dfc_xlate(dfc->cmd));
3250 
3251                 return (DFC_SYSRES_ERROR);
3252         }
3253 
3254         max_count = 0;
3255         for (i = 0; i <= hba->vpi_max; i++) {
3256                 vport = &VPORT(i);
3257                 dfc_vport = &dfc_vport_list[i];
3258 
3259                 if (!(vport->flag & EMLXS_PORT_CONFIG)) {
3260                         continue;
3261                 }
3262 
3263                 bcopy(vport->snn, dfc_vport->snn, 256);
3264                 bcopy(vport->spn, dfc_vport->spn, 256);
3265                 bcopy(&vport->wwpn, dfc_vport->wwpn, 8);
3266                 bcopy(&vport->wwnn, dfc_vport->wwnn, 8);
3267                 dfc_vport->port_id = vport->did;
3268                 dfc_vport->vpi = vport->vpi;
3269                 dfc_vport->ulp_statec = vport->ulp_statec;
3270                 dfc_vport->flags = VPORT_CONFIG;
3271 
3272                 if (vport->flag & EMLXS_PORT_ENABLED) {
3273                         dfc_vport->flags |= VPORT_ENABLED;
3274                 }
3275 
3276                 if (vport->flag & EMLXS_PORT_BOUND) {
3277                         dfc_vport->flags |= VPORT_BOUND;
3278                 }
3279 
3280                 if (vport->flag & EMLXS_PORT_IP_UP) {
3281                         dfc_vport->flags |= VPORT_IP;
3282                 }
3283 
3284                 if (vport->flag & EMLXS_PORT_RESTRICTED) {
3285                         dfc_vport->flags |= VPORT_RESTRICTED;
3286                 }
3287 
3288                 max_count++;
3289         }
3290 
3291         max_count *= sizeof (dfc_vportinfo_t);
3292 
3293         if (max_count > dfc->buf1_size) {
3294                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3295                     "%s: Buffer1 too small. (%d > %d)",
3296                     emlxs_dfc_xlate(dfc->cmd), max_count, dfc->buf1_size);
3297 
3298                 rval = DFC_ARG_TOOSMALL;
3299                 goto done;
3300         }
3301 
3302         bcopy((void *)dfc_vport_list, (void *)dfc->buf1, dfc->buf1_size);
3303 
3304 done:
3305 
3306         if (dfc_vport_list) {
3307                 kmem_free(dfc_vport_list, size);
3308         }
3309 
3310         return (rval);
3311 
3312 } /* emlxs_dfc_get_vportinfo() */
3313 
3314 
3315 static emlxs_port_t *
3316 emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn)
3317 {
3318         emlxs_port_t    *port;
3319         NODELIST        *nlp;
3320         int             i, j;
3321 
3322         for (i = 0; i <= hba->vpi_max; i++) {
3323                 port = &VPORT(i);
3324 
3325                 /* Check Local N-port, including physical port */
3326                 if (bcmp(&port->wwpn, wwpn, 8) == 0) {
3327                         return (port);
3328                 }
3329 
3330                 /* Check Remote N-port */
3331                 rw_enter(&port->node_rwlock, RW_READER);
3332                 for (j = 0; j < EMLXS_NUM_HASH_QUES; j++) {
3333                         nlp = port->node_table[j];
3334                         while (nlp != NULL) {
3335                                 /* Check Local N-port */
3336                                 if (bcmp(&nlp->nlp_portname, wwpn, 8) == 0) {
3337                                         rw_exit(&port->node_rwlock);
3338                                         return (port);
3339                                 }
3340                                 nlp = nlp->nlp_list_next;
3341                         }
3342                 }
3343 
3344                 rw_exit(&port->node_rwlock);
3345         }
3346 
3347         return (0);
3348 
3349 } /* emlxs_vport_find_wwpn() */
3350 
3351 
3352 /*ARGSUSED*/
3353 static int32_t
3354 emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3355 {
3356         emlxs_port_t            *port = &PPORT;
3357         dfc_vport_resource_t    *vres;
3358         MAILBOXQ                *mbq = NULL;
3359         MAILBOX                 *mb;
3360         uint32_t                rval = DFC_SUCCESS;
3361 
3362         if (!dfc->buf1 || !dfc->buf1_size) {
3363                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3364                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3365 
3366                 return (DFC_ARG_NULL);
3367         }
3368 
3369         if (dfc->buf1_size < sizeof (dfc_vport_resource_t)) {
3370                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3371                     "%s: Buffer1 too small. (size=%d)",
3372                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3373 
3374                 return (DFC_ARG_TOOSMALL);
3375         }
3376 
3377         vres = (dfc_vport_resource_t *)dfc->buf1;
3378         bzero(vres, sizeof (dfc_vport_resource_t));
3379 
3380         if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3381                 int i;
3382                 int total_rpi;
3383                 emlxs_port_t *vport;
3384 
3385                 vres->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
3386 
3387                 total_rpi = 0;
3388                 for (i = 0; i < vres->vpi_max; i++) {
3389                         vport = &VPORT(i);
3390                         total_rpi += vport->vpip->rpi_online;
3391                 }
3392 
3393                 vres->vpi_inuse = (port->vpip->vfip == NULL) ? 0 :
3394                     (port->vpip->vfip->vpi_online - 1);
3395                 vres->rpi_max = hba->sli.sli4.RPICount;
3396                 vres->rpi_inuse = total_rpi;
3397 
3398                 return (rval);
3399         }
3400 
3401         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
3402         mb = (MAILBOX *) mbq;
3403 
3404         emlxs_mb_read_config(hba, mbq);
3405 
3406         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
3407 
3408         if (rval == MBX_TIMEOUT) {
3409                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3410                     "%s: Mailbox timed out. cmd=%x",
3411                     emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3412 
3413                 rval = DFC_TIMEOUT;
3414                 goto done;
3415         }
3416 
3417         if (rval) {
3418                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3419                     "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
3420                     emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
3421 
3422                 rval = DFC_IO_ERROR;
3423                 goto done;
3424         }
3425 
3426         vres->vpi_max = mb->un.varRdConfig.max_vpi;
3427         vres->vpi_inuse =
3428             (mb->un.varRdConfig.max_vpi <=
3429             mb->un.varRdConfig.avail_vpi) ? 0 : mb->un.varRdConfig.max_vpi -
3430             mb->un.varRdConfig.avail_vpi;
3431 
3432         vres->rpi_max = mb->un.varRdConfig.max_rpi;
3433         vres->rpi_inuse =
3434             (mb->un.varRdConfig.max_rpi <=
3435             mb->un.varRdConfig.avail_rpi) ? 0 : mb->un.varRdConfig.max_rpi -
3436             mb->un.varRdConfig.avail_rpi;
3437 
3438 done:
3439 
3440         /* Free allocated mbox memory */
3441         if (mbq) {
3442                 kmem_free(mbq, sizeof (MAILBOXQ));
3443         }
3444 
3445         return (rval);
3446 
3447 } /* emlxs_dfc_npiv_resource() */
3448 
3449 
3450 /*ARGSUSED*/
3451 static int32_t
3452 emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3453 {
3454         emlxs_port_t    *port = &PPORT;
3455         emlxs_port_t    *vport = &VPORT(hba->vpi_max);
3456         emlxs_config_t  *cfg = &CFG;
3457         fc_packet_t     *pkt = NULL;
3458         fc_packet_t     *pkt1 = NULL;
3459         ELS_PKT         *els;
3460         LS_RJT          *lsrjt;
3461         uint32_t        checklist = 0;
3462         uint32_t        mask = 0;
3463         uint32_t        rval = DFC_SUCCESS;
3464         uint8_t         wwn[8];
3465         emlxs_vpd_t     *vpd = &VPD;
3466         int             i;
3467 
3468         if (!dfc->buf1 || !dfc->buf1_size) {
3469                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3470                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3471 
3472                 return (DFC_ARG_NULL);
3473         }
3474 
3475         if (dfc->buf1_size < sizeof (uint32_t)) {
3476                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3477                     "%s: Buffer1 too small. (size=%d)",
3478                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3479 
3480                 return (DFC_ARG_TOOSMALL);
3481         }
3482 
3483         if (cfg[CFG_NPIV_ENABLE].current) {
3484                 checklist |= CL_NPIV_PARM_ENABLE;
3485         }
3486 
3487         if (hba->sli_mode >= 3) {
3488                 checklist |= CL_SLI3_ENABLE;
3489         }
3490 
3491 
3492         if ((vpd->feaLevelHigh >= 0x09) || (hba->sli_mode >= 4)) {
3493                 checklist |= CL_HBA_SUPPORT_NPIV;
3494         }
3495 
3496 
3497         if (hba->num_of_ports <= hba->vpi_max) {
3498                 checklist |= CL_HBA_HAS_RESOURCES;
3499         }
3500 
3501         if (hba->state < FC_LINK_UP) {
3502                 goto done;
3503         }
3504 
3505         checklist |= CL_HBA_LINKUP;
3506 
3507         if (hba->topology == TOPOLOGY_LOOP) {
3508                 goto done;
3509         }
3510 
3511         if (!(hba->flag & FC_FABRIC_ATTACHED)) {
3512                 goto done;
3513         }
3514 
3515         checklist |= CL_P2P_TOPOLOGY;
3516 
3517         if (!(hba->flag & FC_NPIV_SUPPORTED)) {
3518                 goto done;
3519         }
3520 
3521         checklist |= CL_FABRIC_SUPPORTS_NPIV;
3522 
3523         mask =
3524             (CL_NPIV_PARM_ENABLE | CL_SLI3_ENABLE | CL_HBA_SUPPORT_NPIV |
3525             CL_HBA_HAS_RESOURCES);
3526 
3527         /*
3528          * Check if those four conditions are met
3529          */
3530         if ((checklist & mask) != mask) {
3531                 /*
3532                  * One or more conditions are not met
3533                  */
3534                 goto done;
3535         }
3536 
3537         /* Now check if fabric have resources */
3538         for (i = 1; i <= hba->vpi_max; i++) {
3539                 vport = &VPORT(i);
3540                 if (vport->did) {
3541                         checklist |= CL_FABRIC_HAS_RESOURCES;
3542                         goto done;
3543                 }
3544         }
3545 
3546         if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3547                 (void) emlxs_vpi_port_bind_notify(vport);
3548                 /* wait one second for INIT_VPI completion */
3549                 drv_usecwait(1000000);
3550         }
3551 
3552         vport->vpi = hba->vpi_max;
3553         vport->hba = hba;
3554 
3555         if (!(pkt = emlxs_pkt_alloc(vport,
3556             sizeof (uint32_t) + sizeof (SERV_PARM), sizeof (FCP_RSP),
3557             0, KM_NOSLEEP))) {
3558                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3559                     "Unable to allocate packet.");
3560                 goto done;
3561         }
3562 
3563         /* Build (FDISC) the fc header */
3564         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3565         pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_UNSOL_CONTROL;
3566         pkt->pkt_cmd_fhdr.s_id = 0;
3567         pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3568         pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
3569         pkt->pkt_cmd_fhdr.seq_id = 0;
3570         pkt->pkt_cmd_fhdr.df_ctl = 0;
3571         pkt->pkt_cmd_fhdr.seq_cnt = 0;
3572         pkt->pkt_cmd_fhdr.ox_id = 0xffff;
3573         pkt->pkt_cmd_fhdr.rx_id = 0xffff;
3574         pkt->pkt_cmd_fhdr.ro = 0;
3575 
3576         /* Build the command (FDISC) */
3577         els = (ELS_PKT *) pkt->pkt_cmd;
3578         els->elsCode = 0x04; /* FLOGI - This will be changed automatically */
3579                                 /* by the drive (See emlxs_send_els()) */
3580 
3581         /* Copy latest service parameters to payload */
3582         bcopy((void *)&port->sparam,
3583             (void *)&els->un.logi, sizeof (SERV_PARM));
3584 
3585         bcopy((caddr_t)&hba->wwnn, (caddr_t)wwn, 8);
3586         wwn[0] = 0x28;
3587         wwn[1] = hba->vpi_max;
3588         bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.nodeName, 8);
3589         bcopy((caddr_t)wwn, (caddr_t)&vport->wwnn, 8);
3590 
3591         bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
3592         wwn[0] = 0x20;
3593         wwn[1] = hba->vpi_max;
3594         bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.portName, 8);
3595         bcopy((caddr_t)wwn, (caddr_t)&vport->wwpn, 8);
3596 
3597         bcopy((void *)&els->un.logi, (void *)&vport->sparam,
3598             sizeof (SERV_PARM));
3599 
3600         /* Make this a polled IO */
3601         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
3602         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
3603         pkt->pkt_comp = NULL;
3604 
3605         pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3606         pkt->pkt_timeout = 60;
3607 
3608         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3609                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3610                     "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
3611 
3612                 goto done;
3613         }
3614 
3615         if (pkt->pkt_state == FC_PKT_SUCCESS) {
3616                 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3617                         (void) emlxs_vpi_port_unbind_notify(vport, 1);
3618                         checklist |= CL_FABRIC_HAS_RESOURCES;
3619                 } else {
3620                         if (!(pkt1 = emlxs_pkt_alloc(vport,
3621                             sizeof (uint32_t) + sizeof (LOGO), sizeof (FCP_RSP),
3622                             0, KM_NOSLEEP))) {
3623                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3624                                     "Unable to allocate LOGO packet.");
3625                                 goto free_resc;
3626                         }
3627 
3628                         /* Make this a polled IO */
3629                         pkt1->pkt_tran_flags &= ~FC_TRAN_INTR;
3630                         pkt1->pkt_tran_flags |= FC_TRAN_NO_INTR;
3631                         pkt1->pkt_comp = NULL;
3632 
3633                         pkt1->pkt_tran_type = FC_PKT_EXCHANGE;
3634                         pkt1->pkt_timeout = 60;
3635 
3636                         /* Build (LOGO) the fc header */
3637                         pkt1->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3638                         pkt1->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
3639                         pkt1->pkt_cmd_fhdr.s_id =
3640                             LE_SWAP24_LO(pkt->pkt_resp_fhdr.d_id);
3641                         pkt1->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3642                         pkt1->pkt_cmd_fhdr.f_ctl =
3643                             F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
3644                             F_CTL_SEQ_INITIATIVE;
3645                         pkt1->pkt_cmd_fhdr.seq_id = 0;
3646                         pkt1->pkt_cmd_fhdr.df_ctl = 0;
3647                         pkt1->pkt_cmd_fhdr.seq_cnt = 0;
3648                         pkt1->pkt_cmd_fhdr.ox_id = 0xFFFF;
3649                         pkt1->pkt_cmd_fhdr.rx_id = 0xFFFF;
3650                         pkt1->pkt_cmd_fhdr.ro = 0;
3651 
3652                         /* Build the command (LOGO) */
3653                         els = (ELS_PKT *) pkt1->pkt_cmd;
3654                         els->elsCode = 0x05; /* LOGO */
3655                         els->un.logo.un.nPortId32 =
3656                             LE_SWAP32(pkt->pkt_resp_fhdr.d_id);
3657                         bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
3658                         wwn[0] = 0x20;
3659                         wwn[1] = hba->vpi_max;
3660                         bcopy(wwn, &els->un.logo.portName, 8);
3661 
3662                         if (emlxs_pkt_send(pkt1, 1) != FC_SUCCESS) {
3663                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3664                                     "%s: Unable to send packet.",
3665                                     emlxs_dfc_xlate(dfc->cmd));
3666 
3667                                 goto free_resc;
3668                         }
3669 
3670                         if (pkt1->pkt_state != FC_PKT_SUCCESS) {
3671                                 if (pkt1->pkt_state == FC_PKT_TIMEOUT) {
3672                                         EMLXS_MSGF(EMLXS_CONTEXT,
3673                                             &emlxs_dfc_error_msg,
3674                                             "%s: Pkt Transport error. "
3675                                             "Pkt Timeout.",
3676                                             emlxs_dfc_xlate(dfc->cmd));
3677                                 } else {
3678                                         EMLXS_MSGF(EMLXS_CONTEXT,
3679                                             &emlxs_dfc_error_msg,
3680                                             "%s: Pkt Transport error. state=%x",
3681                                             emlxs_dfc_xlate(dfc->cmd),
3682                                             pkt1->pkt_state);
3683                                 }
3684                                 goto free_resc;
3685                         }
3686 
3687                         checklist |= CL_FABRIC_HAS_RESOURCES;
3688 free_resc:
3689                         /* Free default RPIs and VPI */
3690                         /* Unregister all nodes */
3691                         (void) EMLXS_SLI_UNREG_NODE(vport, 0, 0, 0, 0);
3692 
3693                         (void) emlxs_mb_unreg_vpi(vport);
3694                 }
3695         } else if (pkt->pkt_state == FC_PKT_LS_RJT) {
3696                 lsrjt = (LS_RJT *) pkt->pkt_resp;
3697                 if (lsrjt->un.b.lsRjtRsnCodeExp != LSEXP_OUT_OF_RESOURCE) {
3698                         checklist |= CL_FABRIC_HAS_RESOURCES;
3699                 }
3700         }
3701 
3702 done:
3703         bcopy((void *)&checklist, (void *)dfc->buf1, sizeof (uint32_t));
3704 
3705         if (pkt) {
3706                 /* Free the pkt */
3707                 emlxs_pkt_free(pkt);
3708         }
3709 
3710         if (pkt1) {
3711                 /* Free the pkt */
3712                 emlxs_pkt_free(pkt1);
3713         }
3714 
3715         return (rval);
3716 
3717 } /* emlxs_dfc_npiv_test() */
3718 
3719 
3720 /*ARGSUSED*/
3721 static int32_t
3722 emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3723 {
3724         emlxs_port_t    *port = &PPORT;
3725         uint32_t        rev;
3726 
3727         if (!dfc->buf1 || !dfc->buf1_size) {
3728                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3729                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3730 
3731                 return (DFC_ARG_NULL);
3732         }
3733 
3734         if (dfc->buf1_size < sizeof (uint32_t)) {
3735                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3736                     "%s: Buffer1 too small. (size=%d)",
3737                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3738 
3739                 return (DFC_ARG_TOOSMALL);
3740         }
3741 
3742         rev = DFC_REV;
3743         bcopy((void *)&rev, (void *)dfc->buf1, sizeof (uint32_t));
3744 
3745         return (0);
3746 
3747 } /* emlxs_dfc_get_rev() */
3748 
3749 
3750 /*ARGSUSED*/
3751 static int32_t
3752 emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3753 {
3754         emlxs_port_t    *port = &PPORT;
3755         emlxs_vpd_t     *vpd = &VPD;
3756         emlxs_config_t  *cfg = &CFG;
3757         dfc_hbainfo_t   *hbainfo;
3758         char            pathname[256];
3759 
3760         if (!dfc->buf1 || !dfc->buf1_size) {
3761                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3762                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3763 
3764                 return (DFC_ARG_NULL);
3765         }
3766 
3767         if (dfc->buf1_size < sizeof (dfc_hbainfo_t)) {
3768                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3769                     "%s: Buffer1 too small. (size=%d)",
3770                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3771 
3772                 return (DFC_ARG_TOOSMALL);
3773         }
3774 
3775         hbainfo = (dfc_hbainfo_t *)dfc->buf1;
3776         bzero((void *) hbainfo, sizeof (dfc_hbainfo_t));
3777 
3778         (void) strncpy(hbainfo->vpd_serial_num, vpd->serial_num,
3779             (sizeof (hbainfo->vpd_serial_num)-1));
3780         (void) strncpy(hbainfo->vpd_part_num, vpd->part_num,
3781             (sizeof (hbainfo->vpd_part_num)-1));
3782         (void) strncpy(hbainfo->vpd_port_num, vpd->port_num,
3783             (sizeof (hbainfo->vpd_port_num)-1));
3784         (void) strncpy(hbainfo->vpd_eng_change, vpd->eng_change,
3785             (sizeof (hbainfo->vpd_eng_change)-1));
3786         (void) strncpy(hbainfo->vpd_manufacturer, vpd->manufacturer,
3787             (sizeof (hbainfo->vpd_manufacturer)-1));
3788         (void) strncpy(hbainfo->vpd_model, vpd->model,
3789             (sizeof (hbainfo->vpd_model)-1));
3790         (void) strncpy(hbainfo->vpd_model_desc, vpd->model_desc,
3791             (sizeof (hbainfo->vpd_model_desc)-1));
3792         (void) strncpy(hbainfo->vpd_prog_types, vpd->prog_types,
3793             (sizeof (hbainfo->vpd_prog_types)-1));
3794         (void) strncpy(hbainfo->vpd_id, vpd->id,
3795             (sizeof (hbainfo->vpd_id)-1));
3796 
3797         hbainfo->device_id = hba->model_info.device_id;
3798         hbainfo->vendor_id =
3799             ddi_get32(hba->pci_acc_handle,
3800             (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)) & 0xffff;
3801 
3802         hbainfo->ports = hba->num_of_ports;
3803         hbainfo->port_index = vpd->port_index;
3804 
3805         bcopy(&hba->wwnn, hbainfo->wwnn, sizeof (hbainfo->wwnn));
3806         (void) strncpy(hbainfo->snn, port->snn, (sizeof (hbainfo->snn)-1));
3807 
3808         bcopy(&hba->wwpn, hbainfo->wwpn, sizeof (hbainfo->wwpn));
3809         (void) strncpy(hbainfo->spn, port->spn, (sizeof (hbainfo->spn)-1));
3810 
3811         hbainfo->biuRev = vpd->biuRev;
3812         hbainfo->smRev = vpd->smRev;
3813         hbainfo->smFwRev = vpd->smFwRev;
3814         hbainfo->endecRev = vpd->endecRev;
3815         hbainfo->rBit = vpd->rBit;
3816         hbainfo->fcphHigh = vpd->fcphHigh;
3817         hbainfo->fcphLow = vpd->fcphLow;
3818         hbainfo->feaLevelHigh = vpd->feaLevelHigh;
3819         hbainfo->feaLevelLow = vpd->feaLevelLow;
3820 
3821         hbainfo->kern_rev = vpd->postKernRev;
3822         (void) strncpy(hbainfo->kern_name, vpd->postKernName,
3823             (sizeof (hbainfo->kern_name)-1));
3824 
3825         hbainfo->stub_rev = vpd->opFwRev;
3826         (void) strncpy(hbainfo->stub_name, vpd->opFwName,
3827             (sizeof (hbainfo->stub_name)-1));
3828 
3829         hbainfo->sli1_rev = vpd->sli1FwRev;
3830         (void) strncpy(hbainfo->sli1_name, vpd->sli1FwName,
3831             (sizeof (hbainfo->sli1_name)-1));
3832 
3833         hbainfo->sli2_rev = vpd->sli2FwRev;
3834         (void) strncpy(hbainfo->sli2_name, vpd->sli2FwName,
3835             (sizeof (hbainfo->sli2_name)-1));
3836 
3837         hbainfo->sli3_rev = vpd->sli3FwRev;
3838         (void) strncpy(hbainfo->sli3_name, vpd->sli3FwName,
3839             (sizeof (hbainfo->sli3_name)-1));
3840 
3841         hbainfo->sli4_rev = vpd->sli4FwRev;
3842         (void) strncpy(hbainfo->sli4_name, vpd->sli4FwName,
3843             (sizeof (hbainfo->sli4_name)-1));
3844 
3845         hbainfo->sli_mode = hba->sli_mode;
3846         hbainfo->vpi_max  = hba->vpi_max;
3847         hbainfo->vpi_high = hba->vpi_high;
3848         hbainfo->flags = 0;
3849 
3850         /* Set support flags */
3851         hbainfo->flags  = HBA_FLAG_DYN_WWN;
3852         hbainfo->flags |= HBA_FLAG_NPIV;
3853 
3854 #ifdef DHCHAP_SUPPORT
3855         hbainfo->flags |= HBA_FLAG_DHCHAP;
3856 
3857         if (cfg[CFG_AUTH_E2E].current) {
3858                 hbainfo->flags |= HBA_FLAG_E2E_AUTH;
3859         }
3860 #endif  /* DHCHAP_SUPPORT */
3861 
3862 #ifdef SAN_DIAG_SUPPORT
3863         hbainfo->flags |= HBA_FLAG_SAN_DIAG;
3864 #endif  /* SAN_DIAG_SUPPORT */
3865 
3866 #ifdef SFCT_SUPPORT
3867         hbainfo->flags |= HBA_FLAG_TARGET_MODE;
3868         if (port->mode == MODE_TARGET) {
3869                 hbainfo->flags |= HBA_FLAG_TARGET_MODE_ENA;
3870         }
3871 #endif /* SFCT_SUPPORT */
3872 
3873         hbainfo->flags |= HBA_FLAG_PERSISTLINK;
3874 
3875         if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3876                 hbainfo->flags |= HBA_FLAG_EXT_MBOX;
3877                 if (SLI4_FCOE_MODE) {
3878                         hbainfo->flags |= HBA_FLAG_FCOE;
3879                         hbainfo->flags &= ~HBA_FLAG_PERSISTLINK;
3880                 }
3881         }
3882 
3883         (void) strncpy(hbainfo->fcode_version, vpd->fcode_version,
3884             (sizeof (hbainfo->fcode_version)-1));
3885         (void) strncpy(hbainfo->boot_version, vpd->boot_version,
3886             (sizeof (hbainfo->boot_version)-1));
3887         (void) strncpy(hbainfo->fw_version, vpd->fw_version,
3888             (sizeof (hbainfo->fw_version)-1));
3889         (void) strncpy(hbainfo->drv_label, emlxs_label,
3890             (sizeof (hbainfo->drv_label)-1));
3891         (void) strncpy(hbainfo->drv_module, emlxs_name,
3892             (sizeof (hbainfo->drv_module)-1));
3893         (void) strncpy(hbainfo->drv_name, DRIVER_NAME,
3894             (sizeof (hbainfo->drv_name)-1));
3895         (void) strncpy(hbainfo->drv_version, emlxs_version,
3896             (sizeof (hbainfo->drv_version)-1));
3897         (void) strncpy(hbainfo->drv_revision, emlxs_revision,
3898             (sizeof (hbainfo->drv_revision)-1));
3899         (void) strncpy(hbainfo->hostname, (char *)utsname.nodename,
3900             (sizeof (hbainfo->hostname)-1));
3901 
3902         (void) ddi_pathname(hba->dip, pathname);
3903         (void) snprintf(hbainfo->os_devname, (sizeof (hbainfo->os_devname)-1),
3904             "/devices%s", pathname);
3905 
3906         if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
3907                 hbainfo->flags |= HBA_FLAG_OFFLINE;
3908         }
3909 
3910         hbainfo->drv_instance = hba->ddiinst;
3911         hbainfo->port_id = port->did;
3912         hbainfo->port_type = HBA_PORTTYPE_UNKNOWN;
3913 
3914 #ifdef MENLO_SUPPORT
3915         if (hba->flag & FC_MENLO_MODE) {
3916                 hbainfo->topology  = LNK_MENLO_MAINTENANCE;
3917         } else
3918 #endif /* MENLO_SUPPORT */
3919 
3920         if (hba->state >= FC_LINK_UP) {
3921                 if (hba->topology == TOPOLOGY_LOOP) {
3922                         if (hba->flag & FC_FABRIC_ATTACHED) {
3923                                 hbainfo->port_type = HBA_PORTTYPE_NLPORT;
3924                                 hbainfo->topology = LNK_PUBLIC_LOOP;
3925                         } else {
3926                                 hbainfo->port_type = HBA_PORTTYPE_LPORT;
3927                                 hbainfo->topology = LNK_LOOP;
3928                         }
3929 
3930                         hbainfo->alpa_count = port->alpa_map[0];
3931                         bcopy((void *)&port->alpa_map[1], hbainfo->alpa_map,
3932                             hbainfo->alpa_count);
3933                 } else {
3934                         if (hba->flag & FC_PT_TO_PT) {
3935                                 hbainfo->port_type = HBA_PORTTYPE_PTP;
3936                                 hbainfo->topology = LNK_PT2PT;
3937                         } else {
3938                                 hbainfo->port_type = HBA_PORTTYPE_NPORT;
3939                                 hbainfo->topology = LNK_FABRIC;
3940                         }
3941                 }
3942 
3943                 if (hba->flag & FC_FABRIC_ATTACHED) {
3944                         bcopy(&port->fabric_sparam.nodeName,
3945                             hbainfo->fabric_wwnn,
3946                             sizeof (hbainfo->fabric_wwnn));
3947                         bcopy(&port->fabric_sparam.portName,
3948                             hbainfo->fabric_wwpn,
3949                             sizeof (hbainfo->fabric_wwpn));
3950                 }
3951 
3952                 if (hba->linkspeed == LA_2GHZ_LINK) {
3953                         hbainfo->port_speed = HBA_PORTSPEED_2GBIT;
3954                 } else if (hba->linkspeed == LA_4GHZ_LINK) {
3955                         hbainfo->port_speed = HBA_PORTSPEED_4GBIT;
3956                 } else if (hba->linkspeed == LA_8GHZ_LINK) {
3957                         hbainfo->port_speed = HBA_PORTSPEED_8GBIT;
3958                 } else if (hba->linkspeed == LA_10GHZ_LINK) {
3959                         hbainfo->port_speed = HBA_PORTSPEED_10GBIT;
3960                 } else if (hba->linkspeed == LA_16GHZ_LINK) {
3961                         hbainfo->port_speed = HBA_PORTSPEED_16GBIT;
3962                 } else {
3963                         hbainfo->port_speed = HBA_PORTSPEED_1GBIT;
3964                 }
3965 
3966                 hbainfo->node_count = port->node_count;
3967         }
3968 
3969         hbainfo->hard_alpa = cfg[CFG_ASSIGN_ALPA].current;
3970         hbainfo->supported_cos = LE_SWAP32((FC_NS_CLASS3 | FC_NS_CLASS2));
3971 
3972         hbainfo->supported_types[0] = LE_SWAP32(0x00000120);
3973         hbainfo->supported_types[1] = LE_SWAP32(0x00000001);
3974 
3975         hbainfo->active_types[0] = LE_SWAP32(0x00000120);
3976         hbainfo->active_types[1] = LE_SWAP32(0x00000001);
3977 
3978         if (!cfg[CFG_NETWORK_ON].current) {
3979                 hbainfo->active_types[0] &= ~(LE_SWAP32(0x00000020));
3980         }
3981 
3982         if (vpd->link_speed & LMT_16GB_CAPABLE) {
3983                 hbainfo->supported_speeds |= FC_HBA_PORTSPEED_16GBIT;
3984         }
3985         if (vpd->link_speed & LMT_10GB_CAPABLE) {
3986                 hbainfo->supported_speeds |= FC_HBA_PORTSPEED_10GBIT;
3987         }
3988         if (vpd->link_speed & LMT_8GB_CAPABLE) {
3989                 hbainfo->supported_speeds |= FC_HBA_PORTSPEED_8GBIT;
3990         }
3991         if (vpd->link_speed & LMT_4GB_CAPABLE) {
3992                 hbainfo->supported_speeds |= FC_HBA_PORTSPEED_4GBIT;
3993         }
3994         if (vpd->link_speed & LMT_2GB_CAPABLE) {
3995                 hbainfo->supported_speeds |= FC_HBA_PORTSPEED_2GBIT;
3996         }
3997         if (vpd->link_speed & LMT_1GB_CAPABLE) {
3998                 hbainfo->supported_speeds |= FC_HBA_PORTSPEED_1GBIT;
3999         }
4000 
4001         hbainfo->max_frame_size = FF_FRAME_SIZE;
4002 
4003         if (hba->bus_type == SBUS_FC) {
4004                 hbainfo->flags |= HBA_FLAG_SBUS;
4005         }
4006 
4007         if (hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE)) {
4008                 hbainfo->flags |= HBA_FLAG_OFFLINE;
4009                 hbainfo->port_state = HBA_PORTSTATE_UNKNOWN;
4010         } else if (hba->flag & FC_ONLINE_MODE) {
4011                 if (hba->flag & FC_LOOPBACK_MODE) {
4012                         hbainfo->port_state = HBA_PORTSTATE_LOOPBACK;
4013                 } else if (hba->state <= FC_LINK_DOWN) {
4014                         hbainfo->port_state = HBA_PORTSTATE_LINKDOWN;
4015                 }
4016 #ifdef MENLO_SUPPORT
4017                 else if (hba->flag & FC_MENLO_MODE) {
4018                         hbainfo->port_state = HBA_PORTSTATE_LINKDOWN;
4019                 }
4020 #endif /* MENLO_SUPPORT */
4021                 else {
4022                         hbainfo->port_state = HBA_PORTSTATE_ONLINE;
4023                 }
4024         } else {
4025                 hbainfo->flags |= HBA_FLAG_OFFLINE;
4026 
4027                 if (hba->state == FC_ERROR) {
4028                         hbainfo->port_state = HBA_PORTSTATE_ERROR;
4029                 } else {
4030                         hbainfo->port_state = HBA_PORTSTATE_OFFLINE;
4031                 }
4032         }
4033 
4034         hbainfo->pci_function_number = hba->pci_function_number;
4035         hbainfo->pci_device_number = hba->pci_device_number;
4036         hbainfo->pci_bus_number = hba->pci_bus_number;
4037 
4038 #ifdef FMA_SUPPORT
4039         /* Access handle validation */
4040         if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
4041             != DDI_FM_OK) {
4042                 EMLXS_MSGF(EMLXS_CONTEXT,
4043                     &emlxs_invalid_access_handle_msg, NULL);
4044                 return (DFC_DRV_ERROR);
4045         }
4046 #endif  /* FMA_SUPPORT */
4047 
4048         return (0);
4049 
4050 } /* emlxs_dfc_get_hbainfo() */
4051 
4052 
4053 
4054 /*ARGSUSED*/
4055 static int32_t
4056 emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4057 {
4058         emlxs_port_t    *port = &PPORT;
4059         dfc_hbastats_t  *stats;
4060         MAILBOX         *mb = NULL;
4061         MAILBOXQ        *mbq = NULL;
4062         uint32_t        rval = 0;
4063 
4064         if (!dfc->buf1 || !dfc->buf1_size) {
4065                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4066                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4067 
4068                 return (DFC_ARG_NULL);
4069         }
4070 
4071         if (dfc->buf1_size < sizeof (dfc_hbastats_t)) {
4072                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4073                     "%s: Buffer1 too small. (size=%d)",
4074                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4075 
4076                 return (DFC_ARG_TOOSMALL);
4077         }
4078 
4079         mbq =
4080             (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
4081 
4082         mb = (MAILBOX *)mbq;
4083 
4084         emlxs_mb_read_status(hba, mbq);
4085 
4086         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
4087 
4088         if (rval == MBX_TIMEOUT) {
4089                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4090                     "%s: Mailbox timed out. cmd=%x",
4091                     emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4092 
4093                 rval = DFC_TIMEOUT;
4094                 goto done;
4095         }
4096 
4097         if (rval) {
4098                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4099                     "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
4100                     emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
4101 
4102                 rval = DFC_IO_ERROR;
4103                 goto done;
4104         }
4105 
4106         stats = (dfc_hbastats_t *)dfc->buf1;
4107         bzero((void *)stats, sizeof (dfc_hbastats_t));
4108 
4109         stats->tx_frame_cnt = mb->un.varRdStatus.xmitFrameCnt;
4110         stats->rx_frame_cnt = mb->un.varRdStatus.rcvFrameCnt;
4111         stats->tx_kbyte_cnt = mb->un.varRdStatus.xmitByteCnt;
4112         stats->rx_kbyte_cnt = mb->un.varRdStatus.rcvByteCnt;
4113         stats->tx_seq_cnt = mb->un.varRdStatus.xmitSeqCnt;
4114         stats->rx_seq_cnt = mb->un.varRdStatus.rcvSeqCnt;
4115         stats->orig_exch_cnt = mb->un.varRdStatus.totalOrigExchanges;
4116         stats->resp_exch_cnt = mb->un.varRdStatus.totalRespExchanges;
4117         stats->pbsy_cnt = mb->un.varRdStatus.rcvPbsyCnt;
4118         stats->fbsy_cnt = mb->un.varRdStatus.rcvFbsyCnt;
4119 
4120         emlxs_mb_read_lnk_stat(hba, mbq);
4121 
4122         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
4123 
4124         if (rval == MBX_TIMEOUT) {
4125                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4126                     "%s: Mailbox timed out. cmd=%x",
4127                     emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4128 
4129                 rval = DFC_TIMEOUT;
4130                 goto done;
4131         }
4132 
4133         if (rval) {
4134                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4135                     "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
4136                     emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
4137 
4138                 rval = DFC_IO_ERROR;
4139                 goto done;
4140         }
4141 
4142         stats->link_failure_cnt = mb->un.varRdLnk.linkFailureCnt;
4143         stats->loss_sync_cnt = mb->un.varRdLnk.lossSyncCnt;
4144         stats->loss_signal_cnt = mb->un.varRdLnk.lossSignalCnt;
4145         stats->seq_error_cnt = mb->un.varRdLnk.primSeqErrCnt;
4146         stats->inval_tx_word_cnt = mb->un.varRdLnk.invalidXmitWord;
4147         stats->crc_error_cnt = mb->un.varRdLnk.crcCnt;
4148         stats->seq_timeout_cnt = mb->un.varRdLnk.primSeqTimeout;
4149         stats->elastic_overrun_cnt = mb->un.varRdLnk.elasticOverrun;
4150         stats->arb_timeout_cnt = mb->un.varRdLnk.arbTimeout;
4151         stats->rx_buf_credit = mb->un.varRdLnk.rxBufCredit;
4152         stats->rx_buf_cnt = mb->un.varRdLnk.rxBufCreditCur;
4153         stats->tx_buf_credit = mb->un.varRdLnk.txBufCredit;
4154         stats->tx_buf_cnt = mb->un.varRdLnk.txBufCreditCur;
4155         stats->EOFa_cnt = mb->un.varRdLnk.EOFaCnt;
4156         stats->EOFdti_cnt = mb->un.varRdLnk.EOFdtiCnt;
4157         stats->EOFni_cnt = mb->un.varRdLnk.EOFniCnt;
4158         stats->SOFf_cnt = mb->un.varRdLnk.SOFfCnt;
4159         stats->link_event_tag = hba->link_event_tag;
4160         stats->last_reset_time = hba->timer_tics - hba->stats.ResetTime;
4161         stats->port_type = HBA_PORTTYPE_UNKNOWN;
4162 
4163 #ifdef MENLO_SUPPORT
4164         if (hba->flag & FC_MENLO_MODE) {
4165                 stats->topology = LNK_MENLO_MAINTENANCE;
4166         } else
4167 #endif /* MENLO_SUPPORT */
4168 
4169         if (hba->state >= FC_LINK_UP) {
4170                 if (hba->topology == TOPOLOGY_LOOP) {
4171                         if (hba->flag & FC_FABRIC_ATTACHED) {
4172                                 stats->port_type = HBA_PORTTYPE_NLPORT;
4173                                 stats->topology = LNK_PUBLIC_LOOP;
4174                         } else {
4175                                 stats->port_type = HBA_PORTTYPE_LPORT;
4176                                 stats->topology = LNK_LOOP;
4177                         }
4178                 } else {
4179                         if (hba->flag & FC_PT_TO_PT) {
4180                                 stats->port_type = HBA_PORTTYPE_PTP;
4181                                 stats->topology = LNK_PT2PT;
4182                         } else {
4183                                 stats->port_type = HBA_PORTTYPE_NPORT;
4184                                 stats->topology = LNK_FABRIC;
4185                         }
4186                 }
4187 
4188                 if (hba->linkspeed == LA_2GHZ_LINK) {
4189                         stats->link_speed = HBA_PORTSPEED_2GBIT;
4190                 } else if (hba->linkspeed == LA_4GHZ_LINK) {
4191                         stats->link_speed = HBA_PORTSPEED_4GBIT;
4192                 } else if (hba->linkspeed == LA_8GHZ_LINK) {
4193                         stats->link_speed = HBA_PORTSPEED_8GBIT;
4194                 } else if (hba->linkspeed == LA_10GHZ_LINK) {
4195                         stats->link_speed = HBA_PORTSPEED_10GBIT;
4196                 } else if (hba->linkspeed == LA_16GHZ_LINK) {
4197                         stats->link_speed = HBA_PORTSPEED_16GBIT;
4198                 } else {
4199                         stats->link_speed = HBA_PORTSPEED_1GBIT;
4200                 }
4201         }
4202 
4203 done:
4204 
4205         /* Free allocated mbox memory */
4206         if (mbq) {
4207                 kmem_free(mbq, sizeof (MAILBOXQ));
4208         }
4209 
4210         return (rval);
4211 
4212 } /* emlxs_dfc_get_hbastats() */
4213 
4214 
4215 
4216 /*ARGSUSED*/
4217 static int32_t
4218 emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4219 {
4220         emlxs_port_t    *port = &PPORT;
4221         dfc_drvstats_t  *stats;
4222         uint32_t        rval = 0;
4223 
4224         if (!dfc->buf1 || !dfc->buf1_size) {
4225                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4226                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4227 
4228                 return (DFC_ARG_NULL);
4229         }
4230 
4231         stats = (dfc_drvstats_t *)dfc->buf1;
4232         bzero((void *)stats, sizeof (dfc_drvstats_t));
4233 
4234         stats->LinkUp = hba->stats.LinkUp;
4235         stats->LinkDown = hba->stats.LinkDown;
4236         stats->LinkEvent = hba->stats.LinkEvent;
4237         stats->LinkMultiEvent = hba->stats.LinkMultiEvent;
4238 
4239         stats->MboxIssued = hba->stats.MboxIssued;
4240         stats->MboxCompleted = hba->stats.MboxCompleted;
4241         stats->MboxGood = hba->stats.MboxGood;
4242         stats->MboxError = hba->stats.MboxError;
4243         stats->MboxBusy = hba->stats.MboxBusy;
4244         stats->MboxInvalid = hba->stats.MboxInvalid;
4245 
4246         stats->IocbIssued[0] = hba->stats.IocbIssued[0];
4247         stats->IocbIssued[1] = hba->stats.IocbIssued[1];
4248         stats->IocbIssued[2] = hba->stats.IocbIssued[2];
4249         stats->IocbIssued[3] = hba->stats.IocbIssued[3];
4250         stats->IocbReceived[0] = hba->stats.IocbReceived[0];
4251         stats->IocbReceived[1] = hba->stats.IocbReceived[1];
4252         stats->IocbReceived[2] = hba->stats.IocbReceived[2];
4253         stats->IocbReceived[3] = hba->stats.IocbReceived[3];
4254         stats->IocbTxPut[0] = hba->stats.IocbTxPut[0];
4255         stats->IocbTxPut[1] = hba->stats.IocbTxPut[1];
4256         stats->IocbTxPut[2] = hba->stats.IocbTxPut[2];
4257         stats->IocbTxPut[3] = hba->stats.IocbTxPut[3];
4258         stats->IocbTxGet[0] = hba->stats.IocbTxGet[0];
4259         stats->IocbTxGet[1] = hba->stats.IocbTxGet[1];
4260         stats->IocbTxGet[2] = hba->stats.IocbTxGet[2];
4261         stats->IocbTxGet[3] = hba->stats.IocbTxGet[3];
4262         stats->IocbRingFull[0] = hba->stats.IocbRingFull[0];
4263         stats->IocbRingFull[1] = hba->stats.IocbRingFull[1];
4264         stats->IocbRingFull[2] = hba->stats.IocbRingFull[2];
4265         stats->IocbRingFull[3] = hba->stats.IocbRingFull[3];
4266 
4267         stats->IntrEvent[0] = hba->stats.IntrEvent[0];
4268         stats->IntrEvent[1] = hba->stats.IntrEvent[1];
4269         stats->IntrEvent[2] = hba->stats.IntrEvent[2];
4270         stats->IntrEvent[3] = hba->stats.IntrEvent[3];
4271         stats->IntrEvent[4] = hba->stats.IntrEvent[4];
4272         stats->IntrEvent[5] = hba->stats.IntrEvent[5];
4273         stats->IntrEvent[6] = hba->stats.IntrEvent[6];
4274         stats->IntrEvent[7] = hba->stats.IntrEvent[7];
4275 
4276         stats->FcpIssued = hba->stats.FcpIssued;
4277         stats->FcpCompleted = hba->stats.FcpCompleted;
4278         stats->FcpGood = hba->stats.FcpGood;
4279         stats->FcpError = hba->stats.FcpError;
4280 
4281         stats->FcpEvent = hba->stats.FcpEvent;
4282         stats->FcpStray = hba->stats.FcpStray;
4283 
4284         stats->ElsEvent = hba->stats.ElsEvent;
4285         stats->ElsStray = hba->stats.ElsStray;
4286 
4287         stats->ElsCmdIssued = hba->stats.ElsCmdIssued;
4288         stats->ElsCmdCompleted = hba->stats.ElsCmdCompleted;
4289         stats->ElsCmdGood = hba->stats.ElsCmdGood;
4290         stats->ElsCmdError = hba->stats.ElsCmdError;
4291 
4292         stats->ElsRspIssued = hba->stats.ElsRspIssued;
4293         stats->ElsRspCompleted = hba->stats.ElsRspCompleted;
4294 
4295         stats->ElsRcvEvent = hba->stats.ElsRcvEvent;
4296         stats->ElsRcvError = hba->stats.ElsRcvError;
4297         stats->ElsRcvDropped = hba->stats.ElsRcvDropped;
4298         stats->ElsCmdReceived = hba->stats.ElsCmdReceived;
4299         stats->ElsRscnReceived = hba->stats.ElsRscnReceived;
4300         stats->ElsPlogiReceived = hba->stats.ElsPlogiReceived;
4301         stats->ElsPrliReceived = hba->stats.ElsPrliReceived;
4302         stats->ElsPrloReceived = hba->stats.ElsPrloReceived;
4303         stats->ElsLogoReceived = hba->stats.ElsLogoReceived;
4304         stats->ElsAdiscReceived = hba->stats.ElsAdiscReceived;
4305         stats->ElsGenReceived = hba->stats.ElsGenReceived;
4306 
4307         stats->CtEvent = hba->stats.CtEvent;
4308         stats->CtStray = hba->stats.CtStray;
4309 
4310         stats->CtCmdIssued = hba->stats.CtCmdIssued;
4311         stats->CtCmdCompleted = hba->stats.CtCmdCompleted;
4312         stats->CtCmdGood = hba->stats.CtCmdGood;
4313         stats->CtCmdError = hba->stats.CtCmdError;
4314 
4315         stats->CtRspIssued = hba->stats.CtRspIssued;
4316         stats->CtRspCompleted = hba->stats.CtRspCompleted;
4317 
4318         stats->CtRcvEvent = hba->stats.CtRcvEvent;
4319         stats->CtRcvError = hba->stats.CtRcvError;
4320         stats->CtRcvDropped = hba->stats.CtRcvDropped;
4321         stats->CtCmdReceived = hba->stats.CtCmdReceived;
4322 
4323         stats->IpEvent = hba->stats.IpEvent;
4324         stats->IpStray = hba->stats.IpStray;
4325 
4326         stats->IpSeqIssued = hba->stats.IpSeqIssued;
4327         stats->IpSeqCompleted = hba->stats.IpSeqCompleted;
4328         stats->IpSeqGood = hba->stats.IpSeqGood;
4329         stats->IpSeqError = hba->stats.IpSeqError;
4330 
4331         stats->IpBcastIssued = hba->stats.IpBcastIssued;
4332         stats->IpBcastCompleted = hba->stats.IpBcastCompleted;
4333         stats->IpBcastGood = hba->stats.IpBcastGood;
4334         stats->IpBcastError = hba->stats.IpBcastError;
4335 
4336         stats->IpRcvEvent = hba->stats.IpRcvEvent;
4337         stats->IpDropped = hba->stats.IpDropped;
4338         stats->IpSeqReceived = hba->stats.IpSeqReceived;
4339         stats->IpBcastReceived = hba->stats.IpBcastReceived;
4340 
4341         stats->IpUbPosted = hba->stats.IpUbPosted;
4342         stats->ElsUbPosted = hba->stats.ElsUbPosted;
4343         stats->CtUbPosted = hba->stats.CtUbPosted;
4344 
4345 #if (DFC_REV >= 2)
4346         stats->IocbThrottled   = hba->stats.IocbThrottled;
4347         stats->ElsAuthReceived = hba->stats.ElsAuthReceived;
4348 #endif
4349 
4350         return (rval);
4351 
4352 } /* emlxs_dfc_get_drvstats() */
4353 
4354 
4355 extern uint32_t
4356 emlxs_set_hba_mode(emlxs_hba_t *hba, uint32_t mode)
4357 {
4358         emlxs_port_t    *port = &PPORT;
4359         uint32_t        i;
4360 
4361         mutex_enter(&EMLXS_PORT_LOCK);
4362 
4363         /* Wait if adapter is in transition */
4364         i = 0;
4365         while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
4366                 if (i++ > 30) {
4367                         break;
4368                 }
4369 
4370                 mutex_exit(&EMLXS_PORT_LOCK);
4371                 delay(drv_usectohz(1000000));
4372                 mutex_enter(&EMLXS_PORT_LOCK);
4373         }
4374 
4375         if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
4376                 switch (mode) {
4377                 case DDI_SHOW:
4378                         break;
4379 
4380                 case DDI_ONDI:
4381                         if (hba->flag & FC_OFFLINE_MODE) {
4382                                 mutex_exit(&EMLXS_PORT_LOCK);
4383                                 (void) emlxs_online(hba);
4384                                 mutex_enter(&EMLXS_PORT_LOCK);
4385                         }
4386                         break;
4387 
4388 
4389                 /* Killed + Restart state */
4390                 case DDI_OFFDI:
4391                         if (hba->flag & FC_ONLINE_MODE) {
4392                                 mutex_exit(&EMLXS_PORT_LOCK);
4393 
4394                                 (void) emlxs_offline(hba, 0);
4395 
4396                                 /* Reset with restart */
4397                                 EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4398 
4399                                 mutex_enter(&EMLXS_PORT_LOCK);
4400                         } else if (hba->state < FC_INIT_START) {
4401                                 mutex_exit(&EMLXS_PORT_LOCK);
4402 
4403                                 /* Reset with restart */
4404                                 EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4405 
4406                                 mutex_enter(&EMLXS_PORT_LOCK);
4407                         }
4408 
4409                         break;
4410 
4411                 /* Killed + Reset state */
4412                 case DDI_WARMDI:
4413                         if (hba->flag & FC_ONLINE_MODE) {
4414                                 mutex_exit(&EMLXS_PORT_LOCK);
4415 
4416                                 (void) emlxs_offline(hba, 0);
4417 
4418                                 /* Reset with no restart */
4419                                 EMLXS_SLI_HBA_RESET(hba, 0, 0, 0);
4420 
4421                                 mutex_enter(&EMLXS_PORT_LOCK);
4422                         } else if (hba->state != FC_WARM_START) {
4423                                 mutex_exit(&EMLXS_PORT_LOCK);
4424 
4425                                 /* Reset with no restart */
4426                                 EMLXS_SLI_HBA_RESET(hba, 0, 0, 0);
4427 
4428                                 mutex_enter(&EMLXS_PORT_LOCK);
4429                         }
4430 
4431                         break;
4432 
4433                 /* Killed */
4434                 case DDI_DIAGDI:
4435                         if (hba->flag & FC_ONLINE_MODE) {
4436                                 mutex_exit(&EMLXS_PORT_LOCK);
4437 
4438                                 (void) emlxs_offline(hba, 0);
4439 
4440                                 mutex_enter(&EMLXS_PORT_LOCK);
4441                         } else if (hba->state != FC_KILLED) {
4442                                 mutex_exit(&EMLXS_PORT_LOCK);
4443 
4444                                 EMLXS_SLI_HBA_KILL(hba);
4445 
4446                                 mutex_enter(&EMLXS_PORT_LOCK);
4447                         }
4448 
4449                         break;
4450 
4451                 default:
4452                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4453                             "set_hba_mode: Invalid mode. mode=%x", mode);
4454                         mutex_exit(&EMLXS_PORT_LOCK);
4455                         return (0);
4456                 }
4457 
4458                 /* Wait if adapter is in transition */
4459                 i = 0;
4460                 while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
4461                         if (i++ > 30) {
4462                                 break;
4463                         }
4464 
4465                         mutex_exit(&EMLXS_PORT_LOCK);
4466                         delay(drv_usectohz(1000000));
4467                         mutex_enter(&EMLXS_PORT_LOCK);
4468                 }
4469 
4470                 /* Return current state */
4471                 if (hba->flag & FC_ONLINE_MODE) {
4472                         mode = DDI_ONDI;
4473                 } else if (hba->state == FC_KILLED) {
4474                         mode = DDI_DIAGDI;
4475                 } else if (hba->state == FC_WARM_START) {
4476                         mode = DDI_WARMDI;
4477                 } else {
4478                         mode = DDI_OFFDI;
4479                 }
4480 
4481                 mutex_exit(&EMLXS_PORT_LOCK);
4482 
4483                 return (mode);
4484 
4485         } else { /* SLI4 */
4486                 switch (mode) {
4487                 case DDI_SHOW:
4488                         break;
4489 
4490                 case DDI_ONDI:
4491                         if (hba->flag & FC_OFFLINE_MODE) {
4492                                 mutex_exit(&EMLXS_PORT_LOCK);
4493                                 (void) emlxs_online(hba);
4494                                 mutex_enter(&EMLXS_PORT_LOCK);
4495                         }
4496                         break;
4497 
4498                 case DDI_OFFDI:
4499                         if (hba->flag & FC_ONLINE_MODE) {
4500                                 mutex_exit(&EMLXS_PORT_LOCK);
4501 
4502                                 (void) emlxs_offline(hba, 0);
4503 
4504                                 /* Reset with restart */
4505                                 EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4506 
4507                                 mutex_enter(&EMLXS_PORT_LOCK);
4508                         } else if (hba->state < FC_INIT_START) {
4509                                 mutex_exit(&EMLXS_PORT_LOCK);
4510 
4511                                 /* Reset with restart */
4512                                 EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
4513 
4514                                 mutex_enter(&EMLXS_PORT_LOCK);
4515                         }
4516                         break;
4517 
4518                 case DDI_DIAGDI:
4519                         if (!(hba->model_info.chip & EMLXS_LANCER_CHIP)) {
4520                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4521                                     "set_hba_mode: Invalid mode. mode=%x",
4522                                     mode);
4523                                 mutex_exit(&EMLXS_PORT_LOCK);
4524                                 return (0);
4525                         }
4526 
4527                         mutex_exit(&EMLXS_PORT_LOCK);
4528                         (void) emlxs_reset(port,
4529                             EMLXS_DFC_RESET_ALL_FORCE_DUMP);
4530 
4531                         return (mode);
4532 
4533                 case DDI_WARMDI:
4534                 default:
4535                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4536                             "set_hba_mode: Invalid mode. mode=%x", mode);
4537                         mutex_exit(&EMLXS_PORT_LOCK);
4538                         return (0);
4539                 }
4540 
4541                 /* Wait if adapter is in transition */
4542                 i = 0;
4543                 while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
4544                         if (i++ > 30) {
4545                                 break;
4546                         }
4547 
4548                         mutex_exit(&EMLXS_PORT_LOCK);
4549                         delay(drv_usectohz(1000000));
4550                         mutex_enter(&EMLXS_PORT_LOCK);
4551                 }
4552 
4553                 /* Return current state */
4554                 if (hba->flag & FC_ONLINE_MODE) {
4555                         mode = DDI_ONDI;
4556                 } else {
4557                         mode = DDI_OFFDI;
4558                 }
4559 
4560                 mutex_exit(&EMLXS_PORT_LOCK);
4561 
4562                 return (mode);
4563         }
4564 
4565 } /* emlxs_set_hba_mode() */
4566 
4567 
4568 /*ARGSUSED*/
4569 static int32_t
4570 emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4571 {
4572         emlxs_port_t    *port = &PPORT;
4573         int32_t         rval = 0;
4574         int32_t         flag;
4575 
4576         if (!dfc->buf1 || !dfc->buf1_size) {
4577                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4578                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4579 
4580                 return (DFC_ARG_NULL);
4581         }
4582 
4583         if (dfc->buf1_size < sizeof (uint32_t)) {
4584                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4585                     "%s: Buffer1 too small. (size=%d)",
4586                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4587 
4588                 return (DFC_ARG_TOOSMALL);
4589         }
4590 
4591         flag = emlxs_set_hba_mode(hba, dfc->flag);
4592         bcopy((void *)&flag, (void *)dfc->buf1, sizeof (uint32_t));
4593 
4594         return (rval);
4595 
4596 } /* emlxs_dfc_set_diag() */
4597 
4598 
4599 
4600 /*ARGSUSED*/
4601 static int32_t
4602 emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4603 {
4604         emlxs_port_t    *port  = &PPORT;
4605         MAILBOX         *mb    = NULL;
4606         MAILBOXQ        *mbq   = NULL;
4607         uint32_t        size  = 0;
4608         MATCHMAP        *rx_mp = NULL;
4609         MATCHMAP        *tx_mp = NULL;
4610         uintptr_t       lptr;
4611         int32_t         rval  = 0;
4612         int32_t         mbxstatus = 0;
4613         NODELIST        *ndlp;
4614         uint32_t        did;
4615         uint32_t        extsize = 0;
4616         uint8_t         *extbuf  = NULL;
4617 
4618         if (hba->sli_mode > EMLXS_HBA_SLI3_MODE) {
4619                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4620                     "%s: SLI Mode %d not supported.", emlxs_dfc_xlate(dfc->cmd),
4621                     hba->sli_mode);
4622 
4623                 return (DFC_NOT_SUPPORTED);
4624         }
4625 
4626         if (!dfc->buf1 || !dfc->buf1_size) {
4627                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4628                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4629 
4630                 return (DFC_ARG_NULL);
4631         }
4632 
4633         if (!dfc->buf2 || !dfc->buf2_size) {
4634                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4635                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
4636 
4637                 return (DFC_ARG_NULL);
4638         }
4639 
4640         if (dfc->buf1_size > MAILBOX_CMD_BSIZE) {
4641                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4642                     "%s: Buffer1 too large. (size=%d)",
4643                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4644 
4645                 return (DFC_ARG_TOOBIG);
4646         }
4647 #ifdef MBOX_EXT_SUPPORT
4648         if (dfc->buf3_size || dfc->buf4_size) {
4649                 if (dfc->buf3_size && !dfc->buf3) {
4650                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4651                             "%s: Null buffer3 found.",
4652                             emlxs_dfc_xlate(dfc->cmd));
4653 
4654                         return (DFC_ARG_NULL);
4655                 }
4656 
4657                 if (dfc->buf3_size > MBOX_EXTENSION_SIZE) {
4658                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4659                             "%s: buffer3 too large. (size=%d)",
4660                             emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4661 
4662                         return (DFC_ARG_TOOBIG);
4663                 }
4664 
4665                 if (dfc->buf4_size && !dfc->buf4) {
4666                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4667                             "%s: Null buffer4 found.",
4668                             emlxs_dfc_xlate(dfc->cmd));
4669 
4670                         return (DFC_ARG_NULL);
4671                 }
4672 
4673                 if (dfc->buf4_size > MBOX_EXTENSION_SIZE) {
4674                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4675                             "%s: buffer4 too large. (size=%d)",
4676                             emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4677 
4678                         return (DFC_ARG_TOOBIG);
4679                 }
4680 
4681                 extsize = (dfc->buf3_size > dfc->buf4_size) ?
4682                     dfc->buf3_size : dfc->buf4_size;
4683                 extbuf = (uint8_t *)kmem_zalloc(extsize, KM_SLEEP);
4684 
4685                 if (dfc->buf3_size) {
4686                         bcopy((void *)dfc->buf3, (void *)extbuf,
4687                             dfc->buf3_size);
4688                 }
4689         }
4690 #endif /* MBOX_EXT_SUPPORT */
4691 
4692         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
4693         mb = (MAILBOX *) mbq;
4694         bcopy((void *)dfc->buf1, (void *)mb, dfc->buf1_size);
4695 
4696 #ifdef _LP64
4697         if ((mb->mbxCommand == MBX_READ_SPARM) ||
4698             (mb->mbxCommand == MBX_READ_RPI) ||
4699             (mb->mbxCommand == MBX_REG_LOGIN) ||
4700             (mb->mbxCommand == MBX_READ_LA) ||
4701             (mb->mbxCommand == MBX_RUN_BIU_DIAG)) {
4702 
4703                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4704                     "%s: Invalid mailbox command. Must use 64bit version. "
4705                     "cmd=%x", emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4706 
4707                 /* Must use 64 bit versions of these mbox cmds */
4708                 rval = DFC_ARG_INVALID;
4709                 goto done;
4710         }
4711 #endif
4712 
4713         lptr = 0;
4714         size = 0;
4715         switch (mb->mbxCommand) {
4716         /* Offline only */
4717         case MBX_CONFIG_LINK:   /* 0x07 */
4718         case MBX_PART_SLIM:         /* 0x08 */
4719         case MBX_CONFIG_RING:   /* 0x09 */
4720         case MBX_DUMP_CONTEXT:  /* 0x18 */
4721         case MBX_RUN_DIAGS:         /* 0x19 */
4722         case MBX_RESTART:           /* 0x1A */
4723         case MBX_SET_MASK:          /* 0x20 */
4724         case MBX_FLASH_WR_ULA:  /* 0x98 */
4725                 if (!(hba->flag & FC_OFFLINE_MODE)) {
4726                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4727                             "%s: Adapter not offline. cmd=%x",
4728                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4729 
4730                         rval = DFC_ONLINE_ERROR;
4731                         goto done;
4732                 }
4733                 break;
4734 
4735         /* Online / Offline */
4736         case MBX_UNREG_LOGIN:   /* 0x14 */
4737                 ndlp = emlxs_node_find_rpi(port, mb->un.varUnregLogin.rpi);
4738 
4739                 if (ndlp) {
4740                         did = ndlp->nlp_DID;
4741 
4742                         /* remove it */
4743                         emlxs_node_rm(port, ndlp);
4744 
4745                         /*
4746                          * If we just unregistered the host node then
4747                          * clear the host DID
4748                          */
4749                         if (did == port->did) {
4750                                 port->did = 0;
4751                         }
4752                 } else {
4753                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4754                             "%s: Node not found. cmd=%x rpi=%d",
4755                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand,
4756                             mb->un.varUnregLogin.rpi);
4757 
4758                         /* Node does not exist */
4759                         rval = DFC_ARG_INVALID;
4760                         goto done;
4761                 }
4762 
4763                 /* Send it */
4764                 break;
4765 
4766         case MBX_UNREG_D_ID:    /* 0x23 */
4767 
4768                 did = mb->un.varRegLogin.did;
4769 
4770                 if (did == 0) {
4771                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4772                             "%s: Node not found. cmd=%x did=%x",
4773                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
4774 
4775                         rval = DFC_ARG_INVALID;
4776                         goto done;
4777                 }
4778 
4779                 if (did == 0xffffffff) {
4780                         emlxs_node_destroy_all(port);
4781                         break;
4782                 }
4783 
4784                 /* Check for base node */
4785                 if (did == BCAST_DID) {
4786                         /* just flush base node */
4787                         (void) emlxs_tx_node_flush(port, &port->node_base,
4788                             0, 0, 0);
4789                         (void) emlxs_chipq_node_flush(port, 0, &port->node_base,
4790                             0);
4791 
4792                         /* Return now */
4793                         rval = 0;
4794                         goto done;
4795                 }
4796 
4797                 /* Make sure the node does already exist */
4798                 ndlp = emlxs_node_find_did(port, did, 1);
4799 
4800                 if (ndlp) {
4801                         /* remove it */
4802                         emlxs_node_rm(port, ndlp);
4803 
4804                         /*
4805                          * If we just unregistered the host node then
4806                          * clear the host DID
4807                          */
4808                         if (did == port->did) {
4809                                 port->did = 0;
4810                         }
4811                 } else {
4812 
4813                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4814                             "%s: Node not found. cmd=%x did=%x",
4815                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
4816 
4817                         /* Node does not exist */
4818                         rval = DFC_ARG_INVALID;
4819                         goto done;
4820                 }
4821 
4822                 /* Send it */
4823                 break;
4824 
4825         /* Online / Offline - with DMA */
4826         case MBX_READ_EVENT_LOG:        /* 0x38 */
4827                 lptr =
4828                     (uintptr_t)PADDR(mb->un.varRdEvtLog.un.sp64.addrHigh,
4829                     mb->un.varRdEvtLog.un.sp64.addrLow);
4830                 size = (int)mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize;
4831 
4832                 if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4833                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4834                             "%s: Invalid BDE. cmd=%x",
4835                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4836 
4837                         rval = DFC_ARG_INVALID;
4838                         goto done;
4839                 }
4840 
4841                 /* Allocate receive buffer */
4842                 if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4843                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4844                             "%s: Unable to allocate receive buffer. cmd=%x",
4845                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4846 
4847                         rval = DFC_DRVRES_ERROR;
4848                         goto done;
4849                 }
4850 
4851                 mb->un.varRdEvtLog.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4852                 mb->un.varRdEvtLog.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4853                 mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0;
4854 
4855                 break;
4856 
4857         case MBX_READ_SPARM:    /* 0x0D */
4858         case MBX_READ_SPARM64:  /* 0x8D */
4859                 lptr =
4860                     (uintptr_t)PADDR(mb->un.varRdSparm.un.sp64.addrHigh,
4861                     mb->un.varRdSparm.un.sp64.addrLow);
4862                 size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
4863 
4864                 if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4865                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4866                             "%s: Invalid BDE. cmd=%x",
4867                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4868 
4869                         rval = DFC_ARG_INVALID;
4870                         goto done;
4871                 }
4872 
4873                 /* Allocate receive buffer */
4874                 if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4875                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4876                             "%s: Unable to allocate receive buffer. cmd=%x",
4877                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4878 
4879                         rval = DFC_DRVRES_ERROR;
4880                         goto done;
4881                 }
4882 
4883                 mb->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4884                 mb->un.varRdSparm.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4885                 mb->un.varRdSparm.un.sp64.tus.f.bdeFlags = 0;
4886 
4887                 break;
4888 
4889         case MBX_READ_RPI:      /* 0x0F */
4890         case MBX_READ_RPI64:    /* 0x8F */
4891                 lptr =
4892                     (uintptr_t)PADDR(mb->un.varRdRPI.un.sp64.addrHigh,
4893                     mb->un.varRdRPI.un.sp64.addrLow);
4894                 size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize;
4895 
4896                 if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4897                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4898                             "%s: Invalid BDE. cmd=%x",
4899                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4900 
4901                         rval = DFC_ARG_INVALID;
4902                         goto done;
4903                 }
4904 
4905                 /* Allocate receive buffer */
4906                 if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4907                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4908                             "%s: Unable to allocate receive buffer. cmd=%x",
4909                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4910 
4911                         rval = DFC_DRVRES_ERROR;
4912                         goto done;
4913                 }
4914 
4915                 mb->un.varRdRPI.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4916                 mb->un.varRdRPI.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4917                 mb->un.varRdRPI.un.sp64.tus.f.bdeFlags = 0;
4918 
4919                 break;
4920 
4921         case MBX_RUN_BIU_DIAG:   /* 0x04 */
4922         case MBX_RUN_BIU_DIAG64: /* 0x84 */
4923                 lptr =
4924                     (uintptr_t)PADDR(mb->un.varBIUdiag.un.s2.xmit_bde64.
4925                     addrHigh, mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow);
4926                 size = (int)mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize;
4927 
4928                 if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4929                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4930                             "%s: Invalid xmit BDE. cmd=%x",
4931                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4932 
4933                         rval = DFC_ARG_INVALID;
4934                         goto done;
4935                 }
4936 
4937                 /* Allocate xmit buffer */
4938                 if ((tx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4939                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4940                             "%s: Unable to allocate xmit buffer. cmd=%x",
4941                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4942 
4943                         rval = DFC_DRVRES_ERROR;
4944                         goto done;
4945                 }
4946 
4947                 /* Initialize the xmit buffer */
4948                 if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size,
4949                     mode) != 0) {
4950                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4951                             "%s: ddi_copyin failed. cmd=%x",
4952                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4953 
4954                         rval = DFC_COPYIN_ERROR;
4955                         goto done;
4956                 }
4957                 EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
4958                     DDI_DMA_SYNC_FORDEV);
4959 
4960                 mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
4961                     PADDR_HI(tx_mp->phys);
4962                 mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
4963                     PADDR_LO(tx_mp->phys);
4964                 mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0;
4965 
4966                 /* Initialize the receive buffer */
4967                 lptr =
4968                     (uintptr_t)PADDR(mb->un.varBIUdiag.un.s2.rcv_bde64.
4969                     addrHigh, mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow);
4970                 size = (int)mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize;
4971 
4972                 if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4973                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4974                             "%s: Invalid rcv BDE. cmd=%x",
4975                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4976 
4977                         rval = DFC_ARG_INVALID;
4978                         goto done;
4979                 }
4980 
4981                 /* Allocate receive buffer */
4982                 if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4983                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4984                             "%s: Unable to allocate receive buffer. cmd=%x",
4985                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4986 
4987                         rval = DFC_DRVRES_ERROR;
4988                         goto done;
4989                 }
4990 
4991                 mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
4992                     PADDR_HI(rx_mp->phys);
4993                 mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
4994                     PADDR_LO(rx_mp->phys);
4995                 mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0;
4996 
4997                 break;
4998 
4999         case MBX_REG_LOGIN:     /* 0x13 */
5000         case MBX_REG_LOGIN64:   /* 0x93 */
5001 
5002                 did = mb->un.varRegLogin.did;
5003 
5004                 /* Check for invalid node ids to register */
5005                 if (did == 0 || (did & 0xff000000)) {
5006                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5007                             "%s: Invalid node id. cmd=%x did=%x",
5008                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
5009 
5010                         rval = DFC_ARG_INVALID;
5011                         goto done;
5012                 }
5013 
5014                 /* Check if the node limit has been reached */
5015                 if (port->node_count >= hba->max_nodes) {
5016                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5017                             "%s: Too many nodes. cmd=%x",
5018                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5019 
5020                         rval = DFC_HBARES_ERROR;
5021                         goto done;
5022                 }
5023 
5024                 lptr =
5025                     (uintptr_t)PADDR(mb->un.varRegLogin.un.sp64.addrHigh,
5026                     mb->un.varRegLogin.un.sp64.addrLow);
5027                 size = (int)mb->un.varRegLogin.un.sp64.tus.f.bdeSize;
5028 
5029                 if (!lptr || (size > MEM_BUF_SIZE)) {
5030                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5031                             "%s: Invalid BDE. cmd=%x",
5032                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5033 
5034                         rval = DFC_ARG_INVALID;
5035                         goto done;
5036                 }
5037 
5038                 /* Allocate xmit buffer */
5039                 if ((tx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
5040                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5041                             "%s: Unable to allocate xmit buffer. cmd=%x",
5042                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5043 
5044                         rval = DFC_DRVRES_ERROR;
5045                         goto done;
5046                 }
5047 
5048                 /* Initialize the xmit buffer */
5049                 if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size,
5050                     mode) != 0) {
5051                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5052                             "%s: Unable to allocate xmit buffer. cmd=%x",
5053                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5054 
5055                         rval = DFC_COPYIN_ERROR;
5056                         goto done;
5057                 }
5058                 EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
5059                     DDI_DMA_SYNC_FORDEV);
5060 
5061                 mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(tx_mp->phys);
5062                 mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(tx_mp->phys);
5063                 mb->un.varRegLogin.un.sp64.tus.f.bdeFlags = 0;
5064 
5065                 break;
5066 
5067         case MBX_READ_LA:       /* 0x15 */
5068         case MBX_READ_LA64:     /* 0x95 */
5069                 lptr =
5070                     (uintptr_t)PADDR(mb->un.varReadLA.un.lilpBde64.
5071                     addrHigh, mb->un.varReadLA.un.lilpBde64.addrLow);
5072                 size = (int)mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize;
5073 
5074                 if (!lptr || !size || (size > MEM_BUF_SIZE)) {
5075                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5076                             "%s: Invalid BDE. cmd=%x",
5077                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5078 
5079                         rval = DFC_ARG_INVALID;
5080                         goto done;
5081                 }
5082 
5083                 /* Allocate receive buffer */
5084                 if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
5085                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5086                             "%s: Unable to allocate receive buffer. cmd=%x",
5087                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5088 
5089                         rval = DFC_DRVRES_ERROR;
5090                         goto done;
5091                 }
5092 
5093                 mb->un.varReadLA.un.lilpBde64.addrHigh =
5094                     PADDR_HI(rx_mp->phys);
5095                 mb->un.varReadLA.un.lilpBde64.addrLow =
5096                     PADDR_LO(rx_mp->phys);
5097                 mb->un.varReadLA.un.lilpBde64.tus.f.bdeFlags = 0;
5098 
5099                 break;
5100 
5101 
5102                 /* Do not allow these commands */
5103         case MBX_CONFIG_PORT:   /* 0x88 */
5104                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5105                     "%s: Command not allowed. cmd=%x",
5106                     emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5107 
5108                 rval = DFC_ARG_INVALID;
5109                 goto done;
5110 
5111 
5112         /* Online / Offline */
5113         default:
5114                 break;
5115 
5116         }       /* switch() */
5117 
5118         mb->mbxOwner = OWN_HOST;
5119 
5120         /* Set or don't set the PASSTHRU bit. */
5121         /* Setting will prevent the driver from processing it as its own */
5122         switch (mb->mbxCommand) {
5123         case MBX_REG_LOGIN:     /* 0x13 */
5124         case MBX_REG_LOGIN64:   /* 0x93 */
5125                 break;
5126 
5127         default:
5128                 mbq->flag |= MBQ_PASSTHRU;
5129         }
5130 
5131 #ifdef MBOX_EXT_SUPPORT
5132         if (extbuf) {
5133                 mbq->extbuf  = extbuf;
5134                 mbq->extsize = extsize;
5135         }
5136 #endif /* MBOX_EXT_SUPPORT */
5137 
5138         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5139             "%s: %s sent.  (%x %x %x %x)", emlxs_dfc_xlate(dfc->cmd),
5140             emlxs_mb_cmd_xlate(mb->mbxCommand), mb->un.varWords[0],
5141             mb->un.varWords[1], mb->un.varWords[2], mb->un.varWords[3]);
5142 
5143         /* issue the mbox cmd to the sli */
5144         mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
5145 
5146         if (mbxstatus) {
5147                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5148                     "%s: %s failed. mbxstatus=0x%x",
5149                     emlxs_dfc_xlate(dfc->cmd),
5150                     emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
5151 
5152         }
5153 
5154         bcopy((void *)mb, (void *)dfc->buf2, dfc->buf2_size);
5155 
5156         if (rx_mp) {
5157                 EMLXS_MPDATA_SYNC(rx_mp->dma_handle, 0, size,
5158                     DDI_DMA_SYNC_FORKERNEL);
5159 
5160                 if (ddi_copyout((void *)rx_mp->virt, (void *)lptr, size,
5161                     mode) != 0) {
5162                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5163                             "%s: ddi_copyout failed for receive buffer. cmd=%x",
5164                             emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
5165 
5166                         rval = DFC_COPYOUT_ERROR;
5167                         goto done;
5168                 }
5169         }
5170 #ifdef MBOX_EXT_SUPPORT
5171         /*  Any data needs to copy to mbox extension area */
5172         if (dfc->buf4_size) {
5173                 bcopy((void *)extbuf, (void *)dfc->buf4, dfc->buf4_size);
5174         }
5175 #endif /* MBOX_EXT_SUPPORT */
5176 
5177         rval = 0;
5178 
5179 done:
5180 
5181         /* Free allocated mbox memory */
5182         if (extbuf) {
5183                 kmem_free(extbuf, extsize);
5184         }
5185 
5186         /* Free allocated mbox memory */
5187         if (mbq) {
5188                 kmem_free(mbq, sizeof (MAILBOXQ));
5189         }
5190 
5191         /* Free allocated mbuf memory */
5192         if (rx_mp) {
5193 #ifdef FMA_SUPPORT
5194                 if (!rval) {
5195                         if (emlxs_fm_check_dma_handle(hba, rx_mp->dma_handle)
5196                             != DDI_FM_OK) {
5197                                 EMLXS_MSGF(EMLXS_CONTEXT,
5198                                     &emlxs_invalid_dma_handle_msg,
5199                                     "dfc_send_mbox: hdl=%p",
5200                                     rx_mp->dma_handle);
5201                                 rval = DFC_IO_ERROR;
5202                         }
5203                 }
5204 #endif  /* FMA_SUPPORT */
5205                 emlxs_mem_buf_free(hba, rx_mp);
5206         }
5207 
5208         if (tx_mp) {
5209 #ifdef FMA_SUPPORT
5210                 if (!rval) {
5211                         if (emlxs_fm_check_dma_handle(hba, tx_mp->dma_handle)
5212                             != DDI_FM_OK) {
5213                                 EMLXS_MSGF(EMLXS_CONTEXT,
5214                                     &emlxs_invalid_dma_handle_msg,
5215                                     "dfc_send_mbox: hdl=%p",
5216                                     tx_mp->dma_handle);
5217                                 rval = DFC_IO_ERROR;
5218                         }
5219                 }
5220 #endif  /* FMA_SUPPORT */
5221                 emlxs_mem_buf_free(hba, tx_mp);
5222         }
5223 
5224         return (rval);
5225 
5226 } /* emlxs_dfc_send_mbox() */
5227 
5228 
5229 /*ARGSUSED*/
5230 static int32_t
5231 emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5232 {
5233         emlxs_port_t    *port = &PPORT;
5234         uint32_t        offset;
5235         uint32_t        cnt;
5236         uint32_t        outsz;
5237         uint32_t        i;
5238         uint32_t        *bptr;
5239         uint32_t        value;
5240         uint32_t        max = 4096;
5241 
5242         offset = dfc->data1;
5243         cnt = dfc->data2;
5244         outsz = dfc->buf1_size;
5245 
5246         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5247             "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt);
5248 
5249         if (!dfc->buf1_size || !dfc->buf1) {
5250                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5251                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5252 
5253                 return (DFC_ARG_NULL);
5254         }
5255 
5256         if (offset & 0x3) {
5257                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5258                     "%s: Offset misaligned. (offset=%d)",
5259                     emlxs_dfc_xlate(dfc->cmd), offset);
5260 
5261                 return (DFC_ARG_MISALIGNED);
5262         }
5263 
5264         if (cnt & 0x3) {
5265                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5266                     "%s: Count misaligned. (count=%d)",
5267                     emlxs_dfc_xlate(dfc->cmd), cnt);
5268 
5269                 return (DFC_ARG_MISALIGNED);
5270         }
5271 
5272         if (outsz & 0x3) {
5273                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5274                     "%s: Output size misaligned. (size=%d)",
5275                     emlxs_dfc_xlate(dfc->cmd), outsz);
5276 
5277                 return (DFC_ARG_MISALIGNED);
5278         }
5279 
5280         /* Get max PCI config range */
5281         if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
5282                 max = 256;
5283         } else {
5284                 max = 4096;
5285         }
5286 
5287         if ((cnt + offset) > max) {
5288                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5289                     "%s: Offset+Count too large. (offset=%d count=%d max=%d)",
5290                     emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
5291 
5292                 return (DFC_ARG_TOOBIG);
5293         }
5294 
5295         if (outsz > max) {
5296                 outsz = max;
5297         }
5298 
5299         if (cnt > outsz) {
5300                 cnt = outsz;
5301         }
5302 
5303         bptr = (uint32_t *)dfc->buf1;
5304         for (i = offset; i < (offset + cnt); i += 4) {
5305                 value =
5306                     ddi_get32(hba->pci_acc_handle,
5307                     (uint32_t *)(hba->pci_addr + i));
5308                 *bptr++ = BE_SWAP32(value);
5309         }
5310 
5311 #ifdef FMA_SUPPORT
5312         /* Access handle validation */
5313         if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
5314             != DDI_FM_OK) {
5315                 EMLXS_MSGF(EMLXS_CONTEXT,
5316                     &emlxs_invalid_access_handle_msg, NULL);
5317                 return (DFC_DRV_ERROR);
5318         }
5319 #endif  /* FMA_SUPPORT */
5320 
5321         return (0);
5322 
5323 } /* emlxs_dfc_read_pci() */
5324 
5325 
5326 /*ARGSUSED*/
5327 static int32_t
5328 emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5329 {
5330         emlxs_port_t    *port = &PPORT;
5331         uint32_t        offset;
5332         uint32_t        cnt;
5333         uint32_t        value;
5334         uint32_t        i;
5335         uint32_t        max;
5336         uint32_t        *bptr;
5337         uint16_t        word0;
5338         uint16_t        word1;
5339 
5340         offset = dfc->data1;
5341         cnt = dfc->data2;
5342 
5343         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5344             "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt);
5345 
5346         if (!dfc->buf1 || !dfc->buf1_size) {
5347                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5348                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5349 
5350                 return (DFC_ARG_NULL);
5351         }
5352 
5353         if (offset & 0x3) {
5354                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5355                     "%s: Offset misaligned. (offset=%d)",
5356                     emlxs_dfc_xlate(dfc->cmd), offset);
5357 
5358                 return (DFC_ARG_MISALIGNED);
5359         }
5360 
5361         if (cnt > dfc->buf1_size) {
5362                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5363                     "%s: Count too large. (count=%d)",
5364                     emlxs_dfc_xlate(dfc->cmd), cnt);
5365 
5366                 return (DFC_ARG_TOOBIG);
5367         }
5368 
5369         if (cnt & 0x3) {
5370                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5371                     "%s: Count misaligned. (count=%d)",
5372                     emlxs_dfc_xlate(dfc->cmd), cnt);
5373 
5374                 return (DFC_ARG_MISALIGNED);
5375         }
5376 
5377         /* Get max PCI config range */
5378         if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
5379                 max = 256;
5380         } else {
5381                 max = 4096;
5382         }
5383 
5384         if ((cnt + offset) > max) {
5385                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5386                     "%s: Count+Offset too large. (offset=%d count=%d max=%d)",
5387                     emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
5388 
5389                 return (DFC_ARG_TOOBIG);
5390         }
5391 
5392         bptr = (uint32_t *)dfc->buf1;
5393         for (i = offset; i < (offset + cnt); i += 4) {
5394                 value = *bptr++;
5395                 value = BE_SWAP32(value);
5396 
5397                 word0 = value & 0xFFFF;
5398                 word1 = value >> 16;
5399 
5400                 /*
5401                  * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
5402                  * "%s: Writing. offset=%x cnt=%d value=%08x %04x %04x",
5403                  * emlxs_dfc_xlate(dfc->cmd), i, value, word0, word1);
5404                  */
5405 
5406                 /* word0 = PCIMEM_SHORT(word0); */
5407                 ddi_put16(hba->pci_acc_handle,
5408                     (uint16_t *)(hba->pci_addr + i), (uint16_t)word0);
5409 
5410                 /* word1 = PCIMEM_SHORT(word1); */
5411                 ddi_put16(hba->pci_acc_handle,
5412                     (uint16_t *)(hba->pci_addr + i + 2), (uint16_t)word1);
5413         }
5414 
5415 #ifdef FMA_SUPPORT
5416         /* Access handle validation */
5417         if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
5418             != DDI_FM_OK) {
5419                 EMLXS_MSGF(EMLXS_CONTEXT,
5420                     &emlxs_invalid_access_handle_msg, NULL);
5421                 return (DFC_DRV_ERROR);
5422         }
5423 #endif  /* FMA_SUPPORT */
5424 
5425         return (0);
5426 
5427 } /* emlxs_dfc_write_pci() */
5428 
5429 
5430 /*ARGSUSED*/
5431 static int32_t
5432 emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5433 {
5434         emlxs_port_t    *port = &PPORT;
5435         dfc_cfgparam_t  *cfgparam;
5436         uint32_t        count;
5437         uint32_t        i;
5438         emlxs_config_t  *cfg;
5439 
5440         if (!dfc->buf1 || !dfc->buf1_size) {
5441                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5442                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5443 
5444                 return (DFC_ARG_NULL);
5445         }
5446 
5447         count = dfc->buf1_size / sizeof (dfc_cfgparam_t);
5448 
5449         if (count > MAX_CFG_PARAM) {
5450                 count = MAX_CFG_PARAM;
5451         }
5452 
5453         cfgparam = (dfc_cfgparam_t *)dfc->buf1;
5454         bzero(cfgparam, sizeof (dfc_cfgparam_t));
5455 
5456         cfg = &CFG;
5457         for (i = 0; i < count; i++) {
5458                 (void) strncpy(cfgparam[i].a_string, cfg[i].string,
5459                     (sizeof (cfgparam[i].a_string)-1));
5460                 cfgparam[i].a_low = cfg[i].low;
5461                 cfgparam[i].a_hi = cfg[i].hi;
5462                 cfgparam[i].a_default = cfg[i].def;
5463                 cfgparam[i].a_current = cfg[i].current;
5464 
5465                 if (!(cfg[i].flags & PARM_HIDDEN)) {
5466                         cfgparam[i].a_flag |= CFG_EXPORT;
5467                 }
5468                 cfgparam[i].a_flag |= CFG_COMMON;
5469 
5470                 /* Adjust a_flag based on the hba model */
5471                 switch (i) {
5472                         case CFG_NETWORK_ON:
5473                         case CFG_TOPOLOGY:
5474                         case CFG_LINK_SPEED:
5475                         case CFG_CR_DELAY:
5476                         case CFG_CR_COUNT:
5477                         if (! ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
5478                             SLI4_FCOE_MODE)) {
5479                                 cfgparam[i].a_flag |= CFG_APPLICABLE;
5480                         }
5481                         break;
5482 
5483                         case CFG_NUM_WQ:
5484                         if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
5485                             SLI4_FCOE_MODE) {
5486                                 cfgparam[i].a_flag |= CFG_APPLICABLE;
5487                         }
5488                         break;
5489 
5490                         case CFG_PERSIST_LINKDOWN:
5491                         cfgparam[i].a_flag &= ~CFG_EXPORT;
5492                         break;
5493 
5494                         default:
5495                         cfgparam[i].a_flag |= CFG_APPLICABLE;
5496                         break;
5497                 }
5498 
5499                 if ((cfg[i].flags & PARM_DYNAMIC)) {
5500                         if ((cfg[i].flags & PARM_DYNAMIC_RESET) ==
5501                             PARM_DYNAMIC_RESET) {
5502                                 cfgparam[i].a_changestate = CFG_RESTART;
5503                         } else if ((cfg[i].flags & PARM_DYNAMIC_LINK) ==
5504                             PARM_DYNAMIC_LINK) {
5505                                 cfgparam[i].a_changestate = CFG_LINKRESET;
5506                         } else {
5507                                 cfgparam[i].a_changestate = CFG_DYMANIC;
5508                         }
5509                 } else {
5510                         cfgparam[i].a_changestate = CFG_REBOOT;
5511                 }
5512 
5513                 (void) strncpy(cfgparam[i].a_help, cfg[i].help,
5514                     (sizeof (cfgparam[i].a_help)-1));
5515         }
5516 
5517         return (0);
5518 
5519 } /* emlxs_dfc_get_cfg() */
5520 
5521 
5522 /* ARGSUSED */
5523 static int32_t
5524 emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5525 {
5526         emlxs_port_t    *port = &PPORT;
5527         uint32_t        index;
5528         uint32_t        new_value;
5529         uint32_t        rc;
5530 
5531         index = dfc->data1;
5532         new_value = dfc->data2;
5533 
5534         rc = emlxs_set_parm(hba, index, new_value);
5535 
5536         if (rc) {
5537                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5538                     "%s: Unable to set parameter. code=%d",
5539                     emlxs_dfc_xlate(dfc->cmd), rc);
5540 
5541                 switch (rc) {
5542                 case 2:
5543                         return (DFC_NPIV_ACTIVE);
5544 
5545                 default:
5546                         return (DFC_ARG_INVALID);
5547                 }
5548         }
5549 
5550         return (0);
5551 
5552 } /* emlxs_dfc_set_cfg() */
5553 
5554 
5555 /*ARGSUSED*/
5556 static int32_t
5557 emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5558 {
5559         emlxs_port_t    *port = &PPORT;
5560         uint8_t         *rsp_buf;
5561         uint8_t         *cmd_buf;
5562         uint32_t        did;
5563         uint32_t        rsp_size;
5564         uint32_t        cmd_size;
5565         uint32_t        timeout;
5566         fc_packet_t     *pkt = NULL;
5567         uint32_t        rval = 0;
5568         dfc_destid_t    *destid;
5569         NODELIST        *nlp;
5570         char            buffer[128];
5571 
5572         cmd_buf = dfc->buf1;
5573         cmd_size = dfc->buf1_size;
5574         rsp_buf = dfc->buf2;
5575         rsp_size = dfc->buf2_size;
5576         timeout = dfc->data1;
5577 
5578         if (timeout < (2 * hba->fc_ratov)) {
5579                 timeout = 2 * hba->fc_ratov;
5580         }
5581 
5582         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5583             "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), cmd_size,
5584             rsp_size);
5585 
5586 
5587         if (!cmd_size || !cmd_buf) {
5588                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5589                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5590 
5591                 rval = DFC_ARG_NULL;
5592                 goto done;
5593         }
5594 
5595         if (!rsp_size || !rsp_buf) {
5596                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5597                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
5598 
5599                 rval = DFC_ARG_NULL;
5600                 goto done;
5601         }
5602 
5603         if (!dfc->buf3 || !dfc->buf3_size) {
5604                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5605                     "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
5606 
5607                 rval = DFC_ARG_NULL;
5608                 goto done;
5609         }
5610 
5611         if (!dfc->buf4 || !dfc->buf4_size) {
5612                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5613                     "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
5614 
5615                 rval = DFC_ARG_NULL;
5616                 goto done;
5617         }
5618 
5619         if (rsp_size > MAX_CT_PAYLOAD) {
5620                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5621                     "%s: Buffer2 too large. size=%d",
5622                     emlxs_dfc_xlate(dfc->cmd), rsp_size);
5623 
5624                 rval = DFC_ARG_TOOBIG;
5625                 goto done;
5626         }
5627 
5628         if (cmd_size > MAX_CT_PAYLOAD) {
5629                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5630                     "%s: Buffer1 too large. size=%d",
5631                     emlxs_dfc_xlate(dfc->cmd), cmd_size);
5632 
5633                 rval = DFC_ARG_TOOBIG;
5634                 goto done;
5635         }
5636 
5637         if (dfc->buf3_size < sizeof (dfc_destid_t)) {
5638                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5639                     "%s: Buffer3 too small. (size=%d)",
5640                     emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
5641 
5642                 rval = DFC_ARG_TOOSMALL;
5643                 goto done;
5644         }
5645 
5646         if (dfc->buf4_size < sizeof (uint32_t)) {
5647                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5648                     "%s: Buffer4 too small. (size=%d)",
5649                     emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
5650 
5651                 rval = DFC_ARG_TOOSMALL;
5652                 goto done;
5653         }
5654 
5655         destid = (dfc_destid_t *)dfc->buf3;
5656 
5657         if (destid->idType == 0) {
5658                 if ((nlp = emlxs_node_find_wwpn(port, destid->wwpn, 1))
5659                     == NULL) {
5660                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5661                             "%s: WWPN does not exists. %s",
5662                             emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
5663                             sizeof (buffer), destid->wwpn));
5664 
5665                         rval = DFC_ARG_INVALID;
5666                         goto done;
5667                 }
5668                 did = nlp->nlp_DID;
5669         } else {
5670                 if (emlxs_node_find_did(port, destid->d_id, 1) == NULL) {
5671                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5672                             "%s: DID does not exist. did=%x",
5673                             emlxs_dfc_xlate(dfc->cmd), destid->d_id);
5674 
5675                         rval = DFC_ARG_INVALID;
5676                         goto done;
5677                 }
5678                 did = destid->d_id;
5679         }
5680 
5681         if (did == 0) {
5682                 did = port->did;
5683         }
5684 
5685         if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
5686                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5687                     "%s: Unable to allocate packet.",
5688                     emlxs_dfc_xlate(dfc->cmd));
5689 
5690                 rval = DFC_SYSRES_ERROR;
5691                 goto done;
5692         }
5693 
5694         /* Make this a polled IO */
5695         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5696         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5697         pkt->pkt_comp = NULL;
5698 
5699         pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5700         pkt->pkt_timeout = (timeout) ? timeout : 30;
5701 
5702         /* Build the fc header */
5703         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
5704         pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
5705         pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5706         pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
5707         pkt->pkt_cmd_fhdr.f_ctl =
5708             F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
5709         pkt->pkt_cmd_fhdr.seq_id = 0;
5710         pkt->pkt_cmd_fhdr.df_ctl = 0;
5711         pkt->pkt_cmd_fhdr.seq_cnt = 0;
5712         pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5713         pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5714         pkt->pkt_cmd_fhdr.ro = 0;
5715 
5716         /* Copy in the command buffer */
5717         bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
5718 
5719         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5720                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5721                     "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
5722 
5723                 rval = DFC_IO_ERROR;
5724                 goto done;
5725         }
5726 
5727         if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
5728             (pkt->pkt_state != FC_PKT_FS_RJT)) {
5729                 if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5730                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5731                             "Pkt Transport error. Pkt Timeout.");
5732                         rval = DFC_TIMEOUT;
5733                 } else {
5734                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5735                             "Pkt Transport error. state=%x", pkt->pkt_state);
5736                         rval = DFC_IO_ERROR;
5737                 }
5738                 goto done;
5739         }
5740 
5741         bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size);
5742 
5743         rsp_size -= pkt->pkt_resp_resid;
5744         bcopy((void *)&rsp_size, (void *)dfc->buf4, sizeof (uint32_t));
5745 
5746         rval = 0;
5747 
5748 done:
5749 
5750         if (pkt) {
5751                 emlxs_pkt_free(pkt);
5752         }
5753 
5754         return (rval);
5755 
5756 } /* emlxs_dfc_send_ct() */
5757 
5758 
5759 /*ARGSUSED*/
5760 static int32_t
5761 emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5762 {
5763         emlxs_port_t    *port = &PPORT;
5764         uint8_t         *cmd_buf;
5765         uint32_t        rx_id;
5766         uint32_t        cmd_size;
5767         uint32_t        timeout;
5768         fc_packet_t     *pkt = NULL;
5769         uint32_t        rval = 0;
5770 
5771         cmd_buf = dfc->buf1;
5772         cmd_size = dfc->buf1_size;
5773         rx_id = dfc->flag;
5774         timeout = 2 * hba->fc_ratov;
5775 
5776         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s: csize=%d",
5777             emlxs_dfc_xlate(dfc->cmd), cmd_size);
5778 
5779         if (!cmd_size || !cmd_buf) {
5780                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5781                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5782 
5783                 rval = DFC_ARG_NULL;
5784                 goto done;
5785         }
5786 
5787         if (!(pkt = emlxs_pkt_alloc(port, cmd_size, 0, 0, KM_NOSLEEP))) {
5788                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5789                     "%s: Unable to allocate packet.",
5790                     emlxs_dfc_xlate(dfc->cmd));
5791 
5792                 rval = DFC_SYSRES_ERROR;
5793                 goto done;
5794         }
5795 
5796         /* Make this a polled IO */
5797         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5798         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5799         pkt->pkt_comp = NULL;
5800 
5801         pkt->pkt_tran_type = FC_PKT_OUTBOUND;
5802         pkt->pkt_timeout = (timeout) ? timeout : 30;
5803 
5804         /* Build the fc header */
5805         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(0);
5806         pkt->pkt_cmd_fhdr.r_ctl = R_CTL_SOLICITED_CONTROL;
5807         pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5808         pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
5809         pkt->pkt_cmd_fhdr.f_ctl =
5810             F_CTL_LAST_SEQ | F_CTL_END_SEQ | F_CTL_XCHG_CONTEXT;
5811         pkt->pkt_cmd_fhdr.seq_id = 0;
5812         pkt->pkt_cmd_fhdr.df_ctl = 0;
5813         pkt->pkt_cmd_fhdr.seq_cnt = 0;
5814         pkt->pkt_cmd_fhdr.ox_id = 0xffff;
5815         pkt->pkt_cmd_fhdr.rx_id = rx_id;
5816         pkt->pkt_cmd_fhdr.ro = 0;
5817 
5818         /* Copy in the command buffer */
5819         bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
5820 
5821         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5822                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5823                     "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
5824 
5825                 rval = DFC_IO_ERROR;
5826                 goto done;
5827         }
5828 
5829         if (pkt->pkt_state != FC_PKT_SUCCESS) {
5830                 if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5831                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5832                             "Pkt Transport error. Pkt Timeout.");
5833                         rval = DFC_TIMEOUT;
5834                 } else {
5835                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5836                             "Pkt Transport error. state=%x", pkt->pkt_state);
5837                         rval = DFC_IO_ERROR;
5838                 }
5839                 goto done;
5840         }
5841 
5842         rval = 0;
5843 
5844 done:
5845 
5846         if (pkt) {
5847                 emlxs_pkt_free(pkt);
5848         }
5849 
5850         return (rval);
5851 
5852 } /* emlxs_dfc_send_ct_rsp() */
5853 
5854 
5855 #ifdef MENLO_SUPPORT
5856 
5857 /*ARGSUSED*/
5858 static int32_t
5859 emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5860 {
5861         emlxs_port_t    *port = &PPORT;
5862         uint8_t         *rsp_buf = NULL;
5863         uint8_t         *cmd_buf = NULL;
5864         uint32_t        rsp_size = 0;
5865         uint32_t        cmd_size = 0;
5866         uint32_t        rval = 0;
5867 
5868         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5869             "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size,
5870             dfc->buf2_size);
5871 
5872         if (hba->model_info.device_id != PCI_DEVICE_ID_HORNET) {
5873                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5874                     "%s: Menlo device not present. device=%x,%x",
5875                     emlxs_dfc_xlate(dfc->cmd), hba->model_info.device_id,
5876                     hba->model_info.ssdid);
5877 
5878                 rval = DFC_INVALID_ADAPTER;
5879                 goto done;
5880         }
5881 
5882         if (!dfc->buf1_size || !dfc->buf1) {
5883                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5884                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5885 
5886                 rval = DFC_ARG_NULL;
5887                 goto done;
5888         }
5889 
5890         if (!dfc->buf2_size || !dfc->buf2) {
5891                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5892                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
5893 
5894                 rval = DFC_ARG_NULL;
5895                 goto done;
5896         }
5897 
5898         if (!dfc->buf3 || !dfc->buf3_size) {
5899                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5900                     "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
5901 
5902                 rval = DFC_ARG_NULL;
5903                 goto done;
5904         }
5905 
5906         if (dfc->buf3_size < sizeof (uint32_t)) {
5907                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5908                     "%s: Buffer3 too small. %d < %d",
5909                     emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size,
5910                     sizeof (uint32_t));
5911 
5912                 rval = DFC_ARG_TOOSMALL;
5913                 goto done;
5914         }
5915 
5916         cmd_size  = dfc->buf1_size;
5917         cmd_buf = (uint8_t *)dfc->buf1;
5918 
5919         rsp_size  = dfc->buf2_size;
5920         rsp_buf = (uint8_t *)dfc->buf2;
5921 
5922         /* Send the command */
5923         rval = emlxs_send_menlo_cmd(hba, cmd_buf, cmd_size,
5924             rsp_buf, &rsp_size);
5925 
5926         if (rval == 0) {
5927                 /* Return the response & size */
5928                 bcopy((void *)rsp_buf, (void *)dfc->buf2, rsp_size);
5929                 bcopy((void *)&rsp_size, (void *)dfc->buf3, sizeof (uint32_t));
5930         }
5931 
5932 done:
5933 
5934         return (rval);
5935 
5936 } /* emlxs_dfc_send_menlo() */
5937 
5938 
5939 extern int32_t
5940 emlxs_send_menlo_cmd(emlxs_hba_t *hba, uint8_t *cmd_buf, uint32_t cmd_size,
5941     uint8_t *rsp_buf, uint32_t *rsp_size)
5942 {
5943         emlxs_port_t            *port = &PPORT;
5944         uint8_t                 *data_buf = NULL;
5945         uint32_t                data_size = 0;
5946         fc_packet_t             *pkt = NULL;
5947         int32_t                 rval = 0;
5948         menlo_set_cmd_t         set_cmd;
5949         menlo_reset_cmd_t       reset_cmd;
5950         uint32_t                rsp_code;
5951         uint32_t                mm_mode = 0;
5952         uint32_t                cmd_code;
5953         clock_t                 timeout;
5954         MAILBOXQ                *mbq = NULL;
5955         MAILBOX                 *mb;
5956         uint32_t                addr;
5957         uint32_t                value;
5958         uint32_t                mbxstatus;
5959 
5960         cmd_code = *(uint32_t *)cmd_buf;
5961         cmd_code = BE_SWAP32(cmd_code);
5962 
5963         /* Look for Zephyr specific commands */
5964         if (cmd_code & 0x80000000) {
5965                 bzero((uint8_t *)&reset_cmd, sizeof (menlo_reset_cmd_t));
5966                 bzero((uint8_t *)&set_cmd, sizeof (menlo_set_cmd_t));
5967                 bzero((uint8_t *)&rsp_code, sizeof (uint32_t));
5968 
5969                 /* Validate response buffer */
5970                 if (*rsp_size < sizeof (uint32_t)) {
5971                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5972                             "send_menlo_cmd: Response overrun.");
5973                         rval = DFC_RSP_BUF_OVERRUN;
5974                         goto done;
5975                 }
5976 
5977                 /* All of these responses will be 4 bytes only */
5978                 *rsp_size = sizeof (uint32_t);
5979                 rsp_code = 0;
5980 
5981                 /* Validate command buffer */
5982                 switch (cmd_code) {
5983                 case MENLO_CMD_RESET:
5984                         if (cmd_size < sizeof (menlo_reset_cmd_t)) {
5985                                 EMLXS_MSGF(EMLXS_CONTEXT,
5986                                     &emlxs_dfc_error_msg,
5987                                     "send_menlo_cmd: "
5988                                     "Invalid command size. %d < %d",
5989                                     cmd_size,
5990                                     sizeof (menlo_reset_cmd_t));
5991                                 rval = DFC_ARG_INVALID;
5992                                 goto done;
5993                         }
5994                         cmd_size = sizeof (menlo_reset_cmd_t);
5995 
5996                         /* Read the command buffer */
5997                         bcopy((void *)cmd_buf, (void *)&reset_cmd, cmd_size);
5998 
5999                         if (reset_cmd.firmware) {
6000                                 /* MENLO_FW_GOLDEN */
6001                                 value = 1;
6002 
6003                                 EMLXS_MSGF(EMLXS_CONTEXT,
6004                                     &emlxs_dfc_detail_msg,
6005                                     "send_menlo_cmd: Reset with Golden "
6006                                     "firmware requested.");
6007 
6008                         } else {
6009                                 /* MENLO_FW_OPERATIONAL */
6010                                 value = 0;
6011 
6012                                 EMLXS_MSGF(EMLXS_CONTEXT,
6013                                     &emlxs_dfc_detail_msg,
6014                                     "send_menlo_cmd: Reset with "
6015                                     "Operational firmware requested.");
6016                         }
6017 
6018                         addr  = 0x103007;
6019 
6020                         break;
6021 
6022                 case MENLO_CMD_SET_MODE:
6023                         if (cmd_size < sizeof (menlo_set_cmd_t)) {
6024                                 EMLXS_MSGF(EMLXS_CONTEXT,
6025                                     &emlxs_dfc_error_msg,
6026                                     "send_menlo_cmd: "
6027                                     "Invalid command size. %d < %d",
6028                                     cmd_size,
6029                                     sizeof (menlo_set_cmd_t));
6030                                 rval = DFC_ARG_INVALID;
6031                                 goto done;
6032                         }
6033                         cmd_size = sizeof (menlo_set_cmd_t);
6034 
6035                         /* Read the command buffer */
6036                         bcopy((void *)cmd_buf, (void *)&set_cmd, cmd_size);
6037 
6038                         if (set_cmd.value1) {
6039                                 EMLXS_MSGF(EMLXS_CONTEXT,
6040                                     &emlxs_dfc_detail_msg,
6041                                     "send_menlo_cmd: "
6042                                     "Maintenance mode enable requested.");
6043 
6044                                 /* Make sure the mode flag is cleared */
6045                                 if (hba->flag & FC_MENLO_MODE) {
6046                                         mutex_enter(&EMLXS_PORT_LOCK);
6047                                         hba->flag &= ~FC_MENLO_MODE;
6048                                         mutex_exit(&EMLXS_PORT_LOCK);
6049                                 }
6050 
6051                                 mm_mode = 1;
6052                         } else {
6053                                 EMLXS_MSGF(EMLXS_CONTEXT,
6054                                     &emlxs_dfc_detail_msg,
6055                                     "send_menlo_cmd: "
6056                                     "Maintenance mode disable requested.");
6057                         }
6058 
6059                         addr  = 0x103107;
6060                         value = mm_mode;
6061 
6062                         break;
6063 
6064                 default:
6065                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6066                             "send_menlo_cmd: "
6067                             "Invalid command. cmd=%x", cmd_code);
6068                         rval = DFC_ARG_INVALID;
6069                         goto done;
6070                 }
6071 
6072                 mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
6073                     KM_SLEEP);
6074 
6075                 mb = (MAILBOX *) mbq;
6076 
6077                 /* Create the set_variable mailbox request */
6078                 emlxs_mb_set_var(hba, mbq, addr, value);
6079 
6080                 mbq->flag |= MBQ_PASSTHRU;
6081 
6082                 /* issue the mbox cmd to the sli */
6083                 mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
6084 
6085                 if (mbxstatus) {
6086                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6087                             "send_menlo_cmd: %s failed. mbxstatus=0x%x",
6088                             emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
6089 
6090                         if (mbxstatus == MBX_TIMEOUT) {
6091                                 rval = DFC_TIMEOUT;
6092                         } else {
6093                                 rval = DFC_IO_ERROR;
6094                         }
6095                         goto done;
6096                 }
6097 
6098                 bcopy((void *)&rsp_code, (void *)rsp_buf, *rsp_size);
6099 
6100                 /* Check if we need to wait for maintenance mode */
6101                 if (mm_mode && !(hba->flag & FC_MENLO_MODE)) {
6102                         /* Wait for link to come up in maintenance mode */
6103                         mutex_enter(&EMLXS_LINKUP_LOCK);
6104 
6105                         timeout = emlxs_timeout(hba, 30);
6106 
6107                         rval = 0;
6108                         while ((rval != -1) && !(hba->flag & FC_MENLO_MODE)) {
6109                                 rval =
6110                                     cv_timedwait(&EMLXS_LINKUP_CV,
6111                                     &EMLXS_LINKUP_LOCK, timeout);
6112                         }
6113 
6114                         mutex_exit(&EMLXS_LINKUP_LOCK);
6115 
6116                         if (rval == -1) {
6117                                 EMLXS_MSGF(EMLXS_CONTEXT,
6118                                     &emlxs_dfc_error_msg,
6119                                     "send_menlo_cmd: "
6120                                     "Menlo maintenance mode error. Timeout.");
6121 
6122                                 rval = DFC_TIMEOUT;
6123                                 goto done;
6124                         }
6125                 }
6126         } else {        /* Standard commands */
6127 
6128                 if (hba->state <= FC_LINK_DOWN) {
6129                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6130                             "send_menlo_cmd: Adapter link down.");
6131 
6132                         rval = DFC_LINKDOWN_ERROR;
6133                         goto done;
6134                 }
6135 
6136                 if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
6137                         /* Check cmd size */
6138                         /* Must be at least 12 bytes of command */
6139                         /* plus 4 bytes of data */
6140                         if (cmd_size < (12 + 4)) {
6141                                 EMLXS_MSGF(EMLXS_CONTEXT,
6142                                     &emlxs_dfc_error_msg,
6143                                     "send_menlo_cmd: "
6144                                     "Invalid command size. %d < %d",
6145                                     cmd_size,
6146                                     (12 + 4));
6147 
6148                                 rval = DFC_ARG_INVALID;
6149                                 goto done;
6150                         }
6151 
6152                         /* Extract data buffer from command buffer */
6153                         data_buf    = cmd_buf  + 12;
6154                         data_size   = cmd_size - 12;
6155                         cmd_size    = 12;
6156                 }
6157 
6158                 if (!(pkt = emlxs_pkt_alloc(port, cmd_size, *rsp_size, 0,
6159                     KM_NOSLEEP))) {
6160                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6161                             "send_menlo_cmd: Unable to allocate packet.");
6162 
6163                         rval = DFC_SYSRES_ERROR;
6164                         goto done;
6165                 }
6166 
6167                 /* Make this a polled IO */
6168                 pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6169                 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6170                 pkt->pkt_comp = NULL;
6171                 pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6172                 pkt->pkt_timeout = 30;
6173 
6174                 /* Build the fc header */
6175                 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
6176                 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
6177                 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
6178                 pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
6179                 pkt->pkt_cmd_fhdr.f_ctl =
6180                     F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
6181                 pkt->pkt_cmd_fhdr.seq_id = 0;
6182                 pkt->pkt_cmd_fhdr.df_ctl = 0;
6183                 pkt->pkt_cmd_fhdr.seq_cnt = 0;
6184                 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6185                 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
6186                 pkt->pkt_cmd_fhdr.ro = 0;
6187 
6188                 /* Copy in the command buffer */
6189                 bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
6190 
6191                 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6192                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6193                             "send_menlo_cmd: Unable to send packet.");
6194 
6195                         rval = DFC_IO_ERROR;
6196                         goto done;
6197                 }
6198 
6199                 if (pkt->pkt_state != FC_PKT_SUCCESS) {
6200                         if (pkt->pkt_state == FC_PKT_TIMEOUT) {
6201                                 EMLXS_MSGF(EMLXS_CONTEXT,
6202                                     &emlxs_dfc_error_msg,
6203                                     "send_menlo_cmd: "
6204                                     "Pkt Transport error. Pkt Timeout.");
6205                                 rval = DFC_TIMEOUT;
6206                         } else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
6207                             (pkt->pkt_reason == FC_REASON_OVERRUN)) {
6208                                 EMLXS_MSGF(EMLXS_CONTEXT,
6209                                     &emlxs_dfc_error_msg,
6210                                     "send_menlo_cmd: "
6211                                     "Pkt Transport error. Response overrun.");
6212                                 rval = DFC_RSP_BUF_OVERRUN;
6213                         } else {
6214                                 EMLXS_MSGF(EMLXS_CONTEXT,
6215                                     &emlxs_dfc_error_msg,
6216                                     "send_menlo_cmd: "
6217                                     "Pkt Transport error. state=%x",
6218                                     pkt->pkt_state);
6219                                 rval = DFC_IO_ERROR;
6220                         }
6221                         goto done;
6222                 }
6223 
6224                 if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
6225                         uint32_t *rsp;
6226 
6227                         /* Check response code */
6228                         rsp = (uint32_t *)pkt->pkt_resp;
6229                         rsp_code = *rsp;
6230                         rsp_code = BE_SWAP32(rsp_code);
6231 
6232                         if (rsp_code == MENLO_RSP_SUCCESS) {
6233                                 /* Now transmit the data phase */
6234 
6235                                 /* Save last rx_id */
6236                                 uint32_t rx_id = pkt->pkt_cmd_fhdr.rx_id;
6237 
6238                                 /* Free old pkt */
6239                                 emlxs_pkt_free(pkt);
6240 
6241                                 /* Allocate data pkt */
6242                                 if (!(pkt = emlxs_pkt_alloc(port, data_size,
6243                                     *rsp_size, 0, KM_NOSLEEP))) {
6244                                         EMLXS_MSGF(EMLXS_CONTEXT,
6245                                             &emlxs_dfc_error_msg,
6246                                             "send_menlo_cmd: "
6247                                             "Unable to allocate data "
6248                                             "packet.");
6249 
6250                                         rval = DFC_SYSRES_ERROR;
6251                                         goto done;
6252                                 }
6253 
6254                                 /* Make this a polled IO */
6255                                 pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6256                                 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6257                                 pkt->pkt_comp = NULL;
6258                                 pkt->pkt_tran_type = FC_PKT_OUTBOUND;
6259                                 pkt->pkt_timeout = 30;
6260 
6261                                 /* Build the fc header */
6262                                 pkt->pkt_cmd_fhdr.d_id =
6263                                     LE_SWAP24_LO(EMLXS_MENLO_DID);
6264                                 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
6265                                 pkt->pkt_cmd_fhdr.s_id =
6266                                     LE_SWAP24_LO(port->did);
6267                                 pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
6268                                 pkt->pkt_cmd_fhdr.f_ctl =
6269                                     F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
6270                                     F_CTL_SEQ_INITIATIVE;
6271                                 pkt->pkt_cmd_fhdr.seq_id = 0;
6272                                 pkt->pkt_cmd_fhdr.df_ctl = 0;
6273                                 pkt->pkt_cmd_fhdr.seq_cnt = 0;
6274                                 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6275                                 pkt->pkt_cmd_fhdr.rx_id = rx_id;
6276                                 pkt->pkt_cmd_fhdr.ro = 0;
6277 
6278                                 /* Copy in the data buffer */
6279                                 bcopy((void *)data_buf, (void *)pkt->pkt_cmd,
6280                                     data_size);
6281 
6282                                 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6283                                         EMLXS_MSGF(EMLXS_CONTEXT,
6284                                             &emlxs_dfc_error_msg,
6285                                             "send_menlo_cmd: "
6286                                             "Unable to send data packet.");
6287 
6288                                         rval = DFC_IO_ERROR;
6289                                         goto done;
6290                                 }
6291 
6292                                 if (pkt->pkt_state != FC_PKT_SUCCESS) {
6293                                         if (pkt->pkt_state == FC_PKT_TIMEOUT) {
6294                                                 EMLXS_MSGF(EMLXS_CONTEXT,
6295                                                     &emlxs_dfc_error_msg,
6296                                                     "send_menlo_cmd: "
6297                                                     "Data Pkt Transport "
6298                                                     "error. Pkt Timeout.");
6299                                                 rval = DFC_TIMEOUT;
6300                                         } else if ((pkt->pkt_state ==
6301                                             FC_PKT_LOCAL_RJT) &&
6302                                             (pkt->pkt_reason ==
6303                                             FC_REASON_OVERRUN)) {
6304                                                 EMLXS_MSGF(EMLXS_CONTEXT,
6305                                                     &emlxs_dfc_error_msg,
6306                                                     "send_menlo_cmd: "
6307                                                     "Data Pkt Transport "
6308                                                     "error. Response overrun.");
6309                                                 rval = DFC_RSP_BUF_OVERRUN;
6310                                         } else {
6311                                                 EMLXS_MSGF(EMLXS_CONTEXT,
6312                                                     &emlxs_dfc_error_msg,
6313                                                     "send_menlo_cmd: "
6314                                                     "Data Pkt Transport "
6315                                                     "error. state=%x",
6316                                                     pkt->pkt_state);
6317                                                 rval = DFC_IO_ERROR;
6318                                         }
6319                                         goto done;
6320                                 }
6321                         }
6322                 }
6323 
6324                 bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, *rsp_size);
6325                 *rsp_size = *rsp_size - pkt->pkt_resp_resid;
6326         }
6327 
6328         rval = 0;
6329 
6330 done:
6331 
6332         if (pkt) {
6333                 emlxs_pkt_free(pkt);
6334         }
6335 
6336         if (mbq) {
6337                 kmem_free(mbq, sizeof (MAILBOXQ));
6338         }
6339 
6340         return (rval);
6341 
6342 } /* emlxs_send_menlo_cmd() */
6343 
6344 
6345 /* ARGSUSED */
6346 extern void
6347 emlxs_fcoe_attention_thread(emlxs_hba_t *hba,
6348     void *arg1, void *arg2)
6349 {
6350         emlxs_port_t            *port = &PPORT;
6351         menlo_init_rsp_t        *rsp;
6352         menlo_get_cmd_t         *cmd;
6353         fc_packet_t             *pkt = NULL;
6354 
6355         if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_get_cmd_t),
6356             sizeof (menlo_init_rsp_t), 0, KM_NOSLEEP))) {
6357                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6358                     "FCoE attention: Unable to allocate packet.");
6359 
6360                 return;
6361         }
6362 
6363         /* Make this a polled IO */
6364         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6365         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6366         pkt->pkt_comp = NULL;
6367         pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6368         pkt->pkt_timeout = 30;
6369 
6370         /* Build the fc header */
6371         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
6372         pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
6373         pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
6374         pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
6375         pkt->pkt_cmd_fhdr.f_ctl =
6376             F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
6377         pkt->pkt_cmd_fhdr.seq_id = 0;
6378         pkt->pkt_cmd_fhdr.df_ctl = 0;
6379         pkt->pkt_cmd_fhdr.seq_cnt = 0;
6380         pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6381         pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
6382         pkt->pkt_cmd_fhdr.ro = 0;
6383 
6384         cmd = (menlo_get_cmd_t *)pkt->pkt_cmd;
6385         cmd->code = MENLO_CMD_GET_INIT;
6386         cmd->context = 0;
6387         cmd->length = sizeof (menlo_init_rsp_t);
6388 
6389         /* Little Endian Swap */
6390         cmd->code = BE_SWAP32(cmd->code);
6391         cmd->length = BE_SWAP32(cmd->length);
6392 
6393         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6394                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6395                     "FCoE attention: Unable to send packet.");
6396 
6397                 goto done;
6398         }
6399 
6400         if (pkt->pkt_state != FC_PKT_SUCCESS) {
6401                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6402                     "FCoE attention: Pkt Transport error. state=%x",
6403                     pkt->pkt_state);
6404 
6405                 goto done;
6406         }
6407 
6408         /* Check response code */
6409         rsp = (menlo_init_rsp_t *)pkt->pkt_resp;
6410         rsp->code = BE_SWAP32(rsp->code);
6411 
6412         if (rsp->code != MENLO_RSP_SUCCESS) {
6413                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6414                     "FCoE attention: FCOE Response error =%x", rsp->code);
6415 
6416                 goto done;
6417         }
6418 
6419         /* Little Endian Swap */
6420         rsp->bb_credit = BE_SWAP32(rsp->bb_credit);
6421         rsp->frame_size = BE_SWAP32(rsp->frame_size);
6422         rsp->fw_version = BE_SWAP32(rsp->fw_version);
6423         rsp->reset_status = BE_SWAP32(rsp->reset_status);
6424         rsp->maint_status = BE_SWAP32(rsp->maint_status);
6425         rsp->fw_type = BE_SWAP32(rsp->fw_type);
6426         rsp->fru_data_valid = BE_SWAP32(rsp->fru_data_valid);
6427 
6428         /* Log the event */
6429         emlxs_log_fcoe_event(port, rsp);
6430 
6431         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6432             "MENLO_INIT: bb_credit      = 0x%x", rsp->bb_credit);
6433         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6434             "MENLO_INIT: frame_size     = 0x%x", rsp->frame_size);
6435         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6436             "MENLO_INIT: fw_version     = 0x%x", rsp->fw_version);
6437         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6438             "MENLO_INIT: reset_status   = 0x%x", rsp->reset_status);
6439         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6440             "MENLO_INIT: maint_status   = 0x%x", rsp->maint_status);
6441         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6442             "MENLO_INIT: fw_type        = 0x%x", rsp->fw_type);
6443         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6444             "MENLO_INIT: fru_data_valid = 0x%x", rsp->fru_data_valid);
6445 
6446         /* Perform attention checks */
6447         if (rsp->fru_data_valid == 0) {
6448                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_error_msg,
6449                     "Invalid FRU data found on adapter. "
6450                     "Return adapter to Emulex for repair.");
6451         }
6452 
6453         switch (rsp->fw_type) {
6454         case MENLO_FW_TYPE_GOLDEN:
6455                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_warning_msg,
6456                     "FCoE chip is running Golden firmware. "
6457                     "Update FCoE firmware immediately.");
6458                 break;
6459 
6460         case MENLO_FW_TYPE_DIAG:
6461                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_notice_msg,
6462                     "FCoE chip is running Diagnostic firmware. "
6463                     "Operational use of the adapter is suspended.");
6464                 break;
6465         }
6466 
6467 done:
6468 
6469         if (pkt) {
6470                 emlxs_pkt_free(pkt);
6471         }
6472 
6473         return;
6474 
6475 } /* emlxs_fcoe_attention_thread() */
6476 
6477 #endif /* MENLO_SUPPORT */
6478 
6479 
6480 /*ARGSUSED*/
6481 static int32_t
6482 emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6483 {
6484         emlxs_port_t    *port = &PPORT;
6485         uint32_t        offset;
6486         uint32_t        cnt;
6487         uint8_t         *bptr;
6488         uint32_t        i;
6489 
6490         if (hba->bus_type != SBUS_FC) {
6491                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6492                     "%s: Invalid bus_type. (bus_type=%x)",
6493                     emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
6494 
6495                 return (DFC_ARG_INVALID);
6496         }
6497 
6498         if (!(hba->flag & FC_OFFLINE_MODE)) {
6499                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6500                     "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
6501 
6502                 return (DFC_ONLINE_ERROR);
6503         }
6504 
6505         if (!dfc->buf1 || !dfc->buf1_size) {
6506                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6507                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6508 
6509                 return (DFC_ARG_NULL);
6510         }
6511 
6512         offset = dfc->data1;
6513         cnt = dfc->data2;
6514 
6515         if (offset > (64 * 1024)) {
6516                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6517                     "%s: Offset too large. (offset=%d)",
6518                     emlxs_dfc_xlate(dfc->cmd), offset);
6519 
6520                 return (DFC_ARG_TOOBIG);
6521         }
6522 
6523         if (cnt > dfc->buf1_size) {
6524                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6525                     "%s: Count too large. (count=%d)",
6526                     emlxs_dfc_xlate(dfc->cmd), cnt);
6527 
6528                 return (DFC_ARG_TOOBIG);
6529         }
6530 
6531         if ((cnt + offset) > (64 * 1024)) {
6532                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6533                     "%s: Count+Offset too large. (count=%d offset=%d)",
6534                     emlxs_dfc_xlate(dfc->cmd), cnt, offset);
6535 
6536                 return (DFC_ARG_TOOBIG);
6537         }
6538 
6539         if (cnt == 0) {
6540                 return (0);
6541         }
6542 
6543         bptr = (uint8_t *)dfc->buf1;
6544         for (i = 0; i < cnt; i++) {
6545                 SBUS_WRITE_FLASH_COPY(hba, offset, *bptr);
6546                 offset++;
6547                 bptr++;
6548         }
6549 
6550 #ifdef FMA_SUPPORT
6551         /* Access handle validation */
6552         if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
6553             != DDI_FM_OK) {
6554                 EMLXS_MSGF(EMLXS_CONTEXT,
6555                     &emlxs_invalid_access_handle_msg, NULL);
6556                 return (DFC_DRV_ERROR);
6557         }
6558 #endif  /* FMA_SUPPORT */
6559 
6560         return (0);
6561 
6562 } /* emlxs_dfc_write_flash() */
6563 
6564 
6565 /*ARGSUSED*/
6566 static int32_t
6567 emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6568 {
6569         emlxs_port_t    *port = &PPORT;
6570         uint32_t        offset;
6571         uint32_t        count;
6572         uint32_t        outsz;
6573         uint8_t         *bptr;
6574         uint32_t        i;
6575 
6576         if (hba->bus_type != SBUS_FC) {
6577                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6578                     "%s: Invalid bus_type. (bus_type=%x)",
6579                     emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
6580 
6581                 return (DFC_ARG_INVALID);
6582         }
6583 
6584         if (!(hba->flag & FC_OFFLINE_MODE)) {
6585                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6586                     "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
6587 
6588                 return (DFC_ONLINE_ERROR);
6589         }
6590 
6591         if (!dfc->buf1 || !dfc->buf1_size) {
6592                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6593                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6594 
6595                 return (DFC_ARG_NULL);
6596         }
6597 
6598         offset = dfc->data1;
6599         count = dfc->data2;
6600         outsz = dfc->buf1_size;
6601 
6602         if (offset > (64 * 1024)) {
6603                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6604                     "%s: Offset too large. (offset=%d)",
6605                     emlxs_dfc_xlate(dfc->cmd), offset);
6606 
6607                 return (DFC_ARG_TOOBIG);
6608         }
6609 
6610         if ((count + offset) > (64 * 1024)) {
6611                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6612                     "%s: Count+Offset too large. (count=%d offset=%d)",
6613                     emlxs_dfc_xlate(dfc->cmd), count, offset);
6614 
6615                 return (DFC_ARG_TOOBIG);
6616         }
6617 
6618         if (count < outsz) {
6619                 outsz = count;
6620         }
6621 
6622         bptr = (uint8_t *)dfc->buf1;
6623         for (i = 0; i < outsz; i++) {
6624                 *bptr++ = SBUS_READ_FLASH_COPY(hba, offset++);
6625         }
6626 
6627 #ifdef FMA_SUPPORT
6628         /* Access handle validation */
6629         if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
6630             != DDI_FM_OK) {
6631                 EMLXS_MSGF(EMLXS_CONTEXT,
6632                     &emlxs_invalid_access_handle_msg, NULL);
6633                 return (DFC_DRV_ERROR);
6634         }
6635 #endif  /* FMA_SUPPORT */
6636 
6637         return (0);
6638 
6639 } /* emlxs_dfc_read_flash() */
6640 
6641 
6642 /*ARGSUSED*/
6643 static int32_t
6644 emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6645 {
6646         emlxs_port_t    *port = &PPORT;
6647         uint8_t         *rsp_buf;
6648         uint8_t         *cmd_buf;
6649         dfc_destid_t    *destid;
6650         uint32_t        rsp_size;
6651         uint32_t        cmd_size;
6652         uint32_t        timeout;
6653         fc_packet_t     *pkt = NULL;
6654         NODELIST        *ndlp;
6655         uint32_t        did;
6656         uint32_t        rval = 0;
6657         char            buffer[128];
6658 
6659         cmd_buf = dfc->buf1;
6660         cmd_size = dfc->buf1_size;
6661         rsp_buf = dfc->buf2;
6662         rsp_size = dfc->buf2_size;
6663 
6664         timeout = 2 * hba->fc_ratov;
6665 
6666         if (!cmd_size || !cmd_buf) {
6667                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6668                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6669 
6670                 rval = DFC_ARG_NULL;
6671                 goto done;
6672         }
6673 
6674         if (!rsp_buf || !rsp_size) {
6675                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6676                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
6677 
6678                 rval = DFC_ARG_NULL;
6679                 goto done;
6680         }
6681 
6682         if (!dfc->buf3 || !dfc->buf3_size) {
6683                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6684                     "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
6685 
6686                 rval = DFC_ARG_NULL;
6687                 goto done;
6688         }
6689 
6690         if (dfc->buf3_size < sizeof (dfc_destid_t)) {
6691                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6692                     "%s: Buffer3 too small. (size=%d)",
6693                     emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
6694 
6695                 rval = DFC_ARG_TOOSMALL;
6696                 goto done;
6697         }
6698 
6699         if (!dfc->buf4 || !dfc->buf4_size) {
6700                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6701                     "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
6702 
6703                 rval = DFC_ARG_NULL;
6704                 goto done;
6705         }
6706 
6707         if (dfc->buf4_size < sizeof (uint32_t)) {
6708                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6709                     "%s: Buffer4 too small. (size=%d)",
6710                     emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
6711 
6712                 rval = DFC_ARG_TOOSMALL;
6713                 goto done;
6714         }
6715 
6716         destid = (dfc_destid_t *)dfc->buf3;
6717 
6718         if (destid->idType == 0) {
6719                 if ((ndlp = emlxs_node_find_wwpn(port, destid->wwpn, 1))
6720                     == NULL) {
6721                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6722                             "%s: WWPN does not exists. %s",
6723                             emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
6724                             sizeof (buffer), destid->wwpn));
6725 
6726                         rval = DFC_ARG_INVALID;
6727                         goto done;
6728                 }
6729                 did = ndlp->nlp_DID;
6730         } else {
6731                 if (emlxs_node_find_did(port, destid->d_id, 1) == NULL) {
6732                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6733                             "%s: DID does not exist. did=%x",
6734                             emlxs_dfc_xlate(dfc->cmd), destid->d_id);
6735 
6736                         rval = DFC_ARG_INVALID;
6737                         goto done;
6738                 }
6739                 did = destid->d_id;
6740         }
6741 
6742         if (did == 0) {
6743                 did = port->did;
6744         }
6745 
6746         if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
6747                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6748                     "%s: Unable to allocate packet.",
6749                     emlxs_dfc_xlate(dfc->cmd));
6750 
6751                 rval = DFC_SYSRES_ERROR;
6752                 goto done;
6753         }
6754 
6755         /* Make this a polled IO */
6756         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6757         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6758         pkt->pkt_comp = NULL;
6759 
6760         pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6761         pkt->pkt_timeout = (timeout) ? timeout : 30;
6762 
6763         /* Build the fc header */
6764         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
6765         pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
6766         pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
6767         pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
6768         pkt->pkt_cmd_fhdr.f_ctl =
6769             F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
6770         pkt->pkt_cmd_fhdr.seq_id = 0;
6771         pkt->pkt_cmd_fhdr.df_ctl = 0;
6772         pkt->pkt_cmd_fhdr.seq_cnt = 0;
6773         pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6774         pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
6775         pkt->pkt_cmd_fhdr.ro = 0;
6776 
6777         /* Copy in the command buffer */
6778         bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
6779 
6780         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6781                 rval = DFC_IO_ERROR;
6782                 bzero((void *)rsp_buf, rsp_size);
6783                 bzero((void *)dfc->buf4, sizeof (uint32_t));
6784                 goto done;
6785         }
6786 
6787         if (pkt->pkt_state != FC_PKT_SUCCESS) {
6788                 if (pkt->pkt_state == FC_PKT_LS_RJT) {
6789                         LS_RJT *ls_rjt;
6790                         uint32_t *word;
6791 
6792                         word = (uint32_t *)rsp_buf;
6793                         word[0] = ELS_CMD_LS_RJT;
6794 
6795                         word[1] = 0;
6796                         ls_rjt = (LS_RJT *)&word[1];
6797                         ls_rjt->un.b.lsRjtRsnCode = pkt->pkt_reason;
6798                         ls_rjt->un.b.lsRjtRsnCodeExp = pkt->pkt_expln;
6799 
6800                         rsp_size = 8;
6801                         bcopy((void *)&rsp_size, (void *)dfc->buf4,
6802                             sizeof (uint32_t));
6803 
6804                         goto done;
6805 
6806                 } else if (pkt->pkt_state == FC_PKT_TIMEOUT) {
6807                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6808                             "Pkt Transport error. Pkt Timeout.");
6809                         rval = DFC_TIMEOUT;
6810                 } else {
6811                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6812                             "Pkt Transport error. state=%x", pkt->pkt_state);
6813                         rval = DFC_IO_ERROR;
6814                 }
6815 
6816                 bzero((void *)rsp_buf, rsp_size);
6817                 bzero((void *)dfc->buf4, sizeof (uint32_t));
6818                 goto done;
6819         }
6820 
6821         rsp_size -= pkt->pkt_resp_resid;
6822         bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size);
6823         bcopy((void *)&rsp_size, (void *)dfc->buf4, sizeof (uint32_t));
6824 
6825         rval = 0;
6826 
6827 done:
6828         if (pkt) {
6829                 emlxs_pkt_free(pkt);
6830         }
6831 
6832         return (rval);
6833 
6834 } /* emlxs_dfc_send_els() */
6835 
6836 
6837 /*ARGSUSED*/
6838 static int32_t
6839 emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6840 {
6841         emlxs_port_t    *port = &PPORT;
6842         dfc_ioinfo_t    *ioinfo;
6843         uint32_t        i;
6844 
6845         if (!dfc->buf1 || !dfc->buf1_size) {
6846                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6847                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6848 
6849                 return (DFC_ARG_NULL);
6850         }
6851 
6852         if (dfc->buf1_size < sizeof (dfc_ioinfo_t)) {
6853                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6854                     "%s: Buffer1 too small. (size=%d)",
6855                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6856 
6857                 return (DFC_ARG_TOOSMALL);
6858         }
6859 
6860         ioinfo = (dfc_ioinfo_t *)dfc->buf1;
6861         bzero(ioinfo, sizeof (dfc_ioinfo_t));
6862 
6863         ioinfo->a_mboxCmd = HBASTATS.MboxIssued;
6864         ioinfo->a_mboxCmpl = HBASTATS.MboxCompleted;
6865         ioinfo->a_mboxErr = HBASTATS.MboxError;
6866 
6867         for (i = 0; i < hba->chan_count; i++) {
6868                 ioinfo->a_iocbCmd += HBASTATS.IocbIssued[i];
6869                 ioinfo->a_iocbRsp += HBASTATS.IocbReceived[i];
6870         }
6871 
6872         ioinfo->a_adapterIntr = HBASTATS.IntrEvent[0] + HBASTATS.IntrEvent[1] +
6873             HBASTATS.IntrEvent[2] + HBASTATS.IntrEvent[3] +
6874             HBASTATS.IntrEvent[4] + HBASTATS.IntrEvent[5] +
6875             HBASTATS.IntrEvent[6] + HBASTATS.IntrEvent[7];
6876 
6877         ioinfo->a_fcpCmd = HBASTATS.FcpIssued;
6878         ioinfo->a_fcpCmpl = HBASTATS.FcpCompleted;
6879         ioinfo->a_fcpErr = HBASTATS.FcpCompleted - HBASTATS.FcpGood;
6880 
6881         ioinfo->a_seqXmit = HBASTATS.IpSeqIssued;
6882         ioinfo->a_seqRcv = HBASTATS.IpSeqReceived;
6883         ioinfo->a_seqXmitErr = HBASTATS.IpSeqCompleted - HBASTATS.IpSeqGood;
6884 
6885         ioinfo->a_bcastXmit = HBASTATS.IpBcastIssued;
6886         ioinfo->a_bcastRcv = HBASTATS.IpBcastReceived;
6887 
6888         ioinfo->a_elsXmit = HBASTATS.ElsCmdIssued;
6889         ioinfo->a_elsRcv = HBASTATS.ElsCmdReceived;
6890         ioinfo->a_elsXmitErr = HBASTATS.ElsCmdCompleted - HBASTATS.ElsCmdGood;
6891 
6892         ioinfo->a_RSCNRcv = HBASTATS.ElsRscnReceived;
6893 
6894         ioinfo->a_elsBufPost = HBASTATS.ElsUbPosted;
6895         ioinfo->a_ipBufPost = HBASTATS.IpUbPosted;
6896 
6897         ioinfo->a_cnt1 = 0;
6898         ioinfo->a_cnt2 = 0;
6899         ioinfo->a_cnt3 = 0;
6900         ioinfo->a_cnt4 = 0;
6901 
6902         return (0);
6903 
6904 } /* emlxs_dfc_get_ioinfo() */
6905 
6906 
6907 /*ARGSUSED*/
6908 static int32_t
6909 emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6910 {
6911         emlxs_port_t    *port = &PPORT;
6912         dfc_linkinfo_t  *linkinfo;
6913 
6914         if (!dfc->buf1 || !dfc->buf1_size) {
6915                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6916                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6917 
6918                 return (DFC_ARG_NULL);
6919         }
6920 
6921         if (dfc->buf1_size < sizeof (dfc_linkinfo_t)) {
6922                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6923                     "%s: Buffer1 too small. (size=%d)",
6924                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6925 
6926                 return (DFC_ARG_TOOSMALL);
6927         }
6928 
6929         linkinfo = (dfc_linkinfo_t *)dfc->buf1;
6930         bzero(linkinfo, sizeof (dfc_linkinfo_t));
6931 
6932         linkinfo->a_linkEventTag = hba->link_event_tag;
6933         linkinfo->a_linkUp = HBASTATS.LinkUp;
6934         linkinfo->a_linkDown = HBASTATS.LinkDown;
6935         linkinfo->a_linkMulti = HBASTATS.LinkMultiEvent;
6936         linkinfo->a_DID = port->did;
6937         linkinfo->a_topology = 0;
6938 
6939         if (hba->state <= FC_LINK_DOWN) {
6940                 linkinfo->a_linkState = LNK_DOWN;
6941         }
6942 #ifdef MENLO_SUPPORT
6943         else if (hba->flag & FC_MENLO_MODE) {
6944                 linkinfo->a_linkState = LNK_DOWN;
6945                 linkinfo->a_topology  = LNK_MENLO_MAINTENANCE;
6946 
6947         }
6948 #endif /* MENLO_SUPPORT */
6949         else if (hba->state == FC_LINK_DOWN_PERSIST) {
6950                 linkinfo->a_linkState = LNK_DOWN_PERSIST;
6951         } else if (hba->state < FC_READY) {
6952                 linkinfo->a_linkState = LNK_DISCOVERY;
6953         } else {
6954                 linkinfo->a_linkState = LNK_READY;
6955         }
6956 
6957         if (linkinfo->a_linkState != LNK_DOWN) {
6958                 if (hba->topology == TOPOLOGY_LOOP) {
6959                         if (hba->flag & FC_FABRIC_ATTACHED) {
6960                                 linkinfo->a_topology = LNK_PUBLIC_LOOP;
6961                         } else {
6962                                 linkinfo->a_topology = LNK_LOOP;
6963                         }
6964 
6965                         linkinfo->a_alpa = port->did & 0xff;
6966                         linkinfo->a_alpaCnt = port->alpa_map[0];
6967 
6968                         if (linkinfo->a_alpaCnt > 127) {
6969                                 linkinfo->a_alpaCnt = 127;
6970                         }
6971 
6972                         bcopy((void *)&port->alpa_map[0], linkinfo->a_alpaMap,
6973                             linkinfo->a_alpaCnt+1);
6974                 } else {
6975                         if (hba->flag & FC_FABRIC_ATTACHED) {
6976                                 linkinfo->a_topology = LNK_FABRIC;
6977                         } else {
6978                                 linkinfo->a_topology = LNK_PT2PT;
6979                         }
6980                 }
6981         }
6982 
6983         bcopy(&hba->wwpn, linkinfo->a_wwpName, 8);
6984         bcopy(&hba->wwnn, linkinfo->a_wwnName, 8);
6985 
6986         return (0);
6987 
6988 } /* emlxs_dfc_get_linkinfo() */
6989 
6990 #ifdef SFCT_SUPPORT
6991 /*ARGSUSED*/
6992 static int32_t
6993 emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6994 {
6995         emlxs_port_t            *port = &PPORT;
6996         emlxs_tgtport_stat_t    *statp = &TGTPORTSTAT;
6997         dfc_tgtport_stat_t      *dfcstat;
6998 
6999         if (!dfc->buf1 || !dfc->buf1_size) {
7000                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7001                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7002 
7003                 return (DFC_ARG_NULL);
7004         }
7005 
7006         if (dfc->buf1_size < sizeof (emlxs_tgtport_stat_t)) {
7007                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7008                     "%s: Buffer1 too small. (size=%d)",
7009                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7010 
7011                 return (DFC_ARG_TOOSMALL);
7012         }
7013 
7014         dfcstat = (dfc_tgtport_stat_t *)dfc->buf1;
7015         bzero(dfcstat, sizeof (dfc_tgtport_stat_t));
7016 
7017         dfcstat->Version = DFC_TGTPORT_STAT_VERSION;
7018 
7019         dfcstat->FctRcvDropped = statp->FctRcvDropped;
7020         dfcstat->FctOverQDepth = statp->FctOverQDepth;
7021         dfcstat->FctOutstandingIO = statp->FctOutstandingIO;
7022         dfcstat->FctFailedPortRegister = statp->FctFailedPortRegister;
7023         dfcstat->FctPortRegister = statp->FctPortRegister;
7024         dfcstat->FctPortDeregister = statp->FctPortDeregister;
7025 
7026         dfcstat->FctAbortSent = statp->FctAbortSent;
7027         dfcstat->FctNoBuffer = statp->FctNoBuffer;
7028         dfcstat->FctScsiStatusErr = statp->FctScsiStatusErr;
7029         dfcstat->FctScsiQfullErr = statp->FctScsiQfullErr;
7030         dfcstat->FctScsiResidOver = statp->FctScsiResidOver;
7031         dfcstat->FctScsiResidUnder = statp->FctScsiResidUnder;
7032         dfcstat->FctScsiSenseErr = statp->FctScsiSenseErr;
7033 
7034         dfcstat->FctEvent = statp->FctEvent;
7035         dfcstat->FctCompleted = statp->FctCompleted;
7036         dfcstat->FctCmplGood = statp->FctCmplGood;
7037         dfcstat->FctCmplError = statp->FctCmplError;
7038         dfcstat->FctStray = statp->FctStray;
7039 
7040         bcopy(&statp->FctP2IOWcnt[0], &dfcstat->FctP2IOWcnt[0],
7041             (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7042         bcopy(&statp->FctP2IORcnt[0], &dfcstat->FctP2IORcnt[0],
7043             (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7044         dfcstat->FctIOCmdCnt = statp->FctIOCmdCnt;
7045         dfcstat->FctReadBytes = statp->FctReadBytes;
7046         dfcstat->FctWriteBytes = statp->FctWriteBytes;
7047         dfcstat->FctCmdReceived = statp->FctCmdReceived;
7048 
7049         if (dfc->flag) {     /* Clear counters after read */
7050                 bzero(&statp->FctP2IOWcnt[0],
7051                     (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7052                 bzero(&statp->FctP2IORcnt[0],
7053                     (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
7054                 statp->FctIOCmdCnt = 0;
7055                 statp->FctReadBytes = 0;
7056                 statp->FctWriteBytes = 0;
7057                 statp->FctCmdReceived = 0;
7058         }
7059         if (hba->state <= FC_LINK_DOWN) {
7060                 dfcstat->FctLinkState = LNK_DOWN;
7061         }
7062 #ifdef MENLO_SUPPORT
7063         else if (hba->flag & FC_MENLO_MODE) {
7064                 dfcstat->FctLinkState = LNK_DOWN;
7065         }
7066 #endif /* MENLO_SUPPORT */
7067         else if (hba->state < FC_READY) {
7068                 dfcstat->FctLinkState = LNK_DISCOVERY;
7069         } else {
7070                 dfcstat->FctLinkState = LNK_READY;
7071         }
7072 
7073         return (0);
7074 
7075 } /* emlxs_dfc_get_fctstat() */
7076 #endif /* SFCT_SUPPORT */
7077 
7078 /*ARGSUSED*/
7079 static int32_t
7080 emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7081 {
7082         emlxs_port_t    *port;
7083         emlxs_config_t  *cfg = &CFG;
7084         dfc_node_t      *dnp;
7085         uint32_t        node_count;
7086         NODELIST        *nlp;
7087         uint32_t        i;
7088 
7089         port = &VPORT(dfc->data1);
7090 
7091         if (!dfc->buf1 || !dfc->buf1_size) {
7092                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7093                     "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7094 
7095                 return (DFC_ARG_NULL);
7096         }
7097 
7098         if (dfc->buf1_size < (sizeof (dfc_node_t) * MAX_NODES)) {
7099                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7100                     "%s: Buffer1 too small. (size=%d)",
7101                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7102 
7103                 return (DFC_ARG_TOOSMALL);
7104         }
7105 
7106         if (!dfc->buf2 || !dfc->buf2_size) {
7107                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7108                     "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
7109 
7110                 return (DFC_ARG_NULL);
7111         }
7112 
7113         if (dfc->buf2_size < sizeof (uint32_t)) {
7114                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7115                     "%s: Buffer2 too small. (size=%d)",
7116                     emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
7117 
7118                 return (DFC_ARG_TOOSMALL);
7119         }
7120 
7121         node_count = port->node_count;
7122 
7123         if (node_count == 0) {
7124                 return (0);
7125         }
7126 
7127         dnp = (dfc_node_t *)dfc->buf1;
7128 
7129         node_count = 0;
7130         rw_enter(&port->node_rwlock, RW_READER);
7131         for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
7132                 nlp = port->node_table[i];
7133                 while (nlp && nlp->nlp_active &&
7134                     *((uint64_t *)&nlp->nlp_portname)) {
7135                         dnp->port_id = nlp->nlp_DID;
7136                         dnp->rpi = nlp->nlp_Rpi;
7137                         dnp->xri = nlp->nlp_Xri;
7138 
7139                         bcopy((char *)&nlp->sparm, (char *)&dnp->sparm,
7140                             sizeof (dnp->sparm));
7141 
7142                         if (nlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE) {
7143                                 dnp->flags |= PORT_FLAG_FCP_TARGET;
7144                         }
7145                         if (nlp->nlp_fcp_info & NLP_FCP_INI_DEVICE) {
7146                                 dnp->flags |= PORT_FLAG_FCP_INI;
7147 
7148                         }
7149                         if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
7150                                 dnp->flags |= PORT_FLAG_FCP2;
7151                         }
7152                         if (cfg[CFG_NETWORK_ON].current && nlp->nlp_Xri) {
7153                                 dnp->flags |= PORT_FLAG_IP;
7154                         }
7155                         if (nlp->nlp_fcp_info & NLP_EMLX_VPORT) {
7156                                 dnp->flags |= PORT_FLAG_VPORT;
7157                         }
7158 
7159                         /* Copy our dfc_state */
7160                         dnp->flags |= ((nlp->dfc_state & 0xF) << 28);
7161                         dnp->flags |= PORT_FLAG_DFC_STATE_VALID;
7162 
7163                         dnp++;
7164                         node_count++;
7165                         nlp = (NODELIST *) nlp->nlp_list_next;
7166                 }
7167         }
7168         rw_exit(&port->node_rwlock);
7169 
7170         bcopy((void *)&node_count, (void *)dfc->buf2, sizeof (uint32_t));
7171         return (0);
7172 
7173 } /* emlxs_dfc_get_nodeinfo() */
7174 
7175 
7176 /*ARGSUSED*/
7177 static int32_t
7178 emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7179 {
7180         emlxs_port_t    *port = &PPORT;
7181         uint32_t        offset;
7182         uint32_t        size;
7183         uint32_t        max_size;
7184         uint8_t         *slim;
7185 
7186         offset = dfc->data1;
7187         size = dfc->data2;
7188 
7189         if (!dfc->buf1 || !dfc->buf1_size) {
7190                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7191                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7192 
7193                 return (DFC_ARG_NULL);
7194         }
7195 
7196         if (size > dfc->buf1_size) {
7197                 size = dfc->buf1_size;
7198         }
7199 
7200         if (offset % 4) {
7201                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7202                     "%s: Offset misaligned. (offset=%d)",
7203                     emlxs_dfc_xlate(dfc->cmd), offset);
7204 
7205                 return (DFC_ARG_MISALIGNED);
7206         }
7207 
7208         if (size % 4) {
7209                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7210                     "%s: Size misaligned. (size=%d)",
7211                     emlxs_dfc_xlate(dfc->cmd), size);
7212 
7213                 return (DFC_ARG_MISALIGNED);
7214         }
7215 
7216         if (hba->flag & FC_SLIM2_MODE) {
7217                 max_size = SLI2_SLIM2_SIZE;
7218         } else {
7219                 max_size = 4096;
7220         }
7221 
7222         if (offset >= max_size) {
7223                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7224                     "%s: Offset too large. (offset=%d)",
7225                     emlxs_dfc_xlate(dfc->cmd), offset);
7226 
7227                 return (DFC_ARG_TOOBIG);
7228         }
7229 
7230         if ((size + offset) > max_size) {
7231                 size = (max_size - offset);
7232         }
7233 
7234         if (hba->flag & FC_SLIM2_MODE) {
7235                 slim = (uint8_t *)hba->sli.sli3.slim2.virt + offset;
7236                 BE_SWAP32_BCOPY((uint8_t *)slim, (uint8_t *)dfc->buf1, size);
7237         } else {
7238                 slim = (uint8_t *)hba->sli.sli3.slim_addr + offset;
7239                 READ_SLIM_COPY(hba, (uint32_t *)dfc->buf1, (uint32_t *)slim,
7240                     (size / 4));
7241         }
7242 
7243 #ifdef FMA_SUPPORT
7244         /* Access handle validation */
7245         if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
7246             != DDI_FM_OK) {
7247                 EMLXS_MSGF(EMLXS_CONTEXT,
7248                     &emlxs_invalid_access_handle_msg, NULL);
7249                 return (DFC_DRV_ERROR);
7250         }
7251 #endif  /* FMA_SUPPORT */
7252 
7253         return (0);
7254 
7255 } /* emlxs_dfc_read_mem() */
7256 
7257 
7258 /*ARGSUSED*/
7259 static int32_t
7260 emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7261 {
7262         emlxs_port_t    *port = &PPORT;
7263         uint32_t        offset;
7264         uint32_t        size;
7265         uint32_t        max_size;
7266         uint8_t         *slim;
7267 
7268         offset = dfc->data1;
7269         size = dfc->data2;
7270 
7271         if (!dfc->buf1 || !dfc->buf1_size) {
7272                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7273                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7274 
7275                 return (DFC_ARG_NULL);
7276         }
7277 
7278         if (size > dfc->buf1_size) {
7279                 size = dfc->buf1_size;
7280         }
7281 
7282         if (offset % 4) {
7283                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7284                     "%s: Offset misaligned. (offset=%d)",
7285                     emlxs_dfc_xlate(dfc->cmd), offset);
7286 
7287                 return (DFC_ARG_MISALIGNED);
7288         }
7289 
7290         if (size % 4) {
7291                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7292                     "%s: Size misaligned. (szie=%d)",
7293                     emlxs_dfc_xlate(dfc->cmd), size);
7294 
7295                 return (DFC_ARG_MISALIGNED);
7296         }
7297 
7298         if (hba->flag & FC_SLIM2_MODE) {
7299                 max_size = SLI2_SLIM2_SIZE;
7300         } else {
7301                 max_size = 4096;
7302         }
7303 
7304         if (offset >= max_size) {
7305                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7306                     "%s: Offset too large. (offset=%d)",
7307                     emlxs_dfc_xlate(dfc->cmd), offset);
7308 
7309                 return (DFC_ARG_TOOBIG);
7310         }
7311 
7312         if ((size + offset) > max_size) {
7313                 size = (max_size - offset);
7314         }
7315 
7316         if (hba->flag & FC_SLIM2_MODE) {
7317                 slim = (uint8_t *)hba->sli.sli3.slim2.virt + offset;
7318                 BE_SWAP32_BCOPY((uint8_t *)dfc->buf1, (uint8_t *)slim, size);
7319         } else {
7320                 slim = (uint8_t *)hba->sli.sli3.slim_addr + offset;
7321                 WRITE_SLIM_COPY(hba, (uint32_t *)dfc->buf1, (uint32_t *)slim,
7322                     (size / 4));
7323         }
7324 
7325 #ifdef FMA_SUPPORT
7326         /* Access handle validation */
7327         if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
7328             != DDI_FM_OK) {
7329                 EMLXS_MSGF(EMLXS_CONTEXT,
7330                     &emlxs_invalid_access_handle_msg, NULL);
7331                 return (DFC_DRV_ERROR);
7332         }
7333 #endif  /* FMA_SUPPORT */
7334 
7335         return (0);
7336 
7337 } /* emlxs_dfc_write_mem() */
7338 
7339 
7340 /* ARGSUSED */
7341 static int32_t
7342 emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7343 {
7344         emlxs_port_t    *port = &PPORT;
7345         uint32_t        offset;
7346         uint32_t        value;
7347 
7348         offset = dfc->data1;
7349         value = dfc->data2;
7350 
7351         if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
7352                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7353                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
7354 
7355                 return (DFC_NOT_SUPPORTED);
7356         }
7357 
7358         if (!(hba->flag & FC_OFFLINE_MODE)) {
7359                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7360                     "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
7361 
7362                 return (DFC_ONLINE_ERROR);
7363         }
7364 
7365         if (offset % 4) {
7366                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7367                     "%s: Offset misaligned. (offset=%d)",
7368                     emlxs_dfc_xlate(dfc->cmd), offset);
7369 
7370                 return (DFC_ARG_MISALIGNED);
7371         }
7372 
7373         if (offset > 255) {
7374                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7375                     "%s: Offset too large. (offset=%d)",
7376                     emlxs_dfc_xlate(dfc->cmd), offset);
7377 
7378                 return (DFC_ARG_TOOBIG);
7379         }
7380 
7381         WRITE_CSR_REG(hba, (hba->sli.sli3.csr_addr + offset), value);
7382 
7383 #ifdef FMA_SUPPORT
7384         /* Access handle validation */
7385         if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7386             != DDI_FM_OK) {
7387                 EMLXS_MSGF(EMLXS_CONTEXT,
7388                     &emlxs_invalid_access_handle_msg, NULL);
7389                 return (DFC_DRV_ERROR);
7390         }
7391 #endif  /* FMA_SUPPORT */
7392 
7393         return (0);
7394 
7395 } /* emlxs_dfc_write_ctlreg() */
7396 
7397 
7398 /*ARGSUSED*/
7399 static int32_t
7400 emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7401 {
7402         emlxs_port_t    *port = &PPORT;
7403         uint32_t        offset;
7404         uint32_t        value;
7405 
7406         offset = dfc->data1;
7407 
7408         if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
7409                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7410                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
7411 
7412                 return (DFC_NOT_SUPPORTED);
7413         }
7414 
7415         if (offset % 4) {
7416                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7417                     "%s: Offset misaligned. (offset=%d)",
7418                     emlxs_dfc_xlate(dfc->cmd), offset);
7419 
7420                 return (DFC_ARG_MISALIGNED);
7421         }
7422 
7423         if (offset > 255) {
7424                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7425                     "%s: Offset too large. (offset=%d)",
7426                     emlxs_dfc_xlate(dfc->cmd), offset);
7427 
7428                 return (DFC_ARG_TOOBIG);
7429         }
7430 
7431         if (!dfc->buf1 || !dfc->buf1_size) {
7432                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7433                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7434 
7435                 return (DFC_ARG_NULL);
7436         }
7437 
7438         if (dfc->buf1_size < sizeof (uint32_t)) {
7439                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7440                     "%s: Buffer1 too small. (size=%d)",
7441                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7442 
7443                 return (DFC_ARG_TOOSMALL);
7444         }
7445 
7446         value = READ_CSR_REG(hba, (hba->sli.sli3.csr_addr + offset));
7447         bcopy((void *)&value, (void *)dfc->buf1, sizeof (uint32_t));
7448 
7449 #ifdef FMA_SUPPORT
7450         /* Access handle validation */
7451         if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7452             != DDI_FM_OK) {
7453                 EMLXS_MSGF(EMLXS_CONTEXT,
7454                     &emlxs_invalid_access_handle_msg, NULL);
7455                 return (DFC_DRV_ERROR);
7456         }
7457 #endif  /* FMA_SUPPORT */
7458 
7459         return (0);
7460 
7461 } /* emlxs_dfc_read_ctlreg() */
7462 
7463 
7464 /*ARGSUSED*/
7465 static int32_t
7466 emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7467 {
7468         emlxs_port_t            *port = &PPORT;
7469         uint32_t                event;
7470         uint32_t                enable;
7471         uint32_t                pid;
7472         uint32_t                count;
7473         uint32_t                i;
7474         emlxs_dfc_event_t       *dfc_event;
7475 
7476         event = dfc->data1;
7477         pid = dfc->data2;
7478         enable = dfc->flag;
7479 
7480         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7481             "%s: %s. pid=%d enable=%d", emlxs_dfc_xlate(dfc->cmd),
7482             emlxs_dfc_event_xlate(event), pid, enable);
7483 
7484         switch (event) {
7485         case FC_REG_LINK_EVENT:
7486         case FC_REG_RSCN_EVENT:
7487         case FC_REG_CT_EVENT:
7488         case FC_REG_DUMP_EVENT:
7489         case FC_REG_TEMP_EVENT:
7490         case FC_REG_VPORTRSCN_EVENT:
7491         case FC_REG_FCOE_EVENT:
7492                 break;
7493 
7494         case FC_REG_MULTIPULSE_EVENT:
7495         default:
7496                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7497                     "%s: %s. Invalid event. pid=%d enable=%d",
7498                     emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7499                     pid, enable);
7500 
7501                 return (DFC_ARG_INVALID);
7502         }
7503 
7504         if (enable) {
7505                 if (dfc->buf1_size < sizeof (uint32_t)) {
7506                         dfc->buf1 = NULL;
7507                 } else if (!dfc->buf1) {
7508                         dfc->buf1_size = 0;
7509                 }
7510 
7511                 /* Make sure this pid/event is not already registered */
7512                 dfc_event = NULL;
7513                 for (i = 0; i < MAX_DFC_EVENTS; i++) {
7514                         dfc_event = &hba->dfc_event[i];
7515 
7516                         if (dfc_event->pid == pid &&
7517                             dfc_event->event == event) {
7518                                 break;
7519                         }
7520                 }
7521 
7522                 if (i == MAX_DFC_EVENTS) {
7523                         /* Find next available event object */
7524                         for (i = 0; i < MAX_DFC_EVENTS; i++) {
7525                                 dfc_event = &hba->dfc_event[i];
7526 
7527                                 if (!dfc_event->pid && !dfc_event->event) {
7528                                         break;
7529                                 }
7530                         }
7531 
7532                         /* Return if all event objects are busy */
7533                         if (i == MAX_DFC_EVENTS) {
7534                                 EMLXS_MSGF(EMLXS_CONTEXT,
7535                                     &emlxs_dfc_error_msg,
7536                                     "%s: %s. Too many events registered. "
7537                                     "pid=%d enable=%d",
7538                                     emlxs_dfc_xlate(dfc->cmd),
7539                                     emlxs_dfc_event_xlate(event), pid,
7540                                     enable);
7541 
7542                                 return (DFC_DRVRES_ERROR);
7543                         }
7544                 }
7545 
7546                 /* Initialize */
7547                 dfc_event->pid = pid;
7548                 dfc_event->event = event;
7549                 dfc_event->last_id = (uint32_t)-1;
7550                 dfc_event->dataout = NULL;
7551                 dfc_event->size = 0;
7552                 dfc_event->mode = 0;
7553 
7554                 emlxs_get_dfc_event(port, dfc_event, 0);
7555 
7556                 if (dfc->buf1) {
7557                         bcopy((void *)&dfc_event->last_id, dfc->buf1,
7558                             sizeof (uint32_t));
7559                 }
7560 
7561                 /*
7562                  * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7563                  * "%s: %s. Enabled. pid=%d id=%d", emlxs_dfc_xlate(dfc->cmd),
7564                  * emlxs_dfc_event_xlate(event), pid, dfc_event->last_id);
7565                  */
7566 
7567                 hba->event_mask |= event;
7568 
7569         } else {        /* Disable */
7570 
7571                 /* Find the event entry */
7572                 dfc_event = NULL;
7573                 for (i = 0; i < MAX_DFC_EVENTS; i++) {
7574                         dfc_event = &hba->dfc_event[i];
7575 
7576                         if (dfc_event->pid == pid &&
7577                             dfc_event->event == event) {
7578                                 break;
7579                         }
7580                 }
7581 
7582                 if (i == MAX_DFC_EVENTS) {
7583                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7584                             "%s: %s. Event not registered. pid=%d enable=%d",
7585                             emlxs_dfc_xlate(dfc->cmd),
7586                             emlxs_dfc_event_xlate(event), pid, enable);
7587 
7588                         return (DFC_ARG_INVALID);
7589                 }
7590 
7591                 /* Kill the event thread if it is sleeping */
7592                 (void) emlxs_kill_dfc_event(port, dfc_event);
7593 
7594                 /* Count the number of pids still registered for this event */
7595                 count = 0;
7596                 for (i = 0; i < MAX_DFC_EVENTS; i++) {
7597                         dfc_event = &hba->dfc_event[i];
7598 
7599                         if (dfc_event->event == event) {
7600                                 count++;
7601                         }
7602                 }
7603 
7604                 /* If no more pids need this event, */
7605                 /* then disable logging for this event */
7606                 if (count == 0) {
7607                         hba->event_mask &= ~event;
7608                 }
7609         }
7610 
7611         return (0);
7612 
7613 } /* emlxs_dfc_set_event() */
7614 
7615 
7616 /*ARGSUSED*/
7617 static int32_t
7618 emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7619 {
7620         emlxs_port_t    *port = &PPORT;
7621         uint32_t        size;
7622         int32_t         rval = 0;
7623         HBA_EVENTINFO   *event_buffer = NULL;
7624         uint32_t        event_count = 0;
7625         uint32_t        missed = 0;
7626 
7627         if (!dfc->buf1 || !dfc->buf1_size) {
7628                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7629                     "%s: Null buffer1 buffer.", emlxs_dfc_xlate(dfc->cmd));
7630 
7631                 return (DFC_ARG_NULL);
7632         }
7633 
7634         event_count = dfc->buf1_size / sizeof (HBA_EVENTINFO);
7635 
7636         if (!event_count) {
7637                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7638                     "%s: Buffer1 too small. (size=%d)",
7639                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7640 
7641                 return (DFC_ARG_TOOSMALL);
7642         }
7643 
7644         if (!dfc->buf2 || !dfc->buf2_size) {
7645                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7646                     "%s: Null buffer2 buffer.", emlxs_dfc_xlate(dfc->cmd));
7647 
7648                 return (DFC_ARG_NULL);
7649         }
7650 
7651         if (dfc->buf2_size < sizeof (uint32_t)) {
7652                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7653                     "%s: Buffer2 too small. (size=%d)",
7654                     emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
7655 
7656                 return (DFC_ARG_TOOSMALL);
7657         }
7658 
7659         if (!dfc->buf3 || !dfc->buf3_size) {
7660                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7661                     "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
7662 
7663                 return (DFC_ARG_NULL);
7664         }
7665 
7666         if (dfc->buf3_size < sizeof (uint32_t)) {
7667                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7668                     "%s: Buffer3 too small. (size=%d)",
7669                     emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
7670 
7671                 return (DFC_ARG_TOOSMALL);
7672         }
7673 
7674         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s called. max=%d",
7675             emlxs_dfc_xlate(dfc->cmd), event_count);
7676 
7677         size = (event_count * sizeof (HBA_EVENTINFO));
7678         event_buffer = (HBA_EVENTINFO *)kmem_zalloc(size, KM_SLEEP);
7679 
7680         if (emlxs_get_dfc_eventinfo(port, event_buffer, &event_count,
7681             &missed) != 0) {
7682                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7683                     "%s: get_dfc_eventinfo failed.",
7684                     emlxs_dfc_xlate(dfc->cmd));
7685 
7686                 rval = DFC_DRV_ERROR;
7687                 goto done;
7688         }
7689 
7690         if (event_count) {
7691                 bcopy((void *)event_buffer, dfc->buf1,
7692                     (event_count * sizeof (HBA_EVENTINFO)));
7693         }
7694 
7695         bcopy((void *)&event_count, dfc->buf2, sizeof (uint32_t));
7696         bcopy((void *)&missed, dfc->buf3, sizeof (uint32_t));
7697 
7698         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7699             "%s: events=%d missed=%d new=%d last_id=%d",
7700             emlxs_dfc_xlate(dfc->cmd), event_count, hba->hba_event.missed,
7701             hba->hba_event.new, hba->hba_event.last_id);
7702 
7703 done:
7704 
7705         if (event_buffer) {
7706                 kmem_free(event_buffer, size);
7707         }
7708 
7709         return (rval);
7710 
7711 } /* emlxs_dfc_get_eventinfo() */
7712 
7713 
7714 /*ARGSUSED*/
7715 static int32_t
7716 emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7717 {
7718         emlxs_port_t            *port = &PPORT;
7719         uint32_t                event;
7720         uint32_t                pid;
7721         uint32_t                sleep;
7722         uint32_t                i;
7723         int32_t                 rval = DFC_SUCCESS;
7724         emlxs_dfc_event_t       *dfc_event;
7725 
7726         event = dfc->data1;
7727         pid = dfc->data2;
7728 
7729         if (!dfc->buf1_size) {
7730                 dfc->buf1 = NULL;
7731         } else if (!dfc->buf1) {
7732                 dfc->buf1_size = 0;
7733         }
7734 
7735         if (dfc->buf2_size < sizeof (uint32_t)) {
7736                 dfc->buf2 = NULL;
7737         } else if (!dfc->buf2) {
7738                 dfc->buf2_size = 0;
7739         }
7740 
7741         if (dfc->buf3_size < sizeof (uint32_t)) {
7742                 dfc->buf3 = NULL;
7743         } else if (!dfc->buf3) {
7744                 dfc->buf3_size = 0;
7745         }
7746 
7747         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7748             "%s: %s. pid=%d size=%d,%p rcv_size=%d,%p id=%d",
7749             emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid,
7750             dfc->buf1_size, dfc->buf1, dfc->buf2_size, dfc->buf2, dfc->data3);
7751 
7752         /* Find the event entry */
7753         dfc_event = NULL;
7754         for (i = 0; i < MAX_DFC_EVENTS; i++) {
7755                 dfc_event = &hba->dfc_event[i];
7756 
7757                 if (dfc_event->pid == pid && dfc_event->event == event) {
7758                         break;
7759                 }
7760         }
7761 
7762         if (i == MAX_DFC_EVENTS) {
7763                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7764                     "%s: %s. Event not registered. pid=%d",
7765                     emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7766                     pid);
7767 
7768                 return (DFC_ARG_INVALID);
7769         }
7770 
7771         if (!(hba->event_mask & dfc_event->event)) {
7772                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7773                     "%s: %s. Event not registered. pid=%d",
7774                     emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7775                     pid);
7776 
7777                 return (DFC_ARG_INVALID);
7778         }
7779 
7780         /* Initialize event buffer pointers */
7781         dfc_event->dataout = dfc->buf1;
7782         dfc_event->size = dfc->buf1_size;
7783         dfc_event->last_id = dfc->data3;
7784         dfc_event->mode = mode;
7785 
7786         sleep = (dfc->flag & 0x01) ? 1 : 0;
7787 
7788         emlxs_get_dfc_event(port, dfc_event, sleep);
7789 
7790         if (dfc->buf2) {
7791                 bcopy((void *)&dfc_event->size, dfc->buf2, sizeof (uint32_t));
7792         }
7793 
7794         if (dfc->buf3) {
7795                 bcopy((void *)&dfc_event->last_id, dfc->buf3,
7796                     sizeof (uint32_t));
7797         }
7798 
7799         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7800             "%s: %s. Completed. pid=%d rsize=%d id=%d",
7801             emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid,
7802             dfc_event->size, dfc_event->last_id);
7803 
7804         return (rval);
7805 
7806 } /* emlxs_dfc_get_event() */
7807 
7808 
7809 extern uint32_t
7810 emlxs_get_dump_region(emlxs_hba_t *hba, uint32_t region,
7811     uint8_t *buffer, uint32_t *psize)
7812 {
7813         emlxs_port_t    *port = &PPORT;
7814         uint32_t        size;
7815         uint32_t        size_only;
7816         uint32_t        rval = 0;
7817         uint8_t         *memptr;
7818         uint32_t        *wptr;
7819 
7820         if (!buffer || !(*psize)) {
7821                 size_only = 1;
7822                 size = 0xffffffff;
7823         } else {
7824                 size_only = 0;
7825                 size = *psize;
7826         }
7827 
7828         if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
7829                 if (region != 7) {
7830                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7831                             "get_dump_region: Invalid sli4 region. "
7832                             "(id=%d)", region);
7833 
7834                         rval = DFC_ARG_INVALID;
7835                         goto done;
7836                 }
7837         }
7838 
7839         switch (region) {
7840         case 0: /* SLI Registers */
7841 
7842                 if (size < (4 * sizeof (uint32_t))) {
7843                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7844                             "get_dump_region: Buffer too small. "
7845                             "(SLI Registers: size=%d)", size);
7846 
7847                         rval = DFC_ARG_TOOSMALL;
7848                         goto done;
7849                 }
7850 
7851                 size = (4 * sizeof (uint32_t));
7852 
7853                 if (size_only) {
7854                         break;
7855                 }
7856 
7857                 wptr = (uint32_t *)buffer;
7858                 wptr[0] = READ_CSR_REG(hba, FC_HA_REG(hba));
7859                 wptr[1] = READ_CSR_REG(hba, FC_CA_REG(hba));
7860                 wptr[2] = READ_CSR_REG(hba, FC_HS_REG(hba));
7861                 wptr[3] = READ_CSR_REG(hba, FC_HC_REG(hba));
7862 
7863 #ifdef FMA_SUPPORT
7864                 /* Access handle validation */
7865                 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7866                     != DDI_FM_OK) {
7867                         EMLXS_MSGF(EMLXS_CONTEXT,
7868                             &emlxs_invalid_access_handle_msg, NULL);
7869                         rval = DFC_DRV_ERROR;
7870                 }
7871 #endif  /* FMA_SUPPORT */
7872 
7873                 break;
7874 
7875         case 1: /* SLIM */
7876 
7877                 if (hba->flag & FC_SLIM2_MODE) {
7878                         size = MIN(SLI2_SLIM2_SIZE, size);
7879                 } else {
7880                         size = MIN(4096, size);
7881                 }
7882 
7883                 if (size_only) {
7884                         break;
7885                 }
7886 
7887                 if (hba->flag & FC_SLIM2_MODE) {
7888                         memptr = (uint8_t *)hba->sli.sli3.slim2.virt;
7889                         BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer,
7890                             size);
7891                 } else {
7892                         memptr = (uint8_t *)hba->sli.sli3.slim_addr;
7893                         READ_SLIM_COPY(hba, (uint32_t *)buffer,
7894                             (uint32_t *)memptr, (size / 4));
7895 #ifdef FMA_SUPPORT
7896                         /* Access handle validation */
7897                         if (emlxs_fm_check_acc_handle(hba,
7898                             hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
7899                                 EMLXS_MSGF(EMLXS_CONTEXT,
7900                                     &emlxs_invalid_access_handle_msg, NULL);
7901                                 rval = DFC_DRV_ERROR;
7902                         }
7903 #endif  /* FMA_SUPPORT */
7904                 }
7905 
7906                 break;
7907 
7908         case 2: /* Port Control Block */
7909 
7910                 if (size < sizeof (PCB)) {
7911                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7912                             "get_dump_region: Buffer too small. "
7913                             "(PCB: size=%d)", size);
7914 
7915                         rval = DFC_ARG_TOOSMALL;
7916                         goto done;
7917                 }
7918 
7919                 size = sizeof (PCB);
7920 
7921                 if (size_only) {
7922                         break;
7923                 }
7924 
7925                 memptr = (uint8_t *)&(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb);
7926                 BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
7927                 break;
7928 
7929         case 3: /* MailBox */
7930 
7931                 if (size < MAILBOX_CMD_BSIZE) {
7932                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7933                             "get_dump_region: Buffer too small. "
7934                             "(Mailbox: size=%d)", size);
7935 
7936                         rval = DFC_ARG_TOOSMALL;
7937                         goto done;
7938                 }
7939 
7940                 size = MAILBOX_CMD_BSIZE;
7941 
7942                 if (size_only) {
7943                         break;
7944                 }
7945 
7946                 if (hba->flag & FC_SLIM2_MODE) {
7947                         memptr = (uint8_t *)hba->sli.sli3.slim2.virt;
7948                         BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer,
7949                             size);
7950                 } else {
7951                         memptr = (uint8_t *)hba->sli.sli3.slim_addr;
7952                         READ_SLIM_COPY(hba, (uint32_t *)buffer,
7953                             (uint32_t *)memptr, (size / 4));
7954 #ifdef FMA_SUPPORT
7955                         /* Access handle validation */
7956                         if (emlxs_fm_check_acc_handle(hba,
7957                             hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
7958                                 EMLXS_MSGF(EMLXS_CONTEXT,
7959                                     &emlxs_invalid_access_handle_msg, NULL);
7960                                 rval = DFC_DRV_ERROR;
7961                         }
7962 #endif  /* FMA_SUPPORT */
7963                 }
7964 
7965                 break;
7966 
7967         case 4: /* Host Put/Get pointer array */
7968 
7969                 if (size < MAX_RINGS * sizeof (HGP)) {
7970                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7971                             "get_dump_region: Buffer too small. "
7972                             "(HGP: size=%d)", size);
7973 
7974                         rval = DFC_ARG_TOOSMALL;
7975                         goto done;
7976                 }
7977 
7978                 size = MAX_RINGS * sizeof (HGP);
7979 
7980                 if (size_only) {
7981                         break;
7982                 }
7983 
7984                 {
7985                         memptr = (uint8_t *)hba->sli.sli3.slim_addr +
7986                             hba->sli.sli3.hgp_ring_offset;
7987 
7988                         READ_SLIM_COPY(hba, (uint32_t *)buffer,
7989                             (uint32_t *)memptr, (size / 4));
7990 #ifdef FMA_SUPPORT
7991                         /* Access handle validation */
7992                         if (emlxs_fm_check_acc_handle(hba,
7993                             hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
7994                                 EMLXS_MSGF(EMLXS_CONTEXT,
7995                                     &emlxs_invalid_access_handle_msg, NULL);
7996                                 rval = DFC_DRV_ERROR;
7997                         }
7998 #endif  /* FMA_SUPPORT */
7999                 }
8000 
8001                 break;
8002 
8003         case 5: /* Port  Get/Put pointer array */
8004 
8005                 if (size < MAX_RINGS * sizeof (PGP)) {
8006                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8007                             "get_dump_region: Buffer too small. "
8008                             "(PGP: size=%d)", size);
8009 
8010                         rval = DFC_ARG_TOOSMALL;
8011                         goto done;
8012                 }
8013 
8014                 size = MAX_RINGS * sizeof (PGP);
8015 
8016                 if (size_only) {
8017                         break;
8018                 }
8019 
8020                 memptr = (uint8_t *)
8021                     ((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port;
8022                 BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
8023                 break;
8024 
8025         case 6: /* Command/Response Ring */
8026 
8027                 if (size < SLI_IOCB_MAX_SIZE) {
8028                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8029                             "get_dump_region: Buffer too small. "
8030                             "(Rings: size=%d)", size);
8031 
8032                         rval = DFC_ARG_TOOSMALL;
8033                         goto done;
8034                 }
8035 
8036                 size = SLI_IOCB_MAX_SIZE;
8037 
8038                 if (size_only) {
8039                         break;
8040                 }
8041 
8042                 memptr = (uint8_t *)((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs;
8043                 BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
8044                 break;
8045 
8046         case 7: /* All driver specific structures */
8047 
8048                 if (size < sizeof (emlxs_hba_t)) {
8049                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8050                             "get_dump_region: Buffer too small. "
8051                             "(Driver: size=%d)", size);
8052 
8053                         rval = DFC_ARG_TOOSMALL;
8054                         goto done;
8055                 }
8056 
8057                 size = sizeof (emlxs_hba_t);
8058 
8059                 if (size_only) {
8060                         break;
8061                 }
8062 
8063                 memptr = (uint8_t *)hba;
8064                 bcopy((void *)memptr, (void *)buffer, size);
8065 
8066                 break;
8067 
8068         default:
8069                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8070                     "get_dump_region: Invalid region. (id=%d)", region);
8071 
8072                 rval = DFC_ARG_INVALID;
8073         }
8074 
8075 done:
8076 
8077         *psize = size;
8078 
8079         return (rval);
8080 
8081 } /* emlxs_get_dump_region() */
8082 
8083 
8084 
8085 /*ARGSUSED*/
8086 static int32_t
8087 emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8088 {
8089         emlxs_port_t    *port = &PPORT;
8090         uint32_t        size;
8091         uint32_t        size_only = 0;
8092         uint32_t        rval = 0;
8093 
8094         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8095             "%s: region=%d size=%d",
8096             emlxs_dfc_xlate(dfc->cmd), dfc->data1, dfc->buf1_size);
8097 
8098         if (!dfc->buf1 || !dfc->buf1_size) {
8099                 size_only = 1;
8100         }
8101 
8102         if (!dfc->buf2 || !dfc->buf2_size) {
8103                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8104                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
8105 
8106                 return (DFC_ARG_NULL);
8107         }
8108 
8109         if (dfc->buf2_size < sizeof (uint32_t)) {
8110                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8111                     "%s: Buffer2 too small. (size=%d)",
8112                     emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
8113 
8114                 return (DFC_ARG_TOOSMALL);
8115         }
8116 
8117         /* First get region size only */
8118         size = 0;
8119         rval = emlxs_get_dump_region(hba, dfc->data1, NULL, &size);
8120 
8121         if (rval != 0) {
8122                 goto done;
8123         }
8124 
8125         if (!size_only) {
8126                 if (dfc->buf1_size < size) {
8127                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8128                             "%s: Buffer1 too small. (size: %d < %d)",
8129                             emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size, size);
8130 
8131                         rval = DFC_ARG_TOOSMALL;
8132                         goto done;
8133                 }
8134 
8135                 /* Get the region data */
8136                 rval = emlxs_get_dump_region(hba, dfc->data1, dfc->buf1, &size);
8137 
8138                 if (rval != 0) {
8139                         goto done;
8140                 }
8141         }
8142 
8143         /* Return the region size */
8144         bcopy((void *) &size, (void *) dfc->buf2, sizeof (uint32_t));
8145 
8146 done:
8147         return (rval);
8148 
8149 } /* emlxs_dfc_get_dump_region() */
8150 
8151 
8152 
8153 #ifdef MENLO_SUPPORT
8154 /*ARGSUSED*/
8155 static int32_t
8156 emlxs_dfc_menlo_port_offset(emlxs_hba_t *hba)
8157 {
8158         uint32_t        cnt;
8159         char            pathname[256];
8160 
8161         (void) ddi_pathname(hba->dip, pathname);
8162         cnt = strlen(pathname);
8163         if ((cnt < 4) || (strcmp(&pathname[cnt-3], "0,1") != 0))
8164                 return (0);
8165         return (1);
8166 }
8167 
8168 /*ARGSUSED*/
8169 static int32_t
8170 emlxs_dfc_set_menlo_loopback(emlxs_hba_t *hba)
8171 {
8172         emlxs_port_t *port = &PPORT;
8173         MAILBOXQ *mbq = NULL;
8174         MAILBOX *mb = NULL;
8175         fc_packet_t *pkt = NULL;
8176         uint32_t mbxstatus;
8177         uint32_t i;
8178         uint32_t offset;
8179         uint32_t rval = 0;
8180         menlo_cmd_t *cmd;
8181 
8182         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8183             KM_SLEEP);
8184 
8185         mb = (MAILBOX *)mbq;
8186 
8187         /* SET MENLO maint mode */
8188         /* Create the set_variable mailbox request */
8189         emlxs_mb_set_var(hba, mbq, 0x103107, 1);
8190 
8191         mbq->flag |= MBQ_PASSTHRU;
8192 
8193         /* issue the mbox cmd to the sli */
8194         mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8195 
8196         if (mbxstatus) {
8197                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8198                     "%s: %s failed. mbxstatus=0x%x",
8199                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8200                     emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8201 
8202                 rval = DFC_IO_ERROR;
8203                 if (mbxstatus == MBX_TIMEOUT)
8204                         rval = DFC_TIMEOUT;
8205                 goto done;
8206         }
8207 
8208 
8209         /* Wait 30 sec for maint mode */
8210         i = 0;
8211         do {
8212                 if (i++ > 300) {
8213                         break;
8214                 }
8215 
8216                 delay(drv_usectohz(100000));
8217 
8218         } while (!(hba->flag & FC_MENLO_MODE));
8219 
8220         if (!(hba->flag & FC_MENLO_MODE)) {
8221                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8222                     "%s: Unable to enter maint mode.",
8223                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8224 
8225                 rval = DFC_DRV_ERROR;
8226                 goto done;
8227         }
8228 
8229         offset = emlxs_dfc_menlo_port_offset(hba);
8230         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8231             "%s: Entered maint mode. Port offset: %d",
8232             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), offset);
8233 
8234 
8235         /* Issue Menlo loopback command */
8236         if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t),
8237             sizeof (uint32_t), 0, KM_NOSLEEP))) {
8238                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8239                     "%s: Unable to allocate packet.",
8240                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8241 
8242                 rval = DFC_SYSRES_ERROR;
8243                 goto done;
8244         }
8245 
8246         /* Make this a polled IO */
8247         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8248         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8249         pkt->pkt_comp = NULL;
8250         pkt->pkt_tran_type = FC_PKT_EXCHANGE;
8251         pkt->pkt_timeout = 30;
8252 
8253         /* Build the fc header */
8254         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
8255         pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
8256         pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
8257         pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
8258         pkt->pkt_cmd_fhdr.f_ctl =
8259             F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
8260         pkt->pkt_cmd_fhdr.seq_id = 0;
8261         pkt->pkt_cmd_fhdr.df_ctl = 0;
8262         pkt->pkt_cmd_fhdr.seq_cnt = 0;
8263         pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8264         pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8265         pkt->pkt_cmd_fhdr.ro = 0;
8266 
8267         cmd = (menlo_cmd_t *)pkt->pkt_cmd;
8268         cmd->code = BE_SWAP32(MENLO_CMD_LOOPBACK);
8269         cmd->lb.context = BE_SWAP32(offset);
8270         cmd->lb.type = BE_SWAP32(MENLO_LOOPBACK_ENABLE);
8271 
8272         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8273                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8274                     "%s: Unable to send packet.",
8275                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8276 
8277                 rval = DFC_IO_ERROR;
8278                 goto done;
8279         }
8280 
8281         if (pkt->pkt_state != FC_PKT_SUCCESS) {
8282                 if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8283                         EMLXS_MSGF(EMLXS_CONTEXT,
8284                             &emlxs_dfc_error_msg,
8285                             "%s: Pkt Transport error. Pkt Timeout.",
8286                             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8287                         rval = DFC_TIMEOUT;
8288                 } else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
8289                     (pkt->pkt_reason == FC_REASON_OVERRUN)) {
8290                         EMLXS_MSGF(EMLXS_CONTEXT,
8291                             &emlxs_dfc_error_msg,
8292                             "%s: Pkt Transport error. Rsp overrun.",
8293                             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8294                         rval = DFC_RSP_BUF_OVERRUN;
8295                 } else {
8296                         EMLXS_MSGF(EMLXS_CONTEXT,
8297                             &emlxs_dfc_error_msg,
8298                             "%s: Pkt Transport error. state=%x",
8299                             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8300                             pkt->pkt_state);
8301                         rval = DFC_IO_ERROR;
8302                 }
8303                 goto done;
8304         }
8305 
8306 
8307         /* CLEAR MENLO maint mode */
8308         /* Create the set_variable mailbox request */
8309         emlxs_mb_set_var(hba, mbq, 0x103107, 0);
8310 
8311         mbq->flag |= MBQ_PASSTHRU;
8312 
8313         /* issue the mbox cmd to the sli */
8314         mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8315 
8316         if (mbxstatus) {
8317                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8318                     "%s: %s failed. mbxstatus=0x%x",
8319                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8320                     emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8321 
8322                 rval = DFC_IO_ERROR;
8323                 if (mbxstatus == MBX_TIMEOUT)
8324                         rval = DFC_TIMEOUT;
8325         }
8326 
8327         delay(drv_usectohz(1000000));
8328         i = 0;
8329         while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
8330                 delay(drv_usectohz(100000));
8331                 i++;
8332 
8333                 if (i == 300) {
8334                         rval = DFC_TIMEOUT;
8335 
8336                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8337                             "%s: Linkup timeout.",
8338                             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8339 
8340                         goto done;
8341                 }
8342         }
8343 
8344 done:
8345         /* Free allocated mbox memory */
8346         if (mbq) {
8347                 kmem_free(mbq, sizeof (MAILBOXQ));
8348         }
8349         if (pkt) {
8350                 emlxs_pkt_free(pkt);
8351         }
8352         return (rval);
8353 }
8354 
8355 /*ARGSUSED*/
8356 static int32_t
8357 emlxs_dfc_set_menlo_fte(emlxs_hba_t *hba)
8358 {
8359         emlxs_port_t *port = &PPORT;
8360         fc_packet_t *pkt = NULL;
8361         uint32_t rval = 0;
8362         menlo_cmd_t *cmd;
8363 
8364 
8365         /* Issue Menlo loopback command */
8366         if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t),
8367             sizeof (uint32_t), 0, KM_NOSLEEP))) {
8368                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8369                     "%s: Unable to allocate packet.",
8370                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8371 
8372                 rval = DFC_SYSRES_ERROR;
8373                 goto done;
8374         }
8375 
8376         /* Make this a polled IO */
8377         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8378         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8379         pkt->pkt_comp = NULL;
8380         pkt->pkt_tran_type = FC_PKT_EXCHANGE;
8381         pkt->pkt_timeout = 30;
8382 
8383         /* Build the fc header */
8384         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
8385         pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
8386         pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
8387         pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
8388         pkt->pkt_cmd_fhdr.f_ctl =
8389             F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
8390         pkt->pkt_cmd_fhdr.seq_id = 0;
8391         pkt->pkt_cmd_fhdr.df_ctl = 0;
8392         pkt->pkt_cmd_fhdr.seq_cnt = 0;
8393         pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8394         pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8395         pkt->pkt_cmd_fhdr.ro = 0;
8396 
8397         cmd = (menlo_cmd_t *)pkt->pkt_cmd;
8398         cmd->code = BE_SWAP32(MENLO_CMD_FTE_INSERT);
8399         cmd->fte_insert.fcid = BE_SWAP32(0);
8400         bcopy((caddr_t)&port->wwpn, (caddr_t)cmd->fte_insert.wwpn, 8);
8401 
8402         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8403                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8404                     "%s: Unable to send packet.",
8405                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8406 
8407                 rval = DFC_IO_ERROR;
8408                 goto done;
8409         }
8410 
8411         if (pkt->pkt_state != FC_PKT_SUCCESS) {
8412                 if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8413                         EMLXS_MSGF(EMLXS_CONTEXT,
8414                             &emlxs_dfc_error_msg,
8415                             "%s: Pkt Transport error. Pkt Timeout.",
8416                             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8417                         rval = DFC_TIMEOUT;
8418                 } else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
8419                     (pkt->pkt_reason == FC_REASON_OVERRUN)) {
8420                         EMLXS_MSGF(EMLXS_CONTEXT,
8421                             &emlxs_dfc_error_msg,
8422                             "%s: Pkt Transport error. Rsp overrun.",
8423                             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8424                         rval = DFC_RSP_BUF_OVERRUN;
8425                 } else {
8426                         EMLXS_MSGF(EMLXS_CONTEXT,
8427                             &emlxs_dfc_error_msg,
8428                             "%s: Pkt Transport error. state=%x",
8429                             emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8430                             pkt->pkt_state);
8431                         rval = DFC_IO_ERROR;
8432                 }
8433                 goto done;
8434         }
8435 
8436 
8437 done:
8438         if (pkt) {
8439                 emlxs_pkt_free(pkt);
8440         }
8441         return (rval);
8442 }
8443 
8444 /*ARGSUSED*/
8445 static int32_t
8446 emlxs_dfc_reset_menlo(emlxs_hba_t *hba)
8447 {
8448         emlxs_port_t *port = &PPORT;
8449         MAILBOXQ *mbq = NULL;
8450         MAILBOX *mb = NULL;
8451         uint32_t mbxstatus;
8452         uint32_t rval = 0;
8453 
8454         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8455             KM_SLEEP);
8456 
8457         mb = (MAILBOX *)mbq;
8458 
8459         /* RESET MENLO */
8460         /* Create the set_variable mailbox request */
8461         emlxs_mb_set_var(hba, mbq, 0x103007, 0);
8462 
8463         mbq->flag |= MBQ_PASSTHRU;
8464 
8465         /* issue the mbox cmd to the sli */
8466         mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8467 
8468         if (mbxstatus) {
8469                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8470                     "%s: %s failed. mbxstatus=0x%x",
8471                     emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8472                     emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8473 
8474                 rval = DFC_IO_ERROR;
8475                 if (mbxstatus == MBX_TIMEOUT)
8476                         rval = DFC_TIMEOUT;
8477                 goto done;
8478         }
8479 done:
8480         /* Free allocated mbox memory */
8481         if (mbq) {
8482                 kmem_free(mbq, sizeof (MAILBOXQ));
8483         }
8484         return (rval);
8485 }
8486 
8487 #endif /* MENLO_SUPPORT */
8488 
8489 /* ARGSUSED */
8490 static int32_t
8491 emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8492 {
8493         emlxs_port_t    *port = &PPORT;
8494         emlxs_config_t  *cfg = &CFG;
8495         MAILBOXQ        *mbq = NULL;
8496         MAILBOX         *mb = NULL;
8497         uint32_t        rval = DFC_SUCCESS;
8498         uint32_t        i;
8499         uint32_t        timeout;
8500         uint32_t        topology;
8501         uint32_t        speed;
8502         uint32_t        new_mode;
8503         NODELIST        *ndlp;
8504         XRIobj_t        *xrip;
8505 
8506         if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
8507                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8508                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
8509 
8510                 return (DFC_NOT_SUPPORTED);
8511         }
8512 
8513         /* Reinitialize the link */
8514         switch (dfc->flag) {
8515         case 0: /* Disable */
8516 
8517                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8518                     "%s: Disabling Loopback.", emlxs_dfc_xlate(dfc->cmd));
8519 
8520                 if (!(hba->flag & FC_LOOPBACK_MODE)) {
8521                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8522                             "%s: Loopback already disabled.",
8523                             emlxs_dfc_xlate(dfc->cmd));
8524 
8525                         return (rval);
8526                 }
8527                 goto resetdone;
8528 
8529         case 1: /* Internal loopback */
8530                 new_mode = FC_ILB_MODE;
8531                 topology = FLAGS_LOCAL_LB;
8532                 speed = 0;
8533 
8534                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8535                     "%s: Enabling ILB.", emlxs_dfc_xlate(dfc->cmd));
8536 
8537                 /* Check if mode already set */
8538                 if ((hba->flag & FC_ILB_MODE)) {
8539                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8540                             "%s: ILB mode already enabled.",
8541                             emlxs_dfc_xlate(dfc->cmd));
8542 
8543                         return (rval);
8544                 }
8545 
8546                 break;
8547 
8548         case 2: /* External loopback */
8549                 new_mode = FC_ELB_MODE;
8550                 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
8551                         topology = FLAGS_TOPOLOGY_MODE_LOOP_PT;
8552                 } else {
8553                         topology = FLAGS_TOPOLOGY_MODE_LOOP;
8554                 }
8555                 speed = cfg[CFG_LINK_SPEED].current;
8556 
8557                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8558                     "%s: Enabling ELB.", emlxs_dfc_xlate(dfc->cmd));
8559 
8560                 /* Check if mode already set */
8561                 if ((hba->flag & FC_ELB_MODE)) {
8562                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8563                             "%s: ELB mode already enabled.",
8564                             emlxs_dfc_xlate(dfc->cmd));
8565 
8566                         return (rval);
8567                 }
8568 
8569                 break;
8570 
8571         default:
8572                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8573                     "%s: Invalid loopback mode. (mode=%x)",
8574                     emlxs_dfc_xlate(dfc->cmd), dfc->flag);
8575 
8576                 return (DFC_ARG_INVALID);
8577         }
8578 
8579         /* Make sure adapter is online */
8580         if (emlxs_online(hba)) {
8581                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8582                     "%s: Unable to bring adapter online.",
8583                     emlxs_dfc_xlate(dfc->cmd));
8584 
8585                 return (DFC_OFFLINE_ERROR);
8586         }
8587 
8588 #ifdef MENLO_SUPPORT
8589         if (hba->model_info.device_id == PCI_DEVICE_ID_HORNET) {
8590                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8591                     "%s: Menlo support detected: mode:x%x",
8592                     emlxs_dfc_xlate(dfc->cmd), new_mode);
8593 
8594                 if (new_mode == FC_ILB_MODE) {
8595                         rval = emlxs_dfc_set_menlo_loopback(hba);
8596                         if (rval)
8597                                 goto done;
8598                 }
8599         }
8600 #endif /* MENLO_SUPPORT */
8601 
8602         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8603             KM_SLEEP);
8604 
8605         mb = (MAILBOX *) mbq;
8606 
8607         /* Take the link down */
8608         emlxs_mb_down_link(hba, mbq);
8609 
8610         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8611 
8612         if (rval == MBX_TIMEOUT) {
8613                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8614                     "%s: Mailbox timed out. cmd=%x",
8615                     emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
8616 
8617                 rval = DFC_TIMEOUT;
8618                 goto done;
8619         }
8620 
8621         if (rval) {
8622                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8623                     "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
8624                     emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
8625 
8626                 rval = DFC_IO_ERROR;
8627                 goto done;
8628         }
8629 
8630         /*
8631          * Need *2 since we wait 1/2 sec in while loop.
8632          */
8633         timeout = dfc->data1;
8634         if (!timeout) {
8635                 timeout = 60 * 2;
8636         } else {
8637                 timeout = timeout * 2;
8638         }
8639 
8640         i = 0;
8641         while ((hba->state >= FC_LINK_UP) && (hba->state != FC_ERROR)) {
8642                 delay(drv_usectohz(500000));
8643                 i++;
8644 
8645                 if (i == timeout) {
8646                         rval = DFC_TIMEOUT;
8647 
8648                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8649                             "%s: Linkdown timeout.", emlxs_dfc_xlate(dfc->cmd));
8650 
8651                         goto done;
8652                 }
8653         }
8654 
8655         /* Reinitialize the link */
8656         emlxs_mb_init_link(hba, mbq, topology, speed);
8657 
8658         /* Set the loopback mode and timer */
8659         mutex_enter(&EMLXS_PORT_LOCK);
8660         hba->flag |= new_mode;
8661         hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
8662         mutex_exit(&EMLXS_PORT_LOCK);
8663 
8664         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8665 
8666         if (rval == MBX_TIMEOUT) {
8667                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8668                     "%s: Mailbox timed out. cmd=%x",
8669                     emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
8670 
8671                 rval = DFC_TIMEOUT;
8672                 goto done;
8673         }
8674 
8675         if (rval) {
8676                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8677                     "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
8678                     emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
8679 
8680                 rval = DFC_IO_ERROR;
8681                 goto done;
8682         }
8683 
8684         i = 0;
8685         while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
8686                 delay(drv_usectohz(500000));
8687                 i++;
8688 
8689                 if (i == timeout) {
8690                         rval = DFC_TIMEOUT;
8691 
8692                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8693                             "%s: Linkup timeout.", emlxs_dfc_xlate(dfc->cmd));
8694 
8695                         goto done;
8696                 }
8697         }
8698 
8699         /* Create host node */
8700         if (EMLXS_SLI_REG_DID(port, port->did, (SERV_PARM *)&hba->sparam,
8701             NULL, NULL, NULL)) {
8702                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8703                     "%s: Unable to register host node.",
8704                     emlxs_dfc_xlate(dfc->cmd));
8705 
8706                 rval = DFC_DRV_ERROR;
8707                 goto done;
8708         }
8709 
8710         i = 0;
8711         do {
8712                 if (i++ > 300) {
8713                         break;
8714                 }
8715 
8716                 delay(drv_usectohz(100000));
8717 
8718         } while (!(ndlp = emlxs_node_find_did(port, port->did, 1)));
8719 
8720         if (!ndlp) {
8721                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8722                     "%s: Unable to create host node.",
8723                     emlxs_dfc_xlate(dfc->cmd));
8724 
8725                 rval = DFC_DRV_ERROR;
8726                 goto done;
8727         }
8728 
8729         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8730             "%s: Node created. node=%p", emlxs_dfc_xlate(dfc->cmd), ndlp);
8731 
8732 #ifdef MENLO_SUPPORT
8733         if (hba->model_info.device_id == PCI_DEVICE_ID_HORNET) {
8734                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8735                     "%s: Menlo support detected: mode:x%x",
8736                     emlxs_dfc_xlate(dfc->cmd), new_mode);
8737 
8738                 rval = emlxs_dfc_set_menlo_fte(hba);
8739                 if (rval)
8740                         goto done;
8741         }
8742 #endif /* MENLO_SUPPORT */
8743 
8744         if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
8745                 /* Create host XRI */
8746                 (void) emlxs_create_xri(port, &hba->chan[hba->channel_ct],
8747                     ndlp);
8748 
8749                 i = 0;
8750                 do {
8751                         if (i++ > 300) {
8752                                 break;
8753                         }
8754 
8755                         delay(drv_usectohz(100000));
8756 
8757                 } while (!ndlp->nlp_Xri);
8758 
8759                 if (!ndlp->nlp_Xri) {
8760                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8761                             "%s: Unable to create XRI.",
8762                             emlxs_dfc_xlate(dfc->cmd));
8763 
8764                         rval = DFC_DRV_ERROR;
8765                         goto done;
8766                 }
8767 
8768                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8769                     "%s: XRI created. xri=%d", emlxs_dfc_xlate(dfc->cmd),
8770                     ndlp->nlp_Xri);
8771         } else {
8772                 xrip = emlxs_sli4_reserve_xri(port,
8773                     EMLXS_NODE_TO_RPI(port, ndlp),
8774                     EMLXS_XRI_SOL_CT_TYPE, 0xffff);
8775 
8776                 if (xrip == NULL) {
8777                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8778                             "%s: Unable to reserve XRI.",
8779                             emlxs_dfc_xlate(dfc->cmd));
8780 
8781                         rval = DFC_DRV_ERROR;
8782                         goto done;
8783                 }
8784 
8785                 ndlp->nlp_Xri = xrip->XRI;
8786                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8787                     "%s: XRI reserved. xri=%d", emlxs_dfc_xlate(dfc->cmd),
8788                     ndlp->nlp_Xri);
8789         }
8790 
8791 done:
8792         /* Free allocated mbox memory */
8793         if (mbq) {
8794                 kmem_free(mbq, sizeof (MAILBOXQ));
8795         }
8796 
8797         if (rval) {
8798 resetdone:
8799                 /* Reset the adapter */
8800 #ifdef MENLO_SUPPORT
8801                 if (hba->model_info.device_id == PCI_DEVICE_ID_HORNET) {
8802 
8803                         rval = emlxs_dfc_reset_menlo(hba);
8804 
8805                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8806                             "%s: Menlo reset: rval:x%x",
8807                             emlxs_dfc_xlate(dfc->cmd), rval);
8808         }
8809 #endif /* MENLO_SUPPORT */
8810 
8811                 /* Reset link whether we are bound to ULP or not */
8812                 (void) emlxs_reset_link(hba, 1, 1);
8813         }
8814 
8815         return (rval);
8816 } /* emlxs_dfc_loopback_mode() */
8817 
8818 
8819 /*ARGSUSED*/
8820 static int32_t
8821 emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8822 {
8823         emlxs_port_t    *port = &PPORT;
8824         int32_t         rval = 0;
8825         NODELIST        *ndlp;
8826         clock_t         timeout;
8827         fc_packet_t     *pkt = NULL;
8828         SLI_CT_REQUEST  *CtCmd;
8829         uint16_t        CtRsp;
8830 
8831         if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
8832                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8833                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
8834 
8835                 return (DFC_NOT_SUPPORTED);
8836         }
8837 
8838         mutex_enter(&EMLXS_PORT_LOCK);
8839         if (!(hba->flag & FC_LOOPBACK_MODE)) {
8840                 mutex_exit(&EMLXS_PORT_LOCK);
8841 
8842                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8843                     "%s: Adapter not in loopback mode.",
8844                     emlxs_dfc_xlate(dfc->cmd));
8845 
8846                 rval = DFC_DRV_ERROR;
8847                 goto done;
8848         }
8849         hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
8850         mutex_exit(&EMLXS_PORT_LOCK);
8851 
8852         if (!(hba->flag & FC_ONLINE_MODE)) {
8853                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8854                     "%s: Adapter offline.", emlxs_dfc_xlate(dfc->cmd));
8855 
8856                 rval = DFC_OFFLINE_ERROR;
8857                 goto done;
8858         }
8859 
8860         if (hba->state < FC_LINK_UP) {
8861                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8862                     "%s: Link not up.", emlxs_dfc_xlate(dfc->cmd));
8863 
8864                 rval = DFC_OFFLINE_ERROR;
8865                 goto done;
8866         }
8867 
8868         if (!dfc->buf1 || !dfc->buf1_size) {
8869                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8870                     "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
8871 
8872                 rval = DFC_ARG_NULL;
8873                 goto done;
8874         }
8875 
8876         if (!dfc->buf2 || !dfc->buf2_size) {
8877                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8878                     "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
8879 
8880                 rval = DFC_ARG_NULL;
8881                 goto done;
8882         }
8883 
8884         if (dfc->buf1_size > MAX_CT_PAYLOAD) {
8885                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8886                     "%s: Buffer1 too large. (size=%d)",
8887                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8888 
8889                 rval = DFC_ARG_TOOBIG;
8890                 goto done;
8891         }
8892 
8893         /* Check if we have a node for ourselves */
8894         ndlp = emlxs_node_find_did(port, port->did, 1);
8895 
8896         if (!ndlp) {
8897                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8898                     "%s: Host node not found.", emlxs_dfc_xlate(dfc->cmd));
8899 
8900                 rval = DFC_ARG_INVALID;
8901                 goto done;
8902         }
8903 
8904         if (!ndlp->nlp_Xri) {
8905                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8906                     "%s: Host XRI not found.", emlxs_dfc_xlate(dfc->cmd));
8907 
8908                 rval = DFC_DRV_ERROR;
8909                 goto done;
8910         }
8911 
8912         pkt = emlxs_pkt_alloc(port, dfc->buf1_size + 16,
8913             dfc->buf2_size + 16, 0, KM_SLEEP);
8914 
8915         if (pkt == NULL) {
8916                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8917                     "%s: Unable to allocate pkt.", emlxs_dfc_xlate(dfc->cmd));
8918                 rval = DFC_SYSRES_ERROR;
8919                 goto done;
8920         }
8921 
8922         CtCmd = (SLI_CT_REQUEST*)pkt->pkt_cmd;
8923         CtRsp = SLI_CT_LOOPBACK;
8924         CtCmd->CommandResponse.bits.CmdRsp = LE_SWAP16(CtRsp);
8925 
8926         bcopy((void *)dfc->buf1, (void *)&CtCmd->un.data, dfc->buf1_size);
8927 
8928         pkt->pkt_tran_type = FC_PKT_OUTBOUND;
8929         pkt->pkt_timeout = 2 * hba->fc_ratov;
8930         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8931         pkt->pkt_comp = NULL;
8932 
8933         pkt->pkt_cmd_fhdr.d_id = port->did;
8934         pkt->pkt_cmd_fhdr.r_ctl = FC_SOL_CTL;
8935         pkt->pkt_cmd_fhdr.s_id = port->did;
8936         pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
8937         pkt->pkt_cmd_fhdr.f_ctl = 0;
8938         pkt->pkt_cmd_fhdr.seq_id = 0;
8939         pkt->pkt_cmd_fhdr.df_ctl = 0;
8940         pkt->pkt_cmd_fhdr.seq_cnt = 0;
8941         pkt->pkt_cmd_fhdr.ox_id = 0xffff;
8942         pkt->pkt_cmd_fhdr.rx_id = ndlp->nlp_Xri;
8943         pkt->pkt_cmd_fhdr.ro = 0;
8944 
8945         mutex_enter(&EMLXS_PKT_LOCK);
8946         timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15));
8947 
8948         if (hba->loopback_pkt) {
8949                 rval = 0;
8950                 while ((rval != -1) && hba->loopback_pkt) {
8951                         rval =
8952                             cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK,
8953                             timeout);
8954                 }
8955 
8956                 if (rval == -1) {
8957                         mutex_exit(&EMLXS_PKT_LOCK);
8958 
8959                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8960                             "Loopback busy timeout.");
8961                         rval = DFC_TIMEOUT;
8962                         goto done;
8963                 }
8964         }
8965         hba->loopback_pkt = (void *) pkt;
8966         mutex_exit(&EMLXS_PKT_LOCK);
8967 
8968         /* Send polled command */
8969         if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
8970                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8971                     "Pkt Transport error. ret=%x state=%x", rval,
8972                     pkt->pkt_state);
8973 
8974                 rval = DFC_IO_ERROR;
8975                 goto done;
8976         }
8977 
8978         if (pkt->pkt_state != FC_PKT_SUCCESS) {
8979                 if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8980                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8981                             "Pkt Transport error. Pkt Timeout.");
8982                         rval = DFC_TIMEOUT;
8983                 } else {
8984                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8985                             "Pkt Transport error. state=%x", pkt->pkt_state);
8986                         rval = DFC_IO_ERROR;
8987                 }
8988                 goto done;
8989         }
8990 
8991         /* Wait for sequence completion */
8992         mutex_enter(&EMLXS_PKT_LOCK);
8993         rval = 0;
8994         while ((rval != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) {
8995                 rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout);
8996         }
8997         mutex_exit(&EMLXS_PKT_LOCK);
8998 
8999         if (rval == -1) {
9000                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9001                     "Loopback sequence timeout.");
9002 
9003                 rval = DFC_TIMEOUT;
9004                 goto done;
9005         }
9006 
9007         CtCmd = (SLI_CT_REQUEST*)pkt->pkt_resp;
9008         bcopy((void *)&CtCmd->un.data, (void *)dfc->buf2, dfc->buf2_size);
9009 
9010         rval = 0;
9011 
9012         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s: Test completed.",
9013             emlxs_dfc_xlate(dfc->cmd));
9014 
9015 done:
9016 
9017         if (rval) {
9018                 mutex_enter(&EMLXS_PKT_LOCK);
9019                 if (pkt && (hba->loopback_pkt == pkt)) {
9020                         hba->loopback_pkt = NULL;
9021                 }
9022                 mutex_exit(&EMLXS_PKT_LOCK);
9023 
9024                 /* Reset the adapter */
9025                 (void) emlxs_reset(port, FC_FCA_LINK_RESET);
9026         }
9027 
9028         if (pkt) {
9029                 emlxs_pkt_free(pkt);
9030         }
9031 
9032         return (rval);
9033 
9034 } /* emlxs_dfc_loopback_test() */
9035 
9036 
9037 /*ARGSUSED*/
9038 static int32_t
9039 emlxs_dfc_reset_port(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9040 {
9041         emlxs_port_t    *port = &PPORT;
9042         int32_t         rval = 0;
9043 
9044         switch (dfc->flag) {
9045         case 1:
9046         case 2:
9047                 rval = emlxs_reset(port, FC_FCA_RESET);
9048                 break;
9049         case 3:
9050                 if ((hba->sli_mode < EMLXS_HBA_SLI4_MODE) ||
9051                     ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
9052                     (hba->model_info.chip & EMLXS_BE_CHIPS))) {
9053                         rval = emlxs_reset(port, FC_FCA_RESET);
9054                 } else {
9055                         /* Perform All Firmware Reset */
9056                         rval = emlxs_reset(port, EMLXS_DFC_RESET_ALL);
9057                 }
9058 
9059                 break;
9060 
9061         default:
9062                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9063                     "%s: Invalid reset type. (mode=%x)",
9064                     emlxs_dfc_xlate(dfc->cmd), dfc->flag);
9065 
9066                 return (DFC_ARG_INVALID);
9067         }
9068 
9069         if (rval) {
9070                 rval = DFC_HBA_ERROR;
9071         }
9072         return (rval);
9073 
9074 } /* emlxs_dfc_reset_port() */
9075 
9076 
9077 extern int32_t
9078 emlxs_dfc_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
9079 {
9080         emlxs_port_t    *port = &PPORT;
9081         IOCB            *cmd;
9082         emlxs_buf_t     *sbp;
9083 
9084         cmd = &iocbq->iocb;
9085 
9086         HBASTATS.CtEvent++;
9087 
9088         sbp = (emlxs_buf_t *)iocbq->sbp;
9089 
9090         if (!sbp) {
9091                 HBASTATS.CtStray++;
9092 
9093                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9094                     "Stray interrupt. cmd=0x%x iotag=0x%x status=0x%x "
9095                     "perr=0x%x", (uint32_t)cmd->ULPCOMMAND,
9096                     (uint32_t)cmd->ULPIOTAG, cmd->ULPSTATUS,
9097                     cmd->un.ulpWord[4]);
9098 
9099                 return (DFC_ARG_INVALID);
9100         }
9101 
9102         if (cp->channelno != hba->channel_ct) {
9103                 HBASTATS.CtStray++;
9104 
9105                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9106                     "CT Event: Invalid IO Channel:%d iocbq=%p", cp->channelno,
9107                     iocbq);
9108 
9109                 return (DFC_ARG_INVALID);
9110         }
9111 
9112         switch (cmd->ULPCOMMAND) {
9113         case CMD_XMIT_SEQUENCE_CR:
9114         case CMD_XMIT_SEQUENCE64_CR:
9115         case CMD_XMIT_SEQUENCE_CX:
9116         case CMD_XMIT_SEQUENCE64_CX:
9117 
9118                 HBASTATS.CtCmdCompleted++;
9119 
9120                 if (cmd->ULPSTATUS == 0) {
9121                         HBASTATS.CtCmdGood++;
9122 
9123                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
9124                             "XMIT_SEQUENCE comp: status=0x%x",
9125                             cmd->ULPSTATUS);
9126                 } else {
9127                         HBASTATS.CtCmdError++;
9128 
9129                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9130                             "XMIT_SEQUENCE comp: status=0x%x [%08x,%08x]",
9131                             cmd->ULPSTATUS, cmd->un.ulpWord[4],
9132                             cmd->un.ulpWord[5]);
9133                 }
9134 
9135                 emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
9136                     cmd->un.grsp.perr.statLocalError, 1);
9137 
9138                 break;
9139 
9140         default:
9141 
9142                 HBASTATS.CtStray++;
9143 
9144                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9145                     "Invalid iocb: cmd=0x%x", cmd->ULPCOMMAND);
9146 
9147                 emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
9148                     cmd->un.grsp.perr.statLocalError, 1);
9149 
9150                 break;
9151 
9152         }       /* switch(cmd->ULPCOMMAND) */
9153 
9154         return (0);
9155 
9156 } /* emlxs_dfc_handle_event() */
9157 
9158 
9159 /* ARGSUSED */
9160 extern int
9161 emlxs_dfc_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
9162     MATCHMAP *mp, uint32_t size)
9163 {
9164         emlxs_hba_t     *hba = HBA;
9165         IOCB            *iocb;
9166         uint8_t         *bp;
9167         fc_packet_t     *pkt;
9168 
9169         iocb = &iocbq->iocb;
9170         bp = (uint8_t *)mp->virt;
9171 
9172         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
9173             "CT Receive: cmd=%x status=0x%x ",
9174             iocb->ULPCOMMAND, iocb->ULPSTATUS);
9175 
9176         if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
9177                 /*
9178                  * No response sent on loopback; free the exchange now
9179                  */
9180                 emlxs_abort_ct_exchange(hba, port, iocb->ULPCONTEXT);
9181         }
9182 
9183         /*
9184          * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
9185          * "CT Receive: payload=%p size=%d [%02x,%02x, %02x, %02x]", bp,
9186          * size, bp[0], bp[1], bp[2],bp[3]);
9187          */
9188 
9189         /* Return payload */
9190         mutex_enter(&EMLXS_PKT_LOCK);
9191         if (hba->loopback_pkt) {
9192                 pkt = (fc_packet_t *)hba->loopback_pkt;
9193                 hba->loopback_pkt = NULL;
9194 
9195                 size = MIN(size, pkt->pkt_rsplen);
9196                 bcopy(bp, pkt->pkt_resp, size);
9197                 pkt->pkt_tran_flags |= FC_TRAN_COMPLETED;
9198 
9199                 cv_broadcast(&EMLXS_PKT_CV);
9200         }
9201         mutex_exit(&EMLXS_PKT_LOCK);
9202 
9203         return (0);
9204 
9205 } /* emlxs_dfc_handle_unsol_req() */
9206 
9207 
9208 #ifdef DHCHAP_SUPPORT
9209 
9210 /*ARGSUSED*/
9211 static int32_t
9212 emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9213 {
9214         emlxs_port_t    *port = &PPORT;
9215         uint8_t         *lwwpn;
9216         uint8_t         *rwwpn;
9217         int32_t         rval = 0;
9218 
9219         if (!dfc->buf1 || !dfc->buf1_size) {
9220                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9221                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9222 
9223                 return (DFC_ARG_NULL);
9224         }
9225 
9226         if (dfc->buf1_size < 8) {
9227                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9228                     "%s: Buffer1 too small. (size=%d)",
9229                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9230 
9231                 return (DFC_ARG_TOOSMALL);
9232         }
9233 
9234         if (!dfc->buf2 || !dfc->buf2_size) {
9235                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9236                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
9237 
9238                 return (DFC_ARG_NULL);
9239         }
9240 
9241         if (dfc->buf2_size < 8) {
9242                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9243                     "%s: Buffer2 too small. (size=%d)",
9244                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9245 
9246                 return (DFC_ARG_TOOSMALL);
9247         }
9248 
9249         lwwpn = (uint8_t *)dfc->buf1;
9250         rwwpn = (uint8_t *)dfc->buf2;
9251 
9252         /* Initiate authentication here */
9253         rval = emlxs_dhc_init_auth(hba, lwwpn, rwwpn);
9254 
9255         return (rval);
9256 
9257 } /* emlxs_dfc_init_auth() */
9258 
9259 
9260 /*ARGSUSED*/
9261 static int32_t
9262 emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9263 {
9264         emlxs_port_t            *port = &PPORT;
9265         dfc_fcsp_config_t       *fcsp_config;
9266         uint32_t                rval = DFC_SUCCESS;
9267 
9268         if (!dfc->buf1 || !dfc->buf1_size) {
9269                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9270                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9271 
9272                 return (DFC_ARG_NULL);
9273         }
9274 
9275         if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
9276                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9277                     "%s: Buffer1 too small. (size=%d)",
9278                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9279 
9280                 return (DFC_ARG_TOOSMALL);
9281         }
9282 
9283         fcsp_config = (dfc_fcsp_config_t *)dfc->buf1;
9284 
9285         if ((rval = emlxs_dhc_get_auth_cfg(hba, fcsp_config)) != 0) {
9286                 return (rval);
9287         }
9288 
9289         return (0);
9290 
9291 } /* emlxs_dfc_get_auth_cfg() */
9292 
9293 
9294 
9295 /*ARGSUSED*/
9296 static int32_t
9297 emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9298 {
9299         emlxs_port_t            *port = &PPORT;
9300         dfc_fcsp_config_t       *fcsp_config;
9301         dfc_password_t          *dfc_pwd;
9302         uint32_t                rval = DFC_SUCCESS;
9303 
9304         if (!dfc->buf1 || !dfc->buf1_size) {
9305                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9306                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9307 
9308                 return (DFC_ARG_NULL);
9309         }
9310 
9311         if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
9312                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9313                     "%s: Buffer1 too small. (size=%d)",
9314                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9315 
9316                 return (DFC_ARG_TOOSMALL);
9317         }
9318 
9319         if (!dfc->buf2 || !dfc->buf2_size) {
9320                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9321                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
9322 
9323                 return (DFC_ARG_NULL);
9324         }
9325 
9326         if (dfc->buf2_size < sizeof (dfc_password_t)) {
9327                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9328                     "%s: Buffer2 too small. (size=%d)",
9329                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9330 
9331                 return (DFC_ARG_TOOSMALL);
9332         }
9333 
9334         fcsp_config = (dfc_fcsp_config_t *)dfc->buf1;
9335         dfc_pwd = (dfc_password_t *)dfc->buf2;
9336 
9337         switch (dfc->flag) {
9338         case EMLXS_AUTH_CFG_ADD:
9339                 rval = emlxs_dhc_add_auth_cfg(hba, fcsp_config, dfc_pwd);
9340                 break;
9341 
9342         case EMLXS_AUTH_CFG_DELETE:
9343                 rval = emlxs_dhc_delete_auth_cfg(hba, fcsp_config, dfc_pwd);
9344                 break;
9345         }
9346 
9347         if (rval) {
9348                 return (rval);
9349         }
9350 
9351         return (0);
9352 
9353 } /* emlxs_dfc_set_auth_cfg() */
9354 
9355 
9356 
9357 /*ARGSUSED*/
9358 static int32_t
9359 emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9360 {
9361         emlxs_port_t            *port = &PPORT;
9362         dfc_auth_password_t     *dfc_pwd;
9363         uint32_t                rval = DFC_SUCCESS;
9364 
9365         if (!dfc->buf1 || !dfc->buf1_size) {
9366                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9367                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9368 
9369                 return (DFC_ARG_NULL);
9370         }
9371 
9372         if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
9373                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9374                     "%s: Buffer1 too small. (size=%d)",
9375                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9376 
9377                 return (DFC_ARG_TOOSMALL);
9378         }
9379 
9380         /* Read the auth password */
9381         dfc_pwd = (dfc_auth_password_t *)dfc->buf1;
9382 
9383         if ((rval = emlxs_dhc_get_auth_key(hba, dfc_pwd)) != 0) {
9384                 return (rval);
9385         }
9386 
9387         return (0);
9388 
9389 } /* emlxs_dfc_get_auth_pwd() */
9390 
9391 
9392 /*ARGSUSED*/
9393 static int32_t
9394 emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9395 {
9396         emlxs_port_t            *port = &PPORT;
9397         dfc_auth_password_t     *dfc_pwd;
9398         uint32_t                rval = DFC_SUCCESS;
9399 
9400         if (!dfc->buf1 || !dfc->buf1_size) {
9401                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9402                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9403 
9404                 return (DFC_ARG_NULL);
9405         }
9406 
9407         if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
9408                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9409                     "%s: Buffer1 too small. (size=%d)",
9410                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9411 
9412                 return (DFC_ARG_TOOSMALL);
9413         }
9414 
9415         dfc_pwd = (dfc_auth_password_t *)dfc->buf1;
9416 
9417         if ((rval = emlxs_dhc_set_auth_key(hba, dfc_pwd))) {
9418                 return (rval);
9419         }
9420 
9421         return (0);
9422 
9423 } /* emlxs_dfc_set_auth_pwd() */
9424 
9425 
9426 /*ARGSUSED*/
9427 static int32_t
9428 emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9429 {
9430         emlxs_port_t            *port = &PPORT;
9431         dfc_auth_status_t       *fcsp_status;
9432         uint32_t                rval = DFC_SUCCESS;
9433 
9434         if (!dfc->buf1 || !dfc->buf1_size) {
9435                 EMLXS_MSGF(EMLXS_CONTEXT,
9436                     &emlxs_dfc_error_msg, "%s: Null buffer1 found.",
9437                     emlxs_dfc_xlate(dfc->cmd));
9438 
9439                 return (DFC_ARG_NULL);
9440         }
9441 
9442         if (dfc->buf1_size < sizeof (dfc_auth_status_t)) {
9443                 EMLXS_MSGF(EMLXS_CONTEXT,
9444                     &emlxs_dfc_error_msg, "%s: Buffer too small. (size=%d)",
9445                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9446 
9447                 return (DFC_ARG_TOOSMALL);
9448         }
9449 
9450         fcsp_status = (dfc_auth_status_t *)dfc->buf1;
9451 
9452         if ((rval = emlxs_dhc_get_auth_status(hba, fcsp_status)) != 0) {
9453                 return (rval);
9454         }
9455 
9456         return (0);
9457 
9458 } /* emlxs_dfc_get_auth_status() */
9459 
9460 
9461 /*ARGSUSED*/
9462 static int32_t
9463 emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9464 {
9465         emlxs_port_t            *port = &PPORT;
9466         uint32_t                count;
9467         uint32_t                rval = DFC_SUCCESS;
9468 
9469         /* Lock cfg table while we do this */
9470         /* This prevents the table from changing while we get a copy */
9471         mutex_enter(&hba->auth_lock);
9472 
9473         if (!dfc->buf2 || !dfc->buf2_size) {
9474                 EMLXS_MSGF(EMLXS_CONTEXT,
9475                     &emlxs_dfc_error_msg, "%s: Null buffer2 found.",
9476                     emlxs_dfc_xlate(dfc->cmd));
9477 
9478                 mutex_exit(&hba->auth_lock);
9479                 return (DFC_ARG_NULL);
9480         }
9481 
9482         if (dfc->buf2_size < sizeof (uint32_t)) {
9483                 EMLXS_MSGF(EMLXS_CONTEXT,
9484                     &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)",
9485                     emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
9486 
9487                 mutex_exit(&hba->auth_lock);
9488                 return (DFC_ARG_TOOSMALL);
9489         }
9490 
9491         bcopy((void *)&hba->auth_cfg_count, (void *)dfc->buf2,
9492             sizeof (uint32_t));
9493 
9494         if (!dfc->buf1 || !dfc->buf1_size) {
9495                 mutex_exit(&hba->auth_lock);
9496                 return (DFC_SUCCESS);
9497         }
9498 
9499         /* Check table size */
9500         count = dfc->buf1_size / sizeof (dfc_fcsp_config_t);
9501         if (count < hba->auth_cfg_count) {
9502                 EMLXS_MSGF(EMLXS_CONTEXT,
9503                     &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)",
9504                     emlxs_dfc_xlate(dfc->cmd), count, hba->auth_cfg_count);
9505 
9506                 mutex_exit(&hba->auth_lock);
9507                 return (DFC_ARG_TOOSMALL);
9508         }
9509 
9510         rval = emlxs_dhc_get_auth_cfg_table(hba,
9511             (dfc_fcsp_config_t *)dfc->buf1);
9512         mutex_exit(&hba->auth_lock);
9513         return (rval);
9514 
9515 } /* emlxs_dfc_get_auth_cfg_table() */
9516 
9517 
9518 /*ARGSUSED*/
9519 static int32_t
9520 emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9521 {
9522         emlxs_port_t            *port = &PPORT;
9523         uint32_t                count;
9524         uint32_t                rval = DFC_SUCCESS;
9525 
9526         /* Lock cfg table while we do this */
9527         /* This prevents the table from changing while we get a copy */
9528         mutex_enter(&hba->auth_lock);
9529 
9530         if (!dfc->buf2 || !dfc->buf2_size) {
9531                 EMLXS_MSGF(EMLXS_CONTEXT,
9532                     &emlxs_dfc_error_msg, "%s: Null buffer2 found.",
9533                     emlxs_dfc_xlate(dfc->cmd));
9534 
9535                 mutex_exit(&hba->auth_lock);
9536                 return (DFC_ARG_NULL);
9537         }
9538 
9539         if (dfc->buf2_size < sizeof (uint32_t)) {
9540                 EMLXS_MSGF(EMLXS_CONTEXT,
9541                     &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)",
9542                     emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
9543 
9544                 mutex_exit(&hba->auth_lock);
9545                 return (DFC_ARG_TOOSMALL);
9546         }
9547 
9548         bcopy((void *)&hba->auth_key_count, (void *)dfc->buf2,
9549             sizeof (uint32_t));
9550 
9551         if (!dfc->buf1 || !dfc->buf1_size) {
9552                 mutex_exit(&hba->auth_lock);
9553                 return (DFC_SUCCESS);
9554         }
9555 
9556         /* Check table size */
9557         count = dfc->buf1_size / sizeof (dfc_auth_password_t);
9558         if (count < hba->auth_key_count) {
9559                 EMLXS_MSGF(EMLXS_CONTEXT,
9560                     &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)",
9561                     emlxs_dfc_xlate(dfc->cmd), count, hba->auth_key_count);
9562 
9563                 mutex_exit(&hba->auth_lock);
9564                 return (DFC_ARG_TOOSMALL);
9565         }
9566 
9567         rval = emlxs_dhc_get_auth_key_table(hba,
9568             (dfc_auth_password_t *)dfc->buf1);
9569         mutex_exit(&hba->auth_lock);
9570         return (rval);
9571 
9572 } /* emlxs_dfc_get_auth_key_table() */
9573 
9574 
9575 
9576 #endif  /* DHCHAP_SUPPORT */
9577 
9578 #ifdef SAN_DIAG_SUPPORT
9579 /*ARGSUSED*/
9580 static int32_t
9581 emlxs_dfc_sd_set_bucket(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9582 {
9583         uint32_t        type, search_type;
9584         uint16_t        state;
9585         int32_t         rval = DFC_SD_OK;
9586 
9587         type = dfc->data1;
9588         search_type = dfc->data2;
9589 
9590         mutex_enter(&emlxs_sd_bucket_mutex);
9591         state = emlxs_sd_bucket.state;
9592 
9593         if (state == SD_COLLECTING)
9594                 rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9595         else if ((search_type < SD_SEARCH_LINEAR) ||
9596             (search_type > SD_SEARCH_POWER_2))
9597                 rval = DFC_SD_ERROR_INVALID_ARG;
9598         else if (type != SD_SCSI_IO_LATENCY_TYPE)
9599                 rval = DFC_SD_ERROR_NOT_SUPPORTED;
9600         else {
9601                 bcopy(dfc->buf3, (void *) &emlxs_sd_bucket,
9602                     sizeof (sd_bucket_info_t));
9603                 emlxs_sd_bucket.state = SD_STOPPED;
9604         }
9605 
9606         mutex_exit(&emlxs_sd_bucket_mutex);
9607         return (rval);
9608 }
9609 
9610 /*ARGSUSED*/
9611 static int32_t
9612 emlxs_dfc_sd_destroy_bucket(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9613 {
9614         uint32_t        type;
9615         int32_t         rval = DFC_SD_OK;
9616 
9617         type = dfc->data1;
9618 
9619         mutex_enter(&emlxs_sd_bucket_mutex);
9620 
9621         if (emlxs_sd_bucket.search_type == 0) {
9622                 rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9623         } else if (emlxs_sd_bucket.state == SD_COLLECTING) {
9624                 rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9625         } else if (type != SD_SCSI_IO_LATENCY_TYPE) {
9626                 rval = DFC_SD_ERROR_NOT_SUPPORTED;
9627         } else {
9628                 bzero((uint8_t *)&emlxs_sd_bucket, sizeof (sd_bucket_info_t));
9629         }
9630 
9631         mutex_exit(&emlxs_sd_bucket_mutex);
9632         return (rval);
9633 
9634 } /* emlxs_dfc_sd_destroy_bucket() */
9635 
9636 
9637 /*ARGSUSED*/
9638 static int32_t
9639 emlxs_dfc_sd_get_bucket(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9640 {
9641         uint32_t        type;
9642         int32_t         rval = DFC_SD_OK;
9643 
9644         type = dfc->data1;
9645 
9646         mutex_enter(&emlxs_sd_bucket_mutex);
9647 
9648         if (emlxs_sd_bucket.search_type == 0) {
9649                 rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9650         } else if (type != SD_SCSI_IO_LATENCY_TYPE) {
9651                 rval = DFC_SD_ERROR_NOT_SUPPORTED;
9652         } else {
9653                 bcopy(&emlxs_sd_bucket, dfc->buf3,
9654                     sizeof (sd_bucket_info_t));
9655         }
9656 
9657         mutex_exit(&emlxs_sd_bucket_mutex);
9658         return (rval);
9659 
9660 } /* emlxs_dfc_sd_get_bucket() */
9661 
9662 
9663 /*ARGSUSED*/
9664 static int32_t
9665 emlxs_dfc_sd_start_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9666 {
9667         emlxs_port_t    *vport;
9668         NODELIST        *nlp;
9669         uint8_t         wwpn[8];
9670         int32_t         rval = DFC_SD_OK;
9671         int             i;
9672 
9673         if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9674                 rval = DFC_SD_ERROR_NOT_SUPPORTED;
9675                 goto start_collect_exit;
9676         }
9677 
9678         if (emlxs_sd_bucket.search_type == 0) {
9679                 rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9680                 goto start_collect_exit;
9681         }
9682 
9683         /* Read the wwn object */
9684         bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9685 
9686         /* Make sure WWPN is unique */
9687         vport = emlxs_vport_find_wwpn(hba, wwpn);
9688 
9689         if (!vport) {
9690                 rval = DFC_SD_ERROR_INVALID_PORT;
9691                 goto start_collect_exit;
9692         }
9693 
9694         /* traverse list of nodes for this vport and reset counter */
9695         rw_enter(&vport->node_rwlock, RW_READER);
9696         if (vport->sd_io_latency_state == SD_COLLECTING) {
9697                 rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9698                 rw_exit(&vport->node_rwlock);
9699                 goto start_collect_exit;
9700         }
9701 
9702         for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9703                 nlp = vport->node_table[i];
9704                 while (nlp != NULL) {
9705                         bzero((void *)&nlp->sd_dev_bucket[0],
9706                             sizeof (struct SD_time_stats_v0) *
9707                             SD_IO_LATENCY_MAX_BUCKETS);
9708 
9709                         nlp = nlp->nlp_list_next;
9710                 }
9711         }
9712 
9713         vport->sd_io_latency_state = SD_COLLECTING;
9714         rw_exit(&vport->node_rwlock);
9715 
9716         mutex_enter(&emlxs_sd_bucket_mutex);
9717         emlxs_sd_bucket.state = SD_COLLECTING;
9718         mutex_exit(&emlxs_sd_bucket_mutex);
9719 
9720 start_collect_exit:
9721         return (rval);
9722 }
9723 
9724 
9725 /*ARGSUSED*/
9726 static int32_t
9727 emlxs_dfc_sd_stop_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9728 {
9729         emlxs_port_t    *vport;
9730         emlxs_hba_t     *temp_hba;
9731         uint8_t         wwpn[8];
9732         int32_t         rval = DFC_SD_OK;
9733         int             i, j;
9734 
9735         if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9736                 rval = DFC_SD_ERROR_NOT_SUPPORTED;
9737                 goto stop_collect_exit;
9738         }
9739 
9740         if (emlxs_sd_bucket.search_type == 0) {
9741                 rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9742                 goto stop_collect_exit;
9743         }
9744 
9745         /* Read the wwn object */
9746         bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9747 
9748         /* Make sure WWPN is unique */
9749         vport = emlxs_vport_find_wwpn(hba, wwpn);
9750 
9751         if (!vport) {
9752                 rval = DFC_SD_ERROR_INVALID_PORT;
9753                 goto stop_collect_exit;
9754         }
9755 
9756         rw_enter(&vport->node_rwlock, RW_READER);
9757         if (vport->sd_io_latency_state != SD_COLLECTING) {
9758                 rval = DFC_SD_ERROR_DATA_COLLECTION_NOT_ACTIVE;
9759                 rw_exit(&vport->node_rwlock);
9760                 goto stop_collect_exit;
9761         }
9762         vport->sd_io_latency_state = SD_STOPPED;
9763         rw_exit(&vport->node_rwlock);
9764 
9765         /* see if any other port is collecting io latency */
9766         for (i = 0; i < emlxs_device.hba_count; i++) {
9767                 temp_hba = emlxs_device.hba[i];
9768                 for (j = 0; j < temp_hba->num_of_ports; j++) {
9769                         vport = &temp_hba->port[j];
9770                         if (vport->sd_io_latency_state == SD_COLLECTING)
9771                                 goto stop_collect_exit;
9772                 }
9773         }
9774 
9775         /*
9776          * if we get here, that means no one else is collecting
9777          * io latency data.
9778          */
9779         mutex_enter(&emlxs_sd_bucket_mutex);
9780         emlxs_sd_bucket.state = SD_STOPPED;
9781         mutex_exit(&emlxs_sd_bucket_mutex);
9782 
9783 stop_collect_exit:
9784         return (rval);
9785 }
9786 
9787 
9788 /*ARGSUSED*/
9789 static int32_t
9790 emlxs_dfc_sd_reset_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9791 {
9792         emlxs_port_t   *vport;
9793         NODELIST        *nlp;
9794         uint8_t         wwpn[8];
9795         int32_t         rval = DFC_SD_OK;
9796         int             i;
9797 
9798         if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9799                 rval = DFC_SD_ERROR_NOT_SUPPORTED;
9800                 goto reset_collect_exit;
9801         }
9802 
9803         if (emlxs_sd_bucket.search_type == 0) {
9804                 rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9805                 goto reset_collect_exit;
9806         }
9807 
9808         /* Read the wwn object */
9809         bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9810 
9811         /* Make sure WWPN is unique */
9812         vport = emlxs_vport_find_wwpn(hba, wwpn);
9813 
9814         if (!vport) {
9815                 rval = DFC_SD_ERROR_INVALID_PORT;
9816                 goto reset_collect_exit;
9817         }
9818 
9819         /* traverse list of nodes for this vport and reset counter */
9820         rw_enter(&vport->node_rwlock, RW_READER);
9821         for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9822                 nlp = vport->node_table[i];
9823                 while (nlp != NULL) {
9824                         bzero((void *)&nlp->sd_dev_bucket[0],
9825                             sizeof (struct SD_time_stats_v0) *
9826                             SD_IO_LATENCY_MAX_BUCKETS);
9827 
9828                         nlp = nlp->nlp_list_next;
9829                 }
9830         }
9831         rw_exit(&vport->node_rwlock);
9832 
9833 reset_collect_exit:
9834         return (rval);
9835 }
9836 
9837 
9838 /*ARGSUSED*/
9839 static int32_t
9840 emlxs_dfc_sd_get_data(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9841 {
9842         emlxs_port_t   *vport;
9843         uint8_t         wwpn[8];
9844         int             i, skip_bytes;
9845         uint16_t        count;
9846         uint32_t        bufsize, size_needed;
9847         NODELIST        *nlp;
9848         int32_t         rval = DFC_SD_OK;
9849 
9850         if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9851                 rval = DFC_SD_ERROR_NOT_SUPPORTED;
9852                 goto get_data_exit;
9853         }
9854 
9855         if (emlxs_sd_bucket.search_type == 0) {
9856                 rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9857                 goto get_data_exit;
9858         }
9859 
9860         /* Read the wwn object */
9861         bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9862 
9863         /* Make sure WWPN is unique */
9864         vport = emlxs_vport_find_wwpn(hba, wwpn);
9865 
9866         if (!vport) {
9867                 rval = DFC_SD_ERROR_INVALID_PORT;
9868                 goto get_data_exit;
9869         }
9870 
9871         bufsize = dfc->buf4_size;
9872 
9873         /*
9874          * count # of targets to see if buffer is big enough
9875          */
9876         count = 0;
9877         rw_enter(&vport->node_rwlock, RW_READER);
9878         for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9879                 nlp = vport->node_table[i];
9880                 while (nlp != NULL) {
9881                         count++;
9882                         nlp = nlp->nlp_list_next;
9883                 }
9884         }
9885         rw_exit(&vport->node_rwlock);
9886 
9887         size_needed = count * (sizeof (HBA_WWN) +
9888             sizeof (struct SD_time_stats_v0) * SD_IO_LATENCY_MAX_BUCKETS);
9889 
9890         if (bufsize < size_needed) {
9891                 rval = DFC_SD_ERROR_MORE_DATA_AVAIL;
9892                 goto update_count;      /* not enough space, return */
9893         }
9894 
9895         /*
9896          * return data collected, reset counter.
9897          */
9898         count = 0;
9899         skip_bytes = 0;
9900         rw_enter(&vport->node_rwlock, RW_READER);
9901         for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9902                 nlp = vport->node_table[i];
9903                 while (nlp != NULL) {
9904                         /* copy port name */
9905                         bcopy((void *)&nlp->nlp_portname,
9906                             (void *)((char *)dfc->buf4 + skip_bytes),
9907                             sizeof (HBA_WWN));
9908                         skip_bytes += sizeof (HBA_WWN);
9909 
9910                         /* copy bucket data */
9911                         bcopy((void *)&nlp->sd_dev_bucket[0],
9912                             (void *)((char *)dfc->buf4 + skip_bytes),
9913                             sizeof (struct SD_time_stats_v0) *
9914                             SD_IO_LATENCY_MAX_BUCKETS);
9915                         skip_bytes += sizeof (struct SD_time_stats_v0) *
9916                             SD_IO_LATENCY_MAX_BUCKETS;
9917 
9918                         bzero((void *)&nlp->sd_dev_bucket[0],
9919                             sizeof (struct SD_time_stats_v0) *
9920                             SD_IO_LATENCY_MAX_BUCKETS);
9921 
9922                         count++;
9923                         bufsize -= sizeof (struct SD_IO_Latency_Response);
9924 
9925                         nlp = nlp->nlp_list_next;
9926                 }
9927         }
9928         rw_exit(&vport->node_rwlock);
9929 
9930 update_count:
9931         bcopy((void *)&count, (void *)dfc->buf2, sizeof (uint16_t));
9932 
9933 get_data_exit:
9934         return (rval);
9935 
9936 } /* emlxs_dfc_sd_get_data() */
9937 
9938 
9939 /*ARGSUSED*/
9940 static int32_t
9941 emlxs_dfc_sd_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9942 {
9943         emlxs_port_t            *vport;
9944         uint8_t                 wwpn[8];
9945         uint32_t                event, pid, enable;
9946         int32_t                 rval = DFC_SD_OK;
9947         int                     i, count;
9948         emlxs_dfc_event_t       *dfc_event;
9949 
9950         /*
9951          * The value of "event" has been shifted left based on
9952          * the category that the application gave to libdfc.
9953          *
9954          * This is so the old Event handling code won't mistakenly
9955          * grab an SD Event.
9956          */
9957         event = dfc->data1;
9958         pid = dfc->data3;
9959         enable = dfc->flag;
9960 
9961         /* Read the wwn object */
9962         bcopy((void *)dfc->buf3, (void *)wwpn, 8);
9963 
9964         /* Make sure WWPN is unique */
9965         vport = emlxs_vport_find_wwpn(hba, wwpn);
9966 
9967         if (!vport) {
9968                 rval = DFC_SD_ERROR_INVALID_PORT;
9969                 goto set_sd_event_exit;
9970         }
9971 
9972         if (enable) {
9973                 /* Find next available event object */
9974                 for (i = 0; i < MAX_DFC_EVENTS; i++) {
9975                         dfc_event = &vport->sd_events[i];
9976 
9977                         if (!dfc_event->pid && !dfc_event->event)
9978                                 break;
9979                 }
9980 
9981                 /* Return if all event objects are busy */
9982                 if (i == MAX_DFC_EVENTS) {
9983                         rval = DFC_SD_ERROR_OUT_OF_HANDLES;
9984                         goto set_sd_event_exit;
9985                 }
9986 
9987                 /* Initialize */
9988                 /* TODO: Should we add SUBCAT in dfc_event ??? */
9989                 dfc_event->pid = pid;
9990                 dfc_event->event = event;
9991                 dfc_event->last_id = (uint32_t)-1;
9992                 dfc_event->dataout = NULL;
9993                 dfc_event->size = 0;
9994                 dfc_event->mode = 0;
9995 
9996                 emlxs_get_sd_event(vport, dfc_event, 0);
9997 
9998                 if (dfc->buf1) {
9999                         bcopy((void *) &dfc_event->last_id, dfc->buf1,
10000                             sizeof (uint32_t));
10001                 }
10002 
10003                 vport->sd_event_mask |= event;
10004         } else { /* Disable */
10005                 /* find event entry */
10006                 for (i = 0; i < MAX_DFC_EVENTS; i++) {
10007                         dfc_event = &vport->sd_events[i];
10008 
10009                         if (dfc_event->pid  == pid && dfc_event->event == event)
10010                                 break;
10011                 }
10012 
10013                 /* Return if not found */
10014                 if (i == MAX_DFC_EVENTS) {
10015                         rval = DFC_SD_ERROR_INVALID_ARG;
10016                         goto set_sd_event_exit;
10017                 }
10018 
10019                 /* Kill the event thread if it is sleeping */
10020                 (void) emlxs_kill_dfc_event(vport, dfc_event);
10021 
10022                 /* Count the number of pids still registered for this event */
10023                 count = 0;
10024                 for (i = 0; i < MAX_DFC_EVENTS; i++) {
10025                         dfc_event = &vport->sd_events[i];
10026 
10027                         if (dfc_event->event == event)
10028                                 count++;
10029                 }
10030 
10031                 /*
10032                  * If no more pids need this event,
10033                  * then disable logging for this event
10034                  */
10035                 if (count == 0)
10036                         vport->sd_event_mask &= ~event;
10037         }
10038 
10039 set_sd_event_exit:
10040         return (rval);
10041 } /* emlxs_dfc_sd_set_event */
10042 
10043 
10044 /*ARGSUSED*/
10045 static int32_t
10046 emlxs_dfc_sd_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10047 {
10048         emlxs_port_t   *vport;
10049         uint8_t         wwpn[8];
10050         uint32_t        event, pid, sleep, i;
10051         int32_t         rval = DFC_SD_OK;
10052         emlxs_dfc_event_t *dfc_event;
10053 
10054         event = dfc->data1;
10055         pid = dfc->data2;
10056 
10057         /* Read the wwn object */
10058         bcopy((void *)dfc->buf4, (void *)wwpn, 8);
10059 
10060         /* Make sure WWPN is unique */
10061         vport = emlxs_vport_find_wwpn(hba, wwpn);
10062 
10063         if (!vport) {
10064                 rval = DFC_SD_ERROR_INVALID_PORT;
10065                 goto get_sd_event_exit;
10066         }
10067 
10068         /* Find the event entry */
10069         dfc_event = NULL;
10070         for (i = 0; i < MAX_DFC_EVENTS; i++) {
10071                 dfc_event = &vport->sd_events[i];
10072 
10073                 if (dfc_event->pid == pid && dfc_event->event == event)
10074                         break;
10075         }
10076 
10077         if (i == MAX_DFC_EVENTS) {
10078                 rval = DFC_SD_ERROR_GENERIC;
10079                 goto get_sd_event_exit;
10080         }
10081 
10082         if (!(vport->sd_event_mask & dfc_event->event)) {
10083                 rval = DFC_SD_ERROR_GENERIC;
10084                 goto get_sd_event_exit;
10085         }
10086 
10087         /* Initialize event buffer pointers */
10088         dfc_event->dataout = dfc->buf1;
10089         dfc_event->size = dfc->buf1_size;
10090         dfc_event->last_id = dfc->data3;
10091         dfc_event->mode = mode;
10092 
10093         sleep = (dfc->flag & 0x01) ? 1 : 0;
10094 
10095         emlxs_get_sd_event(vport, dfc_event, sleep);
10096 
10097         /*
10098          * update rcv_size.
10099          */
10100         if (dfc->buf2) {
10101                 bcopy((void *) &dfc_event->size, dfc->buf2,
10102                     sizeof (uint32_t));
10103         }
10104 
10105         /*
10106          * update index
10107          */
10108         if (dfc->buf3) {
10109                 bcopy((void *) &dfc_event->last_id, dfc->buf3,
10110                     sizeof (uint32_t));
10111         }
10112 
10113 get_sd_event_exit:
10114         return (rval);
10115 } /* emlxs_dfc_sd_get_event */
10116 #endif
10117 
10118 /*ARGSUSED*/
10119 static int32_t
10120 emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10121 {
10122         emlxs_port_t                    *port = &PPORT;
10123         fc_packet_t                     *pkt = NULL;
10124         NODELIST                        *ndlp;
10125         FCP_CMND                        *fcp_cmd;
10126         FCP_RSP                         *fcp_rsp;
10127         void                            *ptr;
10128         char                            buffer[64];
10129         dfc_send_scsi_fcp_cmd_info_t    *cmdinfo;
10130         uint32_t                        rval = 0;
10131 
10132         /* cmd info */
10133         if (!dfc->buf1 ||
10134             (dfc->buf1_size != sizeof (dfc_send_scsi_fcp_cmd_info_t))) {
10135                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10136                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10137 
10138                 rval = DFC_ARG_NULL;
10139                 goto done;
10140         }
10141 
10142         /* reqBuffer info */
10143         if (!dfc->buf2 || (dfc->buf2_size != sizeof (FCP_CMND))) {
10144                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10145                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
10146 
10147                 rval = DFC_ARG_NULL;
10148                 goto done;
10149         }
10150 
10151         /* rspBuffer info, could be 0 for SCSI commands like TUR */
10152         if (!dfc->buf3 && dfc->buf3_size) {
10153                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10154                     "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
10155 
10156                 rval = DFC_ARG_NULL;
10157                 goto done;
10158         }
10159 
10160         /* senseBuffer info */
10161         if (!dfc->buf4 || !dfc->buf4_size) {
10162                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10163                     "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
10164 
10165                 rval = DFC_ARG_NULL;
10166                 goto done;
10167         }
10168 
10169         cmdinfo = (dfc_send_scsi_fcp_cmd_info_t *)dfc->buf1;
10170 
10171         if (cmdinfo->ver == DFC_SEND_SCSI_FCP_V2) {
10172                 port =
10173                     emlxs_vport_find_wwpn(hba, (uint8_t *)&cmdinfo->src_wwn);
10174                 if (port == NULL) {
10175                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10176                             "%s: WWPN does not exists. %s",
10177                             emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
10178                             sizeof (buffer), (uint8_t *)&cmdinfo->src_wwn));
10179 
10180                         rval = DFC_ARG_INVALID;
10181                         goto done;
10182                 }
10183         }
10184 
10185         if ((ndlp = emlxs_node_find_wwpn(port,
10186             (uint8_t *)&cmdinfo->dst_wwn, 1)) == NULL) {
10187                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10188                     "%s: WWPN does not exists. %s", emlxs_dfc_xlate(dfc->cmd),
10189                     emlxs_wwn_xlate(buffer, sizeof (buffer),
10190                     (uint8_t *)&cmdinfo->dst_wwn));
10191 
10192                 rval = DFC_ARG_INVALID;
10193                 goto done;
10194         }
10195 
10196         if (!(pkt = emlxs_pkt_alloc(port, sizeof (FCP_CMND), sizeof (FCP_RSP),
10197             dfc->buf3_size, KM_NOSLEEP))) {
10198                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10199                     "%s: Unable to allocate packet.",
10200                     emlxs_dfc_xlate(dfc->cmd));
10201 
10202                 rval = DFC_SYSRES_ERROR;
10203                 goto done;
10204         }
10205         fcp_cmd = (FCP_CMND *) pkt->pkt_cmd;
10206 
10207         /* Copy in the command buffer */
10208         bcopy((void *)dfc->buf2, (void *)fcp_cmd, sizeof (FCP_CMND));
10209 
10210         /* Make this a polled IO */
10211         pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
10212         pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
10213         pkt->pkt_comp = NULL;
10214 
10215         /* Build the fc header */
10216         pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID);
10217         pkt->pkt_cmd_fhdr.r_ctl = FC_FCP_CMND;
10218         pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
10219         pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP;
10220         pkt->pkt_cmd_fhdr.seq_id = 0;
10221         pkt->pkt_cmd_fhdr.df_ctl = 0;
10222         pkt->pkt_cmd_fhdr.seq_cnt = 0;
10223         pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
10224         pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
10225         pkt->pkt_cmd_fhdr.ro = 0;
10226 
10227         pkt->pkt_timeout = 30;
10228 
10229         if ((fcp_cmd->fcpCntl3 == WRITE_DATA) && dfc->buf3_size) {
10230                 pkt->pkt_tran_type = FC_PKT_FCP_WRITE;
10231                 bcopy((void *)dfc->buf3, (void *)pkt->pkt_data, dfc->buf3_size);
10232         } else {
10233                 pkt->pkt_tran_type = FC_PKT_FCP_READ;
10234         }
10235 
10236         if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
10237                 rval = DFC_IO_ERROR;
10238                 goto done;
10239         }
10240 
10241         if (pkt->pkt_state != FC_PKT_SUCCESS) {
10242                 if (pkt->pkt_state == FC_PKT_TIMEOUT) {
10243                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10244                             "Pkt Transport error. Pkt Timeout.");
10245                         rval = DFC_TIMEOUT;
10246                 } else {
10247                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10248                             "Pkt Transport error. state=%x", pkt->pkt_state);
10249                         rval = DFC_IO_ERROR;
10250                 }
10251                 goto done;
10252         }
10253 
10254         if (pkt->pkt_data_resid) {
10255                 if (pkt->pkt_data_resid < dfc->buf3_size)
10256                         dfc->buf3_size -= pkt->pkt_data_resid;
10257                 else
10258                         dfc->buf3_size = 0;
10259         }
10260 
10261         SCSI_RSP_CNT(cmdinfo) = dfc->buf3_size;
10262 
10263         fcp_rsp = (FCP_RSP *) pkt->pkt_resp;
10264         /*
10265          * This is sense count for flag = 0.
10266          * It is fcp response size for flag = 1.
10267          */
10268         if (dfc->flag) {
10269                 SCSI_SNS_CNT(cmdinfo) = 24 + LE_SWAP32(fcp_rsp->rspSnsLen) +
10270                     LE_SWAP32(fcp_rsp->rspRspLen);
10271                 ptr = (void *)fcp_rsp;
10272         } else {
10273                 SCSI_SNS_CNT(cmdinfo) = LE_SWAP32(fcp_rsp->rspSnsLen);
10274                 ptr = (void *)&fcp_rsp->rspSnsInfo[0];
10275         }
10276 
10277         if (SCSI_SNS_CNT(cmdinfo)) {
10278                 bcopy(ptr, (void *)dfc->buf4, SCSI_SNS_CNT(cmdinfo));
10279         }
10280 
10281         if (SCSI_RSP_CNT(cmdinfo)) {
10282                 bcopy((void *)pkt->pkt_data, (void *)dfc->buf3,
10283                     SCSI_RSP_CNT(cmdinfo));
10284         }
10285 
10286         rval = 0;
10287 
10288 done:
10289         if (pkt) {
10290                 emlxs_pkt_free(pkt);
10291         }
10292 
10293         return (rval);
10294 
10295 } /* emlxs_dfc_send_scsi_fcp() */
10296 
10297 
10298 /*ARGSUSED*/
10299 static int32_t
10300 emlxs_dfc_get_persist_linkdown(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10301 {
10302         emlxs_port_t            *port = &PPORT;
10303         emlxs_config_t          *cfg = &CFG;
10304         uint16_t                linkdown = 0;
10305         uint32_t                rval = 0;
10306 
10307         if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
10308                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10309                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
10310 
10311                 return (DFC_NOT_SUPPORTED);
10312         }
10313 
10314         if (!dfc->buf1 || !dfc->buf1_size) {
10315                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10316                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10317 
10318                 return (DFC_ARG_NULL);
10319         }
10320 
10321         linkdown = (uint16_t)cfg[CFG_PERSIST_LINKDOWN].current;
10322         bcopy((void *)&linkdown, dfc->buf1, sizeof (uint16_t));
10323 
10324         return (rval);
10325 
10326 } /* emlxs_dfc_get_persist_linkdown() */
10327 
10328 
10329 /*ARGSUSED*/
10330 static int32_t
10331 emlxs_dfc_set_persist_linkdown(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10332 {
10333         emlxs_port_t            *port = &PPORT;
10334         emlxs_config_t          *cfg = &CFG;
10335         uint32_t                rval = 0;
10336 
10337         if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE) {
10338                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10339                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
10340 
10341                 return (DFC_NOT_SUPPORTED);
10342         }
10343 
10344         if (dfc->data1) {
10345                 cfg[CFG_PERSIST_LINKDOWN].current = 1;
10346         } else {
10347                 cfg[CFG_PERSIST_LINKDOWN].current = 0;
10348         }
10349 
10350         return (rval);
10351 
10352 } /* emlxs_dfc_set_persist_linkdown() */
10353 
10354 
10355 /*ARGSUSED*/
10356 static int32_t
10357 emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10358 {
10359         emlxs_port_t            *port = &PPORT;
10360         DFC_FCoEFCFInfo_t       *fcflistentry;
10361         DFC_FCoEFCFList_t       *fcflist;
10362         FCFIobj_t               *fcfp;
10363         uint32_t                size;
10364         uint32_t                i;
10365         uint32_t                count = 0;
10366         uint32_t                rval = 0;
10367 
10368         if (!dfc->buf1 || !dfc->buf1_size) {
10369                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10370                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10371 
10372                 return (DFC_ARG_NULL);
10373         }
10374 
10375         if (dfc->buf1_size < sizeof (DFC_FCoEFCFList_t)) {
10376                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10377                     "%s: Buffer1 too small. (size=%d)",
10378                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10379 
10380                 return (DFC_ARG_TOOSMALL);
10381         }
10382 
10383         if (! ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE)) {
10384                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10385                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
10386 
10387                 return (DFC_NOT_SUPPORTED);
10388         }
10389 
10390         if (hba->state != FC_READY) {
10391                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10392                     "%s: HBA not ready.", emlxs_dfc_xlate(dfc->cmd));
10393 
10394                 return (DFC_DRV_ERROR);
10395         }
10396 
10397         size = sizeof (DFC_FCoEFCFList_t) +
10398             hba->sli.sli4.fcftab.table_count * sizeof (DFC_FCoEFCFInfo_t);
10399         fcflist = (DFC_FCoEFCFList_t *)kmem_zalloc(size, KM_SLEEP);
10400 
10401         bcopy(dfc->buf1, (void *)fcflist, sizeof (DFC_FCoEFCFList_t));
10402 
10403         fcflistentry = fcflist->entries;
10404         mutex_enter(&EMLXS_FCF_LOCK);
10405         fcfp = hba->sli.sli4.fcftab.table;
10406         for (i = 0; i < hba->sli.sli4.fcftab.table_count; i++, fcfp++) {
10407                 if ((fcfp->state != FCFI_STATE_FREE) &&
10408                     (fcfp->fcf_rec.fcf_valid)) {
10409                         fcflistentry->Priority = fcfp->fcf_rec.fip_priority;
10410                         if (fcfp->fcf_rec.fcf_available) {
10411                                 fcflistentry->State = FCF_AVAILABLE_STATE;
10412                         }
10413                         fcflistentry->LKA_Period = fcfp->fcf_rec.fka_adv_period;
10414 
10415                         bcopy((void *)fcfp->fcf_rec.vlan_bitmap,
10416                             (void *)fcflistentry->VLanBitMap, 512);
10417                         bcopy((void *)fcfp->fcf_rec.fc_map,
10418                             (void *)fcflistentry->FC_Map, 3);
10419                         bcopy((void *)fcfp->fcf_rec.fabric_name_identifier,
10420                             (void *)fcflistentry->FabricName, 8);
10421                         bcopy((void *)fcfp->fcf_rec.switch_name_identifier,
10422                             (void *)fcflistentry->SwitchName, 8);
10423                         bcopy((void *)&fcfp->fcf_rec.fcf_mac_address_hi,
10424                             (void *)fcflistentry->Mac, 6);
10425 
10426                         count++;
10427                         fcflistentry++;
10428                 }
10429         }
10430         mutex_exit(&EMLXS_FCF_LOCK);
10431 
10432         fcflist->nActiveFCFs = hba->sli.sli4.fcftab.fcfi_count;
10433 
10434         if (count > fcflist->numberOfEntries) {
10435                 rval = DFC_ARG_TOOSMALL;
10436         }
10437 
10438         i = sizeof (DFC_FCoEFCFList_t) +
10439             (fcflist->numberOfEntries - 1) * sizeof (DFC_FCoEFCFInfo_t);
10440         fcflist->numberOfEntries = (uint16_t)count;
10441 
10442         bcopy((void *)fcflist, dfc->buf1, i);
10443 
10444 done:
10445         kmem_free(fcflist, size);
10446         return (rval);
10447 
10448 } /* emlxs_dfc_get_fcflist() */
10449 
10450 
10451 /*ARGSUSED*/
10452 static int32_t
10453 emlxs_dfc_send_mbox4(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10454 {
10455         emlxs_port_t    *port = &PPORT;
10456         MAILBOX4        *mb4 = NULL;
10457         MAILBOXQ        *mbq = NULL;
10458         mbox_req_hdr_t  *hdr_req;
10459         IOCTL_COMMON_WRITE_OBJECT *write_obj;
10460         MATCHMAP        *mp = NULL, *tx_mp = NULL, *rx_mp = NULL;
10461         uintptr_t       addr;   /* Was uint64_t in Emulex drop... */
10462         uint32_t        size;
10463         int32_t         mbxstatus = 0;
10464         uint32_t        rval = 0;
10465 
10466         if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
10467                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10468                     "%s: SLI Mode %d not supported.", emlxs_dfc_xlate(dfc->cmd),
10469                     hba->sli_mode);
10470 
10471                 return (DFC_NOT_SUPPORTED);
10472         }
10473 
10474         if (!dfc->buf1 || !dfc->buf1_size) {
10475                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10476                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10477 
10478                 return (DFC_ARG_NULL);
10479         }
10480 
10481         if (!dfc->buf2 || !dfc->buf2_size) {
10482                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10483                     "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
10484 
10485                 return (DFC_ARG_NULL);
10486         }
10487 
10488         if ((dfc->buf1_size != dfc->buf2_size) ||
10489             (dfc->buf1_size < sizeof (MAILBOX4))) {
10490                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10491                     "%s: Invalid buffer size. (size=%d)",
10492                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10493 
10494                 return (DFC_ARG_INVALID);
10495         }
10496 
10497         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10498         mb4 = (MAILBOX4 *) mbq;
10499         bcopy(dfc->buf1, (void *)mb4, sizeof (MAILBOX4));
10500 
10501         /*
10502          * Now snoop the mailbox command
10503          */
10504         switch (mb4->mbxCommand) {
10505                 case MBX_SLI_CONFIG:
10506                 if (! mb4->un.varSLIConfig.be.embedded) {
10507                         if (mb4->un.varSLIConfig.be.sge_cnt > 1) {
10508                                 /*
10509                                  * Allow only one buffer descriptor
10510                                  * for non-embedded commands
10511                                  */
10512                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10513                                     "%s: Only one buffer descriptor allowed.",
10514                                     emlxs_dfc_xlate(dfc->cmd));
10515 
10516                                 rval = DFC_ARG_INVALID;
10517                                 break;
10518                         }
10519 
10520                         if ((!mb4->un.varSLIConfig.be.payload_length) ||
10521                             (mb4->un.varSLIConfig.be.payload_length !=
10522                             (dfc->buf1_size - sizeof (MAILBOX4)))) {
10523                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10524                                     "%s: Invalid buffer size. (size=%d)",
10525                                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10526 
10527                                 rval = DFC_ARG_INVALID;
10528                                 break;
10529                         }
10530 
10531                         mp = emlxs_mem_buf_alloc(hba,
10532                             mb4->un.varSLIConfig.be.payload_length);
10533 
10534                         if (mp == NULL) {
10535                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10536                                     "%s: Unable to allocate buffer.",
10537                                     emlxs_dfc_xlate(dfc->cmd));
10538 
10539                                 rval = DFC_SYSRES_ERROR;
10540                                 break;
10541                         }
10542 
10543                         bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10544                             mp->virt, mp->size);
10545                         EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10546                             DDI_DMA_SYNC_FORDEV);
10547 
10548                         mbq->nonembed = (void *) mp;
10549                         break;
10550                 }
10551 
10552                 hdr_req = (mbox_req_hdr_t *)
10553                     &mb4->un.varSLIConfig.be.un_hdr.hdr_req;
10554 
10555                 /*
10556                  * WRITE_OBJECT, READ_OBJECT and READ_OBJECT_LIST are
10557                  * special because they use buffer descriptors
10558                  */
10559                 if ((hdr_req->subsystem == IOCTL_SUBSYSTEM_COMMON) &&
10560                     ((hdr_req->opcode == COMMON_OPCODE_WRITE_OBJ) ||
10561                     (hdr_req->opcode == COMMON_OPCODE_READ_OBJ_LIST) ||
10562                     (hdr_req->opcode == COMMON_OPCODE_READ_OBJ))) {
10563                         write_obj =
10564                             (IOCTL_COMMON_WRITE_OBJECT *)(hdr_req + 1);
10565 
10566                         if (write_obj->params.request.buffer_desc_count
10567                             > 1) {
10568                                 /*
10569                                  * Allow only one buffer descriptor
10570                                  * for embedded commands
10571                                  */
10572                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10573                                     "%s: Only one buffer descriptor allowed.",
10574                                     emlxs_dfc_xlate(dfc->cmd));
10575 
10576                                 rval = DFC_ARG_INVALID;
10577                                 break;
10578                         }
10579 
10580                         if (write_obj->params.request.buffer_length !=
10581                             (dfc->buf1_size - sizeof (MAILBOX4))) {
10582                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10583                                     "%s: Invalid buffer size. (size=%d)",
10584                                     emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10585 
10586                                 rval = DFC_ARG_INVALID;
10587                                 break;
10588                         }
10589 
10590                         if (write_obj->params.request.buffer_length) {
10591                                 mp = emlxs_mem_buf_alloc(hba,
10592                                     write_obj->params.request.buffer_length);
10593 
10594                                 if (mp == NULL) {
10595                                         EMLXS_MSGF(EMLXS_CONTEXT,
10596                                             &emlxs_dfc_error_msg,
10597                                             "%s: Unable to allocate buffer.",
10598                                             emlxs_dfc_xlate(dfc->cmd));
10599 
10600                                         rval = DFC_SYSRES_ERROR;
10601                                         break;
10602                                 }
10603 
10604                                 bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10605                                     mp->virt, mp->size);
10606                                 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10607                                     DDI_DMA_SYNC_FORDEV);
10608                                 write_obj->params.request.buffer_addrlo =
10609                                     PADDR_LO(mp->phys);
10610                                 write_obj->params.request.buffer_addrhi =
10611                                     PADDR_HI(mp->phys);
10612                         }
10613                         break;
10614                 }
10615                 break;
10616 
10617                 case MBX_DUMP_MEMORY:
10618                 if (mb4->un.varDmp4.available_cnt == 0)
10619                         break;
10620 
10621                 if (mb4->un.varDmp4.available_cnt !=
10622                     (dfc->buf1_size - sizeof (MAILBOX4))) {
10623                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10624                             "%s: Invalid buffer size. (size=%d)",
10625                             emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10626 
10627                         rval = DFC_ARG_INVALID;
10628                         break;
10629                 }
10630 
10631                 mp = emlxs_mem_buf_alloc(hba,
10632                     mb4->un.varDmp4.available_cnt);
10633 
10634                 if (mp == NULL) {
10635                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10636                             "%s: Unable to allocate buffer.",
10637                             emlxs_dfc_xlate(dfc->cmd));
10638 
10639                         rval = DFC_SYSRES_ERROR;
10640                         break;
10641                 }
10642 
10643                 bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10644                     mp->virt, mp->size);
10645                 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10646                     DDI_DMA_SYNC_FORDEV);
10647 
10648                 mb4->un.varDmp4.addrLow = PADDR_LO(mp->phys);
10649                 mb4->un.varDmp4.addrHigh = PADDR_HI(mp->phys);
10650                 break;
10651 
10652                 case MBX_UPDATE_CFG:
10653                 if (mb4->un.varUpdateCfg.Obit == 0)
10654                         break;
10655 
10656                 if (mb4->un.varUpdateCfg.byte_len !=
10657                     (dfc->buf1_size - sizeof (MAILBOX4))) {
10658                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10659                             "%s: Invalid buffer size. (size=%d)",
10660                             emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10661 
10662                         rval = DFC_ARG_INVALID;
10663                         break;
10664                 }
10665 
10666                 mp = emlxs_mem_buf_alloc(hba,
10667                     mb4->un.varUpdateCfg.byte_len);
10668 
10669                 if (mp == NULL) {
10670                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10671                             "%s: Unable to allocate buffer.",
10672                             emlxs_dfc_xlate(dfc->cmd));
10673 
10674                         rval = DFC_SYSRES_ERROR;
10675                         break;
10676                 }
10677 
10678                 bcopy((uint8_t *)dfc->buf1 + sizeof (MAILBOX4),
10679                     mp->virt, mp->size);
10680                 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
10681                     DDI_DMA_SYNC_FORDEV);
10682 
10683                 mb4->un.varWords[5] = PADDR_LO(mp->phys);
10684                 mb4->un.varWords[6] = PADDR_HI(mp->phys);
10685                 break;
10686 
10687                 case MBX_RUN_BIU_DIAG64:
10688                 size = mb4->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize;
10689                 addr = PADDR(mb4->un.varBIUdiag.un.s2.xmit_bde64.addrHigh,
10690                     mb4->un.varBIUdiag.un.s2.xmit_bde64.addrLow);
10691 
10692                 if (!addr || !size) {
10693                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10694                             "%s: Invalid xmit BDE. cmd=%x",
10695                             emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10696 
10697                         rval = DFC_ARG_INVALID;
10698                         break;
10699                 }
10700 
10701                 /* Allocate xmit buffer */
10702                 if ((tx_mp = emlxs_mem_buf_alloc(hba, size)) == 0) {
10703                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10704                             "%s: Unable to allocate xmit buffer. cmd=%x",
10705                             emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10706 
10707                         rval = DFC_DRVRES_ERROR;
10708                         break;
10709                 }
10710 
10711                 /* Initialize the xmit buffer */
10712                 if (ddi_copyin((void *)addr, (void *)tx_mp->virt, size,
10713                     mode) != 0) {
10714                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10715                             "%s: ddi_copyin failed. cmd=%x",
10716                             emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10717 
10718                         rval = DFC_COPYIN_ERROR;
10719                         break;
10720                 }
10721                 EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
10722                     DDI_DMA_SYNC_FORDEV);
10723 
10724                 mb4->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
10725                     PADDR_HI(tx_mp->phys);
10726                 mb4->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
10727                     PADDR_LO(tx_mp->phys);
10728                 mb4->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0;
10729 
10730                 size = mb4->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize;
10731                 addr = PADDR(mb4->un.varBIUdiag.un.s2.rcv_bde64.addrHigh,
10732                     mb4->un.varBIUdiag.un.s2.rcv_bde64.addrLow);
10733 
10734                 if (!addr || !size) {
10735                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10736                             "%s: Invalid xmit BDE. cmd=%x",
10737                             emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10738 
10739                         rval = DFC_ARG_INVALID;
10740                         break;
10741                 }
10742 
10743                 /* Allocate receive buffer */
10744                 if ((rx_mp = emlxs_mem_buf_alloc(hba, size)) == 0) {
10745                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10746                             "%s: Unable to allocate receive buffer. cmd=%x",
10747                             emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10748 
10749                         rval = DFC_DRVRES_ERROR;
10750                         break;
10751                 }
10752 
10753                 mb4->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
10754                     PADDR_HI(rx_mp->phys);
10755                 mb4->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
10756                     PADDR_LO(rx_mp->phys);
10757                 mb4->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0;
10758                 break;
10759 
10760                 default:
10761                 break;
10762         }
10763 
10764         if (rval)
10765                 goto done;
10766 
10767         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
10768             "%s: %s sent.  (%x %x %x %x)", emlxs_dfc_xlate(dfc->cmd),
10769             emlxs_mb_cmd_xlate(mb4->mbxCommand), mb4->un.varWords[0],
10770             mb4->un.varWords[1], mb4->un.varWords[2], mb4->un.varWords[3]);
10771 
10772         /* issue the mbox cmd to the sli */
10773         mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10774 
10775         if (mbxstatus) {
10776                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
10777                     "%s: %s failed. mbxstatus=0x%x",
10778                     emlxs_dfc_xlate(dfc->cmd),
10779                     emlxs_mb_cmd_xlate(mb4->mbxCommand), mbxstatus);
10780         }
10781 
10782         bcopy((void *)mb4, dfc->buf2, sizeof (MAILBOX4));
10783         if (mp) {
10784                 bcopy(mp->virt, (uint8_t *)dfc->buf2 + sizeof (MAILBOX4),
10785                     mp->size);
10786         }
10787 
10788         if (rx_mp) {
10789                 EMLXS_MPDATA_SYNC(rx_mp->dma_handle, 0, size,
10790                     DDI_DMA_SYNC_FORKERNEL);
10791 
10792                 if (ddi_copyout((void *)rx_mp->virt, (void *)addr, size,
10793                     mode) != 0) {
10794                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10795                             "%s: ddi_copyout failed for receive buffer. cmd=%x",
10796                             emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10797 
10798                         rval = DFC_COPYOUT_ERROR;
10799                         goto done;
10800                 }
10801         }
10802 
10803 done:
10804         /* Free allocated memory */
10805         if (mp) {
10806                 emlxs_mem_buf_free(hba, mp);
10807         }
10808 
10809         if (tx_mp) {
10810                 emlxs_mem_buf_free(hba, tx_mp);
10811         }
10812 
10813         if (rx_mp) {
10814                 emlxs_mem_buf_free(hba, rx_mp);
10815         }
10816 
10817         if (mbq) {
10818                 kmem_free(mbq, sizeof (MAILBOXQ));
10819         }
10820 
10821         return (rval);
10822 } /* emlxs_dfc_send_mbox4() */
10823 
10824 
10825 /* ARGSUSED */
10826 static int
10827 emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10828 {
10829         emlxs_port_t                    *port = &PPORT;
10830         MATCHMAP                        *mp;
10831         MAILBOX4                        *mb  = NULL;
10832         MAILBOXQ                        *mbq = NULL;
10833         IOCTL_FCOE_READ_FCF_TABLE       *fcf;
10834         mbox_req_hdr_t                  *hdr_req;
10835         mbox_rsp_hdr_t                  *hdr_rsp;
10836         FCF_RECORD_t                    *fcfrec;
10837         uint32_t                        rc = 0;
10838         uint32_t                        rval = 0;
10839         uint16_t                        index;
10840 
10841         if (!dfc->buf1 || !dfc->buf1_size) {
10842                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10843                     "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10844 
10845                 return (DFC_ARG_NULL);
10846         }
10847 
10848         mbq =
10849             (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10850 
10851         index = dfc->data1;
10852         mb = (MAILBOX4 *)mbq;
10853 
10854         bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
10855 
10856         if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
10857                 rval = DFC_SYSRES_ERROR;
10858                 goto done;
10859         }
10860         bzero(mp->virt, mp->size);
10861 
10862         /*
10863          * Signifies a non-embedded command
10864          */
10865         mb->un.varSLIConfig.be.embedded = 0;
10866         mbq->nonembed = (void *)mp;
10867         mbq->mbox_cmpl = NULL;
10868 
10869         mb->mbxCommand = MBX_SLI_CONFIG;
10870         mb->mbxOwner = OWN_HOST;
10871 
10872         hdr_req = (mbox_req_hdr_t *)mp->virt;
10873         hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
10874 
10875         hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
10876         hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE;
10877         hdr_req->timeout = 0;
10878         hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE);
10879         fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
10880         fcf->params.request.fcf_index = index;
10881 
10882         rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10883         if (rc == MBX_SUCCESS) {
10884                 fcfrec = &fcf->params.response.fcf_entry[0];
10885 
10886                 bcopy((void *)fcfrec, (void *)dfc->buf1, dfc->buf1_size);
10887                 bcopy((void *)&fcf->params.response.next_valid_fcf_index,
10888                     (void *)dfc->buf2, dfc->buf2_size);
10889         } else {
10890                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
10891                     "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10892                     emlxs_mb_cmd_xlate(mb->mbxCommand), rc);
10893 
10894                 if ((rc == MBX_NONEMBED_ERROR) &&
10895                     (hdr_rsp->status == MBX_RSP_STATUS_NO_FCF)) {
10896                         rval = DFC_NO_DATA;
10897                 } else {
10898                         rval = DFC_IO_ERROR;
10899                 }
10900         }
10901 
10902 done:
10903         if (mp) {
10904                 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
10905         }
10906 
10907         if (mbq) {
10908                 kmem_free(mbq, sizeof (MAILBOXQ));
10909         }
10910 
10911         return (rval);
10912 
10913 } /* emlxs_dfc_rd_be_fcf() */
10914 
10915 
10916 /*ARGSUSED*/
10917 static int
10918 emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10919 {
10920         emlxs_port_t                            *port = &PPORT;
10921         MAILBOXQ                                *mbq = NULL;
10922         MAILBOX4                                *mb;
10923         IOCTL_DCBX_SET_DCBX_MODE                *dcbx_mode;
10924         uint32_t                                port_num = 0;
10925         uint32_t                                rval = 0;
10926 
10927         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10928         mb = (MAILBOX4 *)mbq;
10929 
10930         /*
10931          * Signifies an embedded command
10932          */
10933         mb->un.varSLIConfig.be.embedded = 1;
10934         mbq->mbox_cmpl = NULL;
10935 
10936         mb->mbxCommand = MBX_SLI_CONFIG;
10937         mb->mbxOwner = OWN_HOST;
10938         mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
10939         mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
10940             IOCTL_SUBSYSTEM_DCBX;
10941         mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
10942             DCBX_OPCODE_SET_DCBX_MODE;
10943         mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
10944         mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
10945             sizeof (IOCTL_DCBX_SET_DCBX_MODE);
10946         dcbx_mode = (IOCTL_DCBX_SET_DCBX_MODE *)&mb->un.varSLIConfig.payload;
10947         dcbx_mode->params.request.port_num = (uint8_t)port_num;
10948         dcbx_mode->params.request.dcbx_mode = dfc->data1;
10949 
10950         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
10951             "%s requested on port %d.", emlxs_dfc_xlate(dfc->cmd), port_num);
10952 
10953         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10954         if (rval != MBX_SUCCESS) {
10955                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
10956                     "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10957                     emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
10958 
10959                 rval = DFC_DRV_ERROR;
10960         }
10961 
10962 done:
10963         if (mbq) {
10964                 kmem_free(mbq, sizeof (MAILBOXQ));
10965         }
10966 
10967         return (rval);
10968 
10969 } /* emlxs_dfc_set_be_dcbx() */
10970 
10971 
10972 /* ARGSUSED */
10973 static int
10974 emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10975 {
10976         emlxs_port_t                            *port = &PPORT;
10977         MAILBOXQ                                *mbq = NULL;
10978         MAILBOX4                                *mb;
10979         IOCTL_DCBX_GET_DCBX_MODE                *dcbx_mode;
10980         uint32_t                                port_num = 0;
10981         uint32_t                                rval = 0;
10982 
10983         mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10984         mb = (MAILBOX4 *)mbq;
10985 
10986         /*
10987          * Signifies an embedded command
10988          */
10989         mb->un.varSLIConfig.be.embedded = 1;
10990         mbq->mbox_cmpl = NULL;
10991 
10992         mb->mbxCommand = MBX_SLI_CONFIG;
10993         mb->mbxOwner = OWN_HOST;
10994         mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
10995         mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
10996             IOCTL_SUBSYSTEM_DCBX;
10997         mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
10998             DCBX_OPCODE_GET_DCBX_MODE;
10999         mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
11000         mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
11001             sizeof (IOCTL_DCBX_SET_DCBX_MODE);
11002         dcbx_mode = (IOCTL_DCBX_GET_DCBX_MODE *)&mb->un.varSLIConfig.payload;
11003         dcbx_mode->params.request.port_num = (uint8_t)port_num;
11004 
11005         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
11006             "%s requested on port %d.", emlxs_dfc_xlate(dfc->cmd), port_num);
11007 
11008         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
11009         if (rval != MBX_SUCCESS) {
11010                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
11011                     "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
11012                     emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
11013 
11014                 rval = DFC_DRV_ERROR;
11015                 goto done;
11016         }
11017 
11018         bcopy((void *)&dcbx_mode->params.response.dcbx_mode,
11019             (void *)dfc->buf1, dfc->buf1_size);
11020 
11021 done:
11022         if (mbq) {
11023                 kmem_free(mbq, sizeof (MAILBOXQ));
11024         }
11025 
11026         return (rval);
11027 
11028 } /* emlxs_dfc_get_be_dcbx() */
11029 
11030 
11031 /* ARGSUSED */
11032 static int
11033 emlxs_dfc_get_qos(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
11034 {
11035         emlxs_port_t    *port = &PPORT;
11036         uint32_t        rval = 0;
11037 
11038         if (! ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && SLI4_FCOE_MODE)) {
11039                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
11040                     "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
11041 
11042                 return (DFC_NOT_SUPPORTED);
11043         }
11044 
11045         if (dfc->buf1_size) {
11046                 bcopy((void *)&hba->qos_linkspeed, (void *)dfc->buf1,
11047                     dfc->buf1_size);
11048         }
11049 
11050         return (rval);
11051 
11052 } /* emlxs_dfc_get_qos() */