Changeset 1916d1f in mainline for uspace/drv


Ignore:
Timestamp:
2011-07-12T13:41:26Z (15 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
50fc490
Parents:
11809eab (diff), 6817eba (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 changes.

Location:
uspace/drv/bus/usb
Files:
3 added
1 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/uhci/transfer_list.c

    r11809eab r1916d1f  
    141141        list_append(&batch->link, &instance->batch_list);
    142142
    143         usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
     143        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
    144144            batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name);
    145145        fibril_mutex_unlock(&instance->guard);
  • uspace/drv/bus/usb/usbmast/Makefile

    r11809eab r1916d1f  
    3232        $(LIBUSBDEV_PREFIX)/libusbdev.a \
    3333        $(LIBUSB_PREFIX)/libusb.a \
    34         $(LIBDRV_PREFIX)/libdrv.a
     34        $(LIBDRV_PREFIX)/libdrv.a \
     35        $(LIBSCSI_PREFIX)/libscsi.a
    3536
    3637EXTRA_CFLAGS += \
    3738        -I$(LIBUSB_PREFIX)/include \
    3839        -I$(LIBUSBDEV_PREFIX)/include \
    39         -I$(LIBDRV_PREFIX)/include
     40        -I$(LIBDRV_PREFIX)/include \
     41        -I$(LIBSCSI_PREFIX)/include
    4042
    4143BINARY = usbmast
    4244
    4345SOURCES = \
    44         inquiry.c \
     46        cmds.c \
    4547        main.c \
    46         mast.c
     48        mast.c \
     49        scsi_ms.c
    4750
    4851include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/bus/usb/usbmast/cmds.h

    r11809eab r1916d1f  
    5757} __attribute__((packed)) usb_massstor_csw_t;
    5858
    59 static inline void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
    60     uint32_t tag, uint32_t transfer_length, usb_direction_t dir,
    61     uint8_t lun, uint8_t cmd_len, uint8_t *cmd)
    62 {
    63         cbw->dCBWSignature = uint32_host2usb(0x43425355);
    64         cbw->dCBWTag = tag;
    65         cbw->dCBWDataTransferLength = transfer_length;
    66 
    67         cbw->bmCBWFlags = 0;
    68         if (dir == USB_DIRECTION_IN) {
    69                 cbw->bmCBWFlags |= (1 << 7);
    70         }
    71 
    72         /* Only lowest 4 bits. */
    73         cbw->bCBWLUN = lun & 0x0F;
    74 
    75         /* Only lowest 5 bits. */
    76         cbw->bCBWBLength = cmd_len & 0x1F;
    77 
    78         memcpy(cbw->CBWCB, cmd, cbw->bCBWBLength);
    79 }
     59extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t,
     60    usb_direction_t, uint8_t, uint8_t, const uint8_t *);
    8061
    8162#endif
  • uspace/drv/bus/usb/usbmast/main.c

    r11809eab r1916d1f  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3435 * Main routines of USB mass storage driver.
    3536 */
     37#include <as.h>
     38#include <async.h>
     39#include <ipc/bd.h>
     40#include <macros.h>
    3641#include <usb/dev/driver.h>
    3742#include <usb/debug.h>
     
    4146#include <str_error.h>
    4247#include "cmds.h"
    43 #include "scsi.h"
    4448#include "mast.h"
     49#include "scsi_ms.h"
    4550
    4651#define NAME "usbmast"
    47 
    48 #define BULK_IN_EP 0
    49 #define BULK_OUT_EP 1
    5052
    5153#define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
     
    7577};
    7678
     79/** Mass storage function.
     80 *
     81 * Serves as soft state for function/LUN.
     82 */
     83typedef struct {
     84        /** DDF function */
     85        ddf_fun_t *ddf_fun;
     86        /** Total number of blocks. */
     87        uint64_t nblocks;
     88        /** Block size in bytes. */
     89        size_t block_size;
     90        /** USB device function belongs to */
     91        usb_device_t *usb_dev;
     92} usbmast_fun_t;
     93
     94static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
     95    void *arg);
     96
    7797/** Callback when new device is attached and recognized as a mass storage.
    7898 *
     
    83103{
    84104        int rc;
    85         const char *fun_name = "ctl";
    86 
    87         ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
    88             fun_name);
    89         if (ctl_fun == NULL) {
    90                 usb_log_error("Failed to create control function.\n");
    91                 return ENOMEM;
    92         }
    93         rc = ddf_fun_bind(ctl_fun);
    94         if (rc != EOK) {
    95                 usb_log_error("Failed to bind control function: %s.\n",
    96                     str_error(rc));
    97                 return rc;
    98         }
    99 
    100         usb_log_info("Pretending to control mass storage `%s'.\n",
     105        const char *fun_name = "a";
     106        ddf_fun_t *fun = NULL;
     107        usbmast_fun_t *msfun = NULL;
     108
     109        /* Allocate softstate */
     110        msfun = calloc(1, sizeof(usbmast_fun_t));
     111        if (msfun == NULL) {
     112                usb_log_error("Failed allocating softstate.\n");
     113                rc = ENOMEM;
     114                goto error;
     115        }
     116
     117        fun = ddf_fun_create(dev->ddf_dev, fun_exposed, fun_name);
     118        if (fun == NULL) {
     119                usb_log_error("Failed to create DDF function %s.\n", fun_name);
     120                rc = ENOMEM;
     121                goto error;
     122        }
     123
     124        /* Set up a connection handler. */
     125        fun->conn_handler = usbmast_bd_connection;
     126        fun->driver_data = msfun;
     127
     128        usb_log_info("Initializing mass storage `%s'.\n",
    101129            dev->ddf_dev->name);
    102130        usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
     
    107135            (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
    108136
     137        usb_log_debug("Get LUN count...\n");
    109138        size_t lun_count = usb_masstor_get_lun_count(dev);
    110139
    111         usb_massstor_inquiry_result_t inquiry;
    112         rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
     140        /* XXX Handle more than one LUN properly. */
     141        if (lun_count > 1) {
     142                usb_log_warning ("Mass storage has %zu LUNs. Ignoring all "
     143                    "but first.\n", lun_count);
     144        }
     145
     146        usb_log_debug("Inquire...\n");
     147        usbmast_inquiry_data_t inquiry;
     148        rc = usbmast_inquiry(dev, &inquiry);
    113149        if (rc != EOK) {
    114                 usb_log_warning("Failed to inquiry device `%s': %s.\n",
     150                usb_log_warning("Failed to inquire device `%s': %s.\n",
    115151                    dev->ddf_dev->name, str_error(rc));
    116                 return EOK;
     152                rc = EIO;
     153                goto error;
    117154        }
    118155
    119156        usb_log_info("Mass storage `%s': " \
    120             "`%s' by `%s' is %s (%s), %zu LUN(s).\n",
     157            "%s by %s rev. %s is %s (%s), %zu LUN(s).\n",
    121158            dev->ddf_dev->name,
    122             inquiry.product_and_revision, inquiry.vendor_id,
    123             usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
     159            inquiry.product,
     160            inquiry.vendor,
     161            inquiry.revision,
     162            usbmast_scsi_dev_type_str(inquiry.device_type),
    124163            inquiry.removable ? "removable" : "non-removable",
    125164            lun_count);
    126165
     166        uint32_t nblocks, block_size;
     167
     168        rc = usbmast_read_capacity(dev, &nblocks, &block_size);
     169        if (rc != EOK) {
     170                usb_log_warning("Failed to read capacity, device `%s': %s.\n",
     171                    dev->ddf_dev->name, str_error(rc));
     172                rc = EIO;
     173                goto error;
     174        }
     175
     176        usb_log_info("Read Capacity: nblocks=%" PRIu32 ", "
     177            "block_size=%" PRIu32 "\n", nblocks, block_size);
     178
     179        msfun->nblocks = nblocks;
     180        msfun->block_size = block_size;
     181        msfun->usb_dev = dev;
     182
     183        rc = ddf_fun_bind(fun);
     184        if (rc != EOK) {
     185                usb_log_error("Failed to bind DDF function %s: %s.\n",
     186                    fun_name, str_error(rc));
     187                goto error;
     188        }
     189
    127190        return EOK;
     191
     192        /* Error cleanup */
     193error:
     194        if (fun != NULL)
     195                ddf_fun_destroy(fun);
     196        if (msfun != NULL)
     197                free(msfun);
     198        return rc;
     199}
     200
     201/** Blockdev client connection handler. */
     202static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
     203    void *arg)
     204{
     205        usbmast_fun_t *msfun;
     206        void *comm_buf = NULL;
     207        size_t comm_size;
     208        ipc_callid_t callid;
     209        ipc_call_t call;
     210        unsigned int flags;
     211        sysarg_t method;
     212        uint64_t ba;
     213        size_t cnt;
     214        int retval;
     215
     216        async_answer_0(iid, EOK);
     217
     218        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
     219                async_answer_0(callid, EHANGUP);
     220                return;
     221        }
     222
     223        comm_buf = as_get_mappable_page(comm_size);
     224        if (comm_buf == NULL) {
     225                async_answer_0(callid, EHANGUP);
     226                return;
     227        }
     228
     229        (void) async_share_out_finalize(callid, comm_buf);
     230
     231        msfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
     232
     233        while (true) {
     234                callid = async_get_call(&call);
     235                method = IPC_GET_IMETHOD(call);
     236
     237                if (!method) {
     238                        /* The other side hung up. */
     239                        async_answer_0(callid, EOK);
     240                        return;
     241                }
     242
     243                switch (method) {
     244                case BD_GET_BLOCK_SIZE:
     245                        async_answer_1(callid, EOK, msfun->block_size);
     246                        break;
     247                case BD_GET_NUM_BLOCKS:
     248                        async_answer_2(callid, EOK, LOWER32(msfun->nblocks),
     249                            UPPER32(msfun->nblocks));
     250                        break;
     251                case BD_READ_BLOCKS:
     252                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
     253                        cnt = IPC_GET_ARG3(call);
     254                        retval = usbmast_read(msfun->usb_dev, ba, cnt,
     255                            msfun->block_size, comm_buf);
     256                        async_answer_0(callid, retval);
     257                        break;
     258                case BD_WRITE_BLOCKS:
     259                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
     260                        cnt = IPC_GET_ARG3(call);
     261                        retval = usbmast_write(msfun->usb_dev, ba, cnt,
     262                            msfun->block_size, comm_buf);
     263                        async_answer_0(callid, retval);
     264                        break;
     265                default:
     266                        async_answer_0(callid, EINVAL);
     267                }
     268        }
    128269}
    129270
  • uspace/drv/bus/usb/usbmast/mast.c

    r11809eab r1916d1f  
    4242#include <usb/dev/request.h>
    4343
    44 bool usb_mast_verbose = true;
     44bool usb_mast_verbose = false;
    4545
    4646#define MASTLOG(format, ...) \
    4747        do { \
    4848                if (usb_mast_verbose) { \
    49                         usb_log_debug("USB cl08: " format, ##__VA_ARGS__); \
     49                        usb_log_debug2("USB cl08: " format, ##__VA_ARGS__); \
    5050                } \
    5151        } while (false)
    5252
    53 /** Request data from mass storage device.
    54  *
    55  * @param bulk_in_pipe Bulk in pipe to the device.
    56  * @param bulk_out_pipe Bulk out pipe to the device.
    57  * @param tag Command block wrapper tag (automatically compared with answer).
    58  * @param lun LUN index.
    59  * @param cmd SCSI command buffer (in SCSI endianness).
    60  * @param cmd_size Length of SCSI command @p cmd in bytes.
    61  * @param in_buffer Buffer where to store the answer (CSW is not returned).
    62  * @param in_buffer_size Size of the buffer (size of the request to the device).
    63  * @param received_size Number of actually received bytes.
    64  * @return Error code.
    65  */
    66 int usb_massstor_data_in(usb_device_t *dev,
    67     size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,
    68     uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
    69     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)
    7070{
    7171        int rc;
    7272        size_t act_size;
    73         usb_pipe_t *bulk_in_pipe = dev->pipes[bulk_in_pipe_index].pipe;
    74         usb_pipe_t *bulk_out_pipe = dev->pipes[bulk_out_pipe_index].pipe;
     73        usb_pipe_t *bulk_in_pipe = dev->pipes[BULK_IN_EP].pipe;
     74        usb_pipe_t *bulk_out_pipe = dev->pipes[BULK_OUT_EP].pipe;
    7575
    7676        /* Prepare CBW - command block wrapper */
    7777        usb_massstor_cbw_t cbw;
    78         usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,
    79             USB_DIRECTION_IN, lun, cmd_size, cmd);
    80 
    81         /* First, send the CBW. */
     78        usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, lun, cmd_size,
     79            cmd);
     80
     81        /* Send the CBW. */
    8282        rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
    8383        MASTLOG("CBW '%s' sent: %s.\n",
     
    8888        }
    8989
    90         /* Try to retrieve the data from the device. */
    91         act_size = 0;
    92         rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size);
    93         MASTLOG("Received %zuB (%s): %s.\n", act_size,
    94             usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0),
    95             str_error(rc));
    96         if (rc != EOK) {
     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
     104        if (rc != EOK) {
     105                /*
     106                 * XXX If the pipe is stalled, we should clear it
     107                 * and read CSW.
     108                 */
    97109                return rc;
    98110        }
     
    102114        size_t csw_size;
    103115        rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
    104         MASTLOG("CSW '%s' received (%zuB): %s.\n",
     116        MASTLOG("CSW '%s' received (%zu bytes): %s.\n",
    105117            usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
    106118            str_error(rc));
    107119        if (rc != EOK) {
    108                 return rc;
    109         }
     120                MASTLOG("rc != EOK\n");
     121                return rc;
     122        }
     123
    110124        if (csw_size != sizeof(csw)) {
     125                MASTLOG("csw_size != sizeof(csw)\n");
    111126                return ERANGE;
    112127        }
    113128
    114129        if (csw.dCSWTag != tag) {
     130                MASTLOG("csw.dCSWTag != tag\n");
    115131                return EBADCHECKSUM;
    116132        }
     
    120136         */
    121137        if (csw.dCSWStatus != 0) {
     138                MASTLOG("csw.dCSWStatus != 0\n");
    122139                // FIXME: better error code
    123140                // FIXME: distinguish 0x01 and 0x02
     
    126143
    127144        size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
    128         if (residue > in_buffer_size) {
     145        if (residue > dbuf_size) {
     146                MASTLOG("residue > dbuf_size\n");
    129147                return ERANGE;
    130148        }
    131         if (act_size != in_buffer_size - residue) {
    132                 return ERANGE;
    133         }
    134         if (received_size != NULL) {
    135                 *received_size = in_buffer_size - residue;
    136         }
     149
     150        /*
     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).
     156         */
     157
     158        if (xferred_size != NULL)
     159                *xferred_size = dbuf_size - residue;
    137160
    138161        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);
    139203}
    140204
     
    157221 *
    158222 * @param dev Device to be reseted.
    159  * @param bulk_in_idx Index of bulk in pipe.
    160  * @param bulk_out_idx Index of bulk out pipe.
    161  */
    162 void usb_massstor_reset_recovery(usb_device_t *dev,
    163     size_t bulk_in_idx, size_t bulk_out_idx)
     223 */
     224void usb_massstor_reset_recovery(usb_device_t *dev)
    164225{
    165226        /* We would ignore errors here because if this fails
     
    167228         */
    168229        usb_massstor_reset(dev);
    169         usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_in_idx].pipe);
    170         usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_out_idx].pipe);
     230        usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_IN_EP].pipe);
     231        usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_OUT_EP].pipe);
    171232}
    172233
  • uspace/drv/bus/usb/usbmast/mast.h

    r11809eab r1916d1f  
    3737#define USB_USBMAST_MAST_H_
    3838
     39#include <scsi/spc.h>
    3940#include <sys/types.h>
    4041#include <usb/usb.h>
     
    4243#include <usb/dev/driver.h>
    4344
    44 /** Result of SCSI INQUIRY command.
    45  * This is already parsed structure, not the original buffer returned by
    46  * the device.
    47  */
    48 typedef struct {
    49         /** SCSI peripheral device type. */
    50         int peripheral_device_type;
    51         /** Whether the device is removable. */
    52         bool removable;
    53         /** Vendor ID string. */
    54         char vendor_id[9];
    55         /** Product ID and product revision string. */
    56         char product_and_revision[12];
    57 } usb_massstor_inquiry_result_t;
     45#define BULK_IN_EP 0
     46#define BULK_OUT_EP 1
    5847
    59 int usb_massstor_data_in(usb_device_t *dev, size_t, size_t,
    60     uint32_t, uint8_t, void *, size_t, void *, size_t, size_t *);
    61 int usb_massstor_reset(usb_device_t *);
    62 void usb_massstor_reset_recovery(usb_device_t *, size_t, size_t);
    63 int usb_massstor_get_max_lun(usb_device_t *);
    64 size_t usb_masstor_get_lun_count(usb_device_t *);
    65 int usb_massstor_inquiry(usb_device_t *, size_t, size_t,
    66     usb_massstor_inquiry_result_t *);
    67 const char *usb_str_masstor_scsi_peripheral_device_type(int);
     48extern int usb_massstor_data_in(usb_device_t *, uint32_t, uint8_t, const void *,
     49    size_t, void *, size_t, size_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 *);
    6856
    6957#endif
Note: See TracChangeset for help on using the changeset viewer.