Ignore:
File:
1 edited

Legend:

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

    r38c9505 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>
     
    4641#include <str_error.h>
    4742#include "cmds.h"
     43#include "scsi.h"
    4844#include "mast.h"
    49 #include "scsi_ms.h"
    5045
    5146#define NAME "usbmast"
     47
     48#define BULK_IN_EP 0
     49#define BULK_OUT_EP 1
    5250
    5351#define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
     
    7775};
    7876
    79 /** Mass storage function.
    80  *
    81  * Serves as soft state for function/LUN.
    82  */
    83 typedef 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 
    94 static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
    95     void *arg);
    96 
    9777/** Callback when new device is attached and recognized as a mass storage.
    9878 *
     
    10383{
    10484        int rc;
    105         const char *fun_name = "a";
    106         ddf_fun_t *fun = NULL;
    107         usbmast_fun_t *msfun = NULL;
     85        const char *fun_name = "ctl";
    10886
    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;
     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;
    11598        }
    11699
    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",
     100        usb_log_info("Pretending to control mass storage `%s'.\n",
    129101            dev->ddf_dev->name);
    130102        usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
     
    135107            (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
    136108
    137         usb_log_debug("Get LUN count...\n");
    138109        size_t lun_count = usb_masstor_get_lun_count(dev);
    139110
    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);
     111        usb_massstor_inquiry_result_t inquiry;
     112        rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
    149113        if (rc != EOK) {
    150                 usb_log_warning("Failed to inquire device `%s': %s.\n",
     114                usb_log_warning("Failed to inquiry device `%s': %s.\n",
    151115                    dev->ddf_dev->name, str_error(rc));
    152                 rc = EIO;
    153                 goto error;
     116                return EOK;
    154117        }
    155118
    156119        usb_log_info("Mass storage `%s': " \
    157             "%s by %s rev. %s is %s (%s), %zu LUN(s).\n",
     120            "`%s' by `%s' is %s (%s), %zu LUN(s).\n",
    158121            dev->ddf_dev->name,
    159             inquiry.product,
    160             inquiry.vendor,
    161             inquiry.revision,
    162             usbmast_scsi_dev_type_str(inquiry.device_type),
     122            inquiry.product_and_revision, inquiry.vendor_id,
     123            usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
    163124            inquiry.removable ? "removable" : "non-removable",
    164125            lun_count);
    165126
    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 
    190127        return EOK;
    191 
    192         /* Error cleanup */
    193 error:
    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. */
    202 static 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         }
    269128}
    270129
Note: See TracChangeset for help on using the changeset viewer.