Changes in uspace/drv/bus/usb/usbmast/main.c [2aceec5:5203e256] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbmast/main.c
r2aceec5 r5203e256 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jiri Svoboda4 3 * All rights reserved. 5 4 * … … 35 34 * Main routines of USB mass storage driver. 36 35 */ 37 #include <as.h>38 #include <async.h>39 #include <ipc/bd.h>40 #include <macros.h>41 36 #include <usb/dev/driver.h> 42 37 #include <usb/debug.h> … … 45 40 #include <errno.h> 46 41 #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" 51 45 52 46 #define NAME "usbmast" 47 48 #define BULK_IN_EP 0 49 #define BULK_OUT_EP 1 53 50 54 51 #define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe) … … 78 75 }; 79 76 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 84 77 /** Callback when new device is attached and recognized as a mass storage. 85 78 * … … 90 83 { 91 84 int rc; 92 usbmast_dev_t *mdev = NULL; 93 unsigned i; 85 const char *fun_name = "ctl"; 94 86 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; 101 98 } 102 99 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", 107 101 dev->ddf_dev->name); 108 102 usb_log_debug(" Bulk in endpoint: %d [%zuB].\n", … … 113 107 (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size); 114 108 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); 117 110 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; 122 117 } 123 118 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); 220 126 221 127 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 }300 128 } 301 129
Note:
See TracChangeset
for help on using the changeset viewer.