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

Changeset 38c9505 in mainline


Ignore:
Timestamp:
2011-07-06T21:38:42Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
026793d
Parents:
ff65e91
Message:

Write support in USB mass storage driver.

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

Legend:

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

    rff65e91 r38c9505  
    4242void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
    4343    uint32_t tag, uint32_t transfer_length, usb_direction_t dir,
    44     uint8_t lun, uint8_t cmd_len, uint8_t *cmd)
     44    uint8_t lun, uint8_t cmd_len, const uint8_t *cmd)
    4545{
    4646        cbw->dCBWSignature = uint32_host2usb(0x43425355);
  • uspace/drv/bus/usb/usbmast/cmds.h

    rff65e91 r38c9505  
    5858
    5959extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t,
    60     usb_direction_t, uint8_t, uint8_t, uint8_t *);
     60    usb_direction_t, uint8_t, uint8_t, const uint8_t *);
    6161
    6262#endif
  • uspace/drv/bus/usb/usbmast/main.c

    rff65e91 r38c9505  
    214214        int retval;
    215215
    216         usb_log_debug("usbmast_bd_connection()\n");
    217 
    218216        async_answer_0(iid, EOK);
    219217
     
    259257                        break;
    260258                case BD_WRITE_BLOCKS:
    261                         usb_log_debug("usbmast_bd_connection() - BD_WRITE_BLOCKS\n");
    262 /*                      ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
     259                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    263260                        cnt = IPC_GET_ARG3(call);
    264                         retval = 0;
     261                        retval = usbmast_write(msfun->usb_dev, ba, cnt,
     262                            msfun->block_size, comm_buf);
    265263                        async_answer_0(callid, retval);
    266                         break;*/
     264                        break;
    267265                default:
    268266                        async_answer_0(callid, EINVAL);
  • uspace/drv/bus/usb/usbmast/mast.c

    rff65e91 r38c9505  
    5151        } while (false)
    5252
    53 /** Request data from mass storage device.
    54  *
    55  * @param tag Command block wrapper tag (automatically compared with answer).
    56  * @param lun LUN index.
    57  * @param cmd SCSI command buffer (in SCSI endianness).
    58  * @param cmd_size Length of SCSI command @p cmd in bytes.
    59  * @param in_buffer Buffer where to store the answer (CSW is not returned).
    60  * @param in_buffer_size Size of the buffer (size of the request to the device).
    61  * @param received_size Number of actually received bytes.
    62  * @return Error code.
    63  */
    64 int usb_massstor_data_in(usb_device_t *dev,
    65     uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
    66     void *in_buffer, size_t in_buffer_size, size_t *received_size)
     53/** Send command via bulk-only transport.
     54 *
     55 * @param tag           Command block wrapper tag (automatically compared
     56 *                      with answer)
     57 * @param lun           LUN
     58 * @param cmd           Command block
     59 * @param cmd_size      Command block size in bytes
     60 * @param ddir          Direction in which data will be transferred
     61 * @param dbuf          Data send/receive buffer
     62 * @param dbuf_size     Size of the data buffer
     63 * @param xferred_size  Number of bytes actually transferred
     64 *
     65 * @return              Error code
     66 */
     67static int usb_massstor_cmd(usb_device_t *dev, uint32_t tag, uint8_t lun,
     68    const void *cmd, size_t cmd_size, usb_direction_t ddir, void *dbuf,
     69    size_t dbuf_size, size_t *xferred_size)
    6770{
    6871        int rc;
     
    7376        /* Prepare CBW - command block wrapper */
    7477        usb_massstor_cbw_t cbw;
    75         usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,
    76             USB_DIRECTION_IN, lun, cmd_size, cmd);
    77 
    78         /* First, send the CBW. */
     78        usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, lun, cmd_size,
     79            cmd);
     80
     81        /* Send the CBW. */
    7982        rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
    8083        MASTLOG("CBW '%s' sent: %s.\n",
     
    8588        }
    8689
    87         /* Try to retrieve the data from the device. */
    88         act_size = 0;
    89         rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size);
    90         MASTLOG("Received %zuB (%s): %s.\n", act_size,
    91             usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0),
    92             str_error(rc));
     90        if (ddir == USB_DIRECTION_IN) {
     91                /* Recieve data from the device. */
     92                rc = usb_pipe_read(bulk_in_pipe, dbuf, dbuf_size, &act_size);
     93                MASTLOG("Received %zu bytes (%s): %s.\n", act_size,
     94                    usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
     95                    str_error(rc));
     96        } else {
     97                /* Send data to the device. */
     98                rc = usb_pipe_write(bulk_out_pipe, dbuf, dbuf_size);
     99                MASTLOG("Sent %zu bytes (%s): %s.\n", act_size,
     100                    usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
     101                    str_error(rc));
     102        }
     103
    93104        if (rc != EOK) {
    94105                /*
     
    103114        size_t csw_size;
    104115        rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
    105         MASTLOG("CSW '%s' received (%zuB): %s.\n",
     116        MASTLOG("CSW '%s' received (%zu bytes): %s.\n",
    106117            usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
    107118            str_error(rc));
     
    132143
    133144        size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
    134         if (residue > in_buffer_size) {
    135                 MASTLOG("residue > in_buffer_size\n");
     145        if (residue > dbuf_size) {
     146                MASTLOG("residue > dbuf_size\n");
    136147                return ERANGE;
    137148        }
    138149
    139150        /*
    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.
     151         * When the device has less data to send than requested (or cannot
     152         * receive moredata), it can either stall the pipe or send garbage
     153         * (ignore data) and indicate that via the residue field in CSW.
     154         * That means dbuf_size - residue is the authoritative size of data
     155         * received (sent).
    144156         */
    145157
    146         if (received_size != NULL) {
    147                 *received_size = in_buffer_size - residue;
    148         }
     158        if (xferred_size != NULL)
     159                *xferred_size = dbuf_size - residue;
    149160
    150161        return EOK;
     162}
     163
     164/** Perform data-in command.
     165 *
     166 * @param tag           Command block wrapper tag (automatically compared with
     167 *                      answer)
     168 * @param lun           LUN
     169 * @param cmd           CDB (Command Descriptor)
     170 * @param cmd_size      CDB length in bytes
     171 * @param dbuf          Data receive buffer
     172 * @param dbuf_size     Data receive buffer size in bytes
     173 * @param proc_size     Number of bytes actually processed by device
     174 *
     175 * @return Error code
     176 */
     177int usb_massstor_data_in(usb_device_t *dev, uint32_t tag, uint8_t lun,
     178    const void *cmd, size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size)
     179{
     180        return usb_massstor_cmd(dev, tag, lun, cmd, cmd_size, USB_DIRECTION_IN,
     181            dbuf, dbuf_size, proc_size);
     182}
     183
     184/** Perform data-out command.
     185 *
     186 * @param tag           Command block wrapper tag (automatically compared with
     187 *                      answer)
     188 * @param lun           LUN
     189 * @param cmd           CDB (Command Descriptor)
     190 * @param cmd_size      CDB length in bytes
     191 * @param data          Command data
     192 * @param data_size     Size of @a data in bytes
     193 * @param proc_size     Number of bytes actually processed by device
     194 *
     195 * @return Error code
     196 */
     197int usb_massstor_data_out(usb_device_t *dev, uint32_t tag, uint8_t lun,
     198    const void *cmd, size_t cmd_size, const void *data, size_t data_size,
     199    size_t *proc_size)
     200{
     201        return usb_massstor_cmd(dev, tag, lun, cmd, cmd_size, USB_DIRECTION_OUT,
     202            (void *) data, data_size, proc_size);
    151203}
    152204
  • uspace/drv/bus/usb/usbmast/mast.h

    rff65e91 r38c9505  
    4646#define BULK_OUT_EP 1
    4747
    48 int usb_massstor_data_in(usb_device_t *dev, uint32_t, uint8_t, void *,
     48extern int usb_massstor_data_in(usb_device_t *, uint32_t, uint8_t, const void *,
    4949    size_t, void *, size_t, size_t *);
    50 int usb_massstor_reset(usb_device_t *);
    51 void usb_massstor_reset_recovery(usb_device_t *);
    52 int usb_massstor_get_max_lun(usb_device_t *);
    53 size_t usb_masstor_get_lun_count(usb_device_t *);
     50extern int usb_massstor_data_out(usb_device_t *, uint32_t, uint8_t, const void *,
     51    size_t, const void *, size_t, size_t *);
     52extern int usb_massstor_reset(usb_device_t *);
     53extern void usb_massstor_reset_recovery(usb_device_t *);
     54extern int usb_massstor_get_max_lun(usb_device_t *);
     55extern size_t usb_masstor_get_lun_count(usb_device_t *);
    5456
    5557#endif
  • uspace/drv/bus/usb/usbmast/scsi_ms.c

    rff65e91 r38c9505  
    239239}
    240240
     241/** Perform SCSI Write command on USB mass storage device.
     242 *
     243 * @param dev           USB device
     244 * @param ba            Address of first block
     245 * @param nblocks       Number of blocks to read
     246 * @param bsize         Block size
     247 * @param data          Data to write
     248 *
     249 * @return              Error code
     250 */
     251int usbmast_write(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,
     252    const void *data)
     253{
     254        scsi_cdb_write_12_t cdb;
     255        size_t sent_len;
     256        int rc;
     257
     258        /* XXX Need softstate to store block size. */
     259
     260        if (ba > UINT32_MAX)
     261                return ELIMIT;
     262
     263        if ((uint64_t)nblocks * bsize > UINT32_MAX)
     264                return ELIMIT;
     265
     266        memset(&cdb, 0, sizeof(cdb));
     267        cdb.op_code = SCSI_CMD_WRITE_12;
     268        cdb.lba = host2uint32_t_be(ba);
     269        cdb.xfer_len = host2uint32_t_be(nblocks);
     270
     271        rc = usb_massstor_data_out(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     272            sizeof(cdb), data, nblocks * bsize, &sent_len);
     273
     274        if (rc != EOK) {
     275                usb_log_error("Write (12) failed, device %s: %s.\n",
     276                   dev->ddf_dev->name, str_error(rc));
     277                return rc;
     278        }
     279
     280        if (sent_len < nblocks * bsize) {
     281                usb_log_error("SCSI Write not all bytes transferred (%zu).\n",
     282                    sent_len);
     283                return EIO;
     284        }
     285
     286        return EOK;
     287}
     288
    241289/**
    242290 * @}
  • uspace/drv/bus/usb/usbmast/scsi_ms.h

    rff65e91 r38c9505  
    6363extern int usbmast_read_capacity(usb_device_t *, uint32_t *, uint32_t *);
    6464extern int usbmast_read(usb_device_t *, uint64_t, size_t, size_t, void *);
     65extern int usbmast_write(usb_device_t *, uint64_t, size_t, size_t,
     66    const void *);
    6567extern const char *usbmast_scsi_dev_type_str(unsigned);
    6668
Note: See TracChangeset for help on using the changeset viewer.