Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * SCSI functions used by both the initiator and the target code.
0004  */
0005 
0006 #include <linux/bug.h>
0007 #include <linux/kernel.h>
0008 #include <linux/string.h>
0009 #include <linux/errno.h>
0010 #include <linux/module.h>
0011 #include <asm/unaligned.h>
0012 #include <scsi/scsi_common.h>
0013 
0014 MODULE_LICENSE("GPL v2");
0015 
0016 /* Command group 3 is reserved and should never be used.  */
0017 const unsigned char scsi_command_size_tbl[8] = {
0018     6, 10, 10, 12, 16, 12, 10, 10
0019 };
0020 EXPORT_SYMBOL(scsi_command_size_tbl);
0021 
0022 /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI.
0023  * You may not alter any existing entry (although adding new ones is
0024  * encouraged once assigned by ANSI/INCITS T10).
0025  */
0026 static const char *const scsi_device_types[] = {
0027     "Direct-Access    ",
0028     "Sequential-Access",
0029     "Printer          ",
0030     "Processor        ",
0031     "WORM             ",
0032     "CD-ROM           ",
0033     "Scanner          ",
0034     "Optical Device   ",
0035     "Medium Changer   ",
0036     "Communications   ",
0037     "ASC IT8          ",
0038     "ASC IT8          ",
0039     "RAID             ",
0040     "Enclosure        ",
0041     "Direct-Access-RBC",
0042     "Optical card     ",
0043     "Bridge controller",
0044     "Object storage   ",
0045     "Automation/Drive ",
0046     "Security Manager ",
0047     "Direct-Access-ZBC",
0048 };
0049 
0050 /**
0051  * scsi_device_type - Return 17-char string indicating device type.
0052  * @type: type number to look up
0053  */
0054 const char *scsi_device_type(unsigned type)
0055 {
0056     if (type == 0x1e)
0057         return "Well-known LUN   ";
0058     if (type == 0x1f)
0059         return "No Device        ";
0060     if (type >= ARRAY_SIZE(scsi_device_types))
0061         return "Unknown          ";
0062     return scsi_device_types[type];
0063 }
0064 EXPORT_SYMBOL(scsi_device_type);
0065 
0066 /**
0067  * scsilun_to_int - convert a scsi_lun to an int
0068  * @scsilun:    struct scsi_lun to be converted.
0069  *
0070  * Description:
0071  *     Convert @scsilun from a struct scsi_lun to a four-byte host byte-ordered
0072  *     integer, and return the result. The caller must check for
0073  *     truncation before using this function.
0074  *
0075  * Notes:
0076  *     For a description of the LUN format, post SCSI-3 see the SCSI
0077  *     Architecture Model, for SCSI-3 see the SCSI Controller Commands.
0078  *
0079  *     Given a struct scsi_lun of: d2 04 0b 03 00 00 00 00, this function
0080  *     returns the integer: 0x0b03d204
0081  *
0082  *     This encoding will return a standard integer LUN for LUNs smaller
0083  *     than 256, which typically use a single level LUN structure with
0084  *     addressing method 0.
0085  */
0086 u64 scsilun_to_int(struct scsi_lun *scsilun)
0087 {
0088     int i;
0089     u64 lun;
0090 
0091     lun = 0;
0092     for (i = 0; i < sizeof(lun); i += 2)
0093         lun = lun | (((u64)scsilun->scsi_lun[i] << ((i + 1) * 8)) |
0094                  ((u64)scsilun->scsi_lun[i + 1] << (i * 8)));
0095     return lun;
0096 }
0097 EXPORT_SYMBOL(scsilun_to_int);
0098 
0099 /**
0100  * int_to_scsilun - reverts an int into a scsi_lun
0101  * @lun:        integer to be reverted
0102  * @scsilun:    struct scsi_lun to be set.
0103  *
0104  * Description:
0105  *     Reverts the functionality of the scsilun_to_int, which packed
0106  *     an 8-byte lun value into an int. This routine unpacks the int
0107  *     back into the lun value.
0108  *
0109  * Notes:
0110  *     Given an integer : 0x0b03d204, this function returns a
0111  *     struct scsi_lun of: d2 04 0b 03 00 00 00 00
0112  *
0113  */
0114 void int_to_scsilun(u64 lun, struct scsi_lun *scsilun)
0115 {
0116     int i;
0117 
0118     memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
0119 
0120     for (i = 0; i < sizeof(lun); i += 2) {
0121         scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
0122         scsilun->scsi_lun[i+1] = lun & 0xFF;
0123         lun = lun >> 16;
0124     }
0125 }
0126 EXPORT_SYMBOL(int_to_scsilun);
0127 
0128 /**
0129  * scsi_normalize_sense - normalize main elements from either fixed or
0130  *          descriptor sense data format into a common format.
0131  *
0132  * @sense_buffer:   byte array containing sense data returned by device
0133  * @sb_len:     number of valid bytes in sense_buffer
0134  * @sshdr:      pointer to instance of structure that common
0135  *          elements are written to.
0136  *
0137  * Notes:
0138  *  The "main elements" from sense data are: response_code, sense_key,
0139  *  asc, ascq and additional_length (only for descriptor format).
0140  *
0141  *  Typically this function can be called after a device has
0142  *  responded to a SCSI command with the CHECK_CONDITION status.
0143  *
0144  * Return value:
0145  *  true if valid sense data information found, else false;
0146  */
0147 bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
0148               struct scsi_sense_hdr *sshdr)
0149 {
0150     memset(sshdr, 0, sizeof(struct scsi_sense_hdr));
0151 
0152     if (!sense_buffer || !sb_len)
0153         return false;
0154 
0155     sshdr->response_code = (sense_buffer[0] & 0x7f);
0156 
0157     if (!scsi_sense_valid(sshdr))
0158         return false;
0159 
0160     if (sshdr->response_code >= 0x72) {
0161         /*
0162          * descriptor format
0163          */
0164         if (sb_len > 1)
0165             sshdr->sense_key = (sense_buffer[1] & 0xf);
0166         if (sb_len > 2)
0167             sshdr->asc = sense_buffer[2];
0168         if (sb_len > 3)
0169             sshdr->ascq = sense_buffer[3];
0170         if (sb_len > 7)
0171             sshdr->additional_length = sense_buffer[7];
0172     } else {
0173         /*
0174          * fixed format
0175          */
0176         if (sb_len > 2)
0177             sshdr->sense_key = (sense_buffer[2] & 0xf);
0178         if (sb_len > 7) {
0179             sb_len = (sb_len < (sense_buffer[7] + 8)) ?
0180                      sb_len : (sense_buffer[7] + 8);
0181             if (sb_len > 12)
0182                 sshdr->asc = sense_buffer[12];
0183             if (sb_len > 13)
0184                 sshdr->ascq = sense_buffer[13];
0185         }
0186     }
0187 
0188     return true;
0189 }
0190 EXPORT_SYMBOL(scsi_normalize_sense);
0191 
0192 /**
0193  * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format.
0194  * @sense_buffer:   byte array of descriptor format sense data
0195  * @sb_len:     number of valid bytes in sense_buffer
0196  * @desc_type:      value of descriptor type to find
0197  *          (e.g. 0 -> information)
0198  *
0199  * Notes:
0200  *  only valid when sense data is in descriptor format
0201  *
0202  * Return value:
0203  *  pointer to start of (first) descriptor if found else NULL
0204  */
0205 const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
0206                 int desc_type)
0207 {
0208     int add_sen_len, add_len, desc_len, k;
0209     const u8 * descp;
0210 
0211     if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7])))
0212         return NULL;
0213     if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73))
0214         return NULL;
0215     add_sen_len = (add_sen_len < (sb_len - 8)) ?
0216             add_sen_len : (sb_len - 8);
0217     descp = &sense_buffer[8];
0218     for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
0219         descp += desc_len;
0220         add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
0221         desc_len = add_len + 2;
0222         if (descp[0] == desc_type)
0223             return descp;
0224         if (add_len < 0) // short descriptor ??
0225             break;
0226     }
0227     return NULL;
0228 }
0229 EXPORT_SYMBOL(scsi_sense_desc_find);
0230 
0231 /**
0232  * scsi_build_sense_buffer - build sense data in a buffer
0233  * @desc:   Sense format (non-zero == descriptor format,
0234  *              0 == fixed format)
0235  * @buf:    Where to build sense data
0236  * @key:    Sense key
0237  * @asc:    Additional sense code
0238  * @ascq:   Additional sense code qualifier
0239  *
0240  **/
0241 void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
0242 {
0243     if (desc) {
0244         buf[0] = 0x72;  /* descriptor, current */
0245         buf[1] = key;
0246         buf[2] = asc;
0247         buf[3] = ascq;
0248         buf[7] = 0;
0249     } else {
0250         buf[0] = 0x70;  /* fixed, current */
0251         buf[2] = key;
0252         buf[7] = 0xa;
0253         buf[12] = asc;
0254         buf[13] = ascq;
0255     }
0256 }
0257 EXPORT_SYMBOL(scsi_build_sense_buffer);
0258 
0259 /**
0260  * scsi_set_sense_information - set the information field in a
0261  *      formatted sense data buffer
0262  * @buf:    Where to build sense data
0263  * @buf_len:    buffer length
0264  * @info:   64-bit information value to be set
0265  *
0266  * Return value:
0267  *  0 on success or -EINVAL for invalid sense buffer length
0268  **/
0269 int scsi_set_sense_information(u8 *buf, int buf_len, u64 info)
0270 {
0271     if ((buf[0] & 0x7f) == 0x72) {
0272         u8 *ucp, len;
0273 
0274         len = buf[7];
0275         ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0);
0276         if (!ucp) {
0277             buf[7] = len + 0xc;
0278             ucp = buf + 8 + len;
0279         }
0280 
0281         if (buf_len < len + 0xc)
0282             /* Not enough room for info */
0283             return -EINVAL;
0284 
0285         ucp[0] = 0;
0286         ucp[1] = 0xa;
0287         ucp[2] = 0x80; /* Valid bit */
0288         ucp[3] = 0;
0289         put_unaligned_be64(info, &ucp[4]);
0290     } else if ((buf[0] & 0x7f) == 0x70) {
0291         /*
0292          * Only set the 'VALID' bit if we can represent the value
0293          * correctly; otherwise just fill out the lower bytes and
0294          * clear the 'VALID' flag.
0295          */
0296         if (info <= 0xffffffffUL)
0297             buf[0] |= 0x80;
0298         else
0299             buf[0] &= 0x7f;
0300         put_unaligned_be32((u32)info, &buf[3]);
0301     }
0302 
0303     return 0;
0304 }
0305 EXPORT_SYMBOL(scsi_set_sense_information);
0306 
0307 /**
0308  * scsi_set_sense_field_pointer - set the field pointer sense key
0309  *      specific information in a formatted sense data buffer
0310  * @buf:    Where to build sense data
0311  * @buf_len:    buffer length
0312  * @fp:     field pointer to be set
0313  * @bp:     bit pointer to be set
0314  * @cd:     command/data bit
0315  *
0316  * Return value:
0317  *  0 on success or -EINVAL for invalid sense buffer length
0318  */
0319 int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd)
0320 {
0321     u8 *ucp, len;
0322 
0323     if ((buf[0] & 0x7f) == 0x72) {
0324         len = buf[7];
0325         ucp = (char *)scsi_sense_desc_find(buf, len + 8, 2);
0326         if (!ucp) {
0327             buf[7] = len + 8;
0328             ucp = buf + 8 + len;
0329         }
0330 
0331         if (buf_len < len + 8)
0332             /* Not enough room for info */
0333             return -EINVAL;
0334 
0335         ucp[0] = 2;
0336         ucp[1] = 6;
0337         ucp[4] = 0x80; /* Valid bit */
0338         if (cd)
0339             ucp[4] |= 0x40;
0340         if (bp < 0x8)
0341             ucp[4] |= 0x8 | bp;
0342         put_unaligned_be16(fp, &ucp[5]);
0343     } else if ((buf[0] & 0x7f) == 0x70) {
0344         len = buf[7];
0345         if (len < 18)
0346             buf[7] = 18;
0347 
0348         buf[15] = 0x80;
0349         if (cd)
0350             buf[15] |= 0x40;
0351         if (bp < 0x8)
0352             buf[15] |= 0x8 | bp;
0353         put_unaligned_be16(fp, &buf[16]);
0354     }
0355 
0356     return 0;
0357 }
0358 EXPORT_SYMBOL(scsi_set_sense_field_pointer);