USB Mass Storage and USB-Attached SCSI... are both SCSI
(You may wish to read A brief introduction to SCSI before reading this article.)
The USB standard provides a variety of standardised device classes which allow devices from arbitrary vendors to implement a standardised interface. One of the most commonly known such device classes is the USB Mass Storage device class, which is used for USB-attached block devices such as flash drives, floppy drives, hard drives and optical drives.
The USB Mass Storage device class in actuality is more a category of multiple standards than a standard in itself, in that it can actually support a number of different protocols. The most common protocol implemented by USB Mass Storage devices is the Bulk-Only Transport protocol (abbreviated here as BOT, but mysteriously abbreviated as BBB in the official standards). More recent is the newer USB-Attached SCSI (UAS) protocol, which offers greater performance and functionality than BOT.
The naming of UAS would strongly imply to a casual observer that UAS is in some way SCSI and the older BOT is, in some way, not. Confusingly, in actuality, both BOT and UAS use the SCSI command set.
If BOT and UAS are both SCSI, why is UAS named as it is? Essentially this comes down to standards pedantry and whether something is “truly” SCSI if it reuses SCSI commands, but only supports a subset of the functionality a properly architected SCSI subsystem is supposed to support. However, it's certainly true that BOT has limitations which prevent the use of some SCSI functionality, which are resolved by UAS. Essentially, UAS corrects the botched design of BOT as a SCSI transport and is properly architected to support the full range of SCSI functionality defined by the SCSI architectural model.
Here are some examples of functionality which BOT doesn't support but the SCSI architecture (and UAS) does:
- LUNs larger than 4 bits (LUNs can be up to 64 bits in modern SCSI);
- Commands with both Data-In and Data-Out (bidirectional commands, allowed in modern SCSI);
- Command queueing (only one command may be executed at a time, unlike real SCSI);
- SCSI CDBs larger than 16 bytes (modern SCSI supports 32 byte or variable-length CDBs);
- Command prioritisation
- Task attributes other than Simple
- Auto Contingent Allegiance (ACA)
- Control byte in CDBs (must be zero)
- Linked commands
- Autosense
- The SCSI Status and Status Qualifier bytes
- All task management functions (e.g. can't abort commands)
- USB3 Streams support1
BOT was never really intended to support the full spectrum of SCSI functionality, rather the subset of it needed to support specific, constrained devices that it had in mind; it focused on supporting flash drives (via the SCSI RBC command set), optical drives (via the SCSI MMC command set), and floppy drives (via a subset profile of the SCSI SBC command set), though it can support other commands if they fit within the constraints listed above. There was also a focus on the ability for BOT to be implemented on cheap, inexpensive devices such as low-powered microcontrollers, encouraging the standard to limit itself to a more narrow range of functionality.
CBI. There is another protocol also supported by the USB Mass Storage device class called the Control/Bulk/Interrupt Transport (CBI). This was only intended for use by floppy drives and is now deprecated. It shares all of the limitations listed above, except that it can return the ASC and ASCQ values from sense data automatically (but still not the status byte, or full autosense).
The fact that CBI exposes ASC and ASCQ and BOT does not (other than by explicitly issuing REQUEST SENSE) demonstrates how these protocols were largely designed only to support the minimum amount of SCSI functionality needed to support the kinds of devices the authors in mind, as opposed to providing a neutral channel supporting all aspects of SCSI. Hence, while both use the SCSI command set, UAS is truly “SCSI” in both design and design intention, whereas BOT neither supports the full SCSI architecture, nor was it ever really intended to; rather it simply adopted what aspects and features of SCSI were useful to the specific devices it intended to support.
UAS. UAS was primarily motivated by the performance limitations of BOT. Since only one command can be queued at a time, a command must complete before the next command can be issued, throughput is limited. According to the UAS specification, BOT results in a “significant overhead” for data transfer of “about 20%”, and estimates that using BOT, a throughput of only about 2Gb/s could be achieved for a 5Gb/s USB3 link.
While performance may have been the primary motivation of UAS, the standard also takes the opportunity of a new protocol to implement a proper SCSI architecture. Unlike BOT and as its name implies, UAS explicitly references the SCSI Architectural Model — 4 (SAM-4) standard and implements it fully.
Unlike BOT, UAS supports all of the following:
- 64-bit LUNs
- Commands with both Data-In and Data-Out (bidirectional commands)
- Command queueing with 16-bit command IDs
- SCSI CDBs of up to 268 bytes in length
- Command prioritisation
- Task attributes
- ACA
- Control byte in CDBs
- Linked commands are obsoleted, but could still be used
- Autosense is supported and always enabled
- The SCSI Status and Status Qualifier bytes
- Task management functions (including the ability to abort commands)
- USB3 Streams1
A principal remaining limitation of UAS is that it supports only a single target (and, since USB is not multi-master, only a single initiator). Obviously, this could be worked around using multiple logical USB devices.
It should be noted that while the development of UAS was motivated by USB3, it is also explicitly designed to be usable over USB2; only the USB3 Streams functionality is lost.
NOTE: When UAS shipped, it was announced that to use UAS, you needed not only UAS devices but also a UAS-compatible host controller. I do not understand where this requirement would originate from as UAS does nothing peculiar as a USB3 application and should work with any USB3-compliant host controller, nor have I been able to find details for this claim. If someone knows something about this supposed requirement, please inform me.
1. USB3 Streams is a feature of USB which enhances performance by allowing different packets of data sent over the same USB bulk transfer pipe to be vectored to different buffers on a host. Thus, you could dispatch two READ (10) commands to a UAS device to be deposited by the host controller at different locations in host memory, despite being sent over the same USB transfer pipe.
The mechanism of USB3 Streams is actually very simple: a 16-bit integer Stream ID is prepended to every packet transferred over a given USB bulk transfer pipe. It must be emphasised that this in no way means that USB3 has “DMA” functionality; the interpretation of the 16-bit Stream ID value is entirely up to the USB3 host controller, which could simply choose to ignore it entirely. A host driver stack which wishes to make use of USB3 Streams will configure the host controller with a mapping from Stream IDs to the locations in memory data is to be transferred to or from. This is not dissimilar from how modern server NICs can vector incoming packets to a specific RX queue based on values in their headers, such as TCP port numbers, for load balancing purposes. No USB device ever sees, or is able to directly specify, any host memory addresses, any more than an Ethernet peer speaking TCP/IP is.
For UAS, the 16-bit command ID provided during command submission is reused as the stream ID. ⏎ ⏎