mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
d49ed218ab
Signed-off-by: Dylan Laduranty <dylan.laduranty@mesotic.com>
296 lines
10 KiB
C
296 lines
10 KiB
C
/*
|
||
* 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 */
|
||
/** @} */
|