Changeset 1916d1f in mainline for uspace/drv
- Timestamp:
- 2011-07-12T13:41:26Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 50fc490
- Parents:
- 11809eab (diff), 6817eba (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/drv/bus/usb
- Files:
-
- 3 added
- 1 deleted
- 6 edited
-
uhci/transfer_list.c (modified) (1 diff)
-
usbmast/Makefile (modified) (1 diff)
-
usbmast/cmds.c (added)
-
usbmast/cmds.h (modified) (1 diff)
-
usbmast/inquiry.c (deleted)
-
usbmast/main.c (modified) (6 diffs)
-
usbmast/mast.c (modified) (7 diffs)
-
usbmast/mast.h (modified) (2 diffs)
-
usbmast/scsi_ms.c (added)
-
usbmast/scsi_ms.h (added)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/transfer_list.c
r11809eab r1916d1f 141 141 list_append(&batch->link, &instance->batch_list); 142 142 143 usb_log_debug ("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",143 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n", 144 144 batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name); 145 145 fibril_mutex_unlock(&instance->guard); -
uspace/drv/bus/usb/usbmast/Makefile
r11809eab r1916d1f 32 32 $(LIBUSBDEV_PREFIX)/libusbdev.a \ 33 33 $(LIBUSB_PREFIX)/libusb.a \ 34 $(LIBDRV_PREFIX)/libdrv.a 34 $(LIBDRV_PREFIX)/libdrv.a \ 35 $(LIBSCSI_PREFIX)/libscsi.a 35 36 36 37 EXTRA_CFLAGS += \ 37 38 -I$(LIBUSB_PREFIX)/include \ 38 39 -I$(LIBUSBDEV_PREFIX)/include \ 39 -I$(LIBDRV_PREFIX)/include 40 -I$(LIBDRV_PREFIX)/include \ 41 -I$(LIBSCSI_PREFIX)/include 40 42 41 43 BINARY = usbmast 42 44 43 45 SOURCES = \ 44 inquiry.c \46 cmds.c \ 45 47 main.c \ 46 mast.c 48 mast.c \ 49 scsi_ms.c 47 50 48 51 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/bus/usb/usbmast/cmds.h
r11809eab r1916d1f 57 57 } __attribute__((packed)) usb_massstor_csw_t; 58 58 59 static inline void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw, 60 uint32_t tag, uint32_t transfer_length, usb_direction_t dir, 61 uint8_t lun, uint8_t cmd_len, uint8_t *cmd) 62 { 63 cbw->dCBWSignature = uint32_host2usb(0x43425355); 64 cbw->dCBWTag = tag; 65 cbw->dCBWDataTransferLength = transfer_length; 66 67 cbw->bmCBWFlags = 0; 68 if (dir == USB_DIRECTION_IN) { 69 cbw->bmCBWFlags |= (1 << 7); 70 } 71 72 /* Only lowest 4 bits. */ 73 cbw->bCBWLUN = lun & 0x0F; 74 75 /* Only lowest 5 bits. */ 76 cbw->bCBWBLength = cmd_len & 0x1F; 77 78 memcpy(cbw->CBWCB, cmd, cbw->bCBWBLength); 79 } 59 extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t, 60 usb_direction_t, uint8_t, uint8_t, const uint8_t *); 80 61 81 62 #endif -
uspace/drv/bus/usb/usbmast/main.c
r11809eab r1916d1f 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 -
uspace/drv/bus/usb/usbmast/mast.c
r11809eab r1916d1f 42 42 #include <usb/dev/request.h> 43 43 44 bool usb_mast_verbose = true;44 bool usb_mast_verbose = false; 45 45 46 46 #define MASTLOG(format, ...) \ 47 47 do { \ 48 48 if (usb_mast_verbose) { \ 49 usb_log_debug ("USB cl08: " format, ##__VA_ARGS__); \49 usb_log_debug2("USB cl08: " format, ##__VA_ARGS__); \ 50 50 } \ 51 51 } while (false) 52 52 53 /** Request data from mass storage device.54 * 55 * @param bulk_in_pipe Bulk in pipe to the device.56 * @param bulk_out_pipe Bulk out pipe to the device.57 * @param tag Command block wrapper tag (automatically compared with answer).58 * @param lun LUN index.59 * @param cmd SCSI command buffer (in SCSI endianness).60 * @param cmd_size Length of SCSI command @p cmd in bytes.61 * @param in_buffer Buffer where to store the answer (CSW is not returned).62 * @param in_buffer_size Size of the buffer (size of the request to the device).63 * @param received_size Number of actually received bytes.64 * @return Error code.65 * /66 int usb_massstor_data_in(usb_device_t *dev, 67 size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,68 uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,69 void *in_buffer, size_t in_buffer_size, size_t *received_size)53 /** Send command via bulk-only transport. 54 * 55 * @param tag Command block wrapper tag (automatically compared 56 * with answer) 57 * @param lun LUN 58 * @param cmd Command block 59 * @param cmd_size Command block size in bytes 60 * @param ddir Direction in which data will be transferred 61 * @param dbuf Data send/receive buffer 62 * @param dbuf_size Size of the data buffer 63 * @param xferred_size Number of bytes actually transferred 64 * 65 * @return Error code 66 */ 67 static int usb_massstor_cmd(usb_device_t *dev, uint32_t tag, uint8_t lun, 68 const void *cmd, size_t cmd_size, usb_direction_t ddir, void *dbuf, 69 size_t dbuf_size, size_t *xferred_size) 70 70 { 71 71 int rc; 72 72 size_t act_size; 73 usb_pipe_t *bulk_in_pipe = dev->pipes[ bulk_in_pipe_index].pipe;74 usb_pipe_t *bulk_out_pipe = dev->pipes[ bulk_out_pipe_index].pipe;73 usb_pipe_t *bulk_in_pipe = dev->pipes[BULK_IN_EP].pipe; 74 usb_pipe_t *bulk_out_pipe = dev->pipes[BULK_OUT_EP].pipe; 75 75 76 76 /* Prepare CBW - command block wrapper */ 77 77 usb_massstor_cbw_t cbw; 78 usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,79 USB_DIRECTION_IN, lun, cmd_size,cmd);80 81 /* First, send the CBW. */78 usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, lun, cmd_size, 79 cmd); 80 81 /* Send the CBW. */ 82 82 rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw)); 83 83 MASTLOG("CBW '%s' sent: %s.\n", … … 88 88 } 89 89 90 /* Try to retrieve the data from the device. */ 91 act_size = 0; 92 rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size); 93 MASTLOG("Received %zuB (%s): %s.\n", act_size, 94 usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0), 95 str_error(rc)); 96 if (rc != EOK) { 90 if (ddir == USB_DIRECTION_IN) { 91 /* Recieve data from the device. */ 92 rc = usb_pipe_read(bulk_in_pipe, dbuf, dbuf_size, &act_size); 93 MASTLOG("Received %zu bytes (%s): %s.\n", act_size, 94 usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0), 95 str_error(rc)); 96 } else { 97 /* Send data to the device. */ 98 rc = usb_pipe_write(bulk_out_pipe, dbuf, dbuf_size); 99 MASTLOG("Sent %zu bytes (%s): %s.\n", act_size, 100 usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0), 101 str_error(rc)); 102 } 103 104 if (rc != EOK) { 105 /* 106 * XXX If the pipe is stalled, we should clear it 107 * and read CSW. 108 */ 97 109 return rc; 98 110 } … … 102 114 size_t csw_size; 103 115 rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size); 104 MASTLOG("CSW '%s' received (%zu B): %s.\n",116 MASTLOG("CSW '%s' received (%zu bytes): %s.\n", 105 117 usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size, 106 118 str_error(rc)); 107 119 if (rc != EOK) { 108 return rc; 109 } 120 MASTLOG("rc != EOK\n"); 121 return rc; 122 } 123 110 124 if (csw_size != sizeof(csw)) { 125 MASTLOG("csw_size != sizeof(csw)\n"); 111 126 return ERANGE; 112 127 } 113 128 114 129 if (csw.dCSWTag != tag) { 130 MASTLOG("csw.dCSWTag != tag\n"); 115 131 return EBADCHECKSUM; 116 132 } … … 120 136 */ 121 137 if (csw.dCSWStatus != 0) { 138 MASTLOG("csw.dCSWStatus != 0\n"); 122 139 // FIXME: better error code 123 140 // FIXME: distinguish 0x01 and 0x02 … … 126 143 127 144 size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue); 128 if (residue > in_buffer_size) { 145 if (residue > dbuf_size) { 146 MASTLOG("residue > dbuf_size\n"); 129 147 return ERANGE; 130 148 } 131 if (act_size != in_buffer_size - residue) { 132 return ERANGE; 133 } 134 if (received_size != NULL) { 135 *received_size = in_buffer_size - residue; 136 } 149 150 /* 151 * When the device has less data to send than requested (or cannot 152 * receive moredata), it can either stall the pipe or send garbage 153 * (ignore data) and indicate that via the residue field in CSW. 154 * That means dbuf_size - residue is the authoritative size of data 155 * received (sent). 156 */ 157 158 if (xferred_size != NULL) 159 *xferred_size = dbuf_size - residue; 137 160 138 161 return EOK; 162 } 163 164 /** Perform data-in command. 165 * 166 * @param tag Command block wrapper tag (automatically compared with 167 * answer) 168 * @param lun LUN 169 * @param cmd CDB (Command Descriptor) 170 * @param cmd_size CDB length in bytes 171 * @param dbuf Data receive buffer 172 * @param dbuf_size Data receive buffer size in bytes 173 * @param proc_size Number of bytes actually processed by device 174 * 175 * @return Error code 176 */ 177 int usb_massstor_data_in(usb_device_t *dev, uint32_t tag, uint8_t lun, 178 const void *cmd, size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size) 179 { 180 return usb_massstor_cmd(dev, tag, lun, cmd, cmd_size, USB_DIRECTION_IN, 181 dbuf, dbuf_size, proc_size); 182 } 183 184 /** Perform data-out command. 185 * 186 * @param tag Command block wrapper tag (automatically compared with 187 * answer) 188 * @param lun LUN 189 * @param cmd CDB (Command Descriptor) 190 * @param cmd_size CDB length in bytes 191 * @param data Command data 192 * @param data_size Size of @a data in bytes 193 * @param proc_size Number of bytes actually processed by device 194 * 195 * @return Error code 196 */ 197 int usb_massstor_data_out(usb_device_t *dev, uint32_t tag, uint8_t lun, 198 const void *cmd, size_t cmd_size, const void *data, size_t data_size, 199 size_t *proc_size) 200 { 201 return usb_massstor_cmd(dev, tag, lun, cmd, cmd_size, USB_DIRECTION_OUT, 202 (void *) data, data_size, proc_size); 139 203 } 140 204 … … 157 221 * 158 222 * @param dev Device to be reseted. 159 * @param bulk_in_idx Index of bulk in pipe. 160 * @param bulk_out_idx Index of bulk out pipe. 161 */ 162 void usb_massstor_reset_recovery(usb_device_t *dev, 163 size_t bulk_in_idx, size_t bulk_out_idx) 223 */ 224 void usb_massstor_reset_recovery(usb_device_t *dev) 164 225 { 165 226 /* We would ignore errors here because if this fails … … 167 228 */ 168 229 usb_massstor_reset(dev); 169 usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[ bulk_in_idx].pipe);170 usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[ bulk_out_idx].pipe);230 usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_IN_EP].pipe); 231 usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_OUT_EP].pipe); 171 232 } 172 233 -
uspace/drv/bus/usb/usbmast/mast.h
r11809eab r1916d1f 37 37 #define USB_USBMAST_MAST_H_ 38 38 39 #include <scsi/spc.h> 39 40 #include <sys/types.h> 40 41 #include <usb/usb.h> … … 42 43 #include <usb/dev/driver.h> 43 44 44 /** Result of SCSI INQUIRY command. 45 * This is already parsed structure, not the original buffer returned by 46 * the device. 47 */ 48 typedef struct { 49 /** SCSI peripheral device type. */ 50 int peripheral_device_type; 51 /** Whether the device is removable. */ 52 bool removable; 53 /** Vendor ID string. */ 54 char vendor_id[9]; 55 /** Product ID and product revision string. */ 56 char product_and_revision[12]; 57 } usb_massstor_inquiry_result_t; 45 #define BULK_IN_EP 0 46 #define BULK_OUT_EP 1 58 47 59 int usb_massstor_data_in(usb_device_t *dev, size_t, size_t, 60 uint32_t, uint8_t, void *, size_t, void *, size_t, size_t *); 61 int usb_massstor_reset(usb_device_t *); 62 void usb_massstor_reset_recovery(usb_device_t *, size_t, size_t); 63 int usb_massstor_get_max_lun(usb_device_t *); 64 size_t usb_masstor_get_lun_count(usb_device_t *); 65 int usb_massstor_inquiry(usb_device_t *, size_t, size_t, 66 usb_massstor_inquiry_result_t *); 67 const char *usb_str_masstor_scsi_peripheral_device_type(int); 48 extern int usb_massstor_data_in(usb_device_t *, uint32_t, uint8_t, const void *, 49 size_t, void *, size_t, size_t *); 50 extern int usb_massstor_data_out(usb_device_t *, uint32_t, uint8_t, const void *, 51 size_t, const void *, size_t, size_t *); 52 extern int usb_massstor_reset(usb_device_t *); 53 extern void usb_massstor_reset_recovery(usb_device_t *); 54 extern int usb_massstor_get_max_lun(usb_device_t *); 55 extern size_t usb_masstor_get_lun_count(usb_device_t *); 68 56 69 57 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
