Changeset bd5f3b7 in mainline for uspace/drv/bus/usb/usbmast/main.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/main.c

    r86a34d3e rbd5f3b7  
    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>
     
    4045#include <errno.h>
    4146#include <str_error.h>
    42 #include "cmds.h"
    43 #include "mast.h"
     47#include "cmdw.h"
     48#include "bo_trans.h"
    4449#include "scsi_ms.h"
     50#include "usbmast.h"
    4551
    4652#define NAME "usbmast"
     
    7278};
    7379
     80static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
     81static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
     82    void *arg);
     83
    7484/** Callback when new device is attached and recognized as a mass storage.
    7585 *
     
    8090{
    8191        int rc;
    82         const char *fun_name = "ctl";
    83 
    84         ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
    85             fun_name);
    86         if (ctl_fun == NULL) {
    87                 usb_log_error("Failed to create control function.\n");
    88                 return ENOMEM;
    89         }
    90         rc = ddf_fun_bind(ctl_fun);
    91         if (rc != EOK) {
    92                 usb_log_error("Failed to bind control function: %s.\n",
    93                     str_error(rc));
    94                 return rc;
    95         }
    96 
    97         usb_log_info("Pretending to control mass storage `%s'.\n",
     92        usbmast_dev_t *mdev = NULL;
     93        unsigned i;
     94
     95        /* Allocate softstate */
     96        mdev = calloc(1, sizeof(usbmast_dev_t));
     97        if (mdev == NULL) {
     98                usb_log_error("Failed allocating softstate.\n");
     99                rc = ENOMEM;
     100                goto error;
     101        }
     102
     103        mdev->ddf_dev = dev->ddf_dev;
     104        mdev->usb_dev = dev;
     105
     106        usb_log_info("Initializing mass storage `%s'.\n",
    98107            dev->ddf_dev->name);
    99108        usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
     
    105114
    106115        usb_log_debug("Get LUN count...\n");
    107         size_t lun_count = usb_masstor_get_lun_count(dev);
     116        mdev->luns = usb_masstor_get_lun_count(mdev);
     117
     118        for (i = 0; i < mdev->luns; i++) {
     119                rc = usbmast_fun_create(mdev, i);
     120                if (rc != EOK)
     121                        goto error;
     122        }
     123
     124        return EOK;
     125error:
     126        /* XXX Destroy functions */
     127        if (mdev != NULL)
     128                free(mdev);
     129        return rc;
     130}
     131
     132/** Create mass storage function.
     133 *
     134 * Called once for each LUN.
     135 *
     136 * @param mdev          Mass storage device
     137 * @param lun           LUN
     138 * @return              EOK on success or negative error code.
     139 */
     140static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun)
     141{
     142        int rc;
     143        char *fun_name = NULL;
     144        ddf_fun_t *fun = NULL;
     145        usbmast_fun_t *mfun = NULL;
     146
     147        /* Allocate softstate */
     148        mfun = calloc(1, sizeof(usbmast_fun_t));
     149        if (mfun == NULL) {
     150                usb_log_error("Failed allocating softstate.\n");
     151                rc = ENOMEM;
     152                goto error;
     153        }
     154
     155        mfun->mdev = mdev;
     156        mfun->lun = lun;
     157
     158        if (asprintf(&fun_name, "l%u", lun) < 0) {
     159                usb_log_error("Out of memory.\n");
     160                rc = ENOMEM;
     161                goto error;
     162        }
     163
     164        fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name);
     165        if (fun == NULL) {
     166                usb_log_error("Failed to create DDF function %s.\n", fun_name);
     167                rc = ENOMEM;
     168                goto error;
     169        }
     170
     171        free(fun_name);
     172        fun_name = NULL;
     173
     174        /* Set up a connection handler. */
     175        fun->conn_handler = usbmast_bd_connection;
     176        fun->driver_data = mfun;
    108177
    109178        usb_log_debug("Inquire...\n");
    110179        usbmast_inquiry_data_t inquiry;
    111         rc = usbmast_inquiry(dev, &inquiry);
     180        rc = usbmast_inquiry(mfun, &inquiry);
    112181        if (rc != EOK) {
    113182                usb_log_warning("Failed to inquire device `%s': %s.\n",
    114                     dev->ddf_dev->name, str_error(rc));
    115                 return EOK;
    116         }
    117 
    118         usb_log_info("Mass storage `%s': " \
    119             "%s by %s rev. %s is %s (%s), %zu LUN(s).\n",
    120             dev->ddf_dev->name,
     183                    mdev->ddf_dev->name, str_error(rc));
     184                rc = EIO;
     185                goto error;
     186        }
     187
     188        usb_log_info("Mass storage `%s' LUN %u: " \
     189            "%s by %s rev. %s is %s (%s).\n",
     190            mdev->ddf_dev->name,
     191            lun,
    121192            inquiry.product,
    122193            inquiry.vendor,
    123194            inquiry.revision,
    124195            usbmast_scsi_dev_type_str(inquiry.device_type),
    125             inquiry.removable ? "removable" : "non-removable",
    126             lun_count);
     196            inquiry.removable ? "removable" : "non-removable");
    127197
    128198        uint32_t nblocks, block_size;
    129199
    130         rc = usbmast_read_capacity(dev, &nblocks, &block_size);
     200        rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
    131201        if (rc != EOK) {
    132202                usb_log_warning("Failed to read capacity, device `%s': %s.\n",
    133                     dev->ddf_dev->name, str_error(rc));
    134                 return EOK;
     203                    mdev->ddf_dev->name, str_error(rc));
     204                rc = EIO;
     205                goto error;
    135206        }
    136207
     
    138209            "block_size=%" PRIu32 "\n", nblocks, block_size);
    139210
    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);
     211        mfun->nblocks = nblocks;
     212        mfun->block_size = block_size;
     213
     214        rc = ddf_fun_bind(fun);
    144215        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;
     216                usb_log_error("Failed to bind DDF function %s: %s.\n",
     217                    fun_name, str_error(rc));
     218                goto error;
    158219        }
    159220
    160221        return EOK;
     222
     223        /* Error cleanup */
     224error:
     225        if (fun != NULL)
     226                ddf_fun_destroy(fun);
     227        if (fun_name != NULL)
     228                free(fun_name);
     229        if (mfun != NULL)
     230                free(mfun);
     231        return rc;
     232}
     233
     234/** Blockdev client connection handler. */
     235static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
     236    void *arg)
     237{
     238        usbmast_fun_t *mfun;
     239        void *comm_buf = NULL;
     240        size_t comm_size;
     241        ipc_callid_t callid;
     242        ipc_call_t call;
     243        unsigned int flags;
     244        sysarg_t method;
     245        uint64_t ba;
     246        size_t cnt;
     247        int retval;
     248
     249        async_answer_0(iid, EOK);
     250
     251        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
     252                async_answer_0(callid, EHANGUP);
     253                return;
     254        }
     255
     256        comm_buf = as_get_mappable_page(comm_size);
     257        if (comm_buf == NULL) {
     258                async_answer_0(callid, EHANGUP);
     259                return;
     260        }
     261
     262        (void) async_share_out_finalize(callid, comm_buf);
     263
     264        mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
     265
     266        while (true) {
     267                callid = async_get_call(&call);
     268                method = IPC_GET_IMETHOD(call);
     269
     270                if (!method) {
     271                        /* The other side hung up. */
     272                        async_answer_0(callid, EOK);
     273                        return;
     274                }
     275
     276                switch (method) {
     277                case BD_GET_BLOCK_SIZE:
     278                        async_answer_1(callid, EOK, mfun->block_size);
     279                        break;
     280                case BD_GET_NUM_BLOCKS:
     281                        async_answer_2(callid, EOK, LOWER32(mfun->nblocks),
     282                            UPPER32(mfun->nblocks));
     283                        break;
     284                case BD_READ_BLOCKS:
     285                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
     286                        cnt = IPC_GET_ARG3(call);
     287                        retval = usbmast_read(mfun, ba, cnt, comm_buf);
     288                        async_answer_0(callid, retval);
     289                        break;
     290                case BD_WRITE_BLOCKS:
     291                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
     292                        cnt = IPC_GET_ARG3(call);
     293                        retval = usbmast_write(mfun, ba, cnt, comm_buf);
     294                        async_answer_0(callid, retval);
     295                        break;
     296                default:
     297                        async_answer_0(callid, EINVAL);
     298                }
     299        }
    161300}
    162301
Note: See TracChangeset for help on using the changeset viewer.