forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.2 KiB
181 lines
5.2 KiB
// SPDX-License-Identifier: GPL-2.0+ |
|
/* |
|
* Driver for USB Mass Storage compliant devices |
|
* |
|
* Current development and maintenance by: |
|
* (c) 1999-2002 Matthew Dharm ([email protected]) |
|
* |
|
* Developed with the assistance of: |
|
* (c) 2000 David L. Brown, Jr. ([email protected]) |
|
* (c) 2002 Alan Stern ([email protected]) |
|
* |
|
* Initial work by: |
|
* (c) 1999 Michael Gee ([email protected]) |
|
* |
|
* This driver is based on the 'USB Mass Storage Class' document. This |
|
* describes in detail the protocol used to communicate with such |
|
* devices. Clearly, the designers had SCSI and ATAPI commands in |
|
* mind when they created this document. The commands are all very |
|
* similar to commands in the SCSI-II and ATAPI specifications. |
|
* |
|
* It is important to note that in a number of cases this class |
|
* exhibits class-specific exemptions from the USB specification. |
|
* Notably the usage of NAK, STALL and ACK differs from the norm, in |
|
* that they are used to communicate wait, failed and OK on commands. |
|
* |
|
* Also, for certain devices, the interrupt endpoint is used to convey |
|
* status of a command. |
|
*/ |
|
|
|
#include <linux/highmem.h> |
|
#include <linux/export.h> |
|
#include <scsi/scsi.h> |
|
#include <scsi/scsi_cmnd.h> |
|
|
|
#include "usb.h" |
|
#include "protocol.h" |
|
#include "debug.h" |
|
#include "scsiglue.h" |
|
#include "transport.h" |
|
|
|
/*********************************************************************** |
|
* Protocol routines |
|
***********************************************************************/ |
|
|
|
void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) |
|
{ |
|
/* |
|
* Pad the SCSI command with zeros out to 12 bytes. If the |
|
* command already is 12 bytes or longer, leave it alone. |
|
* |
|
* NOTE: This only works because a scsi_cmnd struct field contains |
|
* a unsigned char cmnd[16], so we know we have storage available |
|
*/ |
|
for (; srb->cmd_len < 12; srb->cmd_len++) |
|
srb->cmnd[srb->cmd_len] = 0; |
|
|
|
/* send the command to the transport layer */ |
|
usb_stor_invoke_transport(srb, us); |
|
} |
|
|
|
void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us) |
|
{ |
|
/* |
|
* fix some commands -- this is a form of mode translation |
|
* UFI devices only accept 12 byte long commands |
|
* |
|
* NOTE: This only works because a scsi_cmnd struct field contains |
|
* a unsigned char cmnd[16], so we know we have storage available |
|
*/ |
|
|
|
/* Pad the ATAPI command with zeros */ |
|
for (; srb->cmd_len < 12; srb->cmd_len++) |
|
srb->cmnd[srb->cmd_len] = 0; |
|
|
|
/* set command length to 12 bytes (this affects the transport layer) */ |
|
srb->cmd_len = 12; |
|
|
|
/* XXX We should be constantly re-evaluating the need for these */ |
|
|
|
/* determine the correct data length for these commands */ |
|
switch (srb->cmnd[0]) { |
|
|
|
/* for INQUIRY, UFI devices only ever return 36 bytes */ |
|
case INQUIRY: |
|
srb->cmnd[4] = 36; |
|
break; |
|
|
|
/* again, for MODE_SENSE_10, we get the minimum (8) */ |
|
case MODE_SENSE_10: |
|
srb->cmnd[7] = 0; |
|
srb->cmnd[8] = 8; |
|
break; |
|
|
|
/* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ |
|
case REQUEST_SENSE: |
|
srb->cmnd[4] = 18; |
|
break; |
|
} /* end switch on cmnd[0] */ |
|
|
|
/* send the command to the transport layer */ |
|
usb_stor_invoke_transport(srb, us); |
|
} |
|
|
|
void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, |
|
struct us_data *us) |
|
{ |
|
/* send the command to the transport layer */ |
|
usb_stor_invoke_transport(srb, us); |
|
} |
|
EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command); |
|
|
|
/*********************************************************************** |
|
* Scatter-gather transfer buffer access routines |
|
***********************************************************************/ |
|
|
|
/* |
|
* Copy a buffer of length buflen to/from the srb's transfer buffer. |
|
* Update the **sgptr and *offset variables so that the next copy will |
|
* pick up from where this one left off. |
|
*/ |
|
unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, |
|
unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr, |
|
unsigned int *offset, enum xfer_buf_dir dir) |
|
{ |
|
unsigned int cnt = 0; |
|
struct scatterlist *sg = *sgptr; |
|
struct sg_mapping_iter miter; |
|
unsigned int nents = scsi_sg_count(srb); |
|
|
|
if (sg) |
|
nents = sg_nents(sg); |
|
else |
|
sg = scsi_sglist(srb); |
|
|
|
sg_miter_start(&miter, sg, nents, dir == FROM_XFER_BUF ? |
|
SG_MITER_FROM_SG: SG_MITER_TO_SG); |
|
|
|
if (!sg_miter_skip(&miter, *offset)) |
|
return cnt; |
|
|
|
while (sg_miter_next(&miter) && cnt < buflen) { |
|
unsigned int len = min_t(unsigned int, miter.length, |
|
buflen - cnt); |
|
|
|
if (dir == FROM_XFER_BUF) |
|
memcpy(buffer + cnt, miter.addr, len); |
|
else |
|
memcpy(miter.addr, buffer + cnt, len); |
|
|
|
if (*offset + len < miter.piter.sg->length) { |
|
*offset += len; |
|
*sgptr = miter.piter.sg; |
|
} else { |
|
*offset = 0; |
|
*sgptr = sg_next(miter.piter.sg); |
|
} |
|
cnt += len; |
|
} |
|
sg_miter_stop(&miter); |
|
|
|
return cnt; |
|
} |
|
EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf); |
|
|
|
/* |
|
* Store the contents of buffer into srb's transfer buffer and set the |
|
* SCSI residue. |
|
*/ |
|
void usb_stor_set_xfer_buf(unsigned char *buffer, |
|
unsigned int buflen, struct scsi_cmnd *srb) |
|
{ |
|
unsigned int offset = 0; |
|
struct scatterlist *sg = NULL; |
|
|
|
buflen = min(buflen, scsi_bufflen(srb)); |
|
buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset, |
|
TO_XFER_BUF); |
|
if (buflen < scsi_bufflen(srb)) |
|
scsi_set_resid(srb, scsi_bufflen(srb) - buflen); |
|
} |
|
EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf);
|
|
|