Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f7a55f9 in mainline


Ignore:
Timestamp:
2011-07-05T10:43:21Z (11 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
5e2aa83, bee37cf
Parents:
b5085a7
Message:

Implement Read and Request Sense commands for USB mass storage. In bulk-only
transport fix case when less data is returned by padding + residue. Add note
for case when less data is returned by stalling the pipe.

Location:
uspace
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbmast/main.c

    rb5085a7 rf7a55f9  
    138138            "block_size=%" PRIu32 "\n", nblocks, block_size);
    139139
     140        usb_log_info("Doing test read of block 0.\n");
     141        static uint8_t bdata[512];
     142
     143        rc = usbmast_read(dev, 0, 1, 512, &bdata);
     144        if (rc != EOK) {
     145                usb_log_warning("Failed to read block 0, device `%s': %s.\n",
     146                    dev->ddf_dev->name, str_error(rc));
     147                return EOK;
     148        }
     149
     150        usb_log_info("Requesting sense data.\n");
     151        static scsi_sense_data_t sdata;
     152
     153        rc = usbmast_request_sense(dev, &sdata, sizeof(sdata));
     154        if (rc != EOK) {
     155                usb_log_warning("Failed to get sense data, device `%s': %s.\n",
     156                    dev->ddf_dev->name, str_error(rc));
     157                return EOK;
     158        }
     159
    140160        return EOK;
    141161}
  • uspace/drv/bus/usb/usbmast/mast.c

    rb5085a7 rf7a55f9  
    9292            str_error(rc));
    9393        if (rc != EOK) {
     94                /*
     95                 * XXX If the pipe is stalled, we should clear it
     96                 * and read CSW.
     97                 */
    9498                return rc;
    9599        }
     
    103107            str_error(rc));
    104108        if (rc != EOK) {
    105                 return rc;
    106         }
     109                MASTLOG("rc != EOK\n");
     110                return rc;
     111        }
     112
    107113        if (csw_size != sizeof(csw)) {
     114                MASTLOG("csw_size != sizeof(csw)\n");
    108115                return ERANGE;
    109116        }
    110117
    111118        if (csw.dCSWTag != tag) {
     119                MASTLOG("csw.dCSWTag != tag\n");
    112120                return EBADCHECKSUM;
    113121        }
     
    117125         */
    118126        if (csw.dCSWStatus != 0) {
     127                MASTLOG("csw.dCSWStatus != 0\n");
    119128                // FIXME: better error code
    120129                // FIXME: distinguish 0x01 and 0x02
     
    124133        size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
    125134        if (residue > in_buffer_size) {
     135                MASTLOG("residue > in_buffer_size\n");
    126136                return ERANGE;
    127137        }
    128         if (act_size != in_buffer_size - residue) {
    129                 return ERANGE;
    130         }
     138
     139        /*
     140         * When the device has less data to send than requested, it can
     141         * either stall the pipe or send garbage and indicate that via
     142         * the residue field in CSW. That means in_buffer_size - residue
     143         * is the authoritative size of data received.
     144         */
     145
    131146        if (received_size != NULL) {
    132147                *received_size = in_buffer_size - residue;
  • uspace/drv/bus/usb/usbmast/scsi_ms.c

    rb5085a7 rf7a55f9  
    3838#include <byteorder.h>
    3939#include <inttypes.h>
     40#include <macros.h>
    4041#include <usb/dev/driver.h>
    4142#include <usb/debug.h>
     
    115116}
    116117
     118/** Perform SCSI Request Sense command on USB mass storage device.
     119 *
     120 * @param dev           USB device
     121 * @param buf           Destination buffer
     122 * @param size          Size of @a buf
     123 *
     124 * @return              Error code.
     125 */
     126int usbmast_request_sense(usb_device_t *dev, void *buf, size_t size)
     127{
     128        scsi_cdb_request_sense_t cdb;
     129        size_t data_len;
     130        int rc;
     131
     132        memset(&cdb, 0, sizeof(cdb));
     133        cdb.op_code = SCSI_CMD_REQUEST_SENSE;
     134        cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE);
     135
     136        rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     137            sizeof(cdb), buf, size, &data_len);
     138
     139        if (rc != EOK) {
     140                usb_log_error("Request Sense failed, device %s: %s.\n",
     141                   dev->ddf_dev->name, str_error(rc));
     142                return rc;
     143        }
     144
     145        if (data_len < SCSI_SENSE_DATA_MIN_SIZE) {
     146                /* The missing bytes should be considered to be zeroes. */
     147                memset((uint8_t *)buf + data_len, 0,
     148                    SCSI_SENSE_DATA_MIN_SIZE - data_len);
     149        }
     150
     151        return EOK;
     152}
     153
    117154/** Perform SCSI Read Capacity command on USB mass storage device.
    118155 *
     
    155192}
    156193
     194/** Perform SCSI Read command on USB mass storage device.
     195 *
     196 * @param dev           USB device.
     197 * @param ba            Address of first block.
     198 * @param nblocks       Number of blocks to read.
     199 * @param bsize         Block size.
     200 *
     201 * @return              Error code.
     202 */
     203int usbmast_read(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,
     204    void *buf)
     205{
     206        scsi_cdb_read_12_t cdb;
     207        size_t data_len;
     208        int rc;
     209
     210        /* XXX Need softstate to store block size. */
     211
     212        if (ba > UINT32_MAX)
     213                return ELIMIT;
     214
     215        if ((uint64_t)nblocks * bsize > UINT32_MAX)
     216                return ELIMIT;
     217
     218        memset(&cdb, 0, sizeof(cdb));
     219        cdb.op_code = SCSI_CMD_READ_12;
     220        cdb.lba = host2uint32_t_be(ba);
     221        cdb.xfer_len = host2uint32_t_be(nblocks);
     222
     223        rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     224            sizeof(cdb), buf, nblocks * bsize, &data_len);
     225
     226        if (rc != EOK) {
     227                usb_log_error("Read (12) failed, device %s: %s.\n",
     228                   dev->ddf_dev->name, str_error(rc));
     229                return rc;
     230        }
     231
     232        if (data_len < nblocks * bsize) {
     233                usb_log_error("SCSI Read response too short (%zu).\n",
     234                    data_len);
     235                return EIO;
     236        }
     237
     238        return EOK;
     239}
     240
    157241/**
    158242 * @}
  • uspace/drv/bus/usb/usbmast/scsi_ms.h

    rb5085a7 rf7a55f9  
    6060
    6161extern int usbmast_inquiry(usb_device_t *, usbmast_inquiry_data_t *);
    62 extern int usbmast_read_capacity(usb_device_t *dev, uint32_t *, uint32_t *);
     62extern int usbmast_request_sense(usb_device_t *, void *, size_t);
     63extern int usbmast_read_capacity(usb_device_t *, uint32_t *, uint32_t *);
     64extern int usbmast_read(usb_device_t *, uint64_t, size_t, size_t, void *);
    6365extern const char *usbmast_scsi_dev_type_str(unsigned);
    6466
  • uspace/lib/scsi/include/scsi/spc.h

    rb5085a7 rf7a55f9  
    4242/** SCSI command codes defined in SCSI-SPC */
    4343enum scsi_cmd_spc {
    44         SCSI_CMD_INQUIRY        = 0x12
     44        SCSI_CMD_INQUIRY        = 0x12,
     45        SCSI_CMD_REQUEST_SENSE  = 0x03
    4546};
    4647
    4748/** SCSI Inquiry command */
    4849typedef struct {
    49         /** Operation code (12h, SCSI_CMD_INQUIRY) */
     50        /** Operation code (SCSI_CMD_INQUIRY) */
    5051        uint8_t op_code;
    5152        /** Reserved:7-2, obsolete:1, evpd:0 */
     
    9293
    9394        /* End of required data */
    94 } scsi_std_inquiry_data_t;
     95} __attribute__((packed)) scsi_std_inquiry_data_t;
    9596
    9697/** Size of struct or union member. */
     
    138139};
    139140
     141/** SCSI Request Sense command */
     142typedef struct {
     143        /** Operation code (SCSI_CMD_REQUEST_SENSE) */
     144        uint8_t op_code;
     145        /** Reserved, Desc */
     146        uint8_t desc;
     147        /* Reserved */
     148        uint16_t res_2;
     149        /* Allocation Length */
     150        uint8_t alloc_len;
     151        /* Control */
     152        uint8_t control;
     153} __attribute__((packed)) scsi_cdb_request_sense_t;
     154
     155/** Minimum size of sense data.
     156 *
     157 * If the target returns less data, the missing bytes should be considered
     158 * zero.
     159 */
     160#define SCSI_SENSE_DATA_MIN_SIZE 18
     161
     162/** Maximum size of sense data */
     163#define SCSI_SENSE_DATA_MAX_SIZE 252
     164
     165/** Fixed-format sense data.
     166 *
     167 * Returned for Request Sense command with Desc bit cleared.
     168 */
     169typedef struct {
     170        /** Valid, Response Code */
     171        uint8_t valid_rcode;
     172        /** Peripheral qualifier, Peripheral device type */
     173        uint8_t obsolete_1;
     174        /** Filemark, EOM, ILI, Reserved, Sense Key */
     175        uint8_t flags_key;
     176        /** Information */
     177        uint32_t info;
     178        /** Additional Sense Length */
     179        uint8_t additional_len;
     180        /** Command-specific Information */
     181        uint8_t cmd_spec;
     182        /** Additional Sense Code */
     183        uint8_t additional_code;
     184        /** Additional Sense Code Qualifier */
     185        uint8_t additional_cqual;
     186        /** Field-replaceable Unit Code */
     187        uint8_t fru_code;
     188        /** SKSV, Sense-key specific */
     189        uint8_t key_spec[3];
     190} __attribute__((packed)) scsi_sense_data_t;
     191
     192/** Sense key */
     193enum scsi_sense_key {
     194        SCSI_SK_NO_SENSE        = 0x0,
     195        SCSI_SK_RECOVERED_ERROR = 0x1,
     196        SCSI_SK_NOT_READY       = 0x2,
     197        SCSI_SK_MEDIUM_ERROR    = 0x3,
     198        SCSI_SK_HARDWARE_ERROR  = 0x4,
     199        SCSI_SK_ILLEGAL_REQUEST = 0x5,
     200        SCSI_SK_UNIT_ATTENTION  = 0x6,
     201        SCSI_SK_DATA_PROTECT    = 0x7,
     202        SCSI_SK_BLANK_CHECK     = 0x8,
     203        SCSI_SK_VENDOR_SPECIFIC = 0x9,
     204        SCSI_SK_COPY_ABORTED    = 0xa,
     205        SCSI_SK_ABORTED_COMMAND = 0xb,
     206        SCSI_SK_VOLUME_OVERFLOW = 0xd,
     207        SCSI_SK_MISCOMPARE      = 0xe
     208};
     209
    140210extern const char *scsi_dev_type_str[SCSI_DEV_LIMIT];
    141211extern const char *scsi_get_dev_type_str(unsigned);
Note: See TracChangeset for help on using the changeset viewer.