Changeset bd5f3b7 in mainline for uspace/drv/bus/usb/usbmast/scsi_ms.c


Ignore:
Timestamp:
2011-08-21T13:07:35Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
00aece0, f1a9e87
Parents:
86a34d3e (diff), a6480d5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    r86a34d3e rbd5f3b7  
    4646#include <scsi/sbc.h>
    4747#include <scsi/spc.h>
    48 #include "cmds.h"
    49 #include "mast.h"
     48#include "cmdw.h"
     49#include "bo_trans.h"
    5050#include "scsi_ms.h"
     51#include "usbmast.h"
    5152
    5253/** Get string representation for SCSI peripheral device type.
     
    6061}
    6162
     63static void usbmast_dump_sense(scsi_sense_data_t *sense_buf)
     64{
     65        unsigned sense_key;
     66
     67        sense_key = sense_buf->flags_key & 0x0f;
     68        printf("Got sense data. Sense key: 0x%x (%s), ASC 0x%02x, "
     69            "ASCQ 0x%02x.\n", sense_key,
     70            scsi_get_sense_key_str(sense_key),
     71            sense_buf->additional_code,
     72            sense_buf->additional_cqual);
     73}
     74
     75/** Run SCSI command.
     76 *
     77 * Run command and repeat in case of unit attention.
     78 * XXX This is too simplified.
     79 */
     80static int usbmast_run_cmd(usbmast_fun_t *mfun, scsi_cmd_t *cmd)
     81{
     82        uint8_t sense_key;
     83        scsi_sense_data_t sense_buf;
     84        int rc;
     85
     86        do {
     87                rc = usb_massstor_cmd(mfun, 0xDEADBEEF, cmd);
     88                if (rc != EOK) {
     89                        usb_log_error("Inquiry transport failed, device %s: %s.\n",
     90                           mfun->mdev->ddf_dev->name, str_error(rc));
     91                        return rc;
     92                }
     93
     94                if (cmd->status == CMDS_GOOD)
     95                        return EOK;
     96
     97                usb_log_error("SCSI command failed, device %s.\n",
     98                    mfun->mdev->ddf_dev->name);
     99
     100                rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf));
     101                if (rc != EOK) {
     102                        usb_log_error("Failed to read sense data.\n");
     103                        return EIO;
     104                }
     105
     106                /* Dump sense data to log */
     107                usbmast_dump_sense(&sense_buf);
     108
     109                /* Get sense key */
     110                sense_key = sense_buf.flags_key & 0x0f;
     111
     112                if (sense_key == SCSI_SK_UNIT_ATTENTION) {
     113                        printf("Got unit attention. Re-trying command.\n");
     114                }
     115
     116        } while (sense_key == SCSI_SK_UNIT_ATTENTION);
     117
     118        /* Command status is not good, nevertheless transport succeeded. */
     119        return EOK;
     120}
     121
    62122/** Perform SCSI Inquiry command on USB mass storage device.
    63123 *
    64  * @param dev           USB device.
    65  * @param inquiry_result Where to store parsed inquiry result.
    66  * @return              Error code.
    67  */
    68 int usbmast_inquiry(usb_device_t *dev, usbmast_inquiry_data_t *inq_res)
     124 * @param mfun          Mass storage function
     125 * @param inquiry_result Where to store parsed inquiry result
     126 * @return              Error code
     127 */
     128int usbmast_inquiry(usbmast_fun_t *mfun, usbmast_inquiry_data_t *inq_res)
    69129{
    70130        scsi_std_inquiry_data_t inq_data;
    71         size_t response_len;
     131        scsi_cmd_t cmd;
    72132        scsi_cdb_inquiry_t cdb;
    73133        int rc;
     
    77137        cdb.alloc_len = host2uint16_t_be(sizeof(inq_data));
    78138
    79         rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    80             sizeof(cdb), &inq_data, sizeof(inq_data), &response_len);
     139        memset(&cmd, 0, sizeof(cmd));
     140        cmd.cdb = &cdb;
     141        cmd.cdb_size = sizeof(cdb);
     142        cmd.data_in = &inq_data;
     143        cmd.data_in_size = sizeof(inq_data);
     144
     145        rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd);
    81146
    82147        if (rc != EOK) {
    83                 usb_log_error("Inquiry failed, device %s: %s.\n",
    84                    dev->ddf_dev->name, str_error(rc));
    85                 return rc;
    86         }
    87 
    88         if (response_len < SCSI_STD_INQUIRY_DATA_MIN_SIZE) {
     148                usb_log_error("Inquiry transport failed, device %s: %s.\n",
     149                   mfun->mdev->ddf_dev->name, str_error(rc));
     150                return rc;
     151        }
     152
     153        if (cmd.status != CMDS_GOOD) {
     154                usb_log_error("Inquiry command failed, device %s.\n",
     155                   mfun->mdev->ddf_dev->name);
     156                return EIO;
     157        }
     158
     159        if (cmd.rcvd_size < SCSI_STD_INQUIRY_DATA_MIN_SIZE) {
    89160                usb_log_error("SCSI Inquiry response too short (%zu).\n",
    90                     response_len);
     161                    cmd.rcvd_size);
    91162                return EIO;
    92163        }
     
    118189/** Perform SCSI Request Sense command on USB mass storage device.
    119190 *
    120  * @param dev           USB device
     191 * @param mfun          Mass storage function
    121192 * @param buf           Destination buffer
    122193 * @param size          Size of @a buf
     
    124195 * @return              Error code.
    125196 */
    126 int usbmast_request_sense(usb_device_t *dev, void *buf, size_t size)
    127 {
     197int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size)
     198{
     199        scsi_cmd_t cmd;
    128200        scsi_cdb_request_sense_t cdb;
    129         size_t data_len;
    130201        int rc;
    131202
     
    134205        cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE);
    135206
    136         rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    137             sizeof(cdb), buf, size, &data_len);
    138 
    139         if (rc != EOK) {
     207        memset(&cmd, 0, sizeof(cmd));
     208        cmd.cdb = &cdb;
     209        cmd.cdb_size = sizeof(cdb);
     210        cmd.data_in = buf;
     211        cmd.data_in_size = size;
     212
     213        rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd);
     214
     215        if (rc != EOK || cmd.status != CMDS_GOOD) {
    140216                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) {
     217                   mfun->mdev->ddf_dev->name, str_error(rc));
     218                return rc;
     219        }
     220
     221        if (cmd.rcvd_size < SCSI_SENSE_DATA_MIN_SIZE) {
    146222                /* 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);
     223                memset((uint8_t *)buf + cmd.rcvd_size, 0,
     224                    SCSI_SENSE_DATA_MIN_SIZE - cmd.rcvd_size);
    149225        }
    150226
     
    154230/** Perform SCSI Read Capacity command on USB mass storage device.
    155231 *
    156  * @param dev           USB device.
    157  * @param nblocks       Output, number of blocks.
    158  * @param block_size    Output, block size in bytes.
     232 * @param mfun          Mass storage function
     233 * @param nblocks       Output, number of blocks
     234 * @param block_size    Output, block size in bytes
    159235 *
    160236 * @return              Error code.
    161237 */
    162 int usbmast_read_capacity(usb_device_t *dev, uint32_t *nblocks,
     238int usbmast_read_capacity(usbmast_fun_t *mfun, uint32_t *nblocks,
    163239    uint32_t *block_size)
    164240{
     241        scsi_cmd_t cmd;
    165242        scsi_cdb_read_capacity_10_t cdb;
    166243        scsi_read_capacity_10_data_t data;
    167         size_t data_len;
    168244        int rc;
    169245
     
    171247        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
    172248
    173         rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    174             sizeof(cdb), &data, sizeof(data), &data_len);
     249        memset(&cmd, 0, sizeof(cmd));
     250        cmd.cdb = &cdb;
     251        cmd.cdb_size = sizeof(cdb);
     252        cmd.data_in = &data;
     253        cmd.data_in_size = sizeof(data);
     254
     255        rc = usbmast_run_cmd(mfun, &cmd);
    175256
    176257        if (rc != EOK) {
    177                 usb_log_error("Read Capacity (10) failed, device %s: %s.\n",
    178                    dev->ddf_dev->name, str_error(rc));
    179                 return rc;
    180         }
    181 
    182         if (data_len < sizeof(data)) {
     258                usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n",
     259                   mfun->mdev->ddf_dev->name, str_error(rc));
     260                return rc;
     261        }
     262
     263        if (cmd.status != CMDS_GOOD) {
     264                usb_log_error("Read Capacity (10) command failed, device %s.\n",
     265                   mfun->mdev->ddf_dev->name);
     266                return EIO;
     267        }
     268
     269        if (cmd.rcvd_size < sizeof(data)) {
    183270                usb_log_error("SCSI Read Capacity response too short (%zu).\n",
    184                     data_len);
     271                    cmd.rcvd_size);
    185272                return EIO;
    186273        }
     
    194281/** Perform SCSI Read command on USB mass storage device.
    195282 *
    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  */
    203 int 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. */
     283 * @param mfun          Mass storage function
     284 * @param ba            Address of first block
     285 * @param nblocks       Number of blocks to read
     286 *
     287 * @return              Error code
     288 */
     289int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf)
     290{
     291        scsi_cmd_t cmd;
     292        scsi_cdb_read_10_t cdb;
     293        int rc;
    211294
    212295        if (ba > UINT32_MAX)
    213296                return ELIMIT;
    214297
    215         if ((uint64_t)nblocks * bsize > UINT32_MAX)
     298        if (nblocks > UINT16_MAX)
    216299                return ELIMIT;
    217300
    218301        memset(&cdb, 0, sizeof(cdb));
    219         cdb.op_code = SCSI_CMD_READ_12;
     302        cdb.op_code = SCSI_CMD_READ_10;
    220303        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);
     304        cdb.xfer_len = host2uint16_t_be(nblocks);
     305
     306        memset(&cmd, 0, sizeof(cmd));
     307        cmd.cdb = &cdb;
     308        cmd.cdb_size = sizeof(cdb);
     309        cmd.data_in = buf;
     310        cmd.data_in_size = nblocks * mfun->block_size;
     311
     312        rc = usbmast_run_cmd(mfun, &cmd);
    225313
    226314        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) {
     315                usb_log_error("Read (10) transport failed, device %s: %s.\n",
     316                   mfun->mdev->ddf_dev->name, str_error(rc));
     317                return rc;
     318        }
     319
     320        if (cmd.status != CMDS_GOOD) {
     321                usb_log_error("Read (10) command failed, device %s.\n",
     322                   mfun->mdev->ddf_dev->name);
     323                return EIO;
     324        }
     325
     326        if (cmd.rcvd_size < nblocks * mfun->block_size) {
    233327                usb_log_error("SCSI Read response too short (%zu).\n",
    234                     data_len);
     328                    cmd.rcvd_size);
     329                return EIO;
     330        }
     331
     332        return EOK;
     333}
     334
     335/** Perform SCSI Write command on USB mass storage device.
     336 *
     337 * @param mfun          Mass storage function
     338 * @param ba            Address of first block
     339 * @param nblocks       Number of blocks to read
     340 * @param data          Data to write
     341 *
     342 * @return              Error code
     343 */
     344int usbmast_write(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks,
     345    const void *data)
     346{
     347        scsi_cmd_t cmd;
     348        scsi_cdb_write_10_t cdb;
     349        int rc;
     350
     351        if (ba > UINT32_MAX)
     352                return ELIMIT;
     353
     354        if (nblocks > UINT16_MAX)
     355                return ELIMIT;
     356
     357        memset(&cdb, 0, sizeof(cdb));
     358        cdb.op_code = SCSI_CMD_WRITE_10;
     359        cdb.lba = host2uint32_t_be(ba);
     360        cdb.xfer_len = host2uint16_t_be(nblocks);
     361
     362        memset(&cmd, 0, sizeof(cmd));
     363        cmd.cdb = &cdb;
     364        cmd.cdb_size = sizeof(cdb);
     365        cmd.data_out = data;
     366        cmd.data_out_size = nblocks * mfun->block_size;
     367
     368        rc = usbmast_run_cmd(mfun, &cmd);
     369
     370        if (rc != EOK) {
     371                usb_log_error("Write (10) transport failed, device %s: %s.\n",
     372                   mfun->mdev->ddf_dev->name, str_error(rc));
     373                return rc;
     374        }
     375
     376        if (cmd.status != CMDS_GOOD) {
     377                usb_log_error("Write (10) command failed, device %s.\n",
     378                   mfun->mdev->ddf_dev->name);
    235379                return EIO;
    236380        }
Note: See TracChangeset for help on using the changeset viewer.