Changes in uspace/drv/bus/usb/usbmast/main.c [5203e256:2aceec5] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbmast/main.c
r5203e256 r2aceec5 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 34 35 * Main routines of USB mass storage driver. 35 36 */ 37 #include <as.h> 38 #include <async.h> 39 #include <ipc/bd.h> 40 #include <macros.h> 36 41 #include <usb/dev/driver.h> 37 42 #include <usb/debug.h> … … 40 45 #include <errno.h> 41 46 #include <str_error.h> 42 #include "cmds.h" 43 #include "scsi.h" 44 #include "mast.h" 47 #include "cmdw.h" 48 #include "bo_trans.h" 49 #include "scsi_ms.h" 50 #include "usbmast.h" 45 51 46 52 #define NAME "usbmast" 47 48 #define BULK_IN_EP 049 #define BULK_OUT_EP 150 53 51 54 #define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe) … … 75 78 }; 76 79 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 77 84 /** Callback when new device is attached and recognized as a mass storage. 78 85 * … … 83 90 { 84 91 int rc; 85 const char *fun_name = "ctl"; 86 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; 98 } 99 100 usb_log_info("Pretending to control mass storage `%s'.\n", 92 usbmast_dev_t *mdev = NULL; 93 unsigned i; 94 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; 101 } 102 103 mdev->ddf_dev = dev->ddf_dev; 104 mdev->usb_dev = dev; 105 106 usb_log_info("Initializing mass storage `%s'.\n", 101 107 dev->ddf_dev->name); 102 108 usb_log_debug(" Bulk in endpoint: %d [%zuB].\n", … … 107 113 (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size); 108 114 109 size_t lun_count = usb_masstor_get_lun_count(dev); 110 111 usb_massstor_inquiry_result_t inquiry; 112 rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry); 115 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; 177 178 usb_log_debug("Inquire...\n"); 179 usbmast_inquiry_data_t inquiry; 180 rc = usbmast_inquiry(mfun, &inquiry); 113 181 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; 117 } 118 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); 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 } 126 220 127 221 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 } 128 300 } 129 301
Note:
See TracChangeset
for help on using the changeset viewer.