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