Ignore:
File:
1 edited

Legend:

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

    r2aceec5 rf7a55f9  
    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"
     42#include "cmds.h"
     43#include "mast.h"
    4944#include "scsi_ms.h"
    50 #include "usbmast.h"
    5145
    5246#define NAME "usbmast"
     
    7872};
    7973
    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 
    8474/** Callback when new device is attached and recognized as a mass storage.
    8575 *
     
    9080{
    9181        int rc;
    92         usbmast_dev_t *mdev = NULL;
    93         unsigned i;
     82        const char *fun_name = "ctl";
    9483
    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;
     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;
    10195        }
    10296
    103         mdev->ddf_dev = dev->ddf_dev;
    104         mdev->usb_dev = dev;
    105 
    106         usb_log_info("Initializing mass storage `%s'.\n",
     97        usb_log_info("Pretending to control mass storage `%s'.\n",
    10798            dev->ddf_dev->name);
    10899        usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
     
    114105
    115106        usb_log_debug("Get LUN count...\n");
    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;
    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;
     107        size_t lun_count = usb_masstor_get_lun_count(dev);
    177108
    178109        usb_log_debug("Inquire...\n");
    179110        usbmast_inquiry_data_t inquiry;
    180         rc = usbmast_inquiry(mfun, &inquiry);
     111        rc = usbmast_inquiry(dev, &inquiry);
    181112        if (rc != EOK) {
    182113                usb_log_warning("Failed to inquire device `%s': %s.\n",
    183                     mdev->ddf_dev->name, str_error(rc));
    184                 rc = EIO;
    185                 goto error;
     114                    dev->ddf_dev->name, str_error(rc));
     115                return EOK;
    186116        }
    187117
    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,
     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,
    192121            inquiry.product,
    193122            inquiry.vendor,
    194123            inquiry.revision,
    195124            usbmast_scsi_dev_type_str(inquiry.device_type),
    196             inquiry.removable ? "removable" : "non-removable");
     125            inquiry.removable ? "removable" : "non-removable",
     126            lun_count);
    197127
    198128        uint32_t nblocks, block_size;
    199129
    200         rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
     130        rc = usbmast_read_capacity(dev, &nblocks, &block_size);
    201131        if (rc != EOK) {
    202132                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;
     133                    dev->ddf_dev->name, str_error(rc));
     134                return EOK;
    206135        }
    207136
     
    209138            "block_size=%" PRIu32 "\n", nblocks, block_size);
    210139
    211         mfun->nblocks = nblocks;
    212         mfun->block_size = block_size;
     140        usb_log_info("Doing test read of block 0.\n");
     141        static uint8_t bdata[512];
    213142
    214         rc = ddf_fun_bind(fun);
     143        rc = usbmast_read(dev, 0, 1, 512, &bdata);
    215144        if (rc != EOK) {
    216                 usb_log_error("Failed to bind DDF function %s: %s.\n",
    217                     fun_name, str_error(rc));
    218                 goto error;
     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;
    219158        }
    220159
    221160        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         }
    300161}
    301162
Note: See TracChangeset for help on using the changeset viewer.