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

Cache object: 3a8d57688a44dd63dbea68feb57b5e05


[ 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.