1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00
RIOT/sys/include/usb/usbus/msc/scsi.h

296 lines
10 KiB
C
Raw Normal View History

/*
* Copyright (C) 2019-2021 Mesotic SAS
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for
* more details.
*/
/**
* @ingroup usbus_msc
*
* @{
*
* @file
* @brief SCSI protocol definitions for USBUS
*
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
*/
#ifndef USB_USBUS_MSC_SCSI_H
#define USB_USBUS_MSC_SCSI_H
#include "byteorder.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef USBUS_MSC_VENDOR_ID
#define USBUS_MSC_VENDOR_ID "RIOT-OS"
#endif /* USBUS_MSC_VENDOR_ID */
#ifndef USBUS_MSC_PRODUCT_ID
#define USBUS_MSC_PRODUCT_ID "RIOT_MSC_DISK "
#endif /* USBUS_MSC_PRODUCT_ID */
#ifndef USBUS_MSC_PRODUCT_REV
#define USBUS_MSC_PRODUCT_REV " 1.0"
#endif /* USBUS_MSC_PRODUCT_REV */
/**
* @name USB SCSI Commands
*
* @see Table 9 - Packet Commands Supported by ATAPI Block Devices
* from INF-8070i draft published by SFF
* @{
*/
#define SCSI_TEST_UNIT_READY 0x00 /**< SCSI Test Unit Ready */
#define SCSI_REQUEST_SENSE 0x03 /**< SCSI Request Sense */
#define SCSI_FORMAT_UNIT 0x04 /**< SCSI Format Unit */
#define SCSI_INQUIRY 0x12 /**< SCSI Inquiry */
#define SCSI_MODE_SELECT6 0x15 /**< SCSI Mode Select6 */
#define SCSI_MODE_SENSE6 0x1A /**< SCSI Mode Sense6 */
#define SCSI_START_STOP_UNIT 0x1B /**< SCSI Start Stop Unit */
#define SCSI_MEDIA_REMOVAL 0x1E /**< SCSI Media Removal */
#define SCSI_READ_FORMAT_CAPACITIES 0x23 /**< SCSI Read Format Capacities */
#define SCSI_READ_CAPACITY 0x25 /**< SCSI Read Capacity */
#define SCSI_READ10 0x28 /**< SCSI Read10 */
#define SCCI_READ12 0xA8 /**< SCSI Read12 */
#define SCSI_WRITE10 0x2A /**< SCSI Write10 */
#define SCSI_WRITE12 0xAA /**< SCSI Write12 */
#define SCSI_SEEK 0x2B /**< SCSI Seek */
#define SCSI_WRITE_AND_VERIFY 0x2E /**< SCSI Write and Verify */
#define SCSI_VERIFY10 0x2F /**< SCSI Verify10 */
#define SCSI_MODE_SELECT10 0x55 /**< SCSI Mode Select10 */
#define SCSI_MODE_SENSE10 0x5A /**< SCSI Mode Sense10 */
/** @} */
/**
* @brief Command Block Wrapper signature
*/
#define SCSI_CBW_SIGNATURE 0x43425355
/**
* @brief Command Status Wrapper signature
*/
#define SCSI_CSW_SIGNATURE 0x53425355
/**
* @name USB SCSI Version list
* @{
*/
#define SCSI_VERSION_NONE 0x0000
#define SCSI_VERSION_SCSI1 0x0001
#define SCSI_VERSION_SCSI2 0x0002
/** @} */
/**
* @name USB SCSI Read format capacities descriptor type
*
* @see ( @ref msc_read_fmt_capa_pkt_t )
* @{
*/
#define SCSI_READ_FMT_CAPA_TYPE_RESERVED 0x00
#define SCSI_READ_FMT_CAPA_TYPE_UNFORMATTED 0x01
#define SCSI_READ_FMT_CAPA_TYPE_FORMATTED 0x02
#define SCSI_READ_FMT_CAPA_TYPE_NO_MEDIA 0x03
/** @} */
/**
* @brief SCSI Request Sense error type
*/
#define SCSI_REQUEST_SENSE_ERROR 0x70
/**
* @name USB SCSI Request Sense Sense Key type
*
* @{
*/
#define SCSI_SENSE_KEY_NO_SENSE 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
/** @} */
/**
* @brief Packet structure to answer (@ref SCSI_TEST_UNIT_READY) request
*
* @see Inquiry Command from SCSI Primary Command
*/
typedef struct __attribute__((packed)) {
uint8_t type; /**< type of device */
uint8_t logical_unit; /**< Selected LUN */
uint8_t reserved[10]; /**< Reserved */
} msc_test_unit_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_MODE_SELECT6) and
* (@ref SCSI_MODE_SENSE6) requests
*
* @see Inquiry Command from SCSI Primary Command
*/
typedef struct __attribute__((packed)) {
uint8_t mode_data_len; /**< Size of the whole packet */
uint8_t medium_type; /**< Type of medium */
uint8_t flags; /**< Miscellaneous flags */
uint8_t block_desc_len; /**< Length of block descriptor */
} msc_mode_parameter_pkt_t;
/**
* @brief CBW Packet structure for (@ref SCSI_READ10) and
* (@ref SCSI_WRITE10) requests
*
* @see Read10 or Write10 Command from SCSI Primary Command
*
* @warning uint16_t and uint32_t will be BIG ENDIAN
*/
typedef struct __attribute__((packed)) {
uint8_t opcode; /**< Operation code */
uint8_t flags; /**< Miscellaneous flags */
be_uint32_t blk_addr; /**< Block address */
uint8_t group_number; /**< Group number */
be_uint16_t xfer_len; /**< Transfer length in bytes */
} msc_cbw_rw10_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_INQUIRY) request
*
* @see Inquiry Command from SCSI Primary Command
*
* @note Vendor specific information (Byte 36 and above) and flags from bytes
* 5 to 7 are currently unsupported
*/
typedef struct __attribute__((packed)) {
uint8_t type; /**< Byte 0 Peripheral type */
uint8_t reserved1 : 7; /**< Byte 1 [B6..B0] Reserved */
uint8_t removable : 1; /**< Byte 1 [B7] Removable device flag */
uint8_t version; /**< Byte 2 SCSI Version */
uint8_t response_format : 4; /**< Byte 3 [B3..B0] Response Data Format */
uint8_t reserved3 : 4; /**< Byte 3 [B7..B4] Reserved */
uint8_t length; /**< Byte 4 Additional Length (n-4) */
uint8_t flags[3]; /**< Byte 7..5 Miscellaneous flags UNUSED BY USBUS ONLY */
uint8_t vendor_id[8]; /**< Byte 15..8 Vendor Identification */
uint8_t product_id[16]; /**< Byte 31..16 Product Identification */
uint8_t product_rev[4]; /**< Byte 35..32 Product Revision */
} msc_inquiry_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_READ_FORMAT_CAPACITIES) request
*
* @see READ FORMAT CAPACITIES from SCSI Multimedia Commands 2 (MMC-2)
*
*/
typedef struct __attribute__((packed)) {
uint8_t reserved1[3]; /**< Byte 2..0 reserved */
uint8_t list_length; /**< Byte 3 Capacity list length */
be_uint32_t blk_nb; /**< Byte 7..4 Number of blocks */
uint8_t type; /**< Byte 8 Descriptor type */
uint8_t blk_len[3]; /**< Byte 11..9 Block length */
} msc_read_fmt_capa_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_REQUEST_SENSE) request
*
*/
typedef struct __attribute__((packed)) {
uint8_t error_code; /**< Byte 0 Error code */
uint8_t reserved1; /**< Reserved */
uint8_t sense_key; /**< Byte 2 Sense key */
uint8_t reserved2[4]; /**< Byte 6..3 Information */
uint8_t add_len; /**< Byte 7 Additional sense length */
uint8_t reserved3[4]; /**< Byte 11..8 Vendor specific */
uint8_t asc; /**< Byte 12 Additional Sense Code */
uint8_t ascq; /**< Byte 13 Additional Sense Code Qualifier */
uint8_t fruc; /**< Byte 14 Field Replaceable Unit Code */
uint16_t sk_spec; /**< Byte 16..15 Sense Key Specific */
} msc_request_sense_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_READ_CAPACITY) request
*
* @note Multiply the two values from this struct between them
* indicates the total size of your MTD device
*
* @see Read Capacities from SCSI Primary Command
*/
typedef struct __attribute__((packed)) {
be_uint32_t last_blk; /**< Indicate last block number */
be_uint32_t blk_len; /**< Total size of a block in bytes */
} msc_read_capa_pkt_t;
/**
* @brief Command Block Wrapper packet structure
*
* @see Table 5.1 Command Block Wrapper (CBW)
* from Universal Serial Bus Mass Storage Class Bulk-Only Transport
*/
typedef struct __attribute__((packed)) {
uint32_t signature; /**< CBW signature (@ref SCSI_CBW_SIGNATURE) */
uint32_t tag; /**< ID for the current command */
uint32_t data_len; /**< Number of bytes host expects to transfer from/to */
uint8_t flags; /**< Command block flags */
uint8_t lun; /**< Target Logical Unit Number */
uint8_t cb_len; /**< Length of the block in bytes (max: 16 bytes) */
uint8_t cb[16]; /**< Command block buffer */
} msc_cbw_buf_t;
/**
* @brief Command Status Wrapper packet structure
*
* @see Table 5.2 - Command Status Wrapper
* from Universal Serial Bus Mass Storage Class Bulk-Only Transport
*/
typedef struct __attribute__((packed)) {
uint32_t signature; /**< CSW signature (@ref SCSI_CSW_SIGNATURE) */
uint32_t tag; /**< ID for the answered CBW */
uint32_t data_left; /**< Indicate how many bytes from the CBW were not processed */
uint8_t status; /**< Status of the command */
} msc_csw_buf_t;
/**
* @brief USBUS Command Block Wrapper information
*
*/
typedef struct {
uint32_t tag; /**< Store tag information from CBW */
size_t len; /**< Remaining bytes to handle */
uint8_t status; /**< Status of the current operation */
uint8_t lun; /**< Store LUN from CBW */
} cbw_info_t;
/**
* @brief Process incoming Command Block Wrapper buffer
*
* @param usbus USBUS thread to use
* @param handler MSC device struct
* @param ep Endpoint pointer to read CBW from
* @param len Size of the received CBW buffer
*/
void usbus_msc_scsi_process_cmd(usbus_t *usbus, usbus_handler_t *handler, usbdev_ep_t *ep,
size_t len);
/**
* @brief Generate Command Status Wrapper and send it to the host
*
* @param handler MSC device struct
* @param cmd struct containing needed information to generate CBW response
*/
void scsi_gen_csw(usbus_handler_t *handler, cbw_info_t *cmd);
#ifdef __cplusplus
}
#endif
#endif /* USB_USBUS_MSC_SCSI_H */
/** @} */