Ignore:
File:
1 edited

Legend:

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

    r2aceec5 r5203e256  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
    3  * Copyright (c) 2011 Jiri Svoboda
    43 * All rights reserved.
    54 *
     
    3534 * Main routines of USB mass storage driver.
    3635 */
    37 #include <as.h>
    38 #include <async.h>
    39 #include <ipc/bd.h>
    40 #include <macros.h>
    4136#include <usb/dev/driver.h>
    4237#include <usb/debug.h>
     
    4540#include <errno.h>
    4641#include <str_error.h>
    47 #include "cmdw.h"
    48 #include "bo_trans.h"
    49 #include "scsi_ms.h"
    50 #include "usbmast.h"
     42#include "cmds.h"
     43#include "scsi.h"
     44#include "mast.h"
    5145
    5246#define NAME "usbmast"
     47
     48#define BULK_IN_EP 0
     49#define BULK_OUT_EP 1
    5350
    5451#define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
     
    7875};
    7976
    80 static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
    81 static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
    82     void *arg);
    83 
    8477/** Callback when new device is attached and recognized as a mass storage.
    8578 *
     
    9083{
    9184        int rc;
    92         usbmast_dev_t *mdev = NULL;
    93         unsigned i;
     85        const char *fun_name = "ctl";
    9486
    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;
     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;
    10198        }
    10299
    103         mdev->ddf_dev = dev->ddf_dev;
    104         mdev->usb_dev = dev;
    105 
    106         usb_log_info("Initializing mass storage `%s'.\n",
     100        usb_log_info("Pretending to control mass storage `%s'.\n",
    107101            dev->ddf_dev->name);
    108102        usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
     
    113107            (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
    114108
    115         usb_log_debug("Get LUN count...\n");
    116         mdev->luns = usb_masstor_get_lun_count(mdev);
     109        size_t lun_count = usb_masstor_get_lun_count(dev);
    117110
    118         for (i = 0; i < mdev->luns; i++) {
    119                 rc = usbmast_fun_create(mdev, i);
    120                 if (rc != EOK)
    121                         goto error;
     111        usb_massstor_inquiry_result_t inquiry;
     112        rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
     113        if (rc != EOK) {
     114                usb_log_warning("Failed to inquiry device `%s': %s.\n",
     115                    dev->ddf_dev->name, str_error(rc));
     116                return EOK;
    122117        }
    123118
    124         return EOK;
    125 error:
    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  */
    140 static 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;
    177 
    178         usb_log_debug("Inquire...\n");
    179         usbmast_inquiry_data_t inquiry;
    180         rc = usbmast_inquiry(mfun, &inquiry);
    181         if (rc != EOK) {
    182                 usb_log_warning("Failed to inquire device `%s': %s.\n",
    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,
    192             inquiry.product,
    193             inquiry.vendor,
    194             inquiry.revision,
    195             usbmast_scsi_dev_type_str(inquiry.device_type),
    196             inquiry.removable ? "removable" : "non-removable");
    197 
    198         uint32_t nblocks, block_size;
    199 
    200         rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
    201         if (rc != EOK) {
    202                 usb_log_warning("Failed to read capacity, device `%s': %s.\n",
    203                     mdev->ddf_dev->name, str_error(rc));
    204                 rc = EIO;
    205                 goto error;
    206         }
    207 
    208         usb_log_info("Read Capacity: nblocks=%" PRIu32 ", "
    209             "block_size=%" PRIu32 "\n", nblocks, block_size);
    210 
    211         mfun->nblocks = nblocks;
    212         mfun->block_size = block_size;
    213 
    214         rc = ddf_fun_bind(fun);
    215         if (rc != EOK) {
    216                 usb_log_error("Failed to bind DDF function %s: %s.\n",
    217                     fun_name, str_error(rc));
    218                 goto error;
    219         }
     119        usb_log_info("Mass storage `%s': " \
     120            "`%s' by `%s' is %s (%s), %zu LUN(s).\n",
     121            dev->ddf_dev->name,
     122            inquiry.product_and_revision, inquiry.vendor_id,
     123            usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
     124            inquiry.removable ? "removable" : "non-removable",
     125            lun_count);
    220126
    221127        return EOK;
    222 
    223         /* Error cleanup */
    224 error:
    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. */
    235 static 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         }
    300128}
    301129
Note: See TracChangeset for help on using the changeset viewer.