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