Changes in uspace/drv/bus/usb/usbmast/main.c [f7a55f9:2aceec5] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbmast/main.c
rf7a55f9 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 "cmd s.h"43 #include " mast.h"47 #include "cmdw.h" 48 #include "bo_trans.h" 44 49 #include "scsi_ms.h" 50 #include "usbmast.h" 45 51 46 52 #define NAME "usbmast" … … 72 78 }; 73 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 74 84 /** Callback when new device is attached and recognized as a mass storage. 75 85 * … … 80 90 { 81 91 int rc; 82 const char *fun_name = "ctl"; 83 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; 95 } 96 97 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", 98 107 dev->ddf_dev->name); 99 108 usb_log_debug(" Bulk in endpoint: %d [%zuB].\n", … … 105 114 106 115 usb_log_debug("Get LUN count...\n"); 107 size_t lun_count = usb_masstor_get_lun_count(dev); 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; 108 177 109 178 usb_log_debug("Inquire...\n"); 110 179 usbmast_inquiry_data_t inquiry; 111 rc = usbmast_inquiry( dev, &inquiry);180 rc = usbmast_inquiry(mfun, &inquiry); 112 181 if (rc != EOK) { 113 182 usb_log_warning("Failed to inquire device `%s': %s.\n", 114 dev->ddf_dev->name, str_error(rc)); 115 return EOK; 116 } 117 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, 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, 121 192 inquiry.product, 122 193 inquiry.vendor, 123 194 inquiry.revision, 124 195 usbmast_scsi_dev_type_str(inquiry.device_type), 125 inquiry.removable ? "removable" : "non-removable", 126 lun_count); 196 inquiry.removable ? "removable" : "non-removable"); 127 197 128 198 uint32_t nblocks, block_size; 129 199 130 rc = usbmast_read_capacity( dev, &nblocks, &block_size);200 rc = usbmast_read_capacity(mfun, &nblocks, &block_size); 131 201 if (rc != EOK) { 132 202 usb_log_warning("Failed to read capacity, device `%s': %s.\n", 133 dev->ddf_dev->name, str_error(rc)); 134 return EOK; 203 mdev->ddf_dev->name, str_error(rc)); 204 rc = EIO; 205 goto error; 135 206 } 136 207 … … 138 209 "block_size=%" PRIu32 "\n", nblocks, block_size); 139 210 140 usb_log_info("Doing test read of block 0.\n");141 static uint8_t bdata[512];142 143 rc = usbmast_read(dev, 0, 1, 512, &bdata);211 mfun->nblocks = nblocks; 212 mfun->block_size = block_size; 213 214 rc = ddf_fun_bind(fun); 144 215 if (rc != EOK) { 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; 216 usb_log_error("Failed to bind DDF function %s: %s.\n", 217 fun_name, str_error(rc)); 218 goto error; 158 219 } 159 220 160 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 } 161 300 } 162 301
Note:
See TracChangeset
for help on using the changeset viewer.