0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <linux/highmem.h>
0031 #include <linux/export.h>
0032 #include <scsi/scsi.h>
0033 #include <scsi/scsi_cmnd.h>
0034
0035 #include "usb.h"
0036 #include "protocol.h"
0037 #include "debug.h"
0038 #include "scsiglue.h"
0039 #include "transport.h"
0040
0041
0042
0043
0044
0045 void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
0046 {
0047
0048
0049
0050
0051
0052
0053
0054 for (; srb->cmd_len < 12; srb->cmd_len++)
0055 srb->cmnd[srb->cmd_len] = 0;
0056
0057
0058 usb_stor_invoke_transport(srb, us);
0059 }
0060
0061 void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
0062 {
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 for (; srb->cmd_len < 12; srb->cmd_len++)
0073 srb->cmnd[srb->cmd_len] = 0;
0074
0075
0076 srb->cmd_len = 12;
0077
0078
0079
0080
0081 switch (srb->cmnd[0]) {
0082
0083
0084 case INQUIRY:
0085 srb->cmnd[4] = 36;
0086 break;
0087
0088
0089 case MODE_SENSE_10:
0090 srb->cmnd[7] = 0;
0091 srb->cmnd[8] = 8;
0092 break;
0093
0094
0095 case REQUEST_SENSE:
0096 srb->cmnd[4] = 18;
0097 break;
0098 }
0099
0100
0101 usb_stor_invoke_transport(srb, us);
0102 }
0103
0104 void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
0105 struct us_data *us)
0106 {
0107
0108 usb_stor_invoke_transport(srb, us);
0109 }
0110 EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command);
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
0122 unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
0123 unsigned int *offset, enum xfer_buf_dir dir)
0124 {
0125 unsigned int cnt = 0;
0126 struct scatterlist *sg = *sgptr;
0127 struct sg_mapping_iter miter;
0128 unsigned int nents = scsi_sg_count(srb);
0129
0130 if (sg)
0131 nents = sg_nents(sg);
0132 else
0133 sg = scsi_sglist(srb);
0134
0135 sg_miter_start(&miter, sg, nents, dir == FROM_XFER_BUF ?
0136 SG_MITER_FROM_SG: SG_MITER_TO_SG);
0137
0138 if (!sg_miter_skip(&miter, *offset))
0139 return cnt;
0140
0141 while (sg_miter_next(&miter) && cnt < buflen) {
0142 unsigned int len = min_t(unsigned int, miter.length,
0143 buflen - cnt);
0144
0145 if (dir == FROM_XFER_BUF)
0146 memcpy(buffer + cnt, miter.addr, len);
0147 else
0148 memcpy(miter.addr, buffer + cnt, len);
0149
0150 if (*offset + len < miter.piter.sg->length) {
0151 *offset += len;
0152 *sgptr = miter.piter.sg;
0153 } else {
0154 *offset = 0;
0155 *sgptr = sg_next(miter.piter.sg);
0156 }
0157 cnt += len;
0158 }
0159 sg_miter_stop(&miter);
0160
0161 return cnt;
0162 }
0163 EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf);
0164
0165
0166
0167
0168
0169 void usb_stor_set_xfer_buf(unsigned char *buffer,
0170 unsigned int buflen, struct scsi_cmnd *srb)
0171 {
0172 unsigned int offset = 0;
0173 struct scatterlist *sg = NULL;
0174
0175 buflen = min(buflen, scsi_bufflen(srb));
0176 buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
0177 TO_XFER_BUF);
0178 if (buflen < scsi_bufflen(srb))
0179 scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
0180 }
0181 EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf);