Changes in uspace/drv/bus/usb/usbmast/main.c [5203e256:38c9505] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbmast/main.c
r5203e256 r38c9505 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> … … 41 46 #include <str_error.h> 42 47 #include "cmds.h" 43 #include "scsi.h"44 48 #include "mast.h" 49 #include "scsi_ms.h" 45 50 46 51 #define NAME "usbmast" 47 48 #define BULK_IN_EP 049 #define BULK_OUT_EP 150 52 51 53 #define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe) … … 75 77 }; 76 78 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 77 97 /** Callback when new device is attached and recognized as a mass storage. 78 98 * … … 83 103 { 84 104 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", 105 const char *fun_name = "a"; 106 ddf_fun_t *fun = NULL; 107 usbmast_fun_t *msfun = NULL; 108 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; 115 } 116 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", 101 129 dev->ddf_dev->name); 102 130 usb_log_debug(" Bulk in endpoint: %d [%zuB].\n", … … 107 135 (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size); 108 136 137 usb_log_debug("Get LUN count...\n"); 109 138 size_t lun_count = usb_masstor_get_lun_count(dev); 110 139 111 usb_massstor_inquiry_result_t inquiry; 112 rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry); 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); 113 149 if (rc != EOK) { 114 usb_log_warning("Failed to inquir ydevice `%s': %s.\n",150 usb_log_warning("Failed to inquire device `%s': %s.\n", 115 151 dev->ddf_dev->name, str_error(rc)); 116 return EOK; 152 rc = EIO; 153 goto error; 117 154 } 118 155 119 156 usb_log_info("Mass storage `%s': " \ 120 " `%s' by `%s'is %s (%s), %zu LUN(s).\n",157 "%s by %s rev. %s is %s (%s), %zu LUN(s).\n", 121 158 dev->ddf_dev->name, 122 inquiry.product_and_revision, inquiry.vendor_id, 123 usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type), 159 inquiry.product, 160 inquiry.vendor, 161 inquiry.revision, 162 usbmast_scsi_dev_type_str(inquiry.device_type), 124 163 inquiry.removable ? "removable" : "non-removable", 125 164 lun_count); 126 165 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 127 190 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 } 128 269 } 129 270
Note:
See TracChangeset
for help on using the changeset viewer.