Changeset 00c2de63 in mainline for uspace/drv


Ignore:
Timestamp:
2011-07-29T14:50:22Z (15 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b6759f4
Parents:
6c69d19 (diff), 7ae249d (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 libposix.

Location:
uspace/drv/bus/usb/usbmast
Files:
4 edited

Legend:

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

    r6c69d19 r00c2de63  
    5858 * @param tag           Command block wrapper tag (automatically compared
    5959 *                      with answer)
    60  * @param cmd           Command block
    61  * @param cmd_size      Command block size in bytes
    62  * @param ddir          Direction in which data will be transferred
    63  * @param dbuf          Data send/receive buffer
    64  * @param dbuf_size     Size of the data buffer
    65  * @param xferred_size  Number of bytes actually transferred
     60 * @param cmd           SCSI command
    6661 *
    6762 * @return              Error code
    6863 */
    69 static int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
    70     size_t cmd_size, usb_direction_t ddir, void *dbuf, size_t dbuf_size,
    71     size_t *xferred_size)
     64int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, scsi_cmd_t *cmd)
    7265{
    7366        int rc;
     67        int retval = EOK;
    7468        size_t act_size;
    7569        usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
    7670        usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
     71        usb_direction_t ddir;
     72        void *dbuf;
     73        size_t dbuf_size;
     74
     75        if (cmd->data_out != NULL && cmd->data_in == NULL) {
     76                ddir = USB_DIRECTION_OUT;
     77                dbuf = (void *)cmd->data_out;
     78                dbuf_size = cmd->data_out_size;
     79        } else if (cmd->data_out == NULL && cmd->data_in != NULL) {
     80                ddir = USB_DIRECTION_IN;
     81                dbuf = cmd->data_in;
     82                dbuf_size = cmd->data_in_size;
     83        } else {
     84                assert(false);
     85        }
    7786
    7887        /* Prepare CBW - command block wrapper */
    7988        usb_massstor_cbw_t cbw;
    8089        usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, mfun->lun,
    81             cmd_size, cmd);
     90            cmd->cdb_size, cmd->cdb);
    8291
    8392        /* Send the CBW. */
     93        MASTLOG("Sending CBW.\n");
    8494        rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
    8595        MASTLOG("CBW '%s' sent: %s.\n",
    8696            usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
    8797            str_error(rc));
    88         if (rc != EOK) {
    89                 return rc;
    90         }
    91 
     98        if (rc != EOK)
     99                return EIO;
     100
     101        MASTLOG("Transferring data.\n");
    92102        if (ddir == USB_DIRECTION_IN) {
    93103                /* Recieve data from the device. */
     
    104114        }
    105115
    106         if (rc != EOK) {
    107                 /*
    108                  * XXX If the pipe is stalled, we should clear it
    109                  * and read CSW.
    110                  */
    111                 return rc;
     116        if (rc == ESTALL) {
     117                /* Clear stall condition and continue below to read CSW. */
     118                if (ddir == USB_DIRECTION_IN) {
     119                        usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
     120                            mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
     121                } else {
     122                        usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
     123                            mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
     124                }
     125        } else if (rc != EOK) {
     126                return EIO;
    112127        }
    113128
     
    115130        usb_massstor_csw_t csw;
    116131        size_t csw_size;
     132        MASTLOG("Reading CSW.\n");
    117133        rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
    118134        MASTLOG("CSW '%s' received (%zu bytes): %s.\n",
     
    121137        if (rc != EOK) {
    122138                MASTLOG("rc != EOK\n");
    123                 return rc;
     139                return EIO;
    124140        }
    125141
    126142        if (csw_size != sizeof(csw)) {
    127143                MASTLOG("csw_size != sizeof(csw)\n");
    128                 return ERANGE;
     144                return EIO;
    129145        }
    130146
    131147        if (csw.dCSWTag != tag) {
    132148                MASTLOG("csw.dCSWTag != tag\n");
    133                 return EBADCHECKSUM;
     149                return EIO;
    134150        }
    135151
     
    137153         * Determine the actual return value from the CSW.
    138154         */
    139         if (csw.dCSWStatus != 0) {
    140                 MASTLOG("csw.dCSWStatus != 0\n");
    141                 // FIXME: better error code
    142                 // FIXME: distinguish 0x01 and 0x02
    143                 return EXDEV;
     155        switch (csw.dCSWStatus) {
     156        case cbs_passed:
     157                cmd->status = CMDS_GOOD;
     158                break;
     159        case cbs_failed:
     160                MASTLOG("Command failed\n");
     161                cmd->status = CMDS_FAILED;
     162                break;
     163        case cbs_phase_error:
     164                MASTLOG("Phase error\n");
     165                retval = EIO;
     166                break;
     167        default:
     168                retval = EIO;
     169                break;
    144170        }
    145171
     
    147173        if (residue > dbuf_size) {
    148174                MASTLOG("residue > dbuf_size\n");
    149                 return ERANGE;
     175                return EIO;
    150176        }
    151177
     
    158184         */
    159185
    160         if (xferred_size != NULL)
    161                 *xferred_size = dbuf_size - residue;
    162 
    163         return EOK;
    164 }
    165 
    166 /** Perform data-in command.
    167  *
    168  * @param mfun          Mass storage function
    169  * @param tag           Command block wrapper tag (automatically compared with
    170  *                      answer)
    171  * @param cmd           CDB (Command Descriptor)
    172  * @param cmd_size      CDB length in bytes
    173  * @param dbuf          Data receive buffer
    174  * @param dbuf_size     Data receive buffer size in bytes
    175  * @param proc_size     Number of bytes actually processed by device
    176  *
    177  * @return Error code
    178  */
    179 int usb_massstor_data_in(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
    180     size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size)
    181 {
    182         return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_IN,
    183             dbuf, dbuf_size, proc_size);
    184 }
    185 
    186 /** Perform data-out command.
    187  *
    188  * @param mfun          Mass storage function
    189  * @param tag           Command block wrapper tag (automatically compared with
    190  *                      answer)
    191  * @param cmd           CDB (Command Descriptor)
    192  * @param cmd_size      CDB length in bytes
    193  * @param data          Command data
    194  * @param data_size     Size of @a data in bytes
    195  * @param proc_size     Number of bytes actually processed by device
    196  *
    197  * @return Error code
    198  */
    199 int usb_massstor_data_out(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
    200     size_t cmd_size, const void *data, size_t data_size, size_t *proc_size)
    201 {
    202         return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_OUT,
    203             (void *) data, data_size, proc_size);
     186        if (ddir == USB_DIRECTION_IN)
     187                cmd->rcvd_size = dbuf_size - residue;
     188
     189        return retval;
    204190}
    205191
  • uspace/drv/bus/usb/usbmast/bo_trans.h

    r6c69d19 r00c2de63  
    4747#define BULK_OUT_EP 1
    4848
    49 extern int usb_massstor_data_in(usbmast_fun_t *, uint32_t, const void *,
    50     size_t, void *, size_t, size_t *);
    51 extern int usb_massstor_data_out(usbmast_fun_t *, uint32_t, const void *,
    52     size_t, const void *, size_t, size_t *);
     49typedef enum cmd_status {
     50        CMDS_GOOD,
     51        CMDS_FAILED
     52} cmd_status_t;
     53
     54/** SCSI command.
     55 *
     56 * Contains (a subset of) the input and output arguments of SCSI
     57 * Execute Command procedure call (see SAM-4 chapter 5.1)
     58 */
     59typedef struct {
     60        /*
     61         * Related to IN fields
     62         */
     63
     64        /** Command Descriptor Block */
     65        void *cdb;
     66        /** CDB size in bytes */
     67        size_t cdb_size;
     68
     69        /** Outgoing data */
     70        const void *data_out;
     71        /** Size of outgoing data in bytes */
     72        size_t data_out_size;
     73
     74        /*
     75         * Related to OUT fields
     76         */
     77
     78        /** Buffer for incoming data */
     79        void *data_in;
     80        /** Size of input buffer in bytes */
     81        size_t data_in_size;
     82
     83        /** Number of bytes actually received */
     84        size_t rcvd_size;
     85
     86        /** Status */
     87        cmd_status_t status;
     88} scsi_cmd_t;
     89
     90extern int usb_massstor_cmd(usbmast_fun_t *, uint32_t, scsi_cmd_t *);
    5391extern int usb_massstor_reset(usbmast_dev_t *);
    5492extern void usb_massstor_reset_recovery(usbmast_dev_t *);
  • uspace/drv/bus/usb/usbmast/cmdw.h

    r6c69d19 r00c2de63  
    5757} __attribute__((packed)) usb_massstor_csw_t;
    5858
     59enum cmd_block_status {
     60        cbs_passed      = 0x00,
     61        cbs_failed      = 0x01,
     62        cbs_phase_error = 0x02
     63};
     64
    5965extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t,
    6066    usb_direction_t, uint8_t, uint8_t, const uint8_t *);
  • uspace/drv/bus/usb/usbmast/scsi_ms.c

    r6c69d19 r00c2de63  
    6161}
    6262
     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
    63122/** Perform SCSI Inquiry command on USB mass storage device.
    64123 *
     
    70129{
    71130        scsi_std_inquiry_data_t inq_data;
    72         size_t response_len;
     131        scsi_cmd_t cmd;
    73132        scsi_cdb_inquiry_t cdb;
    74133        int rc;
     
    78137        cdb.alloc_len = host2uint16_t_be(sizeof(inq_data));
    79138
    80         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    81             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);
    82146
    83147        if (rc != EOK) {
    84                 usb_log_error("Inquiry failed, device %s: %s.\n",
    85                    mfun->mdev->ddf_dev->name, str_error(rc));
    86                 return rc;
    87         }
    88 
    89         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) {
    90160                usb_log_error("SCSI Inquiry response too short (%zu).\n",
    91                     response_len);
     161                    cmd.rcvd_size);
    92162                return EIO;
    93163        }
     
    127197int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size)
    128198{
     199        scsi_cmd_t cmd;
    129200        scsi_cdb_request_sense_t cdb;
    130         size_t data_len;
    131201        int rc;
    132202
     
    135205        cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE);
    136206
    137         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    138             sizeof(cdb), buf, size, &data_len);
    139 
    140         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) {
    141216                usb_log_error("Request Sense failed, device %s: %s.\n",
    142217                   mfun->mdev->ddf_dev->name, str_error(rc));
     
    144219        }
    145220
    146         if (data_len < SCSI_SENSE_DATA_MIN_SIZE) {
     221        if (cmd.rcvd_size < SCSI_SENSE_DATA_MIN_SIZE) {
    147222                /* The missing bytes should be considered to be zeroes. */
    148                 memset((uint8_t *)buf + data_len, 0,
    149                     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);
    150225        }
    151226
     
    164239    uint32_t *block_size)
    165240{
     241        scsi_cmd_t cmd;
    166242        scsi_cdb_read_capacity_10_t cdb;
    167243        scsi_read_capacity_10_data_t data;
    168         size_t data_len;
    169244        int rc;
    170245
     
    172247        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
    173248
    174         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    175             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);
    176256
    177257        if (rc != EOK) {
    178                 usb_log_error("Read Capacity (10) failed, device %s: %s.\n",
    179                    mfun->mdev->ddf_dev->name, str_error(rc));
    180                 return rc;
    181         }
    182 
    183         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)) {
    184270                usb_log_error("SCSI Read Capacity response too short (%zu).\n",
    185                     data_len);
     271                    cmd.rcvd_size);
    186272                return EIO;
    187273        }
     
    203289int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf)
    204290{
    205         scsi_cdb_read_12_t cdb;
    206         size_t data_len;
    207         int rc;
    208 
    209         /* XXX Need softstate to store block size. */
     291        scsi_cmd_t cmd;
     292        scsi_cdb_read_10_t cdb;
     293        int rc;
    210294
    211295        if (ba > UINT32_MAX)
    212296                return ELIMIT;
    213297
    214         if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)
     298        if (nblocks > UINT16_MAX)
    215299                return ELIMIT;
    216300
    217301        memset(&cdb, 0, sizeof(cdb));
    218         cdb.op_code = SCSI_CMD_READ_12;
     302        cdb.op_code = SCSI_CMD_READ_10;
    219303        cdb.lba = host2uint32_t_be(ba);
    220         cdb.xfer_len = host2uint32_t_be(nblocks);
    221 
    222         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    223             sizeof(cdb), buf, nblocks * mfun->block_size, &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);
    224313
    225314        if (rc != EOK) {
    226                 usb_log_error("Read (12) failed, device %s: %s.\n",
    227                    mfun->mdev->ddf_dev->name, str_error(rc));
    228                 return rc;
    229         }
    230 
    231         if (data_len < nblocks * mfun->block_size) {
     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) {
    232327                usb_log_error("SCSI Read response too short (%zu).\n",
    233                     data_len);
     328                    cmd.rcvd_size);
    234329                return EIO;
    235330        }
     
    250345    const void *data)
    251346{
    252         scsi_cdb_write_12_t cdb;
    253         size_t sent_len;
     347        scsi_cmd_t cmd;
     348        scsi_cdb_write_10_t cdb;
    254349        int rc;
    255350
     
    257352                return ELIMIT;
    258353
    259         if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)
     354        if (nblocks > UINT16_MAX)
    260355                return ELIMIT;
    261356
    262357        memset(&cdb, 0, sizeof(cdb));
    263         cdb.op_code = SCSI_CMD_WRITE_12;
     358        cdb.op_code = SCSI_CMD_WRITE_10;
    264359        cdb.lba = host2uint32_t_be(ba);
    265         cdb.xfer_len = host2uint32_t_be(nblocks);
    266 
    267         rc = usb_massstor_data_out(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    268             sizeof(cdb), data, nblocks * mfun->block_size, &sent_len);
     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);
    269369
    270370        if (rc != EOK) {
    271                 usb_log_error("Write (12) failed, device %s: %s.\n",
    272                    mfun->mdev->ddf_dev->name, str_error(rc));
    273                 return rc;
    274         }
    275 
    276         if (sent_len < nblocks * mfun->block_size) {
    277                 usb_log_error("SCSI Write not all bytes transferred (%zu).\n",
    278                     sent_len);
     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);
    279379                return EIO;
    280380        }
Note: See TracChangeset for help on using the changeset viewer.