Changeset 2aceec5 in mainline for uspace/drv/bus/usb/usbmast/main.c


Ignore:
Timestamp:
2011-07-15T21:24:35Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4118f5f, 8ad496d
Parents:
e6b32a8
Message:

Support multiple LUNs in mass storage driver.

File:
1 edited

Legend:

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

    re6b32a8 r2aceec5  
    7878};
    7979
     80static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
    8081static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
    8182    void *arg);
     
    8990{
    9091        int rc;
    91         const char *fun_name = "a";
    92         ddf_fun_t *fun = NULL;
    93         usbmast_fun_t *msfun = NULL;
     92        usbmast_dev_t *mdev = NULL;
     93        unsigned i;
    9494
    9595        /* Allocate softstate */
    96         msfun = calloc(1, sizeof(usbmast_fun_t));
    97         if (msfun == NULL) {
     96        mdev = calloc(1, sizeof(usbmast_dev_t));
     97        if (mdev == NULL) {
    9898                usb_log_error("Failed allocating softstate.\n");
    9999                rc = ENOMEM;
     
    101101        }
    102102
    103         msfun->usb_dev = dev;
    104         msfun->lun = 0;
    105 
    106         fun = ddf_fun_create(dev->ddf_dev, fun_exposed, fun_name);
    107         if (fun == NULL) {
    108                 usb_log_error("Failed to create DDF function %s.\n", fun_name);
    109                 rc = ENOMEM;
    110                 goto error;
    111         }
    112 
    113         /* Set up a connection handler. */
    114         fun->conn_handler = usbmast_bd_connection;
    115         fun->driver_data = msfun;
     103        mdev->ddf_dev = dev->ddf_dev;
     104        mdev->usb_dev = dev;
    116105
    117106        usb_log_info("Initializing mass storage `%s'.\n",
     
    125114
    126115        usb_log_debug("Get LUN count...\n");
    127         size_t lun_count = usb_masstor_get_lun_count(msfun);
    128 
    129         /* XXX Handle more than one LUN properly. */
    130         if (lun_count > 1) {
    131                 usb_log_warning ("Mass storage has %zu LUNs. Ignoring all "
    132                     "but first.\n", lun_count);
    133         }
     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;
    134177
    135178        usb_log_debug("Inquire...\n");
    136179        usbmast_inquiry_data_t inquiry;
    137         rc = usbmast_inquiry(msfun, &inquiry);
     180        rc = usbmast_inquiry(mfun, &inquiry);
    138181        if (rc != EOK) {
    139182                usb_log_warning("Failed to inquire device `%s': %s.\n",
    140                     dev->ddf_dev->name, str_error(rc));
     183                    mdev->ddf_dev->name, str_error(rc));
    141184                rc = EIO;
    142185                goto error;
    143186        }
    144187
    145         usb_log_info("Mass storage `%s': " \
    146             "%s by %s rev. %s is %s (%s), %zu LUN(s).\n",
    147             dev->ddf_dev->name,
     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,
    148192            inquiry.product,
    149193            inquiry.vendor,
    150194            inquiry.revision,
    151195            usbmast_scsi_dev_type_str(inquiry.device_type),
    152             inquiry.removable ? "removable" : "non-removable",
    153             lun_count);
     196            inquiry.removable ? "removable" : "non-removable");
    154197
    155198        uint32_t nblocks, block_size;
    156199
    157         rc = usbmast_read_capacity(msfun, &nblocks, &block_size);
     200        rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
    158201        if (rc != EOK) {
    159202                usb_log_warning("Failed to read capacity, device `%s': %s.\n",
    160                     dev->ddf_dev->name, str_error(rc));
     203                    mdev->ddf_dev->name, str_error(rc));
    161204                rc = EIO;
    162205                goto error;
     
    166209            "block_size=%" PRIu32 "\n", nblocks, block_size);
    167210
    168         msfun->nblocks = nblocks;
    169         msfun->block_size = block_size;
     211        mfun->nblocks = nblocks;
     212        mfun->block_size = block_size;
    170213
    171214        rc = ddf_fun_bind(fun);
     
    182225        if (fun != NULL)
    183226                ddf_fun_destroy(fun);
    184         if (msfun != NULL)
    185                 free(msfun);
     227        if (fun_name != NULL)
     228                free(fun_name);
     229        if (mfun != NULL)
     230                free(mfun);
    186231        return rc;
    187232}
     
    191236    void *arg)
    192237{
    193         usbmast_fun_t *msfun;
     238        usbmast_fun_t *mfun;
    194239        void *comm_buf = NULL;
    195240        size_t comm_size;
     
    217262        (void) async_share_out_finalize(callid, comm_buf);
    218263
    219         msfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
     264        mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
    220265
    221266        while (true) {
     
    231276                switch (method) {
    232277                case BD_GET_BLOCK_SIZE:
    233                         async_answer_1(callid, EOK, msfun->block_size);
     278                        async_answer_1(callid, EOK, mfun->block_size);
    234279                        break;
    235280                case BD_GET_NUM_BLOCKS:
    236                         async_answer_2(callid, EOK, LOWER32(msfun->nblocks),
    237                             UPPER32(msfun->nblocks));
     281                        async_answer_2(callid, EOK, LOWER32(mfun->nblocks),
     282                            UPPER32(mfun->nblocks));
    238283                        break;
    239284                case BD_READ_BLOCKS:
    240285                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    241286                        cnt = IPC_GET_ARG3(call);
    242                         retval = usbmast_read(msfun, ba, cnt, comm_buf);
     287                        retval = usbmast_read(mfun, ba, cnt, comm_buf);
    243288                        async_answer_0(callid, retval);
    244289                        break;
     
    246291                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    247292                        cnt = IPC_GET_ARG3(call);
    248                         retval = usbmast_write(msfun, ba, cnt, comm_buf);
     293                        retval = usbmast_write(mfun, ba, cnt, comm_buf);
    249294                        async_answer_0(callid, retval);
    250295                        break;
Note: See TracChangeset for help on using the changeset viewer.