18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SCSI functions used by both the initiator and the target code. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/bug.h> 78c2ecf20Sopenharmony_ci#include <linux/kernel.h> 88c2ecf20Sopenharmony_ci#include <linux/string.h> 98c2ecf20Sopenharmony_ci#include <linux/errno.h> 108c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 118c2ecf20Sopenharmony_ci#include <scsi/scsi_common.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. 148c2ecf20Sopenharmony_ci * You may not alter any existing entry (although adding new ones is 158c2ecf20Sopenharmony_ci * encouraged once assigned by ANSI/INCITS T10). 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_cistatic const char *const scsi_device_types[] = { 188c2ecf20Sopenharmony_ci "Direct-Access ", 198c2ecf20Sopenharmony_ci "Sequential-Access", 208c2ecf20Sopenharmony_ci "Printer ", 218c2ecf20Sopenharmony_ci "Processor ", 228c2ecf20Sopenharmony_ci "WORM ", 238c2ecf20Sopenharmony_ci "CD-ROM ", 248c2ecf20Sopenharmony_ci "Scanner ", 258c2ecf20Sopenharmony_ci "Optical Device ", 268c2ecf20Sopenharmony_ci "Medium Changer ", 278c2ecf20Sopenharmony_ci "Communications ", 288c2ecf20Sopenharmony_ci "ASC IT8 ", 298c2ecf20Sopenharmony_ci "ASC IT8 ", 308c2ecf20Sopenharmony_ci "RAID ", 318c2ecf20Sopenharmony_ci "Enclosure ", 328c2ecf20Sopenharmony_ci "Direct-Access-RBC", 338c2ecf20Sopenharmony_ci "Optical card ", 348c2ecf20Sopenharmony_ci "Bridge controller", 358c2ecf20Sopenharmony_ci "Object storage ", 368c2ecf20Sopenharmony_ci "Automation/Drive ", 378c2ecf20Sopenharmony_ci "Security Manager ", 388c2ecf20Sopenharmony_ci "Direct-Access-ZBC", 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/** 428c2ecf20Sopenharmony_ci * scsi_device_type - Return 17-char string indicating device type. 438c2ecf20Sopenharmony_ci * @type: type number to look up 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ciconst char *scsi_device_type(unsigned type) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci if (type == 0x1e) 488c2ecf20Sopenharmony_ci return "Well-known LUN "; 498c2ecf20Sopenharmony_ci if (type == 0x1f) 508c2ecf20Sopenharmony_ci return "No Device "; 518c2ecf20Sopenharmony_ci if (type >= ARRAY_SIZE(scsi_device_types)) 528c2ecf20Sopenharmony_ci return "Unknown "; 538c2ecf20Sopenharmony_ci return scsi_device_types[type]; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(scsi_device_type); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/** 588c2ecf20Sopenharmony_ci * scsilun_to_int - convert a scsi_lun to an int 598c2ecf20Sopenharmony_ci * @scsilun: struct scsi_lun to be converted. 608c2ecf20Sopenharmony_ci * 618c2ecf20Sopenharmony_ci * Description: 628c2ecf20Sopenharmony_ci * Convert @scsilun from a struct scsi_lun to a four-byte host byte-ordered 638c2ecf20Sopenharmony_ci * integer, and return the result. The caller must check for 648c2ecf20Sopenharmony_ci * truncation before using this function. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * Notes: 678c2ecf20Sopenharmony_ci * For a description of the LUN format, post SCSI-3 see the SCSI 688c2ecf20Sopenharmony_ci * Architecture Model, for SCSI-3 see the SCSI Controller Commands. 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * Given a struct scsi_lun of: d2 04 0b 03 00 00 00 00, this function 718c2ecf20Sopenharmony_ci * returns the integer: 0x0b03d204 728c2ecf20Sopenharmony_ci * 738c2ecf20Sopenharmony_ci * This encoding will return a standard integer LUN for LUNs smaller 748c2ecf20Sopenharmony_ci * than 256, which typically use a single level LUN structure with 758c2ecf20Sopenharmony_ci * addressing method 0. 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ciu64 scsilun_to_int(struct scsi_lun *scsilun) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci int i; 808c2ecf20Sopenharmony_ci u64 lun; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci lun = 0; 838c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(lun); i += 2) 848c2ecf20Sopenharmony_ci lun = lun | (((u64)scsilun->scsi_lun[i] << ((i + 1) * 8)) | 858c2ecf20Sopenharmony_ci ((u64)scsilun->scsi_lun[i + 1] << (i * 8))); 868c2ecf20Sopenharmony_ci return lun; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(scsilun_to_int); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/** 918c2ecf20Sopenharmony_ci * int_to_scsilun - reverts an int into a scsi_lun 928c2ecf20Sopenharmony_ci * @lun: integer to be reverted 938c2ecf20Sopenharmony_ci * @scsilun: struct scsi_lun to be set. 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * Description: 968c2ecf20Sopenharmony_ci * Reverts the functionality of the scsilun_to_int, which packed 978c2ecf20Sopenharmony_ci * an 8-byte lun value into an int. This routine unpacks the int 988c2ecf20Sopenharmony_ci * back into the lun value. 998c2ecf20Sopenharmony_ci * 1008c2ecf20Sopenharmony_ci * Notes: 1018c2ecf20Sopenharmony_ci * Given an integer : 0x0b03d204, this function returns a 1028c2ecf20Sopenharmony_ci * struct scsi_lun of: d2 04 0b 03 00 00 00 00 1038c2ecf20Sopenharmony_ci * 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_civoid int_to_scsilun(u64 lun, struct scsi_lun *scsilun) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci int i; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(lun); i += 2) { 1128c2ecf20Sopenharmony_ci scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; 1138c2ecf20Sopenharmony_ci scsilun->scsi_lun[i+1] = lun & 0xFF; 1148c2ecf20Sopenharmony_ci lun = lun >> 16; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(int_to_scsilun); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/** 1208c2ecf20Sopenharmony_ci * scsi_normalize_sense - normalize main elements from either fixed or 1218c2ecf20Sopenharmony_ci * descriptor sense data format into a common format. 1228c2ecf20Sopenharmony_ci * 1238c2ecf20Sopenharmony_ci * @sense_buffer: byte array containing sense data returned by device 1248c2ecf20Sopenharmony_ci * @sb_len: number of valid bytes in sense_buffer 1258c2ecf20Sopenharmony_ci * @sshdr: pointer to instance of structure that common 1268c2ecf20Sopenharmony_ci * elements are written to. 1278c2ecf20Sopenharmony_ci * 1288c2ecf20Sopenharmony_ci * Notes: 1298c2ecf20Sopenharmony_ci * The "main elements" from sense data are: response_code, sense_key, 1308c2ecf20Sopenharmony_ci * asc, ascq and additional_length (only for descriptor format). 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * Typically this function can be called after a device has 1338c2ecf20Sopenharmony_ci * responded to a SCSI command with the CHECK_CONDITION status. 1348c2ecf20Sopenharmony_ci * 1358c2ecf20Sopenharmony_ci * Return value: 1368c2ecf20Sopenharmony_ci * true if valid sense data information found, else false; 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_cibool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, 1398c2ecf20Sopenharmony_ci struct scsi_sense_hdr *sshdr) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (!sense_buffer || !sb_len) 1448c2ecf20Sopenharmony_ci return false; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci sshdr->response_code = (sense_buffer[0] & 0x7f); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (!scsi_sense_valid(sshdr)) 1498c2ecf20Sopenharmony_ci return false; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (sshdr->response_code >= 0x72) { 1528c2ecf20Sopenharmony_ci /* 1538c2ecf20Sopenharmony_ci * descriptor format 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ci if (sb_len > 1) 1568c2ecf20Sopenharmony_ci sshdr->sense_key = (sense_buffer[1] & 0xf); 1578c2ecf20Sopenharmony_ci if (sb_len > 2) 1588c2ecf20Sopenharmony_ci sshdr->asc = sense_buffer[2]; 1598c2ecf20Sopenharmony_ci if (sb_len > 3) 1608c2ecf20Sopenharmony_ci sshdr->ascq = sense_buffer[3]; 1618c2ecf20Sopenharmony_ci if (sb_len > 7) 1628c2ecf20Sopenharmony_ci sshdr->additional_length = sense_buffer[7]; 1638c2ecf20Sopenharmony_ci } else { 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * fixed format 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci if (sb_len > 2) 1688c2ecf20Sopenharmony_ci sshdr->sense_key = (sense_buffer[2] & 0xf); 1698c2ecf20Sopenharmony_ci if (sb_len > 7) { 1708c2ecf20Sopenharmony_ci sb_len = (sb_len < (sense_buffer[7] + 8)) ? 1718c2ecf20Sopenharmony_ci sb_len : (sense_buffer[7] + 8); 1728c2ecf20Sopenharmony_ci if (sb_len > 12) 1738c2ecf20Sopenharmony_ci sshdr->asc = sense_buffer[12]; 1748c2ecf20Sopenharmony_ci if (sb_len > 13) 1758c2ecf20Sopenharmony_ci sshdr->ascq = sense_buffer[13]; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return true; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(scsi_normalize_sense); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/** 1848c2ecf20Sopenharmony_ci * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. 1858c2ecf20Sopenharmony_ci * @sense_buffer: byte array of descriptor format sense data 1868c2ecf20Sopenharmony_ci * @sb_len: number of valid bytes in sense_buffer 1878c2ecf20Sopenharmony_ci * @desc_type: value of descriptor type to find 1888c2ecf20Sopenharmony_ci * (e.g. 0 -> information) 1898c2ecf20Sopenharmony_ci * 1908c2ecf20Sopenharmony_ci * Notes: 1918c2ecf20Sopenharmony_ci * only valid when sense data is in descriptor format 1928c2ecf20Sopenharmony_ci * 1938c2ecf20Sopenharmony_ci * Return value: 1948c2ecf20Sopenharmony_ci * pointer to start of (first) descriptor if found else NULL 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_ciconst u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, 1978c2ecf20Sopenharmony_ci int desc_type) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci int add_sen_len, add_len, desc_len, k; 2008c2ecf20Sopenharmony_ci const u8 * descp; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7]))) 2038c2ecf20Sopenharmony_ci return NULL; 2048c2ecf20Sopenharmony_ci if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73)) 2058c2ecf20Sopenharmony_ci return NULL; 2068c2ecf20Sopenharmony_ci add_sen_len = (add_sen_len < (sb_len - 8)) ? 2078c2ecf20Sopenharmony_ci add_sen_len : (sb_len - 8); 2088c2ecf20Sopenharmony_ci descp = &sense_buffer[8]; 2098c2ecf20Sopenharmony_ci for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { 2108c2ecf20Sopenharmony_ci descp += desc_len; 2118c2ecf20Sopenharmony_ci add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; 2128c2ecf20Sopenharmony_ci desc_len = add_len + 2; 2138c2ecf20Sopenharmony_ci if (descp[0] == desc_type) 2148c2ecf20Sopenharmony_ci return descp; 2158c2ecf20Sopenharmony_ci if (add_len < 0) // short descriptor ?? 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci return NULL; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(scsi_sense_desc_find); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/** 2238c2ecf20Sopenharmony_ci * scsi_build_sense_buffer - build sense data in a buffer 2248c2ecf20Sopenharmony_ci * @desc: Sense format (non-zero == descriptor format, 2258c2ecf20Sopenharmony_ci * 0 == fixed format) 2268c2ecf20Sopenharmony_ci * @buf: Where to build sense data 2278c2ecf20Sopenharmony_ci * @key: Sense key 2288c2ecf20Sopenharmony_ci * @asc: Additional sense code 2298c2ecf20Sopenharmony_ci * @ascq: Additional sense code qualifier 2308c2ecf20Sopenharmony_ci * 2318c2ecf20Sopenharmony_ci **/ 2328c2ecf20Sopenharmony_civoid scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci if (desc) { 2358c2ecf20Sopenharmony_ci buf[0] = 0x72; /* descriptor, current */ 2368c2ecf20Sopenharmony_ci buf[1] = key; 2378c2ecf20Sopenharmony_ci buf[2] = asc; 2388c2ecf20Sopenharmony_ci buf[3] = ascq; 2398c2ecf20Sopenharmony_ci buf[7] = 0; 2408c2ecf20Sopenharmony_ci } else { 2418c2ecf20Sopenharmony_ci buf[0] = 0x70; /* fixed, current */ 2428c2ecf20Sopenharmony_ci buf[2] = key; 2438c2ecf20Sopenharmony_ci buf[7] = 0xa; 2448c2ecf20Sopenharmony_ci buf[12] = asc; 2458c2ecf20Sopenharmony_ci buf[13] = ascq; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(scsi_build_sense_buffer); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci/** 2518c2ecf20Sopenharmony_ci * scsi_set_sense_information - set the information field in a 2528c2ecf20Sopenharmony_ci * formatted sense data buffer 2538c2ecf20Sopenharmony_ci * @buf: Where to build sense data 2548c2ecf20Sopenharmony_ci * @buf_len: buffer length 2558c2ecf20Sopenharmony_ci * @info: 64-bit information value to be set 2568c2ecf20Sopenharmony_ci * 2578c2ecf20Sopenharmony_ci * Return value: 2588c2ecf20Sopenharmony_ci * 0 on success or -EINVAL for invalid sense buffer length 2598c2ecf20Sopenharmony_ci **/ 2608c2ecf20Sopenharmony_ciint scsi_set_sense_information(u8 *buf, int buf_len, u64 info) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci if ((buf[0] & 0x7f) == 0x72) { 2638c2ecf20Sopenharmony_ci u8 *ucp, len; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci len = buf[7]; 2668c2ecf20Sopenharmony_ci ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); 2678c2ecf20Sopenharmony_ci if (!ucp) { 2688c2ecf20Sopenharmony_ci buf[7] = len + 0xc; 2698c2ecf20Sopenharmony_ci ucp = buf + 8 + len; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (buf_len < len + 0xc) 2738c2ecf20Sopenharmony_ci /* Not enough room for info */ 2748c2ecf20Sopenharmony_ci return -EINVAL; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci ucp[0] = 0; 2778c2ecf20Sopenharmony_ci ucp[1] = 0xa; 2788c2ecf20Sopenharmony_ci ucp[2] = 0x80; /* Valid bit */ 2798c2ecf20Sopenharmony_ci ucp[3] = 0; 2808c2ecf20Sopenharmony_ci put_unaligned_be64(info, &ucp[4]); 2818c2ecf20Sopenharmony_ci } else if ((buf[0] & 0x7f) == 0x70) { 2828c2ecf20Sopenharmony_ci /* 2838c2ecf20Sopenharmony_ci * Only set the 'VALID' bit if we can represent the value 2848c2ecf20Sopenharmony_ci * correctly; otherwise just fill out the lower bytes and 2858c2ecf20Sopenharmony_ci * clear the 'VALID' flag. 2868c2ecf20Sopenharmony_ci */ 2878c2ecf20Sopenharmony_ci if (info <= 0xffffffffUL) 2888c2ecf20Sopenharmony_ci buf[0] |= 0x80; 2898c2ecf20Sopenharmony_ci else 2908c2ecf20Sopenharmony_ci buf[0] &= 0x7f; 2918c2ecf20Sopenharmony_ci put_unaligned_be32((u32)info, &buf[3]); 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ciEXPORT_SYMBOL(scsi_set_sense_information); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci/** 2998c2ecf20Sopenharmony_ci * scsi_set_sense_field_pointer - set the field pointer sense key 3008c2ecf20Sopenharmony_ci * specific information in a formatted sense data buffer 3018c2ecf20Sopenharmony_ci * @buf: Where to build sense data 3028c2ecf20Sopenharmony_ci * @buf_len: buffer length 3038c2ecf20Sopenharmony_ci * @fp: field pointer to be set 3048c2ecf20Sopenharmony_ci * @bp: bit pointer to be set 3058c2ecf20Sopenharmony_ci * @cd: command/data bit 3068c2ecf20Sopenharmony_ci * 3078c2ecf20Sopenharmony_ci * Return value: 3088c2ecf20Sopenharmony_ci * 0 on success or -EINVAL for invalid sense buffer length 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_ciint scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci u8 *ucp, len; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if ((buf[0] & 0x7f) == 0x72) { 3158c2ecf20Sopenharmony_ci len = buf[7]; 3168c2ecf20Sopenharmony_ci ucp = (char *)scsi_sense_desc_find(buf, len + 8, 2); 3178c2ecf20Sopenharmony_ci if (!ucp) { 3188c2ecf20Sopenharmony_ci buf[7] = len + 8; 3198c2ecf20Sopenharmony_ci ucp = buf + 8 + len; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if (buf_len < len + 8) 3238c2ecf20Sopenharmony_ci /* Not enough room for info */ 3248c2ecf20Sopenharmony_ci return -EINVAL; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci ucp[0] = 2; 3278c2ecf20Sopenharmony_ci ucp[1] = 6; 3288c2ecf20Sopenharmony_ci ucp[4] = 0x80; /* Valid bit */ 3298c2ecf20Sopenharmony_ci if (cd) 3308c2ecf20Sopenharmony_ci ucp[4] |= 0x40; 3318c2ecf20Sopenharmony_ci if (bp < 0x8) 3328c2ecf20Sopenharmony_ci ucp[4] |= 0x8 | bp; 3338c2ecf20Sopenharmony_ci put_unaligned_be16(fp, &ucp[5]); 3348c2ecf20Sopenharmony_ci } else if ((buf[0] & 0x7f) == 0x70) { 3358c2ecf20Sopenharmony_ci len = buf[7]; 3368c2ecf20Sopenharmony_ci if (len < 18) 3378c2ecf20Sopenharmony_ci buf[7] = 18; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci buf[15] = 0x80; 3408c2ecf20Sopenharmony_ci if (cd) 3418c2ecf20Sopenharmony_ci buf[15] |= 0x40; 3428c2ecf20Sopenharmony_ci if (bp < 0x8) 3438c2ecf20Sopenharmony_ci buf[15] |= 0x8 | bp; 3448c2ecf20Sopenharmony_ci put_unaligned_be16(fp, &buf[16]); 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci return 0; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(scsi_set_sense_field_pointer); 350