106e79492SKenneth D. Merry /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3bec9534dSPedro F. Giffuni *
406e79492SKenneth D. Merry * Copyright (c) 2010 Spectra Logic Corporation
506e79492SKenneth D. Merry * All rights reserved.
606e79492SKenneth D. Merry *
706e79492SKenneth D. Merry * Redistribution and use in source and binary forms, with or without
806e79492SKenneth D. Merry * modification, are permitted provided that the following conditions
906e79492SKenneth D. Merry * are met:
1006e79492SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright
1106e79492SKenneth D. Merry * notice, this list of conditions, and the following disclaimer,
1206e79492SKenneth D. Merry * without modification.
1306e79492SKenneth D. Merry * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1406e79492SKenneth D. Merry * substantially similar to the "NO WARRANTY" disclaimer below
1506e79492SKenneth D. Merry * ("Disclaimer") and any redistribution must be conditioned upon
1606e79492SKenneth D. Merry * including a substantially similar Disclaimer requirement for further
1706e79492SKenneth D. Merry * binary redistribution.
1806e79492SKenneth D. Merry *
1906e79492SKenneth D. Merry * NO WARRANTY
2006e79492SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2106e79492SKenneth D. Merry * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2206e79492SKenneth D. Merry * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
2306e79492SKenneth D. Merry * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2406e79492SKenneth D. Merry * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2506e79492SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2606e79492SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2706e79492SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2806e79492SKenneth D. Merry * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
2906e79492SKenneth D. Merry * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3006e79492SKenneth D. Merry * POSSIBILITY OF SUCH DAMAGES.
3106e79492SKenneth D. Merry *
3206e79492SKenneth D. Merry * $Id: //depot/users/kenm/FreeBSD-test/sys/cam/scsi/smp_all.c#4 $
3306e79492SKenneth D. Merry */
3406e79492SKenneth D. Merry
3506e79492SKenneth D. Merry /*
3606e79492SKenneth D. Merry * Serial Management Protocol helper functions.
3706e79492SKenneth D. Merry */
3806e79492SKenneth D. Merry
3906e79492SKenneth D. Merry #include <sys/param.h>
4006e79492SKenneth D. Merry #include <sys/types.h>
4106e79492SKenneth D. Merry #ifdef _KERNEL
4206e79492SKenneth D. Merry #include <sys/systm.h>
4306e79492SKenneth D. Merry #include <sys/libkern.h>
4406e79492SKenneth D. Merry #include <sys/kernel.h>
4506e79492SKenneth D. Merry #else /* _KERNEL */
4606e79492SKenneth D. Merry #include <errno.h>
4706e79492SKenneth D. Merry #include <stdio.h>
4806e79492SKenneth D. Merry #include <stdlib.h>
4906e79492SKenneth D. Merry #include <string.h>
5006e79492SKenneth D. Merry #include <inttypes.h>
5106e79492SKenneth D. Merry #endif /* _KERNEL */
5206e79492SKenneth D. Merry
5306e79492SKenneth D. Merry #include <cam/cam.h>
5406e79492SKenneth D. Merry #include <cam/cam_ccb.h>
5506e79492SKenneth D. Merry #include <cam/cam_xpt.h>
5606e79492SKenneth D. Merry #include <cam/scsi/smp_all.h>
5706e79492SKenneth D. Merry #include <sys/sbuf.h>
5806e79492SKenneth D. Merry
5906e79492SKenneth D. Merry #ifndef _KERNEL
6006e79492SKenneth D. Merry #include <camlib.h>
6106e79492SKenneth D. Merry #endif
6206e79492SKenneth D. Merry
6306e79492SKenneth D. Merry static char *smp_yesno(int val);
6406e79492SKenneth D. Merry
6506e79492SKenneth D. Merry static char *
smp_yesno(int val)6606e79492SKenneth D. Merry smp_yesno(int val)
6706e79492SKenneth D. Merry {
6806e79492SKenneth D. Merry char *str;
6906e79492SKenneth D. Merry
7006e79492SKenneth D. Merry if (val)
7106e79492SKenneth D. Merry str = "Yes";
7206e79492SKenneth D. Merry else
7306e79492SKenneth D. Merry str = "No";
7406e79492SKenneth D. Merry
7506e79492SKenneth D. Merry return (str);
7606e79492SKenneth D. Merry }
7706e79492SKenneth D. Merry
7806e79492SKenneth D. Merry struct smp_error_table_entry {
7906e79492SKenneth D. Merry uint8_t function_result;
8006e79492SKenneth D. Merry const char *desc;
8106e79492SKenneth D. Merry };
8206e79492SKenneth D. Merry
8306e79492SKenneth D. Merry /* List current as of SPL Revision 7 */
8406e79492SKenneth D. Merry static struct smp_error_table_entry smp_error_table[] = {
8506e79492SKenneth D. Merry {SMP_FR_ACCEPTED, "SMP Function Accepted"},
8606e79492SKenneth D. Merry {SMP_FR_UNKNOWN_FUNC, "Unknown SMP Function"},
8706e79492SKenneth D. Merry {SMP_FR_FUNCTION_FAILED, "SMP Function Failed"},
8806e79492SKenneth D. Merry {SMP_FR_INVALID_REQ_FRAME_LEN, "Invalid Request Frame Length"},
8906e79492SKenneth D. Merry {SMP_FR_INVALID_EXP_CHG_CNT, "Invalid Expander Change Count"},
9006e79492SKenneth D. Merry {SMP_FR_BUSY, "Busy"},
9106e79492SKenneth D. Merry {SMP_FR_INCOMPLETE_DESC_LIST, "Incomplete Descriptor List"},
9206e79492SKenneth D. Merry {SMP_FR_PHY_DOES_NOT_EXIST, "Phy Does Not Exist"},
9306e79492SKenneth D. Merry {SMP_FR_INDEX_DOES_NOT_EXIST, "Index Does Not Exist"},
9406e79492SKenneth D. Merry {SMP_FR_PHY_DOES_NOT_SUP_SATA, "Phy Does Not Support SATA"},
9506e79492SKenneth D. Merry {SMP_FR_UNKNOWN_PHY_OP, "Unknown Phy Operation"},
9606e79492SKenneth D. Merry {SMP_FR_UNKNOWN_PHY_TEST_FUNC, "Unknown Phy Test Function"},
9706e79492SKenneth D. Merry {SMP_FR_PHY_TEST_FUNC_INPROG, "Phy Test Function In Progress"},
9806e79492SKenneth D. Merry {SMP_FR_PHY_VACANT, "Phy Vacant"},
9906e79492SKenneth D. Merry {SMP_FR_UNKNOWN_PHY_EVENT_SRC, "Unknown Phy Event Source"},
10006e79492SKenneth D. Merry {SMP_FR_UNKNOWN_DESC_TYPE, "Unknown Descriptor Type"},
10106e79492SKenneth D. Merry {SMP_FR_UNKNOWN_PHY_FILTER, "Unknown Phy Filter"},
10206e79492SKenneth D. Merry {SMP_FR_AFFILIATION_VIOLATION, "Affiliation Violation"},
10306e79492SKenneth D. Merry {SMP_FR_SMP_ZONE_VIOLATION, "SMP Zone Violation"},
10406e79492SKenneth D. Merry {SMP_FR_NO_MGMT_ACCESS_RIGHTS, "No Management Access Rights"},
10506e79492SKenneth D. Merry {SMP_FR_UNKNOWN_ED_ZONING_VAL, "Unknown Enable Disable Zoning Value"},
10606e79492SKenneth D. Merry {SMP_FR_ZONE_LOCK_VIOLATION, "Zone Lock Violation"},
10706e79492SKenneth D. Merry {SMP_FR_NOT_ACTIVATED, "Not Activated"},
10806e79492SKenneth D. Merry {SMP_FR_ZG_OUT_OF_RANGE, "Zone Group Out of Range"},
10906e79492SKenneth D. Merry {SMP_FR_NO_PHYS_PRESENCE, "No Physical Presence"},
11006e79492SKenneth D. Merry {SMP_FR_SAVING_NOT_SUP, "Saving Not Supported"},
11106e79492SKenneth D. Merry {SMP_FR_SRC_ZONE_DNE, "Source Zone Group Does Not Exist"},
11206e79492SKenneth D. Merry {SMP_FR_DISABLED_PWD_NOT_SUP, "Disabled Password Not Supported"}
11306e79492SKenneth D. Merry };
11406e79492SKenneth D. Merry
11506e79492SKenneth D. Merry const char *
smp_error_desc(int function_result)11606e79492SKenneth D. Merry smp_error_desc(int function_result)
11706e79492SKenneth D. Merry {
11806e79492SKenneth D. Merry int i;
11906e79492SKenneth D. Merry
120323b076eSPedro F. Giffuni for (i = 0; i < nitems(smp_error_table); i++){
12106e79492SKenneth D. Merry if (function_result == smp_error_table[i].function_result)
12206e79492SKenneth D. Merry return (smp_error_table[i].desc);
12306e79492SKenneth D. Merry }
12406e79492SKenneth D. Merry return ("Reserved Function Result");
12506e79492SKenneth D. Merry }
12606e79492SKenneth D. Merry
12706e79492SKenneth D. Merry /* List current as of SPL Revision 7 */
12806e79492SKenneth D. Merry struct smp_cmd_table_entry {
12906e79492SKenneth D. Merry uint8_t cmd_num;
13006e79492SKenneth D. Merry const char *desc;
13106e79492SKenneth D. Merry } smp_cmd_table[] = {
13206e79492SKenneth D. Merry {SMP_FUNC_REPORT_GENERAL, "REPORT GENERAL"},
13306e79492SKenneth D. Merry {SMP_FUNC_REPORT_MANUF_INFO, "REPORT MANUFACTURER INFORMATION"},
13406e79492SKenneth D. Merry {SMP_FUNC_REPORT_SC_STATUS, "REPORT SELF-CONFIGURATION STATUS"},
13506e79492SKenneth D. Merry {SMP_FUNC_REPORT_ZONE_PERM_TBL, "REPORT ZONE PERMISSION TABLE"},
13606e79492SKenneth D. Merry {SMP_FUNC_REPORT_BROADCAST, "REPORT BROADCAST"},
13706e79492SKenneth D. Merry {SMP_FUNC_DISCOVER, "DISCOVER"},
13806e79492SKenneth D. Merry {SMP_FUNC_REPORT_PHY_ERR_LOG, "REPORT PHY ERROR LOG"},
13906e79492SKenneth D. Merry {SMP_FUNC_REPORT_PHY_SATA, "REPORT PHY SATA"},
14006e79492SKenneth D. Merry {SMP_FUNC_REPORT_ROUTE_INFO, "REPORT ROUTE INFORMATION"},
14106e79492SKenneth D. Merry {SMP_FUNC_REPORT_PHY_EVENT, "REPORT PHY EVENT"},
14206e79492SKenneth D. Merry {SMP_FUNC_DISCOVER_LIST, "DISCOVER LIST"},
14306e79492SKenneth D. Merry {SMP_FUNC_REPORT_PHY_EVENT_LIST, "REPORT PHY EVENT LIST"},
14406e79492SKenneth D. Merry {SMP_FUNC_REPORT_EXP_RTL, "REPORT EXPANDER ROUTE TABLE LIST"},
14506e79492SKenneth D. Merry {SMP_FUNC_CONFIG_GENERAL, "CONFIGURE GENERAL"},
14606e79492SKenneth D. Merry {SMP_FUNC_ENABLE_DISABLE_ZONING, "ENABLE DISABLE ZONING"},
14706e79492SKenneth D. Merry {SMP_FUNC_ZONED_BROADCAST, "ZONED BROADCAST"},
14806e79492SKenneth D. Merry {SMP_FUNC_ZONE_LOCK, "ZONE LOCK"},
14906e79492SKenneth D. Merry {SMP_FUNC_ZONE_ACTIVATE, "ZONE ACTIVATE"},
15006e79492SKenneth D. Merry {SMP_FUNC_ZONE_UNLOCK, "ZONE UNLOCK"},
15106e79492SKenneth D. Merry {SMP_FUNC_CONFIG_ZM_PWD, "CONFIGURE ZONE MANAGER PASSWORD"},
15206e79492SKenneth D. Merry {SMP_FUNC_CONFIG_ZONE_PHY_INFO, "CONFIGURE ZONE PHY INFORMATION"},
15306e79492SKenneth D. Merry {SMP_FUNC_CONFIG_ZONE_PERM_TBL, "CONFIGURE ZONE PERMISSION TABLE"},
15406e79492SKenneth D. Merry {SMP_FUNC_CONFIG_ROUTE_INFO, "CONFIGURE ROUTE INFORMATION"},
15506e79492SKenneth D. Merry {SMP_FUNC_PHY_CONTROL, "PHY CONTROL"},
15606e79492SKenneth D. Merry {SMP_FUNC_PHY_TEST_FUNC, "PHY TEST FUNCTION"},
15706e79492SKenneth D. Merry {SMP_FUNC_CONFIG_PHY_EVENT, "CONFIGURE PHY EVENT"}
15806e79492SKenneth D. Merry };
15906e79492SKenneth D. Merry
16006e79492SKenneth D. Merry const char *
smp_command_desc(uint8_t cmd_num)16106e79492SKenneth D. Merry smp_command_desc(uint8_t cmd_num)
16206e79492SKenneth D. Merry {
16306e79492SKenneth D. Merry int i;
16406e79492SKenneth D. Merry
165323b076eSPedro F. Giffuni for (i = 0; i < nitems(smp_cmd_table) &&
16606e79492SKenneth D. Merry smp_cmd_table[i].cmd_num <= cmd_num; i++) {
16706e79492SKenneth D. Merry if (cmd_num == smp_cmd_table[i].cmd_num)
16806e79492SKenneth D. Merry return (smp_cmd_table[i].desc);
16906e79492SKenneth D. Merry }
17006e79492SKenneth D. Merry
17106e79492SKenneth D. Merry /*
17206e79492SKenneth D. Merry * 0x40 to 0x7f and 0xc0 to 0xff are the vendor specific SMP
17306e79492SKenneth D. Merry * command ranges.
17406e79492SKenneth D. Merry */
17506e79492SKenneth D. Merry if (((cmd_num >= 0x40) && (cmd_num <= 0x7f))
17606e79492SKenneth D. Merry || (cmd_num >= 0xc0)) {
17706e79492SKenneth D. Merry return ("Vendor Specific SMP Command");
17806e79492SKenneth D. Merry } else {
17906e79492SKenneth D. Merry return ("Unknown SMP Command");
18006e79492SKenneth D. Merry }
18106e79492SKenneth D. Merry }
18206e79492SKenneth D. Merry
18306e79492SKenneth D. Merry /*
18406e79492SKenneth D. Merry * Decode a SMP request buffer into a string of hexadecimal numbers.
18506e79492SKenneth D. Merry *
18606e79492SKenneth D. Merry * smp_request: SMP request
18706e79492SKenneth D. Merry * request_len: length of the SMP request buffer, may be reduced if the
18806e79492SKenneth D. Merry * caller only wants part of the buffer printed
18906e79492SKenneth D. Merry * sb: sbuf(9) buffer
19006e79492SKenneth D. Merry * line_prefix: prefix for new lines, or an empty string ("")
19106e79492SKenneth D. Merry * first_line_len: length left on first line
19206e79492SKenneth D. Merry * line_len: total length of subsequent lines, 0 for no additional lines
19306e79492SKenneth D. Merry * if there are no additional lines, first line will get ...
19406e79492SKenneth D. Merry * at the end if there is additional data
19506e79492SKenneth D. Merry */
19606e79492SKenneth D. Merry void
smp_command_decode(uint8_t * smp_request,int request_len,struct sbuf * sb,char * line_prefix,int first_line_len,int line_len)19706e79492SKenneth D. Merry smp_command_decode(uint8_t *smp_request, int request_len, struct sbuf *sb,
19806e79492SKenneth D. Merry char *line_prefix, int first_line_len, int line_len)
19906e79492SKenneth D. Merry {
20006e79492SKenneth D. Merry int i, cur_len;
20106e79492SKenneth D. Merry
20206e79492SKenneth D. Merry for (i = 0, cur_len = first_line_len; i < request_len; i++) {
20306e79492SKenneth D. Merry /*
20406e79492SKenneth D. Merry * Each byte takes 3 characters. As soon as we go less
20506e79492SKenneth D. Merry * than 6 (meaning we have at least 3 and at most 5
20606e79492SKenneth D. Merry * characters left), check to see whether the subsequent
20706e79492SKenneth D. Merry * line length (line_len) is long enough to bother with.
20806e79492SKenneth D. Merry * If the user set it to 0, or some other length that isn't
20906e79492SKenneth D. Merry * enough to hold at least the prefix and one byte, put ...
21006e79492SKenneth D. Merry * on the first line to indicate that there is more data
21106e79492SKenneth D. Merry * and bail out.
21206e79492SKenneth D. Merry */
21306e79492SKenneth D. Merry if ((cur_len < 6)
21406e79492SKenneth D. Merry && (line_len < (strlen(line_prefix) + 3))) {
215*519b24f0SAlexander Motin sbuf_cat(sb, "...");
21606e79492SKenneth D. Merry return;
21706e79492SKenneth D. Merry }
21806e79492SKenneth D. Merry if (cur_len < 3) {
21906e79492SKenneth D. Merry sbuf_printf(sb, "\n%s", line_prefix);
22006e79492SKenneth D. Merry cur_len = line_len - strlen(line_prefix);
22106e79492SKenneth D. Merry }
22206e79492SKenneth D. Merry sbuf_printf(sb, "%02x ", smp_request[i]);
22306e79492SKenneth D. Merry cur_len = cur_len - 3;
22406e79492SKenneth D. Merry }
22506e79492SKenneth D. Merry }
22606e79492SKenneth D. Merry
22706e79492SKenneth D. Merry void
smp_command_sbuf(struct ccb_smpio * smpio,struct sbuf * sb,char * line_prefix,int first_line_len,int line_len)22806e79492SKenneth D. Merry smp_command_sbuf(struct ccb_smpio *smpio, struct sbuf *sb,
22906e79492SKenneth D. Merry char *line_prefix, int first_line_len, int line_len)
23006e79492SKenneth D. Merry {
23106e79492SKenneth D. Merry sbuf_printf(sb, "%s. ", smp_command_desc(smpio->smp_request[1]));
23206e79492SKenneth D. Merry
23306e79492SKenneth D. Merry /*
23406e79492SKenneth D. Merry * Acccount for the command description and the period and space
23506e79492SKenneth D. Merry * after the command description.
23606e79492SKenneth D. Merry */
23706e79492SKenneth D. Merry first_line_len -= strlen(smp_command_desc(smpio->smp_request[1])) + 2;
23806e79492SKenneth D. Merry
23906e79492SKenneth D. Merry smp_command_decode(smpio->smp_request, smpio->smp_request_len, sb,
24006e79492SKenneth D. Merry line_prefix, first_line_len, line_len);
24106e79492SKenneth D. Merry }
24206e79492SKenneth D. Merry
24306e79492SKenneth D. Merry /*
24406e79492SKenneth D. Merry * Print SMP error output. For userland commands, we need the cam_device
24506e79492SKenneth D. Merry * structure so we can get the path information from the CCB.
24606e79492SKenneth D. Merry */
24706e79492SKenneth D. Merry #ifdef _KERNEL
24806e79492SKenneth D. Merry void
smp_error_sbuf(struct ccb_smpio * smpio,struct sbuf * sb)24906e79492SKenneth D. Merry smp_error_sbuf(struct ccb_smpio *smpio, struct sbuf *sb)
25006e79492SKenneth D. Merry #else /* !_KERNEL*/
25106e79492SKenneth D. Merry void
25206e79492SKenneth D. Merry smp_error_sbuf(struct cam_device *device, struct ccb_smpio *smpio,
25306e79492SKenneth D. Merry struct sbuf *sb)
25406e79492SKenneth D. Merry #endif /* _KERNEL/!_KERNEL */
25506e79492SKenneth D. Merry {
25606e79492SKenneth D. Merry char path_str[64];
25706e79492SKenneth D. Merry
25806e79492SKenneth D. Merry #ifdef _KERNEL
25906e79492SKenneth D. Merry xpt_path_string(smpio->ccb_h.path, path_str, sizeof(path_str));
26006e79492SKenneth D. Merry #else
26106e79492SKenneth D. Merry cam_path_string(device, path_str, sizeof(path_str));
26206e79492SKenneth D. Merry #endif
26306e79492SKenneth D. Merry smp_command_sbuf(smpio, sb, path_str, 80 - strlen(path_str), 80);
264*519b24f0SAlexander Motin sbuf_putc(sb, '\n');
26506e79492SKenneth D. Merry
26606e79492SKenneth D. Merry sbuf_cat(sb, path_str);
26706e79492SKenneth D. Merry sbuf_printf(sb, "SMP Error: %s (0x%x)\n",
26806e79492SKenneth D. Merry smp_error_desc(smpio->smp_response[2]),
26906e79492SKenneth D. Merry smpio->smp_response[2]);
27006e79492SKenneth D. Merry }
27106e79492SKenneth D. Merry
27206e79492SKenneth D. Merry /*
27306e79492SKenneth D. Merry * Decode the SMP REPORT GENERAL response. The format is current as of SPL
27406e79492SKenneth D. Merry * Revision 7, but the parsing should be backward compatible for older
27506e79492SKenneth D. Merry * versions of the spec.
27606e79492SKenneth D. Merry */
27706e79492SKenneth D. Merry void
smp_report_general_sbuf(struct smp_report_general_response * response,int response_len,struct sbuf * sb)27806e79492SKenneth D. Merry smp_report_general_sbuf(struct smp_report_general_response *response,
27906e79492SKenneth D. Merry int response_len, struct sbuf *sb)
28006e79492SKenneth D. Merry {
281*519b24f0SAlexander Motin sbuf_cat(sb, "Report General\n");
28206e79492SKenneth D. Merry sbuf_printf(sb, "Response Length: %d words (%d bytes)\n",
28306e79492SKenneth D. Merry response->response_len,
28406e79492SKenneth D. Merry response->response_len * SMP_WORD_LEN);
28506e79492SKenneth D. Merry sbuf_printf(sb, "Expander Change Count: %d\n",
28606e79492SKenneth D. Merry scsi_2btoul(response->expander_change_count));
28706e79492SKenneth D. Merry sbuf_printf(sb, "Expander Route Indexes: %d\n",
28806e79492SKenneth D. Merry scsi_2btoul(response->expander_route_indexes));
28906e79492SKenneth D. Merry sbuf_printf(sb, "Long Response: %s\n",
29006e79492SKenneth D. Merry smp_yesno(response->long_response &
29106e79492SKenneth D. Merry SMP_RG_LONG_RESPONSE));
29206e79492SKenneth D. Merry sbuf_printf(sb, "Number of Phys: %d\n", response->num_phys);
29306e79492SKenneth D. Merry sbuf_printf(sb, "Table to Table Supported: %s\n",
29406e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
29506e79492SKenneth D. Merry SMP_RG_TABLE_TO_TABLE_SUP));
29606e79492SKenneth D. Merry sbuf_printf(sb, "Zone Configuring: %s\n",
29706e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
29806e79492SKenneth D. Merry SMP_RG_ZONE_CONFIGURING));
29906e79492SKenneth D. Merry sbuf_printf(sb, "Self Configuring: %s\n",
30006e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
30106e79492SKenneth D. Merry SMP_RG_SELF_CONFIGURING));
30206e79492SKenneth D. Merry sbuf_printf(sb, "STP Continue AWT: %s\n",
30306e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
30406e79492SKenneth D. Merry SMP_RG_STP_CONTINUE_AWT));
30506e79492SKenneth D. Merry sbuf_printf(sb, "Open Reject Retry Supported: %s\n",
30606e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
30706e79492SKenneth D. Merry SMP_RG_OPEN_REJECT_RETRY_SUP));
30806e79492SKenneth D. Merry sbuf_printf(sb, "Configures Others: %s\n",
30906e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
31006e79492SKenneth D. Merry SMP_RG_CONFIGURES_OTHERS));
31106e79492SKenneth D. Merry sbuf_printf(sb, "Configuring: %s\n",
31206e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
31306e79492SKenneth D. Merry SMP_RG_CONFIGURING));
31406e79492SKenneth D. Merry sbuf_printf(sb, "Externally Configurable Route Table: %s\n",
31506e79492SKenneth D. Merry smp_yesno(response->config_bits0 &
31606e79492SKenneth D. Merry SMP_RG_CONFIGURING));
31706e79492SKenneth D. Merry sbuf_printf(sb, "Enclosure Logical Identifier: 0x%016jx\n",
31806e79492SKenneth D. Merry (uintmax_t)scsi_8btou64(response->encl_logical_id));
31906e79492SKenneth D. Merry
32006e79492SKenneth D. Merry /*
32106e79492SKenneth D. Merry * If the response->response_len is 0, then we don't have the
32206e79492SKenneth D. Merry * extended information. Also, if the user didn't allocate enough
32306e79492SKenneth D. Merry * space for the full request, don't try to parse it.
32406e79492SKenneth D. Merry */
32506e79492SKenneth D. Merry if ((response->response_len == 0)
32606e79492SKenneth D. Merry || (response_len < (sizeof(struct smp_report_general_response) -
32706e79492SKenneth D. Merry sizeof(response->crc))))
32806e79492SKenneth D. Merry return;
32906e79492SKenneth D. Merry
33006e79492SKenneth D. Merry sbuf_printf(sb, "STP Bus Inactivity Time Limit: %d\n",
33106e79492SKenneth D. Merry scsi_2btoul(response->stp_bus_inact_time_limit));
33206e79492SKenneth D. Merry sbuf_printf(sb, "STP Maximum Connect Time Limit: %d\n",
33306e79492SKenneth D. Merry scsi_2btoul(response->stp_max_conn_time_limit));
33406e79492SKenneth D. Merry sbuf_printf(sb, "STP SMP I_T Nexus Loss Time: %d\n",
33506e79492SKenneth D. Merry scsi_2btoul(response->stp_smp_it_nexus_loss_time));
33606e79492SKenneth D. Merry
33706e79492SKenneth D. Merry sbuf_printf(sb, "Number of Zone Groups: %d\n",
33806e79492SKenneth D. Merry (response->config_bits1 & SMP_RG_NUM_ZONE_GROUPS_MASK) >>
33906e79492SKenneth D. Merry SMP_RG_NUM_ZONE_GROUPS_SHIFT);
34006e79492SKenneth D. Merry sbuf_printf(sb, "Zone Locked: %s\n",
34106e79492SKenneth D. Merry smp_yesno(response->config_bits1 & SMP_RG_ZONE_LOCKED));
34206e79492SKenneth D. Merry sbuf_printf(sb, "Physical Presence Supported: %s\n",
34306e79492SKenneth D. Merry smp_yesno(response->config_bits1 & SMP_RG_PP_SUPPORTED));
34406e79492SKenneth D. Merry sbuf_printf(sb, "Physical Presence Asserted: %s\n",
34506e79492SKenneth D. Merry smp_yesno(response->config_bits1 & SMP_RG_PP_ASSERTED));
34606e79492SKenneth D. Merry sbuf_printf(sb, "Zoning Supported: %s\n",
34706e79492SKenneth D. Merry smp_yesno(response->config_bits1 &
34806e79492SKenneth D. Merry SMP_RG_ZONING_SUPPORTED));
34906e79492SKenneth D. Merry sbuf_printf(sb, "Zoning Enabled: %s\n",
35006e79492SKenneth D. Merry smp_yesno(response->config_bits1 & SMP_RG_ZONING_ENABLED));
35106e79492SKenneth D. Merry
35206e79492SKenneth D. Merry sbuf_printf(sb, "Saving: %s\n",
35306e79492SKenneth D. Merry smp_yesno(response->config_bits2 & SMP_RG_SAVING));
35406e79492SKenneth D. Merry sbuf_printf(sb, "Saving Zone Manager Password Supported: %s\n",
35506e79492SKenneth D. Merry smp_yesno(response->config_bits2 &
35606e79492SKenneth D. Merry SMP_RG_SAVING_ZM_PWD_SUP));
35706e79492SKenneth D. Merry sbuf_printf(sb, "Saving Zone Phy Information Supported: %s\n",
35806e79492SKenneth D. Merry smp_yesno(response->config_bits2 &
35906e79492SKenneth D. Merry SMP_RG_SAVING_PHY_INFO_SUP));
36006e79492SKenneth D. Merry sbuf_printf(sb, "Saving Zone Permission Table Supported: %s\n",
36106e79492SKenneth D. Merry smp_yesno(response->config_bits2 &
36206e79492SKenneth D. Merry SMP_RG_SAVING_ZPERM_TAB_SUP));
36306e79492SKenneth D. Merry sbuf_printf(sb, "Saving Zoning Enabled Supported: %s\n",
36406e79492SKenneth D. Merry smp_yesno(response->config_bits2 &
36506e79492SKenneth D. Merry SMP_RG_SAVING_ZENABLED_SUP));
36606e79492SKenneth D. Merry
36706e79492SKenneth D. Merry sbuf_printf(sb, "Maximum Number of Routed SAS Addresses: %d\n",
36806e79492SKenneth D. Merry scsi_2btoul(response->max_num_routed_addrs));
36906e79492SKenneth D. Merry
37006e79492SKenneth D. Merry sbuf_printf(sb, "Active Zone Manager SAS Address: 0x%016jx\n",
37106e79492SKenneth D. Merry scsi_8btou64(response->active_zm_address));
37206e79492SKenneth D. Merry
37306e79492SKenneth D. Merry sbuf_printf(sb, "Zone Inactivity Time Limit: %d\n",
37406e79492SKenneth D. Merry scsi_2btoul(response->zone_lock_inact_time_limit));
37506e79492SKenneth D. Merry
37606e79492SKenneth D. Merry sbuf_printf(sb, "First Enclosure Connector Element Index: %d\n",
37706e79492SKenneth D. Merry response->first_encl_conn_el_index);
37806e79492SKenneth D. Merry
37906e79492SKenneth D. Merry sbuf_printf(sb, "Number of Enclosure Connector Element Indexes: %d\n",
38006e79492SKenneth D. Merry response->num_encl_conn_el_indexes);
38106e79492SKenneth D. Merry
38206e79492SKenneth D. Merry sbuf_printf(sb, "Reduced Functionality: %s\n",
38306e79492SKenneth D. Merry smp_yesno(response->reduced_functionality &
38406e79492SKenneth D. Merry SMP_RG_REDUCED_FUNCTIONALITY));
38506e79492SKenneth D. Merry
38606e79492SKenneth D. Merry sbuf_printf(sb, "Time to Reduced Functionality: %d\n",
38706e79492SKenneth D. Merry response->time_to_reduced_func);
38806e79492SKenneth D. Merry sbuf_printf(sb, "Initial Time to Reduced Functionality: %d\n",
38906e79492SKenneth D. Merry response->initial_time_to_reduced_func);
39006e79492SKenneth D. Merry sbuf_printf(sb, "Maximum Reduced Functionality Time: %d\n",
39106e79492SKenneth D. Merry response->max_reduced_func_time);
39206e79492SKenneth D. Merry
39306e79492SKenneth D. Merry sbuf_printf(sb, "Last Self-Configuration Status Descriptor Index: %d\n",
39406e79492SKenneth D. Merry scsi_2btoul(response->last_sc_stat_desc_index));
39506e79492SKenneth D. Merry
39606e79492SKenneth D. Merry sbuf_printf(sb, "Maximum Number of Storated Self-Configuration "
39706e79492SKenneth D. Merry "Status Descriptors: %d\n",
39806e79492SKenneth D. Merry scsi_2btoul(response->max_sc_stat_descs));
39906e79492SKenneth D. Merry
40006e79492SKenneth D. Merry sbuf_printf(sb, "Last Phy Event List Descriptor Index: %d\n",
40106e79492SKenneth D. Merry scsi_2btoul(response->last_phy_evl_desc_index));
40206e79492SKenneth D. Merry
40306e79492SKenneth D. Merry sbuf_printf(sb, "Maximum Number of Stored Phy Event List "
40406e79492SKenneth D. Merry "Descriptors: %d\n",
40506e79492SKenneth D. Merry scsi_2btoul(response->max_stored_pel_descs));
40606e79492SKenneth D. Merry
40706e79492SKenneth D. Merry sbuf_printf(sb, "STP Reject to Open Limit: %d\n",
40806e79492SKenneth D. Merry scsi_2btoul(response->stp_reject_to_open_limit));
40906e79492SKenneth D. Merry }
41006e79492SKenneth D. Merry
41106e79492SKenneth D. Merry /*
41206e79492SKenneth D. Merry * Decode the SMP REPORT MANUFACTURER INFORMATION response. The format is
41306e79492SKenneth D. Merry * current as of SPL Revision 7, but the parsing should be backward
41406e79492SKenneth D. Merry * compatible for older versions of the spec.
41506e79492SKenneth D. Merry */
41606e79492SKenneth D. Merry void
smp_report_manuf_info_sbuf(struct smp_report_manuf_info_response * response,int response_len,struct sbuf * sb)41706e79492SKenneth D. Merry smp_report_manuf_info_sbuf(struct smp_report_manuf_info_response *response,
41806e79492SKenneth D. Merry int response_len, struct sbuf *sb)
41906e79492SKenneth D. Merry {
42006e79492SKenneth D. Merry char vendor[16], product[48], revision[16];
42106e79492SKenneth D. Merry char comp_vendor[16];
42206e79492SKenneth D. Merry
423*519b24f0SAlexander Motin sbuf_cat(sb, "Report Manufacturer Information\n");
42406e79492SKenneth D. Merry sbuf_printf(sb, "Expander Change count: %d\n",
42506e79492SKenneth D. Merry scsi_2btoul(response->expander_change_count));
42606e79492SKenneth D. Merry sbuf_printf(sb, "SAS 1.1 Format: %s\n",
42706e79492SKenneth D. Merry smp_yesno(response->sas_11_format & SMP_RMI_SAS11_FORMAT));
42806e79492SKenneth D. Merry cam_strvis(vendor, response->vendor, sizeof(response->vendor),
42906e79492SKenneth D. Merry sizeof(vendor));
43006e79492SKenneth D. Merry cam_strvis(product, response->product, sizeof(response->product),
43106e79492SKenneth D. Merry sizeof(product));
43206e79492SKenneth D. Merry cam_strvis(revision, response->revision, sizeof(response->revision),
43306e79492SKenneth D. Merry sizeof(revision));
43406e79492SKenneth D. Merry sbuf_printf(sb, "<%s %s %s>\n", vendor, product, revision);
43506e79492SKenneth D. Merry
43606e79492SKenneth D. Merry if ((response->sas_11_format & SMP_RMI_SAS11_FORMAT) == 0) {
43706e79492SKenneth D. Merry uint8_t *curbyte;
43806e79492SKenneth D. Merry int line_start, line_cursor;
43906e79492SKenneth D. Merry
440*519b24f0SAlexander Motin sbuf_cat(sb, "Vendor Specific Data:\n");
44106e79492SKenneth D. Merry
44206e79492SKenneth D. Merry /*
44306e79492SKenneth D. Merry * Print out the bytes roughly in the style of hd(1), but
44406e79492SKenneth D. Merry * without the extra ASCII decoding. Hexadecimal line
44506e79492SKenneth D. Merry * numbers on the left, and 16 bytes per line, with an
44606e79492SKenneth D. Merry * extra space after the first 8 bytes.
44706e79492SKenneth D. Merry *
44806e79492SKenneth D. Merry * It would be nice if this sort of thing were available
44906e79492SKenneth D. Merry * in a library routine.
45006e79492SKenneth D. Merry */
45106e79492SKenneth D. Merry for (curbyte = (uint8_t *)&response->comp_vendor, line_start= 1,
45206e79492SKenneth D. Merry line_cursor = 0; curbyte < (uint8_t *)&response->crc;
45306e79492SKenneth D. Merry curbyte++, line_cursor++) {
45406e79492SKenneth D. Merry if (line_start != 0) {
45506e79492SKenneth D. Merry sbuf_printf(sb, "%08lx ",
45606e79492SKenneth D. Merry (unsigned long)(curbyte -
45706e79492SKenneth D. Merry (uint8_t *)response));
45806e79492SKenneth D. Merry line_start = 0;
45906e79492SKenneth D. Merry line_cursor = 0;
46006e79492SKenneth D. Merry }
46106e79492SKenneth D. Merry sbuf_printf(sb, "%02x", *curbyte);
46206e79492SKenneth D. Merry
46306e79492SKenneth D. Merry if (line_cursor == 15) {
464*519b24f0SAlexander Motin sbuf_putc(sb, '\n');
46506e79492SKenneth D. Merry line_start = 1;
46606e79492SKenneth D. Merry } else
46706e79492SKenneth D. Merry sbuf_printf(sb, " %s", (line_cursor == 7) ?
46806e79492SKenneth D. Merry " " : "");
46906e79492SKenneth D. Merry }
47006e79492SKenneth D. Merry if (line_cursor != 16)
471*519b24f0SAlexander Motin sbuf_putc(sb, '\n');
47206e79492SKenneth D. Merry return;
47306e79492SKenneth D. Merry }
47406e79492SKenneth D. Merry
47506e79492SKenneth D. Merry cam_strvis(comp_vendor, response->comp_vendor,
47606e79492SKenneth D. Merry sizeof(response->comp_vendor), sizeof(comp_vendor));
47706e79492SKenneth D. Merry sbuf_printf(sb, "Component Vendor: %s\n", comp_vendor);
47806e79492SKenneth D. Merry sbuf_printf(sb, "Component ID: %#x\n", scsi_2btoul(response->comp_id));
47906e79492SKenneth D. Merry sbuf_printf(sb, "Component Revision: %#x\n", response->comp_revision);
48006e79492SKenneth D. Merry sbuf_printf(sb, "Vendor Specific: 0x%016jx\n",
48106e79492SKenneth D. Merry (uintmax_t)scsi_8btou64(response->vendor_specific));
48206e79492SKenneth D. Merry }
48306e79492SKenneth D. Merry
48406e79492SKenneth D. Merry /*
48506e79492SKenneth D. Merry * Compose a SMP REPORT GENERAL request and put it into a CCB. This is
48606e79492SKenneth D. Merry * current as of SPL Revision 7.
48706e79492SKenneth D. Merry */
48806e79492SKenneth D. Merry void
smp_report_general(struct ccb_smpio * smpio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),struct smp_report_general_request * request,int request_len,uint8_t * response,int response_len,int long_response,uint32_t timeout)48906e79492SKenneth D. Merry smp_report_general(struct ccb_smpio *smpio, uint32_t retries,
49006e79492SKenneth D. Merry void (*cbfcnp)(struct cam_periph *, union ccb *),
49106e79492SKenneth D. Merry struct smp_report_general_request *request, int request_len,
49206e79492SKenneth D. Merry uint8_t *response, int response_len, int long_response,
49306e79492SKenneth D. Merry uint32_t timeout)
49406e79492SKenneth D. Merry {
49506e79492SKenneth D. Merry cam_fill_smpio(smpio,
49606e79492SKenneth D. Merry retries,
49706e79492SKenneth D. Merry cbfcnp,
49806e79492SKenneth D. Merry /*flags*/CAM_DIR_BOTH,
49906e79492SKenneth D. Merry (uint8_t *)request,
50006e79492SKenneth D. Merry request_len - SMP_CRC_LEN,
50106e79492SKenneth D. Merry response,
50206e79492SKenneth D. Merry response_len,
50306e79492SKenneth D. Merry timeout);
50406e79492SKenneth D. Merry
50506e79492SKenneth D. Merry bzero(request, sizeof(*request));
50606e79492SKenneth D. Merry
50706e79492SKenneth D. Merry request->frame_type = SMP_FRAME_TYPE_REQUEST;
50806e79492SKenneth D. Merry request->function = SMP_FUNC_REPORT_GENERAL;
50906e79492SKenneth D. Merry request->response_len = long_response ? SMP_RG_RESPONSE_LEN : 0;
51006e79492SKenneth D. Merry request->request_len = 0;
51106e79492SKenneth D. Merry }
51206e79492SKenneth D. Merry
51306e79492SKenneth D. Merry /*
51406e79492SKenneth D. Merry * Compose a SMP DISCOVER request and put it into a CCB. This is current
51506e79492SKenneth D. Merry * as of SPL Revision 7.
51606e79492SKenneth D. Merry */
51706e79492SKenneth D. Merry void
smp_discover(struct ccb_smpio * smpio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),struct smp_discover_request * request,int request_len,uint8_t * response,int response_len,int long_response,int ignore_zone_group,int phy,uint32_t timeout)51806e79492SKenneth D. Merry smp_discover(struct ccb_smpio *smpio, uint32_t retries,
51906e79492SKenneth D. Merry void (*cbfcnp)(struct cam_periph *, union ccb *),
52006e79492SKenneth D. Merry struct smp_discover_request *request, int request_len,
52106e79492SKenneth D. Merry uint8_t *response, int response_len, int long_response,
52206e79492SKenneth D. Merry int ignore_zone_group, int phy, uint32_t timeout)
52306e79492SKenneth D. Merry {
52406e79492SKenneth D. Merry cam_fill_smpio(smpio,
52506e79492SKenneth D. Merry retries,
52606e79492SKenneth D. Merry cbfcnp,
52706e79492SKenneth D. Merry /*flags*/CAM_DIR_BOTH,
52806e79492SKenneth D. Merry (uint8_t *)request,
52906e79492SKenneth D. Merry request_len - SMP_CRC_LEN,
53006e79492SKenneth D. Merry response,
53106e79492SKenneth D. Merry response_len,
53206e79492SKenneth D. Merry timeout);
53306e79492SKenneth D. Merry
53406e79492SKenneth D. Merry bzero(request, sizeof(*request));
53506e79492SKenneth D. Merry request->frame_type = SMP_FRAME_TYPE_REQUEST;
53606e79492SKenneth D. Merry request->function = SMP_FUNC_DISCOVER;
53706e79492SKenneth D. Merry request->response_len = long_response ? SMP_DIS_RESPONSE_LEN : 0;
53806e79492SKenneth D. Merry request->request_len = long_response ? SMP_DIS_REQUEST_LEN : 0;
53906e79492SKenneth D. Merry if (ignore_zone_group != 0)
54006e79492SKenneth D. Merry request->ignore_zone_group |= SMP_DIS_IGNORE_ZONE_GROUP;
54106e79492SKenneth D. Merry request->phy = phy;
54206e79492SKenneth D. Merry }
54306e79492SKenneth D. Merry
54406e79492SKenneth D. Merry /*
54506e79492SKenneth D. Merry * Compose a SMP REPORT MANUFACTURER INFORMATION request and put it into a
54606e79492SKenneth D. Merry * CCB. This is current as of SPL Revision 7.
54706e79492SKenneth D. Merry */
54806e79492SKenneth D. Merry void
smp_report_manuf_info(struct ccb_smpio * smpio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),struct smp_report_manuf_info_request * request,int request_len,uint8_t * response,int response_len,int long_response,uint32_t timeout)54906e79492SKenneth D. Merry smp_report_manuf_info(struct ccb_smpio *smpio, uint32_t retries,
55006e79492SKenneth D. Merry void (*cbfcnp)(struct cam_periph *, union ccb *),
55106e79492SKenneth D. Merry struct smp_report_manuf_info_request *request,
55206e79492SKenneth D. Merry int request_len, uint8_t *response, int response_len,
55306e79492SKenneth D. Merry int long_response, uint32_t timeout)
55406e79492SKenneth D. Merry {
55506e79492SKenneth D. Merry cam_fill_smpio(smpio,
55606e79492SKenneth D. Merry retries,
55706e79492SKenneth D. Merry cbfcnp,
55806e79492SKenneth D. Merry /*flags*/CAM_DIR_BOTH,
55906e79492SKenneth D. Merry (uint8_t *)request,
56006e79492SKenneth D. Merry request_len - SMP_CRC_LEN,
56106e79492SKenneth D. Merry response,
56206e79492SKenneth D. Merry response_len,
56306e79492SKenneth D. Merry timeout);
56406e79492SKenneth D. Merry
56506e79492SKenneth D. Merry bzero(request, sizeof(*request));
56606e79492SKenneth D. Merry
56706e79492SKenneth D. Merry request->frame_type = SMP_FRAME_TYPE_REQUEST;
56806e79492SKenneth D. Merry request->function = SMP_FUNC_REPORT_MANUF_INFO;
56906e79492SKenneth D. Merry request->response_len = long_response ? SMP_RMI_RESPONSE_LEN : 0;
57006e79492SKenneth D. Merry request->request_len = long_response ? SMP_RMI_REQUEST_LEN : 0;
57106e79492SKenneth D. Merry }
57206e79492SKenneth D. Merry
57306e79492SKenneth D. Merry /*
57406e79492SKenneth D. Merry * Compose a SMP PHY CONTROL request and put it into a CCB. This is
57506e79492SKenneth D. Merry * current as of SPL Revision 7.
57606e79492SKenneth D. Merry */
57706e79492SKenneth D. Merry void
smp_phy_control(struct ccb_smpio * smpio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),struct smp_phy_control_request * request,int request_len,uint8_t * response,int response_len,int long_response,uint32_t expected_exp_change_count,int phy,int phy_op,int update_pp_timeout_val,uint64_t attached_device_name,int prog_min_prl,int prog_max_prl,int slumber_partial,int pp_timeout_value,uint32_t timeout)57806e79492SKenneth D. Merry smp_phy_control(struct ccb_smpio *smpio, uint32_t retries,
57906e79492SKenneth D. Merry void (*cbfcnp)(struct cam_periph *, union ccb *),
58006e79492SKenneth D. Merry struct smp_phy_control_request *request, int request_len,
58106e79492SKenneth D. Merry uint8_t *response, int response_len, int long_response,
58206e79492SKenneth D. Merry uint32_t expected_exp_change_count, int phy, int phy_op,
58306e79492SKenneth D. Merry int update_pp_timeout_val, uint64_t attached_device_name,
58406e79492SKenneth D. Merry int prog_min_prl, int prog_max_prl, int slumber_partial,
58506e79492SKenneth D. Merry int pp_timeout_value, uint32_t timeout)
58606e79492SKenneth D. Merry {
58706e79492SKenneth D. Merry cam_fill_smpio(smpio,
58806e79492SKenneth D. Merry retries,
58906e79492SKenneth D. Merry cbfcnp,
59006e79492SKenneth D. Merry /*flags*/CAM_DIR_BOTH,
59106e79492SKenneth D. Merry (uint8_t *)request,
59206e79492SKenneth D. Merry request_len - SMP_CRC_LEN,
59306e79492SKenneth D. Merry response,
59406e79492SKenneth D. Merry response_len,
59506e79492SKenneth D. Merry timeout);
59606e79492SKenneth D. Merry
59706e79492SKenneth D. Merry bzero(request, sizeof(*request));
59806e79492SKenneth D. Merry
59906e79492SKenneth D. Merry request->frame_type = SMP_FRAME_TYPE_REQUEST;
60006e79492SKenneth D. Merry request->function = SMP_FUNC_PHY_CONTROL;
60106e79492SKenneth D. Merry request->response_len = long_response ? SMP_PC_RESPONSE_LEN : 0;
60206e79492SKenneth D. Merry request->request_len = long_response ? SMP_PC_REQUEST_LEN : 0;
60306e79492SKenneth D. Merry scsi_ulto2b(expected_exp_change_count, request->expected_exp_chg_cnt);
60406e79492SKenneth D. Merry request->phy = phy;
60506e79492SKenneth D. Merry request->phy_operation = phy_op;
60606e79492SKenneth D. Merry
60706e79492SKenneth D. Merry if (update_pp_timeout_val != 0)
60806e79492SKenneth D. Merry request->update_pp_timeout |= SMP_PC_UPDATE_PP_TIMEOUT;
60906e79492SKenneth D. Merry
61006e79492SKenneth D. Merry scsi_u64to8b(attached_device_name, request->attached_device_name);
61106e79492SKenneth D. Merry request->prog_min_phys_link_rate = (prog_min_prl <<
61206e79492SKenneth D. Merry SMP_PC_PROG_MIN_PL_RATE_SHIFT) & SMP_PC_PROG_MIN_PL_RATE_MASK;
61306e79492SKenneth D. Merry request->prog_max_phys_link_rate = (prog_max_prl <<
61406e79492SKenneth D. Merry SMP_PC_PROG_MAX_PL_RATE_SHIFT) & SMP_PC_PROG_MAX_PL_RATE_MASK;
61506e79492SKenneth D. Merry request->config_bits0 = slumber_partial;
61606e79492SKenneth D. Merry request->pp_timeout_value = pp_timeout_value;
61706e79492SKenneth D. Merry }
618