The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ocs_fc/ocs_mgmt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2017 Broadcom. All rights reserved.
    3  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions are met:
    7  *
    8  * 1. Redistributions of source code must retain the above copyright notice,
    9  *    this list of conditions and the following disclaimer.
   10  *
   11  * 2. Redistributions in binary form must reproduce the above copyright notice,
   12  *    this list of conditions and the following disclaimer in the documentation
   13  *    and/or other materials provided with the distribution.
   14  *
   15  * 3. Neither the name of the copyright holder nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  * $FreeBSD$
   32  */
   33 
   34 /**
   35  * @file
   36  * The ocs_mgmt top level functions for Fibre Channel.
   37  */
   38 
   39 /**
   40  * @defgroup mgmt Management Functions
   41  */
   42 
   43 #include "ocs.h"
   44 #include "ocs_mgmt.h"
   45 #include "ocs_vpd.h"
   46 
   47 #define SFP_PAGE_SIZE 128
   48 
   49 /* Executables*/
   50 
   51 static int ocs_mgmt_firmware_write(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
   52 static int ocs_mgmt_firmware_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
   53 static int ocs_mgmt_function_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
   54 
   55 static void ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, uint32_t change_status, void *arg);
   56 static int ocs_mgmt_force_assert(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
   57 
   58 #if defined(OCS_INCLUDE_RAMD)
   59 static int32_t
   60 ocs_mgmt_read_phys(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
   61 #endif
   62 
   63 /* Getters */
   64 
   65 static void get_nodes_count(ocs_t *, char *, ocs_textbuf_t*);
   66 static void get_desc(ocs_t *, char *, ocs_textbuf_t*);
   67 static void get_fw_rev(ocs_t *, char *, ocs_textbuf_t*);
   68 static void get_fw_rev2(ocs_t *, char *, ocs_textbuf_t*);
   69 static void get_ipl(ocs_t *, char *, ocs_textbuf_t*);
   70 static void get_wwnn(ocs_t *, char *, ocs_textbuf_t*);
   71 static void get_wwpn(ocs_t *, char *, ocs_textbuf_t*);
   72 static void get_fcid(ocs_t *, char *, ocs_textbuf_t *);
   73 static void get_sn(ocs_t *, char *, ocs_textbuf_t*);
   74 static void get_pn(ocs_t *, char *, ocs_textbuf_t*);
   75 static void get_sli4_intf_reg(ocs_t *, char *, ocs_textbuf_t*);
   76 static void get_phy_port_num(ocs_t *, char *, ocs_textbuf_t*);
   77 static void get_asic_id(ocs_t *, char *, ocs_textbuf_t*);
   78 static void get_pci_vendor(ocs_t *, char *, ocs_textbuf_t*);
   79 static void get_pci_device(ocs_t *, char *, ocs_textbuf_t*);
   80 static void get_pci_subsystem_vendor(ocs_t *, char *, ocs_textbuf_t*);
   81 static void get_pci_subsystem_device(ocs_t *, char *, ocs_textbuf_t*);
   82 static void get_businfo(ocs_t *, char *, ocs_textbuf_t*);
   83 static void get_sfp_a0(ocs_t *, char *, ocs_textbuf_t*);
   84 static void get_sfp_a2(ocs_t *, char *, ocs_textbuf_t*);
   85 static void get_hw_rev1(ocs_t *, char *, ocs_textbuf_t*);
   86 static void get_hw_rev2(ocs_t *, char *, ocs_textbuf_t*);
   87 static void get_hw_rev3(ocs_t *, char *, ocs_textbuf_t*);
   88 static void get_debug_mq_dump(ocs_t*, char*, ocs_textbuf_t*);
   89 static void get_debug_cq_dump(ocs_t*, char*, ocs_textbuf_t*);
   90 static void get_debug_wq_dump(ocs_t*, char*, ocs_textbuf_t*);
   91 static void get_debug_eq_dump(ocs_t*, char*, ocs_textbuf_t*);
   92 static void get_logmask(ocs_t*, char*, ocs_textbuf_t*);
   93 static void get_current_speed(ocs_t*, char*, ocs_textbuf_t*);
   94 static void get_current_topology(ocs_t*, char*, ocs_textbuf_t*);
   95 static void get_current_link_state(ocs_t*, char*, ocs_textbuf_t*);
   96 static void get_configured_speed(ocs_t*, char*, ocs_textbuf_t*);
   97 static void get_configured_topology(ocs_t*, char*, ocs_textbuf_t*);
   98 static void get_configured_link_state(ocs_t*, char*, ocs_textbuf_t*);
   99 static void get_linkcfg(ocs_t*, char*, ocs_textbuf_t*);
  100 static void get_req_wwnn(ocs_t*, char*, ocs_textbuf_t*);
  101 static void get_req_wwpn(ocs_t*, char*, ocs_textbuf_t*);
  102 static void get_nodedb_mask(ocs_t*, char*, ocs_textbuf_t*);
  103 static void get_profile_list(ocs_t*, char*, ocs_textbuf_t*);
  104 static void get_active_profile(ocs_t*, char*, ocs_textbuf_t*);
  105 static void get_port_protocol(ocs_t*, char*, ocs_textbuf_t*);
  106 static void get_driver_version(ocs_t*, char*, ocs_textbuf_t*);
  107 static void get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  108 static void get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  109 static void get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  110 static void get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  111 static void get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  112 static void get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  113 static void get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  114 static void get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  115 static void get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  116 static void get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  117 static void get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  118 static void get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  119 static void get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
  120 
  121 /* Setters */
  122 static int set_debug_mq_dump(ocs_t*, char*, char*);
  123 static int set_debug_cq_dump(ocs_t*, char*, char*);
  124 static int set_debug_wq_dump(ocs_t*, char*, char*);
  125 static int set_debug_eq_dump(ocs_t*, char*, char*);
  126 static int set_logmask(ocs_t*, char*, char*);
  127 static int set_configured_link_state(ocs_t*, char*, char*);
  128 static int set_linkcfg(ocs_t*, char*, char*);
  129 static int set_nodedb_mask(ocs_t*, char*, char*);
  130 static int set_port_protocol(ocs_t*, char*, char*);
  131 static int set_active_profile(ocs_t*, char*, char*);
  132 static int set_tgt_rscn_delay(ocs_t*, char*, char*);
  133 static int set_tgt_rscn_period(ocs_t*, char*, char*);
  134 static int set_inject_drop_cmd(ocs_t*, char*, char*);
  135 static int set_inject_free_drop_cmd(ocs_t*, char*, char*);
  136 static int set_inject_drop_data(ocs_t*, char*, char*);
  137 static int set_inject_drop_resp(ocs_t*, char*, char*);
  138 static int set_cmd_err_inject(ocs_t*, char*, char*);
  139 static int set_cmd_delay_value(ocs_t*, char*, char*);
  140 static int set_nv_wwn(ocs_t*, char*, char*);
  141 static int set_loglevel(ocs_t*, char*, char*);
  142 
  143 static void ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg);
  144 #if defined(OCS_INCLUDE_RAMD)
  145 static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr);
  146 #endif
  147 
  148 ocs_mgmt_table_entry_t mgmt_table[] = {
  149                 {"nodes_count", get_nodes_count, NULL, NULL},
  150                 {"desc", get_desc, NULL, NULL},
  151                 {"fw_rev", get_fw_rev, NULL, NULL},
  152                 {"fw_rev2", get_fw_rev2, NULL, NULL},
  153                 {"ipl", get_ipl, NULL, NULL},
  154                 {"hw_rev1", get_hw_rev1, NULL, NULL},
  155                 {"hw_rev2", get_hw_rev2, NULL, NULL},
  156                 {"hw_rev3", get_hw_rev3, NULL, NULL},
  157                 {"wwnn", get_wwnn, NULL, NULL},
  158                 {"wwpn", get_wwpn, NULL, NULL},
  159                 {"fc_id", get_fcid, NULL, NULL},
  160                 {"sn", get_sn, NULL, NULL},
  161                 {"pn", get_pn, NULL, NULL},
  162                 {"sli4_intf_reg", get_sli4_intf_reg, NULL, NULL},
  163                 {"phy_port_num", get_phy_port_num, NULL, NULL},
  164                 {"asic_id_reg", get_asic_id, NULL, NULL},
  165                 {"pci_vendor", get_pci_vendor, NULL, NULL},
  166                 {"pci_device", get_pci_device, NULL, NULL},
  167                 {"pci_subsystem_vendor", get_pci_subsystem_vendor, NULL, NULL},
  168                 {"pci_subsystem_device", get_pci_subsystem_device, NULL, NULL},
  169                 {"businfo", get_businfo, NULL, NULL},
  170                 {"sfp_a0", get_sfp_a0, NULL, NULL},
  171                 {"sfp_a2", get_sfp_a2, NULL, NULL},
  172                 {"profile_list", get_profile_list, NULL, NULL},
  173                 {"driver_version", get_driver_version, NULL, NULL},
  174                 {"current_speed", get_current_speed, NULL, NULL},
  175                 {"current_topology", get_current_topology, NULL, NULL},
  176                 {"current_link_state", get_current_link_state, NULL, NULL},
  177                 {"chip_type", get_chip_type, NULL, NULL},
  178                 {"configured_speed", get_configured_speed, set_configured_speed, NULL},
  179                 {"configured_topology", get_configured_topology, set_configured_topology, NULL},
  180                 {"configured_link_state", get_configured_link_state, set_configured_link_state, NULL},
  181                 {"debug_mq_dump", get_debug_mq_dump, set_debug_mq_dump, NULL},
  182                 {"debug_cq_dump", get_debug_cq_dump, set_debug_cq_dump, NULL},
  183                 {"debug_wq_dump", get_debug_wq_dump, set_debug_wq_dump, NULL},
  184                 {"debug_eq_dump", get_debug_eq_dump, set_debug_eq_dump, NULL},
  185                 {"logmask", get_logmask, set_logmask, NULL},
  186                 {"loglevel", get_loglevel, set_loglevel, NULL},
  187                 {"linkcfg", get_linkcfg, set_linkcfg, NULL},
  188                 {"requested_wwnn", get_req_wwnn, set_req_wwnn, NULL},
  189                 {"requested_wwpn", get_req_wwpn, set_req_wwpn, NULL},
  190                 {"nodedb_mask", get_nodedb_mask, set_nodedb_mask, NULL},
  191                 {"port_protocol", get_port_protocol, set_port_protocol, NULL},
  192                 {"active_profile", get_active_profile, set_active_profile, NULL},
  193                 {"firmware_write", NULL, NULL, ocs_mgmt_firmware_write},
  194                 {"firmware_reset", NULL, NULL, ocs_mgmt_firmware_reset},
  195                 {"function_reset", NULL, NULL, ocs_mgmt_function_reset},
  196 #if defined(OCS_INCLUDE_RAMD)
  197                 {"read_phys", NULL, NULL, ocs_mgmt_read_phys},
  198 #endif
  199                 {"force_assert", NULL, NULL, ocs_mgmt_force_assert},
  200 
  201                 {"tgt_rscn_delay", get_tgt_rscn_delay, set_tgt_rscn_delay, NULL},
  202                 {"tgt_rscn_period", get_tgt_rscn_period, set_tgt_rscn_period, NULL},
  203                 {"inject_drop_cmd", get_inject_drop_cmd, set_inject_drop_cmd, NULL},
  204                 {"inject_free_drop_cmd", get_inject_free_drop_cmd, set_inject_free_drop_cmd, NULL},
  205                 {"inject_drop_data", get_inject_drop_data, set_inject_drop_data, NULL},
  206                 {"inject_drop_resp", get_inject_drop_resp, set_inject_drop_resp, NULL},
  207                 {"cmd_err_inject", get_cmd_err_inject, set_cmd_err_inject, NULL},
  208                 {"cmd_delay_value", get_cmd_delay_value, set_cmd_delay_value, NULL},
  209                 {"nv_wwpn", get_nv_wwpn, NULL, NULL},
  210                 {"nv_wwnn", get_nv_wwnn, NULL, NULL},
  211                 {"nv_wwn", NULL, set_nv_wwn, NULL},
  212                 {"node_abort_cnt", get_node_abort_cnt, NULL, NULL},
  213 };
  214 
  215 /**
  216  * @ingroup mgmt
  217  * @brief Get a list of options supported by the driver.
  218  *
  219  * @par Description
  220  * This is the top level "get list" handler for the driver. It
  221  * performs the following:
  222  *  - Adds entries to the textbuf for any actions supported by this level in the driver.
  223  *  - Calls a back-end function to add any actions supported by the back-end.
  224  *  - Calls a function on each child (domain) to recursively add supported actions.
  225  *
  226  * @param ocs Pointer to the ocs structure.
  227  * @param textbuf Pointer to an ocs_textbuf, which is used to accumulate the results.
  228  *
  229  * @return Returns 0 on success, or a negative value on failure.
  230  */
  231 
  232 void
  233 ocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf)
  234 {
  235         ocs_domain_t *domain;
  236         uint32_t i;
  237         int access;
  238 
  239         ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
  240 
  241         for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
  242                 access = 0;
  243                 if (mgmt_table[i].get_handler) {
  244                         access |= MGMT_MODE_RD;
  245                 }
  246                 if (mgmt_table[i].set_handler) {
  247                         access |= MGMT_MODE_WR;
  248                 }
  249                 if (mgmt_table[i].action_handler) {
  250                         access |= MGMT_MODE_EX;
  251                 }
  252                 ocs_mgmt_emit_property_name(textbuf, access, mgmt_table[i].name);
  253         }
  254 
  255         if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_list_handler)) {
  256                 ocs->mgmt_functions->get_list_handler(textbuf, ocs);
  257         }
  258 
  259         if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_list_handler)) {
  260                 ocs->tgt_mgmt_functions->get_list_handler(textbuf, &(ocs->tgt_ocs));
  261         }
  262 
  263         /* Have each of my children add their actions */
  264         if (ocs_device_lock_try(ocs) == TRUE) {
  265                 /* If we get here then we are holding the device lock */
  266                 ocs_list_foreach(&ocs->domain_list, domain) {
  267                         if ((domain->mgmt_functions) && (domain->mgmt_functions->get_list_handler)) {
  268                                 domain->mgmt_functions->get_list_handler(textbuf, domain);
  269                         }
  270                 }
  271                 ocs_device_unlock(ocs);
  272         }
  273 
  274         ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
  275 
  276 }
  277 
  278 /**
  279  * @ingroup mgmt
  280  * @brief Return the value of a management item.
  281  *
  282  * @par Description
  283  * This is the top level "get" handler for the driver. It
  284  * performs the following:
  285  *  - Checks that the qualifier portion of the name begins with my qualifier (ocs).
  286  *  - If the remaining part of the name matches a parameter that is known at this level,
  287  *    writes the value into textbuf.
  288  *  - If the name is not known, sends the request to the back-ends to fulfill (if possible).
  289  *  - If the request has not been fulfilled by the back-end,
  290  *    passes the request to each of the children (domains) to
  291  *    have them (recursively) try to respond.
  292  *
  293  *  In passing the request to other entities, the request is considered to be answered
  294  *  when a response has been written into textbuf, indicated by textbuf->buffer_written
  295  *  being non-zero.
  296  *
  297  * @param ocs Pointer to the ocs structure.
  298  * @param name Name of the status item to be retrieved.
  299  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
  300  *
  301  * @return Returns 0 if the value was found and returned, or -1 if an error occurred.
  302  */
  303 
  304 int
  305 ocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  306 {
  307         ocs_domain_t *domain;
  308         char qualifier[6];
  309         int retval = -1;
  310         uint32_t i;
  311 
  312         ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
  313 
  314         snprintf(qualifier, sizeof(qualifier), "/ocs");
  315 
  316         /* See if the name starts with my qualifier.  If not then this request isn't for me */
  317         if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
  318                 char *unqualified_name = name + strlen(qualifier) + 1;
  319 
  320                 for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
  321                         if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
  322                                 if (mgmt_table[i].get_handler) {
  323                                         mgmt_table[i].get_handler(ocs, name, textbuf);
  324                                         ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
  325                                         return 0;
  326                                 }
  327                         }
  328                 }
  329 
  330                 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_handler)) {
  331                         retval = ocs->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, ocs);
  332                 }
  333 
  334                 if (retval != 0) {
  335                         if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_handler)) {
  336                                 retval = ocs->tgt_mgmt_functions->get_handler(textbuf, qualifier,
  337                                                 (char*)name, &(ocs->tgt_ocs));
  338                         }
  339                 }
  340 
  341                 if (retval != 0) {
  342                         /* The driver didn't handle it, pass it to each domain */
  343 
  344                         ocs_device_lock(ocs);
  345                         ocs_list_foreach(&ocs->domain_list, domain) {
  346                                 if ((domain->mgmt_functions) && (domain->mgmt_functions->get_handler)) {
  347                                         retval = domain->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, domain);
  348                                 }
  349 
  350                                 if (retval ==  0) {
  351                                         break;
  352                                 }
  353                         }
  354                         ocs_device_unlock(ocs);
  355                 }
  356         }
  357 
  358         ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
  359 
  360         return retval;
  361 }
  362 
  363 /**
  364  * @ingroup mgmt
  365  * @brief Set the value of a mgmt item.
  366  *
  367  * @par Description
  368  * This is the top level "set" handler for the driver. It
  369  * performs the following:
  370  *  - Checks that the qualifier portion of the name begins with my qualifier (ocs).
  371  *  - If the remaining part of the name matches a parameter that is known at this level,
  372  *    calls the correct function to change the configuration.
  373  *  - If the name is not known, sends the request to the back-ends to fulfill (if possible).
  374  *  - If the request has not been fulfilled by the back-end, passes the request to each of the
  375  *    children (domains) to have them (recursively) try to respond.
  376  *
  377  *  In passing the request to other entities, the request is considered to be handled
  378  *  if the function returns 0.
  379  *
  380  * @param ocs Pointer to the ocs structure.
  381  * @param name Name of the property to be changed.
  382  * @param value Requested new value of the property.
  383  *
  384  * @return Returns 0 if the configuration value was updated, or -1 otherwise.
  385  */
  386 
  387 int
  388 ocs_mgmt_set(ocs_t *ocs, char *name, char *value)
  389 {
  390         ocs_domain_t *domain;
  391         int result = -1;
  392         char qualifier[80];
  393         uint32_t i;
  394 
  395         snprintf(qualifier, sizeof(qualifier), "/ocs");
  396 
  397         /* If it doesn't start with my qualifier I don't know what to do with it */
  398         if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
  399                 char *unqualified_name = name + strlen(qualifier) +1;
  400 
  401                 /* See if it's a value I can set */
  402                 for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
  403                         if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
  404                                 if (mgmt_table[i].set_handler) {
  405                                         return mgmt_table[i].set_handler(ocs, name, value);
  406                                 }
  407                         }
  408                 }
  409 
  410                 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->set_handler)) {
  411                         result = ocs->mgmt_functions->set_handler(qualifier, name, (char *)value, ocs);
  412                 }
  413 
  414                 if (result != 0) {
  415                         if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->set_handler)) {
  416                                 result = ocs->tgt_mgmt_functions->set_handler(qualifier, name,
  417                                                 (char *)value, &(ocs->tgt_ocs));
  418                         }
  419                 }
  420 
  421                 /* If I didn't know how to set this config value pass the request to each of my children */
  422                 if (result != 0) {
  423                         ocs_device_lock(ocs);
  424                         ocs_list_foreach(&ocs->domain_list, domain) {
  425                                 if ((domain->mgmt_functions) && (domain->mgmt_functions->set_handler)) {
  426                                         result = domain->mgmt_functions->set_handler(qualifier, name, (char*)value, domain);
  427                                 }
  428                                 if (result == 0) {
  429                                         break;
  430                                 }
  431                         }
  432                         ocs_device_unlock(ocs);
  433                 }
  434         }
  435 
  436         return result;
  437 }
  438 
  439 /**
  440  * @ingroup mgmt
  441  * @brief Perform a management action.
  442  *
  443  * @par Description
  444  * This is the top level "exec" handler for the driver. It
  445  * performs the following:
  446  *  - Checks that the qualifier portion of the name begins with my qualifier (ocs).
  447  *  - If the remaining part of the name matches an action that is known at this level,
  448  *    calls the correct function to perform the action.
  449  *  - If the name is not known, sends the request to the back-ends to fulfill (if possible).
  450  *  - If the request has not been fulfilled by the back-end, passes the request to each of the
  451  *    children (domains) to have them (recursively) try to respond.
  452  *
  453  *  In passing the request to other entities, the request is considered to be handled
  454  *  if the function returns 0.
  455  *
  456  * @param ocs Pointer to the ocs structure.
  457  * @param action Name of the action to be performed.
  458  * @param arg_in Pointer to an argument being passed to the action.
  459  * @param arg_in_length Length of the argument pointed to by @c arg_in.
  460  * @param arg_out Pointer to an argument being passed to the action.
  461  * @param arg_out_length Length of the argument pointed to by @c arg_out.
  462  *
  463  * @return Returns 0 if the action was completed, or -1 otherwise.
  464  *
  465  *
  466  */
  467 
  468 int
  469 ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in,
  470                 uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
  471 {
  472         ocs_domain_t *domain;
  473         int result = -1;
  474         char qualifier[80];
  475         uint32_t i;
  476 
  477         snprintf(qualifier, sizeof(qualifier), "/ocs");
  478 
  479         /* If it doesn't start with my qualifier I don't know what to do with it */
  480         if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) {
  481                 char *unqualified_name = action + strlen(qualifier) +1;
  482 
  483                 /* See if it's an action I can perform */
  484                 for (i=0;i<ARRAY_SIZE(mgmt_table); i++) {
  485                         if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
  486                                 if (mgmt_table[i].action_handler) {
  487                                         return mgmt_table[i].action_handler(ocs, action, arg_in, arg_in_length,
  488                                                         arg_out, arg_out_length);
  489                                 }
  490                         }
  491                 }
  492 
  493                 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->exec_handler)) {
  494                         result = ocs->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
  495                                                                    arg_out, arg_out_length, ocs);
  496                 }
  497 
  498                 if (result != 0) {
  499                         if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->exec_handler)) {
  500                                 result = ocs->tgt_mgmt_functions->exec_handler(qualifier, action,
  501                                                 arg_in, arg_in_length, arg_out, arg_out_length,
  502                                                 &(ocs->tgt_ocs));
  503                         }
  504                 }
  505 
  506                 /* If I didn't know how to do this action pass the request to each of my children */
  507                 if (result != 0) {
  508                         ocs_device_lock(ocs);
  509                         ocs_list_foreach(&ocs->domain_list, domain) {
  510                                 if ((domain->mgmt_functions) && (domain->mgmt_functions->exec_handler)) {
  511                                         result = domain->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length, arg_out,
  512                                                         arg_out_length, domain);
  513                                 }
  514                                 if (result == 0) {
  515                                         break;
  516                                 }
  517                         }
  518                         ocs_device_unlock(ocs);
  519                 }
  520         }
  521 
  522         return result;
  523 }
  524 
  525 void
  526 ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf)
  527 {
  528         ocs_domain_t *domain;
  529         uint32_t i;
  530 
  531         ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
  532 
  533         for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
  534                 if (mgmt_table[i].get_handler) {
  535                         mgmt_table[i].get_handler(ocs, mgmt_table[i].name, textbuf);
  536                 } else if (mgmt_table[i].action_handler) {
  537                         /* No get_handler, but there's an action_handler. Just report
  538                            the name */
  539                         ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, mgmt_table[i].name);
  540                 }
  541         }
  542 
  543         if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_all_handler)) {
  544                 ocs->mgmt_functions->get_all_handler(textbuf, ocs);
  545         }
  546 
  547         if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_all_handler)) {
  548                 ocs->tgt_mgmt_functions->get_all_handler(textbuf, &(ocs->tgt_ocs));
  549         }
  550 
  551         ocs_device_lock(ocs);
  552         ocs_list_foreach(&ocs->domain_list, domain) {
  553                 if ((domain->mgmt_functions) && (domain->mgmt_functions->get_all_handler)) {
  554                         domain->mgmt_functions->get_all_handler(textbuf, domain);
  555                 }
  556         }
  557         ocs_device_unlock(ocs);
  558 
  559         ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
  560 }
  561 
  562 #if defined(OCS_INCLUDE_RAMD)
  563 static int32_t
  564 ocs_mgmt_read_phys(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
  565 {
  566         uint32_t length;
  567         char addr_str[80];
  568         uintptr_t target_addr;
  569         void* vaddr = NULL;
  570         ocs_ramdisc_t **ramdisc_array;
  571         uint32_t ramdisc_count;
  572 
  573         if ((arg_in == NULL) ||
  574             (arg_in_length == 0) ||
  575             (arg_out == NULL) ||
  576             (arg_out_length == 0)) {
  577                 return -1;
  578         }
  579 
  580         if (arg_in_length > 80) {
  581                 arg_in_length = 80;
  582         }
  583 
  584         if (ocs_copy_from_user(addr_str, arg_in, arg_in_length)) {
  585                 ocs_log_test(ocs, "Failed to copy addr from user\n");
  586                 return -EFAULT;
  587         }
  588 
  589         target_addr = (uintptr_t)ocs_strtoul(addr_str, NULL, 0);
  590         /* addr_str must be the physical address of a buffer that was reported
  591          * in an SGL.  Search ramdiscs looking for a segment that contains that
  592          * physical address
  593          */
  594 
  595         if (ocs->tgt_ocs.use_global_ramd) {
  596                 /* Only one target */
  597                 ramdisc_count = ocs->tgt_ocs.rdisc_count;
  598                 ramdisc_array = ocs->tgt_ocs.rdisc;
  599                 vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
  600         } else {
  601                 /* Multiple targets.  Each target is on a sport */
  602                 uint32_t domain_idx;
  603 
  604                 for (domain_idx=0; domain_idx<ocs->domain_instance_count; domain_idx++) {
  605                         ocs_domain_t *domain;
  606                         uint32_t sport_idx;
  607 
  608                         domain = ocs_domain_get_instance(ocs, domain_idx);
  609                         for (sport_idx=0; sport_idx < domain->sport_instance_count; sport_idx++) {
  610                                 ocs_sport_t *sport;
  611 
  612                                 sport = ocs_sport_get_instance(domain, sport_idx);
  613                                 ramdisc_count = sport->tgt_sport.rdisc_count;
  614                                 ramdisc_array = sport->tgt_sport.rdisc;
  615                                 vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
  616 
  617                                 if (vaddr != NULL) {
  618                                         break;
  619                                 }
  620                         }
  621                 }
  622         }
  623 
  624         length = arg_out_length;
  625 
  626         if (vaddr != NULL) {
  627                 if (ocs_copy_to_user(arg_out, vaddr, length)) {
  628                         ocs_log_test(ocs, "Failed to copy buffer to user\n");
  629                         return -EFAULT;
  630                 }
  631 
  632                 return 0;
  633         } else {
  634                 return -EFAULT;
  635         }
  636 
  637 }
  638 
  639 /*
  640  * This function searches a target for a given physical address.
  641  * The target is made up of a number of LUNs, each represented by
  642  * a ocs_ramdisc_t.
  643  */
  644 static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr)
  645 {
  646         void *vaddr = NULL;
  647         uint32_t ramdisc_idx;
  648 
  649         /* Check each ramdisc */
  650         for (ramdisc_idx=0; ramdisc_idx<ramdisc_count; ramdisc_idx++) {
  651                 uint32_t segment_idx;
  652                 ocs_ramdisc_t *rdisc;
  653                 rdisc = ramdisc_array[ramdisc_idx];
  654                 /* Check each segment in the ramdisc */
  655                 for (segment_idx=0; segment_idx<rdisc->segment_count; segment_idx++) {
  656                         ramdisc_segment_t *segment = rdisc->segments[segment_idx];
  657                         uintptr_t segment_start;
  658                         uintptr_t segment_end;
  659                         uint32_t offset;
  660 
  661                         segment_start = segment->data_segment.phys;
  662                         segment_end = segment->data_segment.phys + segment->data_segment.size - 1;
  663                         if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
  664                                 /* Found the target address */
  665                                 offset = target_addr - segment_start;
  666                                 vaddr = (uint32_t*)segment->data_segment.virt + offset;
  667                         }
  668 
  669                         if (rdisc->dif_separate) {
  670                                 segment_start = segment->dif_segment.phys;
  671                                 segment_end = segment->data_segment.phys + segment->dif_segment.size - 1;
  672                                 if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
  673                                         /* Found the target address */
  674                                         offset = target_addr - segment_start;
  675                                         vaddr = (uint32_t*)segment->dif_segment.virt + offset;
  676                                 }
  677                         }
  678 
  679                         if (vaddr != NULL) {
  680                                 break;
  681                         }
  682                 }
  683 
  684                 if (vaddr != NULL) {
  685                         break;
  686                 }
  687         }
  688 
  689         return vaddr;
  690 }
  691 #endif
  692 
  693 static int32_t
  694 ocs_mgmt_firmware_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
  695 {
  696         int rc = 0;
  697         int index = 0;
  698         uint8_t bus, dev, func;
  699         ocs_t *other_ocs;
  700 
  701         ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
  702 
  703         ocs_log_debug(ocs, "Resetting port\n");
  704         if (ocs_hw_reset(&ocs->hw, OCS_HW_RESET_FIRMWARE)) {
  705                 ocs_log_test(ocs, "failed to reset port\n");
  706                 rc = -1;
  707         } else {
  708                 ocs_log_debug(ocs, "successfully reset port\n");
  709 
  710                 /* now reset all functions on the same device */
  711 
  712                 while ((other_ocs = ocs_get_instance(index++)) != NULL) {
  713                         uint8_t other_bus, other_dev, other_func;
  714 
  715                         ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
  716 
  717                         if ((bus == other_bus) && (dev == other_dev)) {
  718                                 if (other_ocs->hw.state !=
  719                                       OCS_HW_STATE_UNINITIALIZED) {
  720                                         other_ocs->hw.state =
  721                                                 OCS_HW_STATE_QUEUES_ALLOCATED;
  722                                 }
  723 
  724                                 ocs_device_detach(other_ocs);
  725                                 if (ocs_device_attach(other_ocs)) {
  726                                         ocs_log_err(other_ocs,
  727                                                 "device %d attach failed \n", index);
  728                                         rc = -1;
  729                                 }
  730                         }
  731                 }
  732         }
  733         return rc;
  734 }
  735 
  736 static int32_t
  737 ocs_mgmt_function_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
  738 {
  739         int32_t rc;
  740 
  741         ocs_device_detach(ocs);
  742         rc = ocs_device_attach(ocs);
  743 
  744         return rc;
  745 }
  746 
  747 static int32_t
  748 ocs_mgmt_firmware_write(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
  749 {
  750         int rc = 0;
  751         uint32_t bytes_left;
  752         uint32_t xfer_size;
  753         uint32_t offset;
  754         uint8_t *userp;
  755         ocs_dma_t dma;
  756         int last = 0;
  757         ocs_mgmt_fw_write_result_t result;
  758         uint32_t change_status = 0;
  759         char status_str[80];
  760 
  761         ocs_sem_init(&(result.semaphore), 0, "fw_write");
  762 
  763         bytes_left = buf_len;
  764         offset = 0;
  765         userp = (uint8_t *)buf;
  766 
  767         if (ocs_dma_alloc(ocs, &dma, FW_WRITE_BUFSIZE, 4096)) {
  768                 ocs_log_err(ocs, "ocs_mgmt_firmware_write: malloc failed");
  769                 return -ENOMEM;
  770         }
  771 
  772         while (bytes_left > 0) {
  773                 if (bytes_left > FW_WRITE_BUFSIZE) {
  774                         xfer_size = FW_WRITE_BUFSIZE;
  775                 } else {
  776                         xfer_size = bytes_left;
  777                 }
  778 
  779                 /* Copy xfer_size bytes from user space to kernel buffer */
  780                 if (ocs_copy_from_user(dma.virt, userp, xfer_size)) {
  781                         rc = -EFAULT;
  782                         break;
  783                 }
  784 
  785                 /* See if this is the last block */
  786                 if (bytes_left == xfer_size) {
  787                         last = 1;
  788                 }
  789 
  790                 /* Send the HW command */
  791                 ocs_hw_firmware_write(&ocs->hw, &dma, xfer_size, offset, last, ocs_mgmt_fw_write_cb, &result);
  792 
  793                 /* Wait for semaphore to be signaled when the command completes
  794                  * TODO:  Should there be a timeout on this?  If so, how long? */
  795                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
  796                         ocs_log_err(ocs, "ocs_sem_p failed\n");
  797                         rc = -ENXIO;
  798                         break;
  799                 }
  800 
  801                 if (result.actual_xfer == 0) {
  802                         ocs_log_test(ocs, "actual_write_length is %d\n", result.actual_xfer);
  803                         rc = -EFAULT;
  804                         break;
  805                 }
  806 
  807                 /* Check status */
  808                 if (result.status != 0) {
  809                         ocs_log_test(ocs, "write returned status %d\n", result.status);
  810                         rc = -EFAULT;
  811                         break;
  812                 }
  813 
  814                 if (last) {
  815                         change_status = result.change_status;
  816                 }
  817 
  818                 bytes_left -= result.actual_xfer;
  819                 offset += result.actual_xfer;
  820                 userp += result.actual_xfer;
  821         }
  822 
  823         /* Create string with status and copy to userland */
  824         if ((arg_out_length > 0) && (arg_out != NULL)) {
  825                 if (arg_out_length > sizeof(status_str)) {
  826                         arg_out_length = sizeof(status_str);
  827                 }
  828                 ocs_memset(status_str, 0, sizeof(status_str));
  829                 ocs_snprintf(status_str, arg_out_length, "%d", change_status);
  830                 if (ocs_copy_to_user(arg_out, status_str, arg_out_length)) {
  831                         ocs_log_test(ocs, "copy to user failed for change_status\n");
  832                 }
  833         }
  834 
  835         ocs_dma_free(ocs, &dma);
  836 
  837         return rc;
  838 }
  839 
  840 static void
  841 ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, uint32_t change_status, void *arg)
  842 {
  843         ocs_mgmt_fw_write_result_t *result = arg;
  844 
  845         result->status = status;
  846         result->actual_xfer = actual_write_length;
  847         result->change_status = change_status;
  848 
  849         ocs_sem_v(&(result->semaphore));
  850 }
  851 
  852 typedef struct ocs_mgmt_sfp_result {
  853         ocs_sem_t semaphore;
  854         ocs_lock_t cb_lock;
  855         int32_t running;
  856         int32_t status;
  857         uint32_t bytes_read;
  858         uint32_t page_data[32];
  859 } ocs_mgmt_sfp_result_t;
  860 
  861 static void
  862 ocs_mgmt_sfp_cb(void *os, int32_t status, uint32_t bytes_read, uint32_t *data, void *arg)
  863 {
  864         ocs_mgmt_sfp_result_t *result = arg;
  865         ocs_t *ocs = os;
  866 
  867         ocs_lock(&(result->cb_lock));
  868         result->running++;
  869         if(result->running == 2) {
  870                 /* get_sfp() has timed out */
  871                 ocs_unlock(&(result->cb_lock));
  872                 ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t));
  873                 return;
  874         }
  875 
  876         result->status = status;
  877         result->bytes_read = bytes_read;
  878         ocs_memcpy(&result->page_data, data, SFP_PAGE_SIZE);
  879 
  880         ocs_sem_v(&(result->semaphore));
  881         ocs_unlock(&(result->cb_lock));
  882 }
  883 
  884 static int32_t
  885 ocs_mgmt_get_sfp(ocs_t *ocs, uint16_t page, void *buf, uint32_t buf_len)
  886 {
  887         int rc = 0;
  888         ocs_mgmt_sfp_result_t *result = ocs_malloc(ocs, sizeof(ocs_mgmt_sfp_result_t),  OCS_M_ZERO | OCS_M_NOWAIT);
  889 
  890         ocs_sem_init(&(result->semaphore), 0, "get_sfp");
  891         ocs_lock_init(ocs, &(result->cb_lock), "get_sfp");
  892 
  893         /* Send the HW command */
  894         ocs_hw_get_sfp(&ocs->hw, page, ocs_mgmt_sfp_cb, result);
  895 
  896         /* Wait for semaphore to be signaled when the command completes */
  897         if (ocs_sem_p(&(result->semaphore), 5 * 1000 * 1000) != 0) {
  898                 /* Timed out, callback will free memory */
  899                 ocs_lock(&(result->cb_lock));
  900                 result->running++;
  901                 if(result->running == 1) {
  902                         ocs_log_err(ocs, "ocs_sem_p failed\n");
  903                         ocs_unlock(&(result->cb_lock));
  904                         return (-ENXIO);
  905                 }
  906                 /* sfp_cb() has already executed, proceed as normal */
  907                 ocs_unlock(&(result->cb_lock));
  908         }
  909 
  910         /* Check status */
  911         if (result->status != 0) {
  912                 ocs_log_test(ocs, "read_transceiver_data returned status %d\n",
  913                              result->status);
  914                 rc = -EFAULT;
  915         }
  916 
  917         if (rc == 0) {
  918                 rc = (result->bytes_read > buf_len ? buf_len : result->bytes_read);
  919                 /* Copy the results back to the supplied buffer */
  920                 ocs_memcpy(buf, result->page_data, rc);
  921         }
  922 
  923         ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t));
  924         return rc;
  925 }
  926 
  927 static int32_t
  928 ocs_mgmt_force_assert(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
  929 {
  930         ocs_assert(FALSE, 0);
  931 }
  932 
  933 static void
  934 get_nodes_count(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  935 {
  936         ocs_xport_t *xport = ocs->xport;
  937 
  938         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "nodes_count", "%d", xport->nodes_count);
  939 }
  940 
  941 static void
  942 get_driver_version(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  943 {
  944         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "driver_version", ocs->driver_version);
  945 }
  946 
  947 static void
  948 get_desc(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  949 {
  950         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "desc", ocs->desc);
  951 }
  952 
  953 static void
  954 get_fw_rev(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  955 {
  956         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev", ocs_hw_get_ptr(&ocs->hw, OCS_HW_FW_REV));
  957 }
  958 
  959 static void
  960 get_fw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  961 {
  962         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev2", ocs_hw_get_ptr(&ocs->hw, OCS_HW_FW_REV2));
  963 }
  964 
  965 static void
  966 get_ipl(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  967 {
  968         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ipl", ocs_hw_get_ptr(&ocs->hw, OCS_HW_IPL));
  969 }
  970 
  971 static void
  972 get_hw_rev1(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  973 {
  974         uint32_t value;
  975 
  976         ocs_hw_get(&ocs->hw, OCS_HW_HW_REV1, &value);
  977 
  978         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev1", "%u", value);
  979 }
  980 
  981 static void
  982 get_hw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  983 {
  984         uint32_t value;
  985 
  986         ocs_hw_get(&ocs->hw, OCS_HW_HW_REV2, &value);
  987 
  988         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev2", "%u", value);
  989 }
  990 
  991 static void
  992 get_hw_rev3(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
  993 {
  994         uint32_t value;
  995         ocs_hw_get(&ocs->hw, OCS_HW_HW_REV3, &value);
  996 
  997         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev3", "%u", value);
  998 }
  999 
 1000 static void
 1001 get_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1002 {
 1003         uint64_t *wwnn;
 1004 
 1005         wwnn = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_NODE);
 1006 
 1007         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwnn", "0x%llx", (unsigned long long)ocs_htobe64(*wwnn));
 1008 }
 1009 
 1010 static void
 1011 get_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1012 {
 1013         uint64_t *wwpn;
 1014 
 1015         wwpn = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_PORT);
 1016 
 1017         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwpn", "0x%llx", (unsigned long long)ocs_htobe64(*wwpn));
 1018 }
 1019 
 1020 static void
 1021 get_fcid(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1022 {
 1023 
 1024         if (ocs->domain && ocs->domain->attached) {
 1025                 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "0x%06x", 
 1026                                                 ocs->domain->sport->fc_id);
 1027         } else {
 1028                 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "UNKNOWN"); 
 1029         }
 1030 
 1031 }
 1032 
 1033 static void
 1034 get_sn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1035 {
 1036         uint8_t *pserial;
 1037         uint32_t len;
 1038         char sn_buf[256];
 1039 
 1040         pserial = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_SERIALNUMBER);
 1041         if (pserial) {
 1042                 len = *pserial ++;
 1043                 strncpy(sn_buf, (char*)pserial, len);
 1044                 sn_buf[len] = '\0';
 1045                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sn", sn_buf);
 1046         }
 1047 }
 1048 
 1049 static void
 1050 get_pn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1051 {
 1052         uint8_t *pserial;
 1053         uint32_t len;
 1054         char sn_buf[256];
 1055 
 1056         pserial = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_PARTNUMBER);
 1057         if (pserial) {
 1058                 len = *pserial ++;
 1059                 strncpy(sn_buf, (char*)pserial, len);
 1060                 sn_buf[len] = '\0';
 1061                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", sn_buf);
 1062         } else {
 1063                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", ocs->model);
 1064         }
 1065 }
 1066 
 1067 static void
 1068 get_sli4_intf_reg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1069 {
 1070 
 1071         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "sli4_intf_reg", "0x%04x",
 1072                 ocs_config_read32(ocs, SLI4_INTF_REG));
 1073 }
 1074 
 1075 static void
 1076 get_phy_port_num(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1077 {
 1078         char *phy_port = NULL;
 1079 
 1080         phy_port = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_PORTNUM);
 1081         if (phy_port) {
 1082                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "phy_port_num", phy_port);
 1083         } else {
 1084                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "phy_port_num", "unknown");
 1085         }
 1086 }
 1087 static void
 1088 get_asic_id(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1089 {
 1090 
 1091         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "asic_id_reg", "0x%04x",
 1092                 ocs_config_read32(ocs, SLI4_ASIC_ID_REG));
 1093 }
 1094 
 1095 static void
 1096 get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1097 {
 1098         uint32_t family;
 1099         uint32_t asic_id;
 1100         uint32_t asic_gen_num;
 1101         uint32_t asic_rev_num;
 1102         uint32_t rev_id;
 1103         char result_buf[80];
 1104         char tmp_buf[80];
 1105 
 1106         family = (ocs_config_read32(ocs, SLI4_INTF_REG) & 0x00000f00) >> 8;
 1107         asic_id = ocs_config_read32(ocs, SLI4_ASIC_ID_REG);
 1108         asic_rev_num = asic_id & 0xff;
 1109         asic_gen_num = (asic_id & 0xff00) >> 8;
 1110 
 1111         rev_id = ocs_config_read32(ocs, SLI4_PCI_CLASS_REVISION) & 0xff;
 1112 
 1113         switch(family) {
 1114         case 0x00:
 1115                 /* BE2 */
 1116                 ocs_strncpy(result_buf,  "BE2 A", sizeof(result_buf));
 1117                 ocs_snprintf(tmp_buf, 2, "%d", rev_id);
 1118                 strcat(result_buf, tmp_buf);
 1119                 break;
 1120         case 0x01:
 1121                 /* BE3 */
 1122                 ocs_strncpy(result_buf, "BE3", sizeof(result_buf));
 1123                 if (rev_id >= 0x10) {
 1124                         strcat(result_buf, "-R");
 1125                 }
 1126                 ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A');
 1127                 strcat(result_buf, tmp_buf);
 1128                 ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
 1129                 strcat(result_buf, tmp_buf);
 1130                 break;
 1131         case 0x02:
 1132                 /* Skyhawk A0 */
 1133                 ocs_strncpy(result_buf, "Skyhawk A0", sizeof(result_buf));
 1134                 break;
 1135         case 0x0a:
 1136                 /* Lancer A0 */
 1137                 ocs_strncpy(result_buf, "Lancer A", sizeof(result_buf));
 1138                 ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
 1139                 strcat(result_buf, tmp_buf);
 1140                 break;
 1141         case 0x0b:
 1142                 /* Lancer B0 or D0 */
 1143                 ocs_strncpy(result_buf, "Lancer", sizeof(result_buf));
 1144                 ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A');
 1145                 strcat(result_buf, tmp_buf);
 1146                 ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
 1147                 strcat(result_buf, tmp_buf);
 1148                 break;
 1149         case 0x0c:
 1150                 ocs_strncpy(result_buf, "Lancer G6", sizeof(result_buf));
 1151                 break;
 1152         case 0x0f:
 1153                 /* Refer to ASIC_ID */
 1154                 switch(asic_gen_num) {
 1155                 case 0x00:
 1156                         ocs_strncpy(result_buf, "BE2", sizeof(result_buf));
 1157                         break;
 1158                 case 0x03:
 1159                         ocs_strncpy(result_buf, "BE3-R", sizeof(result_buf));
 1160                         break;
 1161                 case 0x04:
 1162                         ocs_strncpy(result_buf, "Skyhawk-R", sizeof(result_buf));
 1163                         break;
 1164                 case 0x05:
 1165                         ocs_strncpy(result_buf, "Corsair", sizeof(result_buf));
 1166                         break;
 1167                 case 0x0b:
 1168                         ocs_strncpy(result_buf, "Lancer", sizeof(result_buf));
 1169                         break;
 1170                 case 0x0c:
 1171                         ocs_strncpy(result_buf, "LancerG6", sizeof(result_buf));
 1172                         break;
 1173                 default:
 1174                         ocs_strncpy(result_buf, "Unknown", sizeof(result_buf));
 1175                 }
 1176                 if (ocs_strcmp(result_buf, "Unknown") != 0) {
 1177                         ocs_snprintf(tmp_buf, 3, " %c", ((asic_rev_num & 0xf0) >> 4) + 'A');
 1178                         strcat(result_buf, tmp_buf);
 1179                         ocs_snprintf(tmp_buf, 2, "%d", asic_rev_num & 0x0f);
 1180                         strcat(result_buf, tmp_buf);
 1181                 }
 1182                 break;
 1183         default:
 1184                 ocs_strncpy(result_buf, "Unknown", sizeof(result_buf));
 1185         }
 1186 
 1187         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "chip_type", result_buf);
 1188 
 1189 }
 1190 
 1191 static void
 1192 get_pci_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1193 {
 1194 
 1195         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_vendor", "0x%04x", ocs->pci_vendor);
 1196 }
 1197 
 1198 static void
 1199 get_pci_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1200 {
 1201 
 1202         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_device", "0x%04x", ocs->pci_device);
 1203 }
 1204 
 1205 static void
 1206 get_pci_subsystem_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1207 {
 1208 
 1209         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_vendor", "0x%04x", ocs->pci_subsystem_vendor);
 1210 }
 1211 
 1212 static void
 1213 get_pci_subsystem_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1214 {
 1215 
 1216         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_device", "0x%04x", ocs->pci_subsystem_device);
 1217 }
 1218 
 1219 static void
 1220 get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1221 {
 1222         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tgt_rscn_delay", "%ld", (unsigned long)ocs->tgt_rscn_delay_msec / 1000);
 1223 }
 1224 
 1225 static void
 1226 get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1227 {
 1228         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tgt_rscn_period", "%ld", (unsigned long)ocs->tgt_rscn_period_msec / 1000);
 1229 }
 1230 
 1231 static void
 1232 get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1233 {
 1234         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_cmd", "%d",
 1235                         (ocs->err_injection == INJECT_DROP_CMD ? 1:0));
 1236 }
 1237 
 1238 static void
 1239 get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1240 {
 1241         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_free_drop_cmd", "%d",
 1242                         (ocs->err_injection == INJECT_FREE_DROPPED ? 1:0));
 1243 }
 1244 
 1245 static void
 1246 get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1247 {
 1248         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_data", "%d",
 1249                         (ocs->err_injection == INJECT_DROP_DATA ? 1:0));
 1250 }
 1251 
 1252 static void
 1253 get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1254 {
 1255         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_resp", "%d",
 1256                         (ocs->err_injection == INJECT_DROP_RESP ? 1:0));
 1257 }
 1258 
 1259 static void
 1260 get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1261 {
 1262         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "cmd_err_inject", "0x%02x", ocs->cmd_err_inject);
 1263 }
 1264 
 1265 static void
 1266 get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1267 {
 1268         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "cmd_delay_value", "%ld", (unsigned long)ocs->delay_value_msec);
 1269 }
 1270 
 1271 static void
 1272 get_businfo(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1273 {
 1274         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "businfo", ocs->businfo);
 1275 }
 1276 
 1277 static void
 1278 get_sfp_a0(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1279 {
 1280         uint8_t *page_data;
 1281         char *buf;
 1282         int i;
 1283         int32_t bytes_read;
 1284 
 1285         page_data = ocs_malloc(ocs, SFP_PAGE_SIZE, OCS_M_ZERO | OCS_M_NOWAIT);
 1286         if (page_data == NULL) {
 1287                 return;
 1288         }
 1289 
 1290         buf = ocs_malloc(ocs, (SFP_PAGE_SIZE * 3) + 1, OCS_M_ZERO | OCS_M_NOWAIT);
 1291         if (buf == NULL) {
 1292                 ocs_free(ocs, page_data, SFP_PAGE_SIZE);
 1293                 return;
 1294         }
 1295 
 1296         bytes_read = ocs_mgmt_get_sfp(ocs, 0xa0, page_data, SFP_PAGE_SIZE);
 1297 
 1298         if (bytes_read <= 0) {
 1299                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", "(unknown)");
 1300         } else {
 1301                 char *d = buf;
 1302                 uint8_t *s = page_data;
 1303                 int buffer_remaining = (SFP_PAGE_SIZE * 3) + 1;
 1304                 int bytes_added;
 1305 
 1306                 for (i = 0; i < bytes_read; i++) {
 1307                         bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s);
 1308                         ++s;
 1309                         d += bytes_added;
 1310                         buffer_remaining -= bytes_added;
 1311                 }
 1312                 *d = '\0';
 1313                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", buf);
 1314         }
 1315 
 1316         ocs_free(ocs, page_data, SFP_PAGE_SIZE);
 1317         ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE) + 1);
 1318 }
 1319 
 1320 static void
 1321 get_sfp_a2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1322 {
 1323         uint8_t *page_data;
 1324         char *buf;
 1325         int i;
 1326         int32_t bytes_read;
 1327 
 1328         page_data = ocs_malloc(ocs, SFP_PAGE_SIZE, OCS_M_ZERO | OCS_M_NOWAIT);
 1329         if (page_data == NULL) {
 1330                 return;
 1331         }
 1332 
 1333         buf = ocs_malloc(ocs, (SFP_PAGE_SIZE * 3) + 1, OCS_M_ZERO | OCS_M_NOWAIT);
 1334         if (buf == NULL) {
 1335                 ocs_free(ocs, page_data, SFP_PAGE_SIZE);
 1336                 return;
 1337         }
 1338 
 1339         bytes_read = ocs_mgmt_get_sfp(ocs, 0xa2, page_data, SFP_PAGE_SIZE);
 1340 
 1341         if (bytes_read <= 0) {
 1342                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a2", "(unknown)");
 1343         } else {
 1344                 char *d = buf;
 1345                 uint8_t *s = page_data;
 1346                 int buffer_remaining = (SFP_PAGE_SIZE * 3) + 1;
 1347                 int bytes_added;
 1348 
 1349                 for (i=0; i < bytes_read; i++) {
 1350                         bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s);
 1351                         ++s;
 1352                         d += bytes_added;
 1353                         buffer_remaining -= bytes_added;
 1354                 }
 1355                 *d = '\0';
 1356                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a2", buf);
 1357         }
 1358 
 1359         ocs_free(ocs, page_data, SFP_PAGE_SIZE);
 1360         ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE) + 1);
 1361 }
 1362 
 1363 static void
 1364 get_debug_mq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1365 {
 1366 
 1367         ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_mq_dump",
 1368                 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP));
 1369 }
 1370 
 1371 static void
 1372 get_debug_cq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1373 {
 1374 
 1375         ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_cq_dump",
 1376                 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_CQ_DUMP));
 1377 }
 1378 
 1379 static void
 1380 get_debug_wq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1381 {
 1382         ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_wq_dump",
 1383                 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_WQ_DUMP));
 1384 }
 1385 
 1386 static void
 1387 get_debug_eq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1388 {
 1389         ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_eq_dump",
 1390                 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_EQ_DUMP));
 1391 }
 1392 
 1393 static void
 1394 get_logmask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1395 {
 1396 
 1397         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "logmask", "0x%02x", ocs->logmask);
 1398 
 1399 }
 1400 
 1401 static void
 1402 get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1403 {
 1404 
 1405         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "loglevel", "%d", loglevel);
 1406 
 1407 }
 1408 
 1409 static void
 1410 get_current_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1411 {
 1412         uint32_t value;
 1413 
 1414         ocs_hw_get(&(ocs->hw), OCS_HW_LINK_SPEED, &value);
 1415 
 1416         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "current_speed", "%d", value);
 1417 }
 1418 
 1419 static void
 1420 get_configured_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1421 {
 1422         uint32_t value;
 1423 
 1424         ocs_hw_get(&(ocs->hw), OCS_HW_LINK_CONFIG_SPEED, &value);
 1425         if (value == 0) {
 1426                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_speed", "auto");
 1427         } else {
 1428                 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "configured_speed", "%d", value);
 1429         }
 1430 
 1431 }
 1432 
 1433 static void
 1434 get_current_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1435 {
 1436         uint32_t value;
 1437 
 1438         ocs_hw_get(&(ocs->hw), OCS_HW_TOPOLOGY, &value);
 1439         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "current_topology", "%d", value);
 1440 
 1441 }
 1442 
 1443 static void
 1444 get_configured_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1445 {
 1446         uint32_t value;
 1447 
 1448         ocs_hw_get(&(ocs->hw), OCS_HW_CONFIG_TOPOLOGY, &value);
 1449         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "configured_topology", "%d", value);
 1450 
 1451 }
 1452 
 1453 static void
 1454 get_current_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1455 {
 1456         ocs_xport_stats_t value;
 1457 
 1458         if (ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value) == 0) {
 1459                 if (value.value == OCS_XPORT_PORT_ONLINE) {
 1460                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_link_state", "online");
 1461                 } else {
 1462                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_link_state", "offline");
 1463                 }
 1464         }
 1465 }
 1466 
 1467 static void
 1468 get_configured_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1469 {
 1470         ocs_xport_stats_t value;
 1471 
 1472         if (ocs_xport_status(ocs->xport, OCS_XPORT_CONFIG_PORT_STATUS, &value) == 0) {
 1473                 if (value.value == OCS_XPORT_PORT_ONLINE) {
 1474                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_link_state", "online");
 1475                 } else {
 1476                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_link_state", "offline");
 1477                 }
 1478         }
 1479 }
 1480 
 1481 /**
 1482  * @brief HW link config enum to mgmt string value mapping.
 1483  *
 1484  * This structure provides a mapping from the ocs_hw_linkcfg_e
 1485  * enum (enum exposed for the OCS_HW_PORT_SET_LINK_CONFIG port
 1486  * control) to the mgmt string that is passed in by the mgmt application
 1487  * (elxsdkutil).
 1488  */
 1489 typedef struct ocs_mgmt_linkcfg_map_s {
 1490         ocs_hw_linkcfg_e linkcfg;
 1491         const char *mgmt_str;
 1492 } ocs_mgmt_linkcfg_map_t;
 1493 
 1494 static ocs_mgmt_linkcfg_map_t mgmt_linkcfg_map[] = {
 1495         {OCS_HW_LINKCFG_4X10G, OCS_CONFIG_LINKCFG_4X10G},
 1496         {OCS_HW_LINKCFG_1X40G, OCS_CONFIG_LINKCFG_1X40G},
 1497         {OCS_HW_LINKCFG_2X16G, OCS_CONFIG_LINKCFG_2X16G},
 1498         {OCS_HW_LINKCFG_4X8G, OCS_CONFIG_LINKCFG_4X8G},
 1499         {OCS_HW_LINKCFG_4X1G, OCS_CONFIG_LINKCFG_4X1G},
 1500         {OCS_HW_LINKCFG_2X10G, OCS_CONFIG_LINKCFG_2X10G},
 1501         {OCS_HW_LINKCFG_2X10G_2X8G, OCS_CONFIG_LINKCFG_2X10G_2X8G}};
 1502 
 1503 /**
 1504  * @brief Get the HW linkcfg enum from the mgmt config string.
 1505  *
 1506  * @param mgmt_str mgmt string value.
 1507  *
 1508  * @return Returns the HW linkcfg enum corresponding to clp_str.
 1509  */
 1510 static ocs_hw_linkcfg_e
 1511 ocs_hw_linkcfg_from_mgmt(const char *mgmt_str)
 1512 {
 1513         uint32_t i;
 1514         for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) {
 1515                 if (ocs_strncmp(mgmt_linkcfg_map[i].mgmt_str,
 1516                                 mgmt_str, ocs_strlen(mgmt_str)) == 0) {
 1517                         return mgmt_linkcfg_map[i].linkcfg;
 1518                 }
 1519         }
 1520         return OCS_HW_LINKCFG_NA;
 1521 }
 1522 
 1523 /**
 1524  * @brief Get the mgmt string value from the HW linkcfg enum.
 1525  *
 1526  * @param linkcfg HW linkcfg enum.
 1527  *
 1528  * @return Returns the mgmt string value corresponding to the given HW linkcfg.
 1529  */
 1530 static const char *
 1531 ocs_mgmt_from_hw_linkcfg(ocs_hw_linkcfg_e linkcfg)
 1532 {
 1533         uint32_t i;
 1534         for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) {
 1535                 if (mgmt_linkcfg_map[i].linkcfg == linkcfg) {
 1536                         return mgmt_linkcfg_map[i].mgmt_str;
 1537                 }
 1538         }
 1539         return OCS_CONFIG_LINKCFG_UNKNOWN;
 1540 }
 1541 
 1542 /**
 1543  * @brief Link configuration callback argument
 1544  */
 1545 typedef struct ocs_mgmt_linkcfg_arg_s {
 1546         ocs_sem_t semaphore;
 1547         int32_t status;
 1548         ocs_hw_linkcfg_e linkcfg;
 1549 } ocs_mgmt_linkcfg_arg_t;
 1550 
 1551 /**
 1552  * @brief Get linkcfg config value
 1553  *
 1554  * @param ocs Pointer to the ocs structure.
 1555  * @param name Not used.
 1556  * @param textbuf The textbuf to which the result is written.
 1557  *
 1558  * @return None.
 1559  */
 1560 static void
 1561 get_linkcfg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1562 {
 1563         const char *linkcfg_str = NULL;
 1564         uint32_t value;
 1565         ocs_hw_linkcfg_e linkcfg;
 1566         ocs_hw_get(&ocs->hw, OCS_HW_LINKCFG, &value);
 1567         linkcfg = (ocs_hw_linkcfg_e)value;
 1568         linkcfg_str = ocs_mgmt_from_hw_linkcfg(linkcfg);
 1569         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "linkcfg", linkcfg_str);
 1570 }
 1571 
 1572 /**
 1573  * @brief Get requested WWNN config value
 1574  *
 1575  * @param ocs Pointer to the ocs structure.
 1576  * @param name Not used.
 1577  * @param textbuf The textbuf to which the result is written.
 1578  *
 1579  * @return None.
 1580  */
 1581 static void
 1582 get_req_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1583 {
 1584         ocs_xport_t *xport = ocs->xport;
 1585 
 1586         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "requested_wwnn", "0x%llx", (unsigned long long)xport->req_wwnn);
 1587 }
 1588 
 1589 /**
 1590  * @brief Get requested WWPN config value
 1591  *
 1592  * @param ocs Pointer to the ocs structure.
 1593  * @param name Not used.
 1594  * @param textbuf The textbuf to which the result is written.
 1595  *
 1596  * @return None.
 1597  */
 1598 static void
 1599 get_req_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1600 {
 1601         ocs_xport_t *xport = ocs->xport;
 1602 
 1603         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "requested_wwpn", "0x%llx", (unsigned long long)xport->req_wwpn);
 1604 }
 1605 
 1606 /**
 1607  * @brief Get requested nodedb_mask config value
 1608  *
 1609  * @param ocs Pointer to the ocs structure.
 1610  * @param name Not used.
 1611  * @param textbuf The textbuf to which the result is written.
 1612  *
 1613  * @return None.
 1614  */
 1615 static void
 1616 get_nodedb_mask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 1617 {
 1618         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "nodedb_mask", "0x%08x", ocs->nodedb_mask);
 1619 }
 1620 
 1621 /**
 1622  * @brief Set requested WWNN value.
 1623  *
 1624  * @param ocs Pointer to the ocs structure.
 1625  * @param name Not used.
 1626  * @param value Value to which the linkcfg is set.
 1627  *
 1628  * @return Returns 0 on success.
 1629  */
 1630 
 1631 int
 1632 set_req_wwnn(ocs_t *ocs, char *name, char *value)
 1633 {
 1634         int rc;
 1635         uint64_t wwnn;
 1636 
 1637         if (ocs_strcasecmp(value, "default") == 0) {
 1638                 wwnn = 0;
 1639         }
 1640         else if (parse_wwn(value, &wwnn) != 0) {
 1641                 ocs_log_test(ocs, "Invalid WWNN: %s\n", value);
 1642                 return 1;
 1643         }
 1644 
 1645         rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWNN_SET, wwnn);
 1646 
 1647         if(rc) {
 1648                 ocs_log_test(ocs, "OCS_XPORT_WWNN_SET failed: %d\n", rc);
 1649                 return rc;
 1650         }
 1651 
 1652         rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
 1653         if (rc) {
 1654                 ocs_log_test(ocs, "port offline failed : %d\n", rc);
 1655         }
 1656 
 1657         rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
 1658         if (rc) {
 1659                 ocs_log_test(ocs, "port online failed : %d\n", rc);
 1660         }
 1661 
 1662         return rc;
 1663 }
 1664 
 1665 /**
 1666  * @brief Set requested WWNP value.
 1667  *
 1668  * @param ocs Pointer to the ocs structure.
 1669  * @param name Not used.
 1670  * @param value Value to which the linkcfg is set.
 1671  *
 1672  * @return Returns 0 on success.
 1673  */
 1674 
 1675 int
 1676 set_req_wwpn(ocs_t *ocs, char *name, char *value)
 1677 {
 1678         int rc;
 1679         uint64_t wwpn;
 1680 
 1681         if (ocs_strcasecmp(value, "default") == 0) {
 1682                 wwpn = 0;
 1683         }
 1684         else if (parse_wwn(value, &wwpn) != 0) {
 1685                 ocs_log_test(ocs, "Invalid WWPN: %s\n", value);
 1686                 return 1;
 1687         }
 1688 
 1689         rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWPN_SET, wwpn);
 1690 
 1691         if(rc) {
 1692                 ocs_log_test(ocs, "OCS_XPORT_WWPN_SET failed: %d\n", rc);
 1693                 return rc;
 1694         }
 1695 
 1696         rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
 1697         if (rc) {
 1698                 ocs_log_test(ocs, "port offline failed : %d\n", rc);
 1699         }
 1700 
 1701         rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
 1702         if (rc) {
 1703                 ocs_log_test(ocs, "port online failed : %d\n", rc);
 1704         }
 1705 
 1706         return rc;
 1707 }
 1708 
 1709 /**
 1710  * @brief Set node debug mask value
 1711  *
 1712  * @param ocs Pointer to the ocs structure.
 1713  * @param name Not used.
 1714  * @param value Value to which the nodedb_mask is set.
 1715  *
 1716  * @return Returns 0 on success.
 1717  */
 1718 static int
 1719 set_nodedb_mask(ocs_t *ocs, char *name, char *value)
 1720 {
 1721         ocs->nodedb_mask = ocs_strtoul(value, 0, 0);
 1722         return 0;
 1723 }
 1724 
 1725 /**
 1726  * @brief Set linkcfg config value.
 1727  *
 1728  * @param ocs Pointer to the ocs structure.
 1729  * @param name Not used.
 1730  * @param value Value to which the linkcfg is set.
 1731  *
 1732  * @return Returns 0 on success.
 1733  */
 1734 static int
 1735 set_linkcfg(ocs_t *ocs, char *name, char *value)
 1736 {
 1737         ocs_hw_linkcfg_e linkcfg;
 1738         ocs_mgmt_linkcfg_arg_t cb_arg;
 1739         ocs_hw_rtn_e status;
 1740 
 1741         ocs_sem_init(&cb_arg.semaphore, 0, "mgmt_linkcfg");
 1742 
 1743         /* translate mgmt linkcfg string to HW linkcfg enum */
 1744         linkcfg = ocs_hw_linkcfg_from_mgmt(value);
 1745 
 1746         /* set HW linkcfg */
 1747         status = ocs_hw_port_control(&ocs->hw, OCS_HW_PORT_SET_LINK_CONFIG,
 1748                                       (uintptr_t)linkcfg, ocs_mgmt_linkcfg_cb, &cb_arg);
 1749         if (status) {
 1750                 ocs_log_test(ocs, "ocs_hw_set_linkcfg failed\n");
 1751                 return -1;
 1752         }
 1753 
 1754         if (ocs_sem_p(&cb_arg.semaphore, OCS_SEM_FOREVER)) {
 1755                 ocs_log_err(ocs, "ocs_sem_p failed\n");
 1756                 return -1;
 1757         }
 1758 
 1759         if (cb_arg.status) {
 1760                 ocs_log_test(ocs, "failed to set linkcfg from HW status=%d\n",
 1761                              cb_arg.status);
 1762                 return -1;
 1763         }
 1764 
 1765         return 0;
 1766 }
 1767 
 1768 /**
 1769  * @brief Linkcfg callback
 1770  *
 1771  * @param status Result of the linkcfg get/set operation.
 1772  * @param value Resulting linkcfg value.
 1773  * @param arg Callback argument.
 1774  *
 1775  * @return None.
 1776  */
 1777 static void
 1778 ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg)
 1779 {
 1780         ocs_mgmt_linkcfg_arg_t *cb_arg = (ocs_mgmt_linkcfg_arg_t *)arg;
 1781         cb_arg->status = status;
 1782         cb_arg->linkcfg = (ocs_hw_linkcfg_e)value;
 1783         ocs_sem_v(&cb_arg->semaphore);
 1784 }
 1785 
 1786 static int
 1787 set_debug_mq_dump(ocs_t *ocs, char *name, char *value)
 1788 {
 1789         int result;
 1790 
 1791         if (ocs_strcasecmp(value, "false") == 0) {
 1792                 ocs_debug_disable(OCS_DEBUG_ENABLE_MQ_DUMP);
 1793                 result = 0;
 1794         } else if (ocs_strcasecmp(value, "true") == 0) {
 1795                 ocs_debug_enable(OCS_DEBUG_ENABLE_MQ_DUMP);
 1796                 result = 0;
 1797         } else {
 1798                 result = -1;
 1799         }
 1800 
 1801         return result;
 1802 }
 1803 
 1804 static int
 1805 set_debug_cq_dump(ocs_t *ocs, char *name, char *value)
 1806 {
 1807         int result;
 1808 
 1809         if (ocs_strcasecmp(value, "false") == 0) {
 1810                 ocs_debug_disable(OCS_DEBUG_ENABLE_CQ_DUMP);
 1811                 result = 0;
 1812         } else if (ocs_strcasecmp(value, "true") == 0) {
 1813                 ocs_debug_enable(OCS_DEBUG_ENABLE_CQ_DUMP);
 1814                 result = 0;
 1815         } else {
 1816                 result = -1;
 1817         }
 1818 
 1819         return result;
 1820 }
 1821 
 1822 static int
 1823 set_debug_wq_dump(ocs_t *ocs, char *name, char *value)
 1824 {
 1825         int result;
 1826 
 1827         if (ocs_strcasecmp(value, "false") == 0) {
 1828                 ocs_debug_disable(OCS_DEBUG_ENABLE_WQ_DUMP);
 1829                 result = 0;
 1830         } else if (ocs_strcasecmp(value, "true") == 0) {
 1831                 ocs_debug_enable(OCS_DEBUG_ENABLE_WQ_DUMP);
 1832                 result = 0;
 1833         } else {
 1834                 result = -1;
 1835         }
 1836 
 1837         return result;
 1838 }
 1839 
 1840 static int
 1841 set_debug_eq_dump(ocs_t *ocs, char *name, char *value)
 1842 {
 1843         int result;
 1844 
 1845         if (ocs_strcasecmp(value, "false") == 0) {
 1846                 ocs_debug_disable(OCS_DEBUG_ENABLE_EQ_DUMP);
 1847                 result = 0;
 1848         } else if (ocs_strcasecmp(value, "true") == 0) {
 1849                 ocs_debug_enable(OCS_DEBUG_ENABLE_EQ_DUMP);
 1850                 result = 0;
 1851         } else {
 1852                 result = -1;
 1853         }
 1854 
 1855         return result;
 1856 }
 1857 
 1858 static int
 1859 set_logmask(ocs_t *ocs, char *name, char *value)
 1860 {
 1861 
 1862         ocs->logmask = ocs_strtoul(value, NULL, 0);
 1863 
 1864         return 0;
 1865 }
 1866 
 1867 static int
 1868 set_loglevel(ocs_t *ocs, char *name, char *value)
 1869 {
 1870 
 1871         loglevel = ocs_strtoul(value, NULL, 0);
 1872 
 1873         return 0;
 1874 }
 1875 
 1876 int
 1877 set_configured_speed(ocs_t *ocs, char *name, char *value)
 1878 {
 1879         int result = 0;
 1880         ocs_hw_rtn_e hw_rc;
 1881         int xport_rc;
 1882         uint32_t spd;
 1883 
 1884         spd = ocs_strtoul(value, NULL, 0);
 1885 
 1886         if ((spd != 0) && (spd != 2000) && (spd != 4000) &&
 1887                 (spd != 8000) && (spd != 16000) && (spd != 32000)) {
 1888                 ocs_log_test(ocs, "unsupported speed %d\n", spd);
 1889                 return 1;
 1890         }
 1891 
 1892         ocs_log_debug(ocs, "Taking port offline\n");
 1893         xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
 1894         if (xport_rc != 0) {
 1895                 ocs_log_test(ocs, "Port offline failed\n");
 1896                 result = 1;
 1897         } else {
 1898                 ocs_log_debug(ocs, "Setting port to speed %d\n", spd);
 1899                 hw_rc = ocs_hw_set(&ocs->hw, OCS_HW_LINK_SPEED, spd);
 1900                 if (hw_rc != OCS_HW_RTN_SUCCESS) {
 1901                         ocs_log_test(ocs, "Speed set failed\n");
 1902                         result = 1;
 1903                 }
 1904 
 1905                 /* If we failed to set the speed we still want to try to bring
 1906                  * the port back online */
 1907 
 1908                 ocs_log_debug(ocs, "Bringing port online\n");
 1909                 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
 1910                 if (xport_rc != 0) {
 1911                         result = 1;
 1912                 }
 1913         }
 1914 
 1915         return result;
 1916 }
 1917 
 1918 int
 1919 set_configured_topology(ocs_t *ocs, char *name, char *value)
 1920 {
 1921         int result = 0;
 1922         ocs_hw_rtn_e hw_rc;
 1923         int xport_rc;
 1924         uint32_t topo;
 1925 
 1926         topo = ocs_strtoul(value, NULL, 0);
 1927         if (topo >= OCS_HW_TOPOLOGY_NONE) {
 1928                 return 1;
 1929         }
 1930 
 1931         ocs_log_debug(ocs, "Taking port offline\n");
 1932         xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
 1933         if (xport_rc != 0) {
 1934                 ocs_log_test(ocs, "Port offline failed\n");
 1935                 result = 1;
 1936         } else {
 1937                 ocs_log_debug(ocs, "Setting port to topology %d\n", topo);
 1938                 hw_rc = ocs_hw_set(&ocs->hw, OCS_HW_TOPOLOGY, topo);
 1939                 if (hw_rc != OCS_HW_RTN_SUCCESS) {
 1940                         ocs_log_test(ocs, "Topology set failed\n");
 1941                         result = 1;
 1942                 }
 1943 
 1944                 /* If we failed to set the topology we still want to try to bring
 1945                  * the port back online */
 1946 
 1947                 ocs_log_debug(ocs, "Bringing port online\n");
 1948                 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
 1949                 if (xport_rc != 0) {
 1950                         result = 1;
 1951                 }
 1952         }
 1953 
 1954         return result;
 1955 }
 1956 
 1957 static int
 1958 set_configured_link_state(ocs_t *ocs, char *name, char *value)
 1959 {
 1960         int result = 0;
 1961         int xport_rc;
 1962 
 1963         if (ocs_strcasecmp(value, "offline") == 0) {
 1964                 ocs_log_debug(ocs, "Setting port to %s\n", value);
 1965                 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
 1966                 if (xport_rc != 0) {
 1967                         ocs_log_test(ocs, "Setting port to offline failed\n");
 1968                         result = -1;
 1969                 }
 1970         } else if (ocs_strcasecmp(value, "online") == 0) {
 1971                 ocs_log_debug(ocs, "Setting port to %s\n", value);
 1972                 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
 1973                 if (xport_rc != 0) {
 1974                         ocs_log_test(ocs, "Setting port to online failed\n");
 1975                         result = -1;
 1976                 }
 1977         } else {
 1978                 ocs_log_test(ocs, "Unsupported link state \"%s\"\n", value);
 1979                 result = -1;
 1980         }
 1981 
 1982         return result;
 1983 }
 1984 
 1985 typedef struct ocs_mgmt_get_port_protocol_result {
 1986         ocs_sem_t semaphore;
 1987         int32_t status;
 1988         ocs_hw_port_protocol_e port_protocol;
 1989 } ocs_mgmt_get_port_protocol_result_t;
 1990 
 1991 static void
 1992 ocs_mgmt_get_port_protocol_cb(int32_t status,
 1993                               ocs_hw_port_protocol_e port_protocol,
 1994                               void    *arg)
 1995 {
 1996         ocs_mgmt_get_port_protocol_result_t *result = arg;
 1997 
 1998         result->status = status;
 1999         result->port_protocol = port_protocol;
 2000 
 2001         ocs_sem_v(&(result->semaphore));
 2002 }
 2003 
 2004 static void
 2005 get_port_protocol(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 2006 {
 2007         ocs_mgmt_get_port_protocol_result_t result;
 2008         uint8_t bus;
 2009         uint8_t dev;
 2010         uint8_t func;
 2011 
 2012         ocs_sem_init(&(result.semaphore), 0, "get_port_protocol");
 2013 
 2014         ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
 2015 
 2016         if(ocs_hw_get_port_protocol(&ocs->hw, func, ocs_mgmt_get_port_protocol_cb, &result) == OCS_HW_RTN_SUCCESS) {
 2017                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2018                         /* Undefined failure */
 2019                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2020                 }
 2021                 if (result.status == 0) {
 2022                         switch (result.port_protocol) {
 2023                         case OCS_HW_PORT_PROTOCOL_ISCSI:
 2024                                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "iSCSI");
 2025                                 break;
 2026                         case OCS_HW_PORT_PROTOCOL_FCOE:
 2027                                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FCoE");
 2028                                 break;
 2029                         case OCS_HW_PORT_PROTOCOL_FC:
 2030                                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FC");
 2031                                 break;
 2032                         case OCS_HW_PORT_PROTOCOL_OTHER:
 2033                                 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Other");
 2034                                 break;
 2035                         }
 2036                 } else {
 2037                         ocs_log_test(ocs, "getting port profile status 0x%x\n", result.status);
 2038                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Unknown");
 2039                 }
 2040         }
 2041 }
 2042 
 2043 typedef struct ocs_mgmt_set_port_protocol_result {
 2044         ocs_sem_t semaphore;
 2045         int32_t status;
 2046 } ocs_mgmt_set_port_protocol_result_t;
 2047 
 2048 static void
 2049 ocs_mgmt_set_port_protocol_cb(int32_t status,
 2050                               void    *arg)
 2051 {
 2052         ocs_mgmt_get_port_protocol_result_t *result = arg;
 2053 
 2054         result->status = status;
 2055 
 2056         ocs_sem_v(&(result->semaphore));
 2057 }
 2058 
 2059 /**
 2060  * @brief  Set port protocol
 2061  * @par Description
 2062  * This is a management action handler to set the current
 2063  * port protocol.  Input value should be one of iSCSI,
 2064  * FC, or FCoE.
 2065  *
 2066  * @param ocs Pointer to the ocs structure.
 2067  * @param name Name of the action being performed.
 2068  * @param value The value to be assigned
 2069  *
 2070  * @return Returns 0 on success, non-zero on failure.
 2071  */
 2072 static int32_t
 2073 set_port_protocol(ocs_t *ocs, char *name, char *value)
 2074 {
 2075         ocs_mgmt_set_port_protocol_result_t result;
 2076         int32_t rc = 0;
 2077         ocs_hw_port_protocol_e new_protocol;
 2078         uint8_t bus;
 2079         uint8_t dev;
 2080         uint8_t func;
 2081 
 2082         ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
 2083 
 2084         ocs_sem_init(&(result.semaphore), 0, "set_port_protocol");
 2085 
 2086         if (ocs_strcasecmp(value, "iscsi") == 0) {
 2087                 new_protocol = OCS_HW_PORT_PROTOCOL_ISCSI;
 2088         } else if (ocs_strcasecmp(value, "fc") == 0) {
 2089                 new_protocol = OCS_HW_PORT_PROTOCOL_FC;
 2090         } else if (ocs_strcasecmp(value, "fcoe") == 0) {
 2091                 new_protocol = OCS_HW_PORT_PROTOCOL_FCOE;
 2092         } else {
 2093                 return -1;
 2094         }
 2095 
 2096         rc = ocs_hw_set_port_protocol(&ocs->hw, new_protocol, func,
 2097                                        ocs_mgmt_set_port_protocol_cb, &result);
 2098         if (rc == OCS_HW_RTN_SUCCESS) {
 2099                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2100                         /* Undefined failure */
 2101                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2102                         return -ENXIO;
 2103                 }
 2104                 if (result.status == 0) {
 2105                         /* Success. */
 2106                         rc = 0;
 2107                 } else {
 2108                         rc = -1;
 2109                         ocs_log_test(ocs, "setting active profile status 0x%x\n",
 2110                                      result.status);
 2111                 }
 2112         }
 2113 
 2114         return rc;
 2115 }
 2116 
 2117 typedef struct ocs_mgmt_get_profile_list_result_s {
 2118         ocs_sem_t semaphore;
 2119         int32_t status;
 2120         ocs_hw_profile_list_t *list;
 2121 } ocs_mgmt_get_profile_list_result_t;
 2122 
 2123 static void
 2124 ocs_mgmt_get_profile_list_cb(int32_t status, ocs_hw_profile_list_t *list, void *ul_arg)
 2125 {
 2126         ocs_mgmt_get_profile_list_result_t *result = ul_arg;
 2127 
 2128         result->status = status;
 2129         result->list = list;
 2130 
 2131         ocs_sem_v(&(result->semaphore));
 2132 }
 2133 
 2134 /**
 2135  * @brief  Get list of profiles
 2136  * @par Description
 2137  * This is a management action handler to get the list of
 2138  * profiles supported by the SLI port.  Although the spec says
 2139  * that all SLI platforms support this, only Skyhawk actually
 2140  * has a useful implementation.
 2141  *
 2142  * @param ocs Pointer to the ocs structure.
 2143  * @param name Name of the action being performed.
 2144  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
 2145  *
 2146  * @return none
 2147  */
 2148 static void
 2149 get_profile_list(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 2150 {
 2151         ocs_mgmt_get_profile_list_result_t result;
 2152 
 2153         ocs_sem_init(&(result.semaphore), 0, "get_profile_list");
 2154 
 2155         if(ocs_hw_get_profile_list(&ocs->hw, ocs_mgmt_get_profile_list_cb, &result) == OCS_HW_RTN_SUCCESS) {
 2156                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2157                         /* Undefined failure */
 2158                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2159                 }
 2160                 if (result.status == 0) {
 2161                         /* Success. */
 2162 #define MAX_LINE_SIZE 520
 2163 #define BUFFER_SIZE MAX_LINE_SIZE*40
 2164                         char *result_buf;
 2165                         char result_line[MAX_LINE_SIZE];
 2166                         uint32_t bytes_left;
 2167                         uint32_t i;
 2168 
 2169                         result_buf = ocs_malloc(ocs, BUFFER_SIZE, OCS_M_ZERO);
 2170                         bytes_left = BUFFER_SIZE;
 2171 
 2172                         for (i=0; i<result.list->num_descriptors; i++) {
 2173                                 sprintf(result_line, "0x%02x:%s\n", result.list->descriptors[i].profile_id,
 2174                                         result.list->descriptors[i].profile_description);
 2175                                 if (strlen(result_line) < bytes_left) {
 2176                                         strcat(result_buf, result_line);
 2177                                         bytes_left -= strlen(result_line);
 2178                                 }
 2179                         }
 2180 
 2181                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "profile_list", result_buf);
 2182 
 2183                         ocs_free(ocs, result_buf, BUFFER_SIZE);
 2184                         ocs_free(ocs, result.list, sizeof(ocs_hw_profile_list_t));
 2185                 } else {
 2186                         ocs_log_test(ocs, "getting profile list status 0x%x\n", result.status);
 2187                 }
 2188         }
 2189 }
 2190 
 2191 typedef struct ocs_mgmt_get_active_profile_result {
 2192         ocs_sem_t semaphore;
 2193         int32_t status;
 2194         uint32_t active_profile_id;
 2195 } ocs_mgmt_get_active_profile_result_t;
 2196 
 2197 static void
 2198 ocs_mgmt_get_active_profile_cb(int32_t status, uint32_t active_profile, void *ul_arg)
 2199 {
 2200         ocs_mgmt_get_active_profile_result_t *result = ul_arg;
 2201 
 2202         result->status = status;
 2203         result->active_profile_id = active_profile;
 2204 
 2205         ocs_sem_v(&(result->semaphore));
 2206 }
 2207 
 2208 #define MAX_PROFILE_LENGTH 5
 2209 
 2210 /**
 2211  * @brief  Get active profile
 2212  * @par Description
 2213  * This is a management action handler to get the currently
 2214  * active profile for an SLI port.  Although the spec says that
 2215  * all SLI platforms support this, only Skyhawk actually has a
 2216  * useful implementation.
 2217  *
 2218  * @param ocs Pointer to the ocs structure.
 2219  * @param name Name of the action being performed.
 2220  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
 2221  *
 2222  * @return none
 2223  */
 2224 static void
 2225 get_active_profile(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 2226 {
 2227         char result_string[MAX_PROFILE_LENGTH];
 2228         ocs_mgmt_get_active_profile_result_t result;
 2229 
 2230         ocs_sem_init(&(result.semaphore), 0, "get_active_profile");
 2231 
 2232         if(ocs_hw_get_active_profile(&ocs->hw, ocs_mgmt_get_active_profile_cb, &result) == OCS_HW_RTN_SUCCESS) {
 2233                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2234                         /* Undefined failure */
 2235                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2236                 }
 2237                 if (result.status == 0) {
 2238                         /* Success. */
 2239                         sprintf(result_string, "0x%02x", result.active_profile_id);
 2240                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "active_profile", result_string);
 2241                 } else {
 2242                         ocs_log_test(ocs, "getting active profile status 0x%x\n", result.status);
 2243                 }
 2244         }
 2245 }
 2246 
 2247 typedef struct ocs_mgmt_set_active_profile_result {
 2248         ocs_sem_t semaphore;
 2249         int32_t status;
 2250 } ocs_mgmt_set_active_profile_result_t;
 2251 
 2252 static void
 2253 ocs_mgmt_set_active_profile_cb(int32_t status, void *ul_arg)
 2254 {
 2255         ocs_mgmt_get_profile_list_result_t *result = ul_arg;
 2256 
 2257         result->status = status;
 2258 
 2259         ocs_sem_v(&(result->semaphore));
 2260 }
 2261 
 2262 /**
 2263  * @brief  Set active profile
 2264  * @par Description
 2265  * This is a management action handler to set the currently
 2266  * active profile for an SLI port.  Although the spec says that
 2267  * all SLI platforms support this, only Skyhawk actually has a
 2268  * useful implementation.
 2269  *
 2270  * @param ocs Pointer to the ocs structure.
 2271  * @param name Name of the action being performed.
 2272  * @param value Requested new value of the property.
 2273  *
 2274  * @return Returns 0 on success, non-zero on failure.
 2275  */
 2276 static int32_t
 2277 set_active_profile(ocs_t *ocs, char *name, char *value)
 2278 {
 2279         ocs_mgmt_set_active_profile_result_t result;
 2280         int32_t rc = 0;
 2281         int32_t new_profile;
 2282 
 2283         new_profile = ocs_strtoul(value, NULL, 0);
 2284 
 2285         ocs_sem_init(&(result.semaphore), 0, "set_active_profile");
 2286 
 2287         rc = ocs_hw_set_active_profile(&ocs->hw, ocs_mgmt_set_active_profile_cb, new_profile, &result);
 2288         if (rc == OCS_HW_RTN_SUCCESS) {
 2289                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2290                         /* Undefined failure */
 2291                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2292                         return -ENXIO;
 2293                 }
 2294                 if (result.status == 0) {
 2295                         /* Success. */
 2296                         rc = 0;
 2297                 } else {
 2298                         rc = -1;
 2299                         ocs_log_test(ocs, "setting active profile status 0x%x\n", result.status);
 2300                 }
 2301         }
 2302 
 2303         return rc;
 2304 }
 2305 
 2306 typedef struct ocs_mgmt_get_nvparms_result {
 2307         ocs_sem_t semaphore;
 2308         int32_t status;
 2309         uint8_t wwpn[8];
 2310         uint8_t wwnn[8];
 2311         uint8_t hard_alpa;
 2312         uint32_t preferred_d_id;
 2313 } ocs_mgmt_get_nvparms_result_t;
 2314 
 2315 static void
 2316 ocs_mgmt_get_nvparms_cb(int32_t status, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
 2317                 uint32_t preferred_d_id, void *ul_arg)
 2318 {
 2319         ocs_mgmt_get_nvparms_result_t *result = ul_arg;
 2320 
 2321         result->status = status;
 2322         ocs_memcpy(result->wwpn, wwpn, sizeof(result->wwpn));
 2323         ocs_memcpy(result->wwnn, wwnn, sizeof(result->wwnn));
 2324         result->hard_alpa = hard_alpa;
 2325         result->preferred_d_id = preferred_d_id;
 2326 
 2327         ocs_sem_v(&(result->semaphore));
 2328 }
 2329 
 2330 /**
 2331  * @brief  Get wwpn
 2332  * @par Description
 2333  *
 2334  *
 2335  * @param ocs Pointer to the ocs structure.
 2336  * @param name Name of the action being performed.
 2337  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
 2338  *
 2339  * @return none
 2340  */
 2341 static void
 2342 get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 2343 {
 2344         char result_string[24];
 2345         ocs_mgmt_get_nvparms_result_t result;
 2346 
 2347         ocs_sem_init(&(result.semaphore), 0, "get_nv_wwpn");
 2348 
 2349         if(ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result) == OCS_HW_RTN_SUCCESS) {
 2350                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2351                         /* Undefined failure */
 2352                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2353                         return;
 2354                 }
 2355                 if (result.status == 0) {
 2356                         /* Success.  Copy wwpn from result struct to result string */
 2357                         sprintf(result_string, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
 2358                                         result.wwpn[0], result.wwpn[1], result.wwpn[2],
 2359                                         result.wwpn[3], result.wwpn[4], result.wwpn[5],
 2360                                         result.wwpn[6], result.wwpn[7]);
 2361                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "nv_wwpn", result_string);
 2362                 } else {
 2363                         ocs_log_test(ocs, "getting wwpn status 0x%x\n", result.status);
 2364                 }
 2365         }
 2366 }
 2367 
 2368 /**
 2369  * @brief  Get wwnn
 2370  * @par Description
 2371  *
 2372  *
 2373  * @param ocs Pointer to the ocs structure.
 2374  * @param name Name of the action being performed.
 2375  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
 2376  *
 2377  * @return none
 2378  */
 2379 static void
 2380 get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 2381 {
 2382         char result_string[24];
 2383         ocs_mgmt_get_nvparms_result_t result;
 2384 
 2385         ocs_sem_init(&(result.semaphore), 0, "get_nv_wwnn");
 2386 
 2387         if(ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result) == OCS_HW_RTN_SUCCESS) {
 2388                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2389                         /* Undefined failure */
 2390                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2391                         return;
 2392                 }
 2393                 if (result.status == 0) {
 2394                         /* Success. Copy wwnn from result struct to result string */
 2395                         ocs_snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
 2396                                         result.wwnn[0], result.wwnn[1], result.wwnn[2],
 2397                                         result.wwnn[3], result.wwnn[4], result.wwnn[5],
 2398                                         result.wwnn[6], result.wwnn[7]);
 2399                         ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "nv_wwnn", result_string);
 2400                 } else {
 2401                         ocs_log_test(ocs, "getting wwnn status 0x%x\n", result.status);
 2402                 }
 2403         }
 2404 }
 2405 
 2406 /**
 2407  * @brief Get accumulated node abort counts
 2408  * @par Description Get the sum of all nodes abort count.
 2409  *
 2410  * @param ocs Pointer to the ocs structure.
 2411  * @param name Name of the action being performed.
 2412  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
 2413  *
 2414  * @return None.
 2415  */
 2416 static void
 2417 get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
 2418 {
 2419         uint32_t abort_counts = 0;
 2420         ocs_domain_t *domain;
 2421         ocs_sport_t *sport;
 2422         ocs_node_t *node;
 2423 
 2424         if (ocs_device_lock_try(ocs) != TRUE) {
 2425                 /* Didn't get the lock */
 2426                 return;
 2427         }
 2428 
 2429                 /* Here the Device lock is held */
 2430                 ocs_list_foreach(&ocs->domain_list, domain) {
 2431                         if (ocs_domain_lock_try(domain) != TRUE) {
 2432                                 /* Didn't get the lock */
 2433                                 ocs_device_unlock(ocs);
 2434                                 return;
 2435                         }
 2436 
 2437                                 /* Here the Domain lock is held */
 2438                                 ocs_list_foreach(&domain->sport_list, sport) {
 2439                                         if (ocs_sport_lock_try(sport) != TRUE) {
 2440                                                 /* Didn't get the lock */
 2441                                                 ocs_domain_unlock(domain);
 2442                                                 ocs_device_unlock(ocs);
 2443                                                 return;
 2444                                         }
 2445 
 2446                                                 /* Here the sport lock is held */
 2447                                                 ocs_list_foreach(&sport->node_list, node) {
 2448                                                         abort_counts += node->abort_cnt;
 2449                                                 }
 2450 
 2451                                         ocs_sport_unlock(sport);
 2452                                 }
 2453 
 2454                         ocs_domain_unlock(domain);
 2455                 }
 2456 
 2457         ocs_device_unlock(ocs);
 2458 
 2459         ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "node_abort_cnt", "%d" , abort_counts);
 2460 }
 2461 
 2462 typedef struct ocs_mgmt_set_nvparms_result {
 2463         ocs_sem_t semaphore;
 2464         int32_t status;
 2465 } ocs_mgmt_set_nvparms_result_t;
 2466 
 2467 static void
 2468 ocs_mgmt_set_nvparms_cb(int32_t status, void *ul_arg)
 2469 {
 2470         ocs_mgmt_get_profile_list_result_t *result = ul_arg;
 2471 
 2472         result->status = status;
 2473 
 2474         ocs_sem_v(&(result->semaphore));
 2475 }
 2476 
 2477 /**
 2478  * @brief  Set wwn
 2479  * @par Description Sets the Non-volatile worldwide names,
 2480  * if provided.
 2481  *
 2482  * @param ocs Pointer to the ocs structure.
 2483  * @param name Name of the action being performed.
 2484  * @param wwn_p Requested new WWN values.
 2485  *
 2486  * @return Returns 0 on success, non-zero on failure.
 2487  */
 2488 static int32_t
 2489 set_nv_wwn(ocs_t *ocs, char *name, char *wwn_p)
 2490 {
 2491         ocs_mgmt_get_nvparms_result_t result;
 2492         uint8_t new_wwpn[8];
 2493         uint8_t new_wwnn[8];
 2494         char *wwpn_p = NULL;
 2495         char *wwnn_p = NULL;
 2496         int32_t rc = -1;
 2497         int wwpn = 0;
 2498         int wwnn = 0;
 2499         int i;
 2500 
 2501         /* This is a read-modify-write operation, so first we have to read
 2502          * the current values
 2503          */
 2504         ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn1");
 2505 
 2506         rc = ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result);
 2507 
 2508         if (rc == OCS_HW_RTN_SUCCESS) {
 2509                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2510                         /* Undefined failure */
 2511                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2512                         return -ENXIO;
 2513                 }
 2514                 if (result.status != 0) {
 2515                         ocs_log_test(ocs, "getting nvparms status 0x%x\n", result.status);
 2516                         return -1;
 2517                 }
 2518         }
 2519 
 2520         /* wwn_p contains wwpn_p@wwnn_p values */
 2521         if (wwn_p != NULL) {
 2522                 wwpn_p = ocs_strsep(&wwn_p, "@");
 2523                 wwnn_p = wwn_p;
 2524         }
 2525 
 2526         if (wwpn_p != NULL) {
 2527                 wwpn = ocs_strcmp(wwpn_p, "NA");
 2528         }
 2529 
 2530         if (wwnn_p != NULL) {
 2531                 wwnn = ocs_strcmp(wwnn_p, "NA");
 2532         }
 2533 
 2534         /* Parse the new WWPN */
 2535         if ((wwpn_p != NULL) && (wwpn != 0)) {
 2536                 if (ocs_sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
 2537                                 &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]),
 2538                                 &(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]),
 2539                                 &(new_wwpn[6]), &(new_wwpn[7])) != 8) {
 2540                         ocs_log_test(ocs, "can't parse WWPN %s\n", wwpn_p);
 2541                         return -1;
 2542                 }
 2543         }
 2544 
 2545         /* Parse the new WWNN */
 2546         if ((wwnn_p != NULL) && (wwnn != 0 )) {
 2547                 if (ocs_sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
 2548                                 &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]),
 2549                                 &(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]),
 2550                                 &(new_wwnn[6]), &(new_wwnn[7])) != 8) {
 2551                         ocs_log_test(ocs, "can't parse WWNN %s\n", wwnn_p);
 2552                         return -1;
 2553                 }
 2554         }
 2555 
 2556         for (i = 0; i < 8; i++) {
 2557                 /* Use active wwpn, if new one is not provided */
 2558                 if (wwpn == 0) {
 2559                         new_wwpn[i] = result.wwpn[i];
 2560                 }
 2561 
 2562                 /* Use active wwnn, if new one is not provided */
 2563                 if (wwnn == 0) {
 2564                         new_wwnn[i] = result.wwnn[i];
 2565                 }
 2566         }
 2567 
 2568         /* Modify the nv_wwnn and nv_wwpn, then write it back */
 2569         ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn2");
 2570 
 2571         rc = ocs_hw_set_nvparms(&ocs->hw, ocs_mgmt_set_nvparms_cb, new_wwpn,
 2572                                  new_wwnn, result.hard_alpa, result.preferred_d_id,
 2573                                  &result);
 2574         if (rc == OCS_HW_RTN_SUCCESS) {
 2575                 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
 2576                         /* Undefined failure */
 2577                         ocs_log_err(ocs, "ocs_sem_p failed\n");
 2578                         return -ENXIO;
 2579                 }
 2580                 if (result.status != 0) {
 2581                         ocs_log_test(ocs, "setting wwn status 0x%x\n", result.status);
 2582                         return -1;
 2583                 }
 2584         }
 2585 
 2586         return rc;
 2587 }
 2588 
 2589 static int
 2590 set_tgt_rscn_delay(ocs_t *ocs, char *name, char *value)
 2591 {
 2592         ocs->tgt_rscn_delay_msec = ocs_strtoul(value, NULL, 0) * 1000;
 2593         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2594         return 0;
 2595 }
 2596 
 2597 static int
 2598 set_tgt_rscn_period(ocs_t *ocs, char *name, char *value)
 2599 {
 2600         ocs->tgt_rscn_period_msec = ocs_strtoul(value, NULL, 0) * 1000;
 2601         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2602         return 0;
 2603 }
 2604 
 2605 static int
 2606 set_inject_drop_cmd(ocs_t *ocs, char *name, char *value)
 2607 {
 2608         ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_CMD);
 2609         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2610         return 0;
 2611 }
 2612 
 2613 static int
 2614 set_inject_free_drop_cmd(ocs_t *ocs, char *name, char *value)
 2615 {
 2616         ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_FREE_DROPPED);
 2617         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2618         return 0;
 2619 }
 2620 
 2621 static int
 2622 set_inject_drop_data(ocs_t *ocs, char *name, char *value)
 2623 {
 2624         ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_DATA);
 2625         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2626         return 0;
 2627 }
 2628 
 2629 static int
 2630 set_inject_drop_resp(ocs_t *ocs, char *name, char *value)
 2631 {
 2632         ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_RESP);
 2633         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2634         return 0;
 2635 }
 2636 
 2637 static int
 2638 set_cmd_err_inject(ocs_t *ocs, char *name, char *value)
 2639 {
 2640         ocs->cmd_err_inject = ocs_strtoul(value, NULL, 0);
 2641         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2642         return 0;
 2643 }
 2644 
 2645 static int
 2646 set_cmd_delay_value(ocs_t *ocs, char *name, char *value)
 2647 {
 2648         ocs->delay_value_msec = ocs_strtoul(value, NULL, 0);
 2649         ocs->err_injection = (ocs->delay_value_msec == 0 ? NO_ERR_INJECT : INJECT_DELAY_CMD);
 2650         ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
 2651         return 0;
 2652 }
 2653 
 2654 /**
 2655  * @brief parse a WWN from a string into a 64-bit value
 2656  *
 2657  * Given a pointer to a string, parse the string into a 64-bit
 2658  * WWN value.  The format of the string must be xx:xx:xx:xx:xx:xx:xx:xx
 2659  *
 2660  * @param wwn_in pointer to the string to be parsed
 2661  * @param wwn_out pointer to uint64_t in which to put the parsed result
 2662  *
 2663  * @return 0 if successful, non-zero if the WWN is malformed and couldn't be parsed
 2664  */
 2665 int
 2666 parse_wwn(char *wwn_in, uint64_t *wwn_out)
 2667 {
 2668         uint8_t byte0;
 2669         uint8_t byte1;
 2670         uint8_t byte2;
 2671         uint8_t byte3;
 2672         uint8_t byte4;
 2673         uint8_t byte5;
 2674         uint8_t byte6;
 2675         uint8_t byte7;
 2676         int rc;
 2677 
 2678         rc = ocs_sscanf(wwn_in, "0x%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
 2679                                 &byte0, &byte1, &byte2, &byte3,
 2680                                 &byte4, &byte5, &byte6, &byte7);
 2681 
 2682         if (rc == 8) {
 2683                 *wwn_out = ((uint64_t)byte0 << 56) |
 2684                                 ((uint64_t)byte1 << 48) |
 2685                                 ((uint64_t)byte2 << 40) |
 2686                                 ((uint64_t)byte3 << 32) |
 2687                                 ((uint64_t)byte4 << 24) |
 2688                                 ((uint64_t)byte5 << 16) |
 2689                                 ((uint64_t)byte6 <<  8) |
 2690                                 ((uint64_t)byte7);
 2691                 return 0;
 2692 
 2693         } else {
 2694                 return 1;
 2695         }
 2696 }
 2697 
 2698 static char *mode_string(int mode);
 2699 
 2700 /**
 2701  * @ingroup mgmt
 2702  * @brief Generate the beginning of a numbered section in a management XML document.
 2703  *
 2704  * @par Description
 2705  * This function begins a section. The XML information is appended to
 2706  * the textbuf. This form of the function is used for sections that might have
 2707  * multiple instances, such as a node or a SLI Port (sport). The index number
 2708  * is appended to the name.
 2709  *
 2710  * @param textbuf Pointer to the driver dump text buffer.
 2711  * @param name Name of the section.
 2712  * @param index Index number of this instance of the section.
 2713  *
 2714  * @return None.
 2715  */
 2716 
 2717 extern void ocs_mgmt_start_section(ocs_textbuf_t *textbuf, const char *name, int index)
 2718 {
 2719         ocs_textbuf_printf(textbuf, "<%s instance=\"%d\">\n", name, index);
 2720 }
 2721 
 2722 /**
 2723  * @ingroup mgmt
 2724  * @brief Generate the beginning of an unnumbered section in a management XML document.
 2725  *
 2726  * @par Description
 2727  * This function begins a section. The XML information is appended to
 2728  * the textbuf. This form of the function is used for sections that have
 2729  * a single instance only. Therefore, no index number is needed.
 2730  *
 2731  * @param textbuf Pointer to the driver dump text buffer.
 2732  * @param name Name of the section.
 2733  *
 2734  * @return None.
 2735  */
 2736 
 2737 extern void ocs_mgmt_start_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
 2738 {
 2739         ocs_textbuf_printf(textbuf, "<%s>\n", name);
 2740 }
 2741 
 2742 /**
 2743  * @ingroup mgmt
 2744  * @brief Generate the end of a section in a management XML document.
 2745  *
 2746  * @par Description
 2747  * This function ends a section. The XML information is appended to
 2748  * the textbuf.
 2749  *
 2750  * @param textbuf Pointer to the driver dump text buffer.
 2751  * @param name Name of the section.
 2752  *
 2753  * @return None.
 2754  */
 2755 
 2756 void ocs_mgmt_end_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
 2757 {
 2758         ocs_textbuf_printf(textbuf, "</%s>\n", name);
 2759 }
 2760 
 2761 /**
 2762  * @ingroup mgmt
 2763  * @brief Generate the indexed end of a section in a management XML document.
 2764  *
 2765  * @par Description
 2766  * This function ends a section. The XML information is appended to
 2767  * the textbuf.
 2768  *
 2769  * @param textbuf Pointer to the driver dump text buffer.
 2770  * @param name Name of the section.
 2771  * @param index Index number of this instance of the section.
 2772  *
 2773  * @return None.
 2774  */
 2775 
 2776 void ocs_mgmt_end_section(ocs_textbuf_t *textbuf, const char *name, int index)
 2777 {
 2778 
 2779         ocs_textbuf_printf(textbuf, "</%s>\n", name);
 2780 
 2781 }
 2782 
 2783 /**
 2784  * @ingroup mgmt
 2785  * @brief Generate a property, with no value, in a management XML document.
 2786  *
 2787  * @par Description
 2788  * This function generates a property name. The XML information is appended to
 2789  * the textbuf. This form of the function is used by the list functions
 2790  * when the property name only (and not the current value) is given.
 2791  *
 2792  * @param textbuf Pointer to the driver dump text buffer.
 2793  * @param mode Defines whether the property is read(r)/write(w)/executable(x).
 2794  * @param name Name of the property.
 2795  *
 2796  * @return None.
 2797  */
 2798 
 2799 void ocs_mgmt_emit_property_name(ocs_textbuf_t *textbuf, int mode, const char *name)
 2800 {
 2801         ocs_textbuf_printf(textbuf, "<%s mode=\"%s\"/>\n", name, mode_string(mode));
 2802 }
 2803 
 2804 /**
 2805  * @ingroup mgmt
 2806  * @brief Generate a property with a string value in a management XML document.
 2807  *
 2808  * @par Description
 2809  * This function generates a property name and a string value.
 2810  * The XML information is appended to the textbuf.
 2811  *
 2812  * @param textbuf Pointer to the driver dump text buffer.
 2813  * @param mode Defines whether the property is read(r)/write(w)/executable(x).
 2814  * @param name Name of the property.
 2815  * @param value Value of the property.
 2816  *
 2817  * @return None.
 2818  */
 2819 
 2820 void ocs_mgmt_emit_string(ocs_textbuf_t *textbuf, int mode, const char *name, const char *value)
 2821 {
 2822         ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), value, name);
 2823 }
 2824 
 2825 /**
 2826  * @ingroup mgmt
 2827  * @brief Generate a property with an integer value in a management XML document.
 2828  *
 2829  * @par Description
 2830  * This function generates a property name and an integer value.
 2831  * The XML information is appended to the textbuf.
 2832  *
 2833  * @param textbuf Pointer to driver dump text buffer.
 2834  * @param mode Defines whether the property is read(r)/write(w)/executable(x).
 2835  * @param name Name of the property.
 2836  * @param fmt A printf format for formatting the integer value.
 2837  *
 2838  * @return none
 2839  */
 2840 
 2841 void ocs_mgmt_emit_int(ocs_textbuf_t *textbuf, int mode, const char *name, const char *fmt, ...)
 2842 {
 2843         va_list ap;
 2844         char valuebuf[64];
 2845 
 2846         va_start(ap, fmt);
 2847         ocs_vsnprintf(valuebuf, sizeof(valuebuf), fmt, ap);
 2848         va_end(ap);
 2849 
 2850         ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), valuebuf, name);
 2851 }
 2852 
 2853 /**
 2854  * @ingroup mgmt
 2855  * @brief Generate a property with a boolean value in a management XML document.
 2856  *
 2857  * @par Description
 2858  * This function generates a property name and a boolean value.
 2859  * The XML information is appended to the textbuf.
 2860  *
 2861  * @param textbuf Pointer to the driver dump text buffer.
 2862  * @param mode Defines whether the property is read(r)/write(w)/executable(x).
 2863  * @param name Name of the property.
 2864  * @param value Boolean value to be added to the textbuf.
 2865  *
 2866  * @return None.
 2867  */
 2868 
 2869 void ocs_mgmt_emit_boolean(ocs_textbuf_t *textbuf, int mode, const char *name, int value)
 2870 {
 2871         char *valuebuf = value ? "true" : "false";
 2872 
 2873         ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), valuebuf, name);
 2874 }
 2875 
 2876 static char *mode_string(int mode)
 2877 {
 2878         static char mode_str[4];
 2879 
 2880         mode_str[0] = '\0';
 2881         if (mode & MGMT_MODE_RD) {
 2882                 strcat(mode_str, "r");
 2883         }
 2884         if (mode & MGMT_MODE_WR) {
 2885                 strcat(mode_str, "w");
 2886         }
 2887         if (mode & MGMT_MODE_EX) {
 2888                 strcat(mode_str, "x");
 2889         }
 2890 
 2891         return mode_str;
 2892 
 2893 }

Cache object: 3a3ca519af76cd9709aabe36329cd93a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.