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/cam/scsi/smp_all.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) 2010 Spectra Logic Corporation
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions, and the following disclaimer,
   10  *    without modification.
   11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   12  *    substantially similar to the "NO WARRANTY" disclaimer below
   13  *    ("Disclaimer") and any redistribution must be conditioned upon
   14  *    including a substantially similar Disclaimer requirement for further
   15  *    binary redistribution.
   16  *
   17  * NO WARRANTY
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   22  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28  * POSSIBILITY OF SUCH DAMAGES.
   29  *
   30  * $Id: //depot/users/kenm/FreeBSD-test/sys/cam/scsi/smp_all.c#4 $
   31  */
   32 
   33 /*
   34  * Serial Management Protocol helper functions.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/10.0/sys/cam/scsi/smp_all.c 216088 2010-11-30 22:39:46Z ken $");
   39 
   40 #include <sys/param.h>
   41 #include <sys/types.h>
   42 #ifdef _KERNEL
   43 #include <sys/systm.h>
   44 #include <sys/libkern.h>
   45 #include <sys/kernel.h>
   46 #else /* _KERNEL */
   47 #include <errno.h>
   48 #include <stdio.h>
   49 #include <stdlib.h>
   50 #include <string.h>
   51 #include <inttypes.h>
   52 #endif /* _KERNEL */
   53 
   54 #include <cam/cam.h>
   55 #include <cam/cam_ccb.h>
   56 #include <cam/cam_xpt.h>
   57 #include <cam/scsi/smp_all.h>
   58 #include <sys/sbuf.h>
   59 
   60 #ifndef _KERNEL
   61 #include <camlib.h>
   62 #endif
   63 
   64 static char *smp_yesno(int val);
   65 
   66 static char *
   67 smp_yesno(int val)
   68 {
   69         char *str;
   70 
   71         if (val)
   72                 str = "Yes";
   73         else
   74                 str = "No";
   75 
   76         return (str);
   77 }
   78 
   79 struct smp_error_table_entry {
   80         uint8_t function_result;
   81         const char *desc;
   82 };
   83 
   84 /* List current as of SPL Revision 7 */
   85 static struct smp_error_table_entry smp_error_table[] = {
   86         {SMP_FR_ACCEPTED, "SMP Function Accepted"},
   87         {SMP_FR_UNKNOWN_FUNC, "Unknown SMP Function"},
   88         {SMP_FR_FUNCTION_FAILED, "SMP Function Failed"},
   89         {SMP_FR_INVALID_REQ_FRAME_LEN, "Invalid Request Frame Length"},
   90         {SMP_FR_INVALID_EXP_CHG_CNT, "Invalid Expander Change Count"},
   91         {SMP_FR_BUSY, "Busy"},
   92         {SMP_FR_INCOMPLETE_DESC_LIST, "Incomplete Descriptor List"},
   93         {SMP_FR_PHY_DOES_NOT_EXIST, "Phy Does Not Exist"},
   94         {SMP_FR_INDEX_DOES_NOT_EXIST, "Index Does Not Exist"},
   95         {SMP_FR_PHY_DOES_NOT_SUP_SATA, "Phy Does Not Support SATA"},
   96         {SMP_FR_UNKNOWN_PHY_OP, "Unknown Phy Operation"},
   97         {SMP_FR_UNKNOWN_PHY_TEST_FUNC, "Unknown Phy Test Function"},
   98         {SMP_FR_PHY_TEST_FUNC_INPROG, "Phy Test Function In Progress"},
   99         {SMP_FR_PHY_VACANT, "Phy Vacant"},
  100         {SMP_FR_UNKNOWN_PHY_EVENT_SRC, "Unknown Phy Event Source"},
  101         {SMP_FR_UNKNOWN_DESC_TYPE, "Unknown Descriptor Type"},
  102         {SMP_FR_UNKNOWN_PHY_FILTER, "Unknown Phy Filter"},
  103         {SMP_FR_AFFILIATION_VIOLATION, "Affiliation Violation"},
  104         {SMP_FR_SMP_ZONE_VIOLATION, "SMP Zone Violation"},
  105         {SMP_FR_NO_MGMT_ACCESS_RIGHTS, "No Management Access Rights"},
  106         {SMP_FR_UNKNOWN_ED_ZONING_VAL, "Unknown Enable Disable Zoning Value"},
  107         {SMP_FR_ZONE_LOCK_VIOLATION, "Zone Lock Violation"},
  108         {SMP_FR_NOT_ACTIVATED, "Not Activated"},
  109         {SMP_FR_ZG_OUT_OF_RANGE, "Zone Group Out of Range"},
  110         {SMP_FR_NO_PHYS_PRESENCE, "No Physical Presence"},
  111         {SMP_FR_SAVING_NOT_SUP, "Saving Not Supported"},
  112         {SMP_FR_SRC_ZONE_DNE, "Source Zone Group Does Not Exist"},
  113         {SMP_FR_DISABLED_PWD_NOT_SUP, "Disabled Password Not Supported"}
  114 };
  115 
  116 const char *
  117 smp_error_desc(int function_result)
  118 {
  119         int i;
  120 
  121         for (i = 0; i < (sizeof(smp_error_table)/sizeof(smp_error_table[0]));
  122              i++){
  123                 if (function_result == smp_error_table[i].function_result)
  124                         return (smp_error_table[i].desc);
  125         }
  126         return ("Reserved Function Result");
  127 }
  128 
  129 /* List current as of SPL Revision 7 */
  130 struct smp_cmd_table_entry {
  131         uint8_t cmd_num;
  132         const char *desc;
  133 } smp_cmd_table[] = {
  134         {SMP_FUNC_REPORT_GENERAL, "REPORT GENERAL"},
  135         {SMP_FUNC_REPORT_MANUF_INFO, "REPORT MANUFACTURER INFORMATION"},
  136         {SMP_FUNC_REPORT_SC_STATUS, "REPORT SELF-CONFIGURATION STATUS"},
  137         {SMP_FUNC_REPORT_ZONE_PERM_TBL, "REPORT ZONE PERMISSION TABLE"},
  138         {SMP_FUNC_REPORT_BROADCAST, "REPORT BROADCAST"},
  139         {SMP_FUNC_DISCOVER, "DISCOVER"},
  140         {SMP_FUNC_REPORT_PHY_ERR_LOG, "REPORT PHY ERROR LOG"},
  141         {SMP_FUNC_REPORT_PHY_SATA, "REPORT PHY SATA"},
  142         {SMP_FUNC_REPORT_ROUTE_INFO, "REPORT ROUTE INFORMATION"},
  143         {SMP_FUNC_REPORT_PHY_EVENT, "REPORT PHY EVENT"},
  144         {SMP_FUNC_DISCOVER_LIST, "DISCOVER LIST"},
  145         {SMP_FUNC_REPORT_PHY_EVENT_LIST, "REPORT PHY EVENT LIST"},
  146         {SMP_FUNC_REPORT_EXP_RTL, "REPORT EXPANDER ROUTE TABLE LIST"},
  147         {SMP_FUNC_CONFIG_GENERAL, "CONFIGURE GENERAL"},
  148         {SMP_FUNC_ENABLE_DISABLE_ZONING, "ENABLE DISABLE ZONING"},
  149         {SMP_FUNC_ZONED_BROADCAST, "ZONED BROADCAST"},
  150         {SMP_FUNC_ZONE_LOCK, "ZONE LOCK"},
  151         {SMP_FUNC_ZONE_ACTIVATE, "ZONE ACTIVATE"},
  152         {SMP_FUNC_ZONE_UNLOCK, "ZONE UNLOCK"},
  153         {SMP_FUNC_CONFIG_ZM_PWD, "CONFIGURE ZONE MANAGER PASSWORD"},
  154         {SMP_FUNC_CONFIG_ZONE_PHY_INFO, "CONFIGURE ZONE PHY INFORMATION"},
  155         {SMP_FUNC_CONFIG_ZONE_PERM_TBL, "CONFIGURE ZONE PERMISSION TABLE"},
  156         {SMP_FUNC_CONFIG_ROUTE_INFO, "CONFIGURE ROUTE INFORMATION"},
  157         {SMP_FUNC_PHY_CONTROL, "PHY CONTROL"},
  158         {SMP_FUNC_PHY_TEST_FUNC, "PHY TEST FUNCTION"},
  159         {SMP_FUNC_CONFIG_PHY_EVENT, "CONFIGURE PHY EVENT"}
  160 };
  161 
  162 const char *
  163 smp_command_desc(uint8_t cmd_num)
  164 {
  165         int i;
  166 
  167         for (i = 0; i < (sizeof(smp_cmd_table)/sizeof(smp_cmd_table[0])) &&
  168              smp_cmd_table[i].cmd_num <= cmd_num; i++) {
  169                 if (cmd_num == smp_cmd_table[i].cmd_num)
  170                         return (smp_cmd_table[i].desc);
  171         }
  172 
  173         /*
  174          * 0x40 to 0x7f and 0xc0 to 0xff are the vendor specific SMP
  175          * command ranges.
  176          */
  177         if (((cmd_num >= 0x40) && (cmd_num <= 0x7f))
  178          || (cmd_num >= 0xc0)) {
  179                 return ("Vendor Specific SMP Command");
  180         } else {
  181                 return ("Unknown SMP Command");
  182         }
  183 }
  184 
  185 /*
  186  * Decode a SMP request buffer into a string of hexadecimal numbers.
  187  *
  188  * smp_request:    SMP request
  189  * request_len:    length of the SMP request buffer, may be reduced if the
  190  *                 caller only wants part of the buffer printed
  191  * sb:             sbuf(9) buffer
  192  * line_prefix:    prefix for new lines, or an empty string ("")
  193  * first_line_len: length left on first line
  194  * line_len:       total length of subsequent lines, 0 for no additional lines
  195  *                 if there are no additional lines, first line will get ...
  196  *                 at the end if there is additional data
  197  */
  198 void
  199 smp_command_decode(uint8_t *smp_request, int request_len, struct sbuf *sb,
  200                    char *line_prefix, int first_line_len, int line_len)
  201 {
  202         int i, cur_len;
  203 
  204         for (i = 0, cur_len = first_line_len; i < request_len; i++) {
  205                 /*
  206                  * Each byte takes 3 characters.  As soon as we go less
  207                  * than 6 (meaning we have at least 3 and at most 5
  208                  * characters left), check to see whether the subsequent
  209                  * line length (line_len) is long enough to bother with.
  210                  * If the user set it to 0, or some other length that isn't
  211                  * enough to hold at least the prefix and one byte, put ...
  212                  * on the first line to indicate that there is more data
  213                  * and bail out.
  214                  */
  215                 if ((cur_len < 6)
  216                  && (line_len < (strlen(line_prefix) + 3))) {
  217                         sbuf_printf(sb, "...");
  218                         return;
  219                 }
  220                 if (cur_len < 3) {
  221                         sbuf_printf(sb, "\n%s", line_prefix);
  222                         cur_len = line_len - strlen(line_prefix);
  223                 }
  224                 sbuf_printf(sb, "%02x ", smp_request[i]);
  225                 cur_len = cur_len - 3;
  226         }
  227 }
  228 
  229 void
  230 smp_command_sbuf(struct ccb_smpio *smpio, struct sbuf *sb,
  231                  char *line_prefix, int first_line_len, int line_len)
  232 {
  233         sbuf_printf(sb, "%s. ", smp_command_desc(smpio->smp_request[1]));
  234 
  235         /*
  236          * Acccount for the command description and the period and space
  237          * after the command description.
  238          */
  239         first_line_len -= strlen(smp_command_desc(smpio->smp_request[1])) + 2;
  240 
  241         smp_command_decode(smpio->smp_request, smpio->smp_request_len, sb,
  242                            line_prefix, first_line_len, line_len);
  243 }
  244 
  245 /*
  246  * Print SMP error output.  For userland commands, we need the cam_device
  247  * structure so we can get the path information from the CCB.
  248  */
  249 #ifdef _KERNEL
  250 void
  251 smp_error_sbuf(struct ccb_smpio *smpio, struct sbuf *sb)
  252 #else /* !_KERNEL*/
  253 void
  254 smp_error_sbuf(struct cam_device *device, struct ccb_smpio *smpio,
  255                struct sbuf *sb)
  256 #endif /* _KERNEL/!_KERNEL */
  257 {
  258         char path_str[64];
  259 
  260 #ifdef _KERNEL
  261         xpt_path_string(smpio->ccb_h.path, path_str, sizeof(path_str));
  262 #else
  263         cam_path_string(device, path_str, sizeof(path_str));
  264 #endif
  265         smp_command_sbuf(smpio, sb, path_str, 80 - strlen(path_str), 80);
  266         sbuf_printf(sb, "\n");
  267 
  268         sbuf_cat(sb, path_str);
  269         sbuf_printf(sb, "SMP Error: %s (0x%x)\n",
  270                     smp_error_desc(smpio->smp_response[2]),
  271                     smpio->smp_response[2]);
  272 }
  273 
  274 /*
  275  * Decode the SMP REPORT GENERAL response.  The format is current as of SPL
  276  * Revision 7, but the parsing should be backward compatible for older
  277  * versions of the spec.
  278  */
  279 void
  280 smp_report_general_sbuf(struct smp_report_general_response *response,
  281                         int response_len, struct sbuf *sb)
  282 {
  283         sbuf_printf(sb, "Report General\n");
  284         sbuf_printf(sb, "Response Length: %d words (%d bytes)\n",
  285                     response->response_len,
  286                     response->response_len * SMP_WORD_LEN);
  287         sbuf_printf(sb, "Expander Change Count: %d\n",
  288                     scsi_2btoul(response->expander_change_count));
  289         sbuf_printf(sb, "Expander Route Indexes: %d\n", 
  290                     scsi_2btoul(response->expander_route_indexes));
  291         sbuf_printf(sb, "Long Response: %s\n",
  292                     smp_yesno(response->long_response &
  293                               SMP_RG_LONG_RESPONSE));
  294         sbuf_printf(sb, "Number of Phys: %d\n", response->num_phys);
  295         sbuf_printf(sb, "Table to Table Supported: %s\n",
  296                     smp_yesno(response->config_bits0 &
  297                     SMP_RG_TABLE_TO_TABLE_SUP));
  298         sbuf_printf(sb, "Zone Configuring: %s\n", 
  299                     smp_yesno(response->config_bits0 &
  300                     SMP_RG_ZONE_CONFIGURING));
  301         sbuf_printf(sb, "Self Configuring: %s\n", 
  302                     smp_yesno(response->config_bits0 &
  303                     SMP_RG_SELF_CONFIGURING));
  304         sbuf_printf(sb, "STP Continue AWT: %s\n", 
  305                     smp_yesno(response->config_bits0 &
  306                     SMP_RG_STP_CONTINUE_AWT));
  307         sbuf_printf(sb, "Open Reject Retry Supported: %s\n", 
  308                     smp_yesno(response->config_bits0 &
  309                     SMP_RG_OPEN_REJECT_RETRY_SUP));
  310         sbuf_printf(sb, "Configures Others: %s\n", 
  311                     smp_yesno(response->config_bits0 &
  312                     SMP_RG_CONFIGURES_OTHERS));
  313         sbuf_printf(sb, "Configuring: %s\n", 
  314                     smp_yesno(response->config_bits0 &
  315                     SMP_RG_CONFIGURING));
  316         sbuf_printf(sb, "Externally Configurable Route Table: %s\n", 
  317                     smp_yesno(response->config_bits0 &
  318                     SMP_RG_CONFIGURING));
  319         sbuf_printf(sb, "Enclosure Logical Identifier: 0x%016jx\n",
  320                     (uintmax_t)scsi_8btou64(response->encl_logical_id));
  321 
  322         /*
  323          * If the response->response_len is 0, then we don't have the
  324          * extended information.  Also, if the user didn't allocate enough
  325          * space for the full request, don't try to parse it.
  326          */
  327         if ((response->response_len == 0)
  328          || (response_len < (sizeof(struct smp_report_general_response) -
  329              sizeof(response->crc))))
  330                 return;
  331 
  332         sbuf_printf(sb, "STP Bus Inactivity Time Limit: %d\n",
  333                     scsi_2btoul(response->stp_bus_inact_time_limit));
  334         sbuf_printf(sb, "STP Maximum Connect Time Limit: %d\n",
  335                     scsi_2btoul(response->stp_max_conn_time_limit));
  336         sbuf_printf(sb, "STP SMP I_T Nexus Loss Time: %d\n",
  337                     scsi_2btoul(response->stp_smp_it_nexus_loss_time));
  338 
  339         sbuf_printf(sb, "Number of Zone Groups: %d\n",
  340                     (response->config_bits1 & SMP_RG_NUM_ZONE_GROUPS_MASK) >>
  341                     SMP_RG_NUM_ZONE_GROUPS_SHIFT);
  342         sbuf_printf(sb, "Zone Locked: %s\n",
  343                     smp_yesno(response->config_bits1 & SMP_RG_ZONE_LOCKED));
  344         sbuf_printf(sb, "Physical Presence Supported: %s\n",
  345                     smp_yesno(response->config_bits1 & SMP_RG_PP_SUPPORTED));
  346         sbuf_printf(sb, "Physical Presence Asserted: %s\n",
  347                     smp_yesno(response->config_bits1 & SMP_RG_PP_ASSERTED));
  348         sbuf_printf(sb, "Zoning Supported: %s\n",
  349                     smp_yesno(response->config_bits1 &
  350                               SMP_RG_ZONING_SUPPORTED));
  351         sbuf_printf(sb, "Zoning Enabled: %s\n",
  352                     smp_yesno(response->config_bits1 & SMP_RG_ZONING_ENABLED));
  353 
  354         sbuf_printf(sb, "Saving: %s\n",
  355                     smp_yesno(response->config_bits2 & SMP_RG_SAVING));
  356         sbuf_printf(sb, "Saving Zone Manager Password Supported: %s\n",
  357                     smp_yesno(response->config_bits2 &
  358                               SMP_RG_SAVING_ZM_PWD_SUP));
  359         sbuf_printf(sb, "Saving Zone Phy Information Supported: %s\n",
  360                     smp_yesno(response->config_bits2 &
  361                               SMP_RG_SAVING_PHY_INFO_SUP));
  362         sbuf_printf(sb, "Saving Zone Permission Table Supported: %s\n",
  363                     smp_yesno(response->config_bits2 &
  364                               SMP_RG_SAVING_ZPERM_TAB_SUP));
  365         sbuf_printf(sb, "Saving Zoning Enabled Supported: %s\n",
  366                     smp_yesno(response->config_bits2 &
  367                               SMP_RG_SAVING_ZENABLED_SUP));
  368 
  369         sbuf_printf(sb, "Maximum Number of Routed SAS Addresses: %d\n",
  370                     scsi_2btoul(response->max_num_routed_addrs));
  371 
  372         sbuf_printf(sb, "Active Zone Manager SAS Address: 0x%016jx\n",
  373                     scsi_8btou64(response->active_zm_address));
  374 
  375         sbuf_printf(sb, "Zone Inactivity Time Limit: %d\n",
  376                     scsi_2btoul(response->zone_lock_inact_time_limit));
  377 
  378         sbuf_printf(sb, "First Enclosure Connector Element Index: %d\n",
  379                     response->first_encl_conn_el_index);
  380 
  381         sbuf_printf(sb, "Number of Enclosure Connector Element Indexes: %d\n",
  382                     response->num_encl_conn_el_indexes);
  383 
  384         sbuf_printf(sb, "Reduced Functionality: %s\n",
  385                     smp_yesno(response->reduced_functionality &
  386                               SMP_RG_REDUCED_FUNCTIONALITY));
  387 
  388         sbuf_printf(sb, "Time to Reduced Functionality: %d\n",
  389                     response->time_to_reduced_func);
  390         sbuf_printf(sb, "Initial Time to Reduced Functionality: %d\n",
  391                     response->initial_time_to_reduced_func);
  392         sbuf_printf(sb, "Maximum Reduced Functionality Time: %d\n",
  393                     response->max_reduced_func_time);
  394 
  395         sbuf_printf(sb, "Last Self-Configuration Status Descriptor Index: %d\n",
  396                     scsi_2btoul(response->last_sc_stat_desc_index));
  397 
  398         sbuf_printf(sb, "Maximum Number of Storated Self-Configuration "
  399                     "Status Descriptors: %d\n",
  400                     scsi_2btoul(response->max_sc_stat_descs));
  401 
  402         sbuf_printf(sb, "Last Phy Event List Descriptor Index: %d\n",
  403                     scsi_2btoul(response->last_phy_evl_desc_index));
  404 
  405         sbuf_printf(sb, "Maximum Number of Stored Phy Event List "
  406                     "Descriptors: %d\n",
  407                     scsi_2btoul(response->max_stored_pel_descs));
  408 
  409         sbuf_printf(sb, "STP Reject to Open Limit: %d\n",
  410                     scsi_2btoul(response->stp_reject_to_open_limit));
  411 }
  412 
  413 /*
  414  * Decode the SMP REPORT MANUFACTURER INFORMATION response.  The format is
  415  * current as of SPL Revision 7, but the parsing should be backward
  416  * compatible for older versions of the spec.
  417  */
  418 void
  419 smp_report_manuf_info_sbuf(struct smp_report_manuf_info_response *response,
  420                            int response_len, struct sbuf *sb)
  421 {
  422         char vendor[16], product[48], revision[16];
  423         char comp_vendor[16];
  424 
  425         sbuf_printf(sb, "Report Manufacturer Information\n");
  426         sbuf_printf(sb, "Expander Change count: %d\n",
  427                     scsi_2btoul(response->expander_change_count));
  428         sbuf_printf(sb, "SAS 1.1 Format: %s\n",
  429                     smp_yesno(response->sas_11_format & SMP_RMI_SAS11_FORMAT));
  430         cam_strvis(vendor, response->vendor, sizeof(response->vendor),
  431                    sizeof(vendor));
  432         cam_strvis(product, response->product, sizeof(response->product),
  433                    sizeof(product));
  434         cam_strvis(revision, response->revision, sizeof(response->revision),
  435                    sizeof(revision));
  436         sbuf_printf(sb, "<%s %s %s>\n", vendor, product, revision);
  437 
  438         if ((response->sas_11_format & SMP_RMI_SAS11_FORMAT) == 0) {
  439                 uint8_t *curbyte;
  440                 int line_start, line_cursor;
  441 
  442                 sbuf_printf(sb, "Vendor Specific Data:\n");
  443 
  444                 /*
  445                  * Print out the bytes roughly in the style of hd(1), but
  446                  * without the extra ASCII decoding.  Hexadecimal line
  447                  * numbers on the left, and 16 bytes per line, with an
  448                  * extra space after the first 8 bytes.
  449                  *
  450                  * It would be nice if this sort of thing were available
  451                  * in a library routine.
  452                  */
  453                 for (curbyte = (uint8_t *)&response->comp_vendor, line_start= 1,
  454                      line_cursor = 0; curbyte < (uint8_t *)&response->crc;
  455                      curbyte++, line_cursor++) {
  456                         if (line_start != 0) {
  457                                 sbuf_printf(sb, "%08lx  ",
  458                                             (unsigned long)(curbyte -
  459                                             (uint8_t *)response));
  460                                 line_start = 0;
  461                                 line_cursor = 0;
  462                         }
  463                         sbuf_printf(sb, "%02x", *curbyte);
  464 
  465                         if (line_cursor == 15) {
  466                                 sbuf_printf(sb, "\n");
  467                                 line_start = 1;
  468                         } else
  469                                 sbuf_printf(sb, " %s", (line_cursor == 7) ?
  470                                             " " : "");
  471                 }
  472                 if (line_cursor != 16)
  473                         sbuf_printf(sb, "\n");
  474                 return;
  475         }
  476 
  477         cam_strvis(comp_vendor, response->comp_vendor,
  478                    sizeof(response->comp_vendor), sizeof(comp_vendor));
  479         sbuf_printf(sb, "Component Vendor: %s\n", comp_vendor);
  480         sbuf_printf(sb, "Component ID: %#x\n", scsi_2btoul(response->comp_id));
  481         sbuf_printf(sb, "Component Revision: %#x\n", response->comp_revision);
  482         sbuf_printf(sb, "Vendor Specific: 0x%016jx\n",
  483                     (uintmax_t)scsi_8btou64(response->vendor_specific));
  484 }
  485 
  486 /*
  487  * Compose a SMP REPORT GENERAL request and put it into a CCB.  This is
  488  * current as of SPL Revision 7.
  489  */
  490 void
  491 smp_report_general(struct ccb_smpio *smpio, uint32_t retries,
  492                    void (*cbfcnp)(struct cam_periph *, union ccb *),
  493                    struct smp_report_general_request *request, int request_len,
  494                    uint8_t *response, int response_len, int long_response,
  495                    uint32_t timeout)
  496 {
  497         cam_fill_smpio(smpio,
  498                        retries,
  499                        cbfcnp,
  500                        /*flags*/CAM_DIR_BOTH,
  501                        (uint8_t *)request,
  502                        request_len - SMP_CRC_LEN,
  503                        response,
  504                        response_len,
  505                        timeout);
  506 
  507         bzero(request, sizeof(*request));
  508 
  509         request->frame_type = SMP_FRAME_TYPE_REQUEST;
  510         request->function = SMP_FUNC_REPORT_GENERAL;
  511         request->response_len = long_response ? SMP_RG_RESPONSE_LEN : 0;
  512         request->request_len = 0;
  513 }
  514 
  515 /*
  516  * Compose a SMP DISCOVER request and put it into a CCB.  This is current
  517  * as of SPL Revision 7.
  518  */
  519 void
  520 smp_discover(struct ccb_smpio *smpio, uint32_t retries,
  521              void (*cbfcnp)(struct cam_periph *, union ccb *),
  522              struct smp_discover_request *request, int request_len,
  523              uint8_t *response, int response_len, int long_response,
  524              int ignore_zone_group, int phy, uint32_t timeout)
  525 {
  526         cam_fill_smpio(smpio,
  527                        retries,
  528                        cbfcnp,
  529                        /*flags*/CAM_DIR_BOTH,
  530                        (uint8_t *)request,
  531                        request_len - SMP_CRC_LEN,
  532                        response,
  533                        response_len,
  534                        timeout);
  535 
  536         bzero(request, sizeof(*request));
  537         request->frame_type = SMP_FRAME_TYPE_REQUEST;
  538         request->function = SMP_FUNC_DISCOVER;
  539         request->response_len = long_response ? SMP_DIS_RESPONSE_LEN : 0;
  540         request->request_len = long_response ? SMP_DIS_REQUEST_LEN : 0;
  541         if (ignore_zone_group != 0)
  542                 request->ignore_zone_group |= SMP_DIS_IGNORE_ZONE_GROUP;
  543         request->phy = phy;
  544 }
  545 
  546 /*
  547  * Compose a SMP REPORT MANUFACTURER INFORMATION request and put it into a
  548  * CCB.  This is current as of SPL Revision 7.
  549  */
  550 void
  551 smp_report_manuf_info(struct ccb_smpio *smpio, uint32_t retries,
  552                       void (*cbfcnp)(struct cam_periph *, union ccb *),
  553                       struct smp_report_manuf_info_request *request,
  554                       int request_len, uint8_t *response, int response_len,
  555                       int long_response, uint32_t timeout)
  556 {
  557         cam_fill_smpio(smpio,
  558                        retries,
  559                        cbfcnp,
  560                        /*flags*/CAM_DIR_BOTH,
  561                        (uint8_t *)request,
  562                        request_len - SMP_CRC_LEN,
  563                        response,
  564                        response_len,
  565                        timeout);
  566 
  567         bzero(request, sizeof(*request));
  568 
  569         request->frame_type = SMP_FRAME_TYPE_REQUEST;
  570         request->function = SMP_FUNC_REPORT_MANUF_INFO;
  571         request->response_len = long_response ? SMP_RMI_RESPONSE_LEN : 0;
  572         request->request_len = long_response ? SMP_RMI_REQUEST_LEN : 0;
  573 }
  574 
  575 /*
  576  * Compose a SMP PHY CONTROL request and put it into a CCB.  This is
  577  * current as of SPL Revision 7.
  578  */
  579 void
  580 smp_phy_control(struct ccb_smpio *smpio, uint32_t retries,
  581                 void (*cbfcnp)(struct cam_periph *, union ccb *),
  582                 struct smp_phy_control_request *request, int request_len,
  583                 uint8_t *response, int response_len, int long_response,
  584                 uint32_t expected_exp_change_count, int phy, int phy_op,
  585                 int update_pp_timeout_val, uint64_t attached_device_name,
  586                 int prog_min_prl, int prog_max_prl, int slumber_partial,
  587                 int pp_timeout_value, uint32_t timeout)
  588 {
  589         cam_fill_smpio(smpio,
  590                        retries,
  591                        cbfcnp,
  592                        /*flags*/CAM_DIR_BOTH,
  593                        (uint8_t *)request,
  594                        request_len - SMP_CRC_LEN,
  595                        response,
  596                        response_len,
  597                        timeout);
  598 
  599         bzero(request, sizeof(*request));
  600 
  601         request->frame_type = SMP_FRAME_TYPE_REQUEST;
  602         request->function = SMP_FUNC_PHY_CONTROL;
  603         request->response_len = long_response ? SMP_PC_RESPONSE_LEN : 0;
  604         request->request_len = long_response ? SMP_PC_REQUEST_LEN : 0;
  605         scsi_ulto2b(expected_exp_change_count, request->expected_exp_chg_cnt);
  606         request->phy = phy;
  607         request->phy_operation = phy_op;
  608 
  609         if (update_pp_timeout_val != 0)
  610                 request->update_pp_timeout |= SMP_PC_UPDATE_PP_TIMEOUT;
  611 
  612         scsi_u64to8b(attached_device_name, request->attached_device_name);
  613         request->prog_min_phys_link_rate = (prog_min_prl <<
  614                 SMP_PC_PROG_MIN_PL_RATE_SHIFT) & SMP_PC_PROG_MIN_PL_RATE_MASK;
  615         request->prog_max_phys_link_rate = (prog_max_prl <<
  616                 SMP_PC_PROG_MAX_PL_RATE_SHIFT) & SMP_PC_PROG_MAX_PL_RATE_MASK;
  617         request->config_bits0 = slumber_partial;
  618         request->pp_timeout_value = pp_timeout_value;
  619 }
  620 

Cache object: ff0cbecc0982d6784325ca484c351d5c


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