Changeset 00c2de63 in mainline for uspace/drv
- Timestamp:
- 2011-07-29T14:50:22Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b6759f4
- Parents:
- 6c69d19 (diff), 7ae249d (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/usbmast
- Files:
-
- 4 edited
-
bo_trans.c (modified) (7 diffs)
-
bo_trans.h (modified) (1 diff)
-
cmdw.h (modified) (1 diff)
-
scsi_ms.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbmast/bo_trans.c
r6c69d19 r00c2de63 58 58 * @param tag Command block wrapper tag (automatically compared 59 59 * with answer) 60 * @param cmd Command block 61 * @param cmd_size Command block size in bytes 62 * @param ddir Direction in which data will be transferred 63 * @param dbuf Data send/receive buffer 64 * @param dbuf_size Size of the data buffer 65 * @param xferred_size Number of bytes actually transferred 60 * @param cmd SCSI command 66 61 * 67 62 * @return Error code 68 63 */ 69 static int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, const void *cmd, 70 size_t cmd_size, usb_direction_t ddir, void *dbuf, size_t dbuf_size, 71 size_t *xferred_size) 64 int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, scsi_cmd_t *cmd) 72 65 { 73 66 int rc; 67 int retval = EOK; 74 68 size_t act_size; 75 69 usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe; 76 70 usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe; 71 usb_direction_t ddir; 72 void *dbuf; 73 size_t dbuf_size; 74 75 if (cmd->data_out != NULL && cmd->data_in == NULL) { 76 ddir = USB_DIRECTION_OUT; 77 dbuf = (void *)cmd->data_out; 78 dbuf_size = cmd->data_out_size; 79 } else if (cmd->data_out == NULL && cmd->data_in != NULL) { 80 ddir = USB_DIRECTION_IN; 81 dbuf = cmd->data_in; 82 dbuf_size = cmd->data_in_size; 83 } else { 84 assert(false); 85 } 77 86 78 87 /* Prepare CBW - command block wrapper */ 79 88 usb_massstor_cbw_t cbw; 80 89 usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, mfun->lun, 81 cmd _size, cmd);90 cmd->cdb_size, cmd->cdb); 82 91 83 92 /* Send the CBW. */ 93 MASTLOG("Sending CBW.\n"); 84 94 rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw)); 85 95 MASTLOG("CBW '%s' sent: %s.\n", 86 96 usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0), 87 97 str_error(rc)); 88 if (rc != EOK) {89 return rc;90 } 91 98 if (rc != EOK) 99 return EIO; 100 101 MASTLOG("Transferring data.\n"); 92 102 if (ddir == USB_DIRECTION_IN) { 93 103 /* Recieve data from the device. */ … … 104 114 } 105 115 106 if (rc != EOK) { 107 /* 108 * XXX If the pipe is stalled, we should clear it 109 * and read CSW. 110 */ 111 return rc; 116 if (rc == ESTALL) { 117 /* Clear stall condition and continue below to read CSW. */ 118 if (ddir == USB_DIRECTION_IN) { 119 usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe, 120 mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe); 121 } else { 122 usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe, 123 mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe); 124 } 125 } else if (rc != EOK) { 126 return EIO; 112 127 } 113 128 … … 115 130 usb_massstor_csw_t csw; 116 131 size_t csw_size; 132 MASTLOG("Reading CSW.\n"); 117 133 rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size); 118 134 MASTLOG("CSW '%s' received (%zu bytes): %s.\n", … … 121 137 if (rc != EOK) { 122 138 MASTLOG("rc != EOK\n"); 123 return rc;139 return EIO; 124 140 } 125 141 126 142 if (csw_size != sizeof(csw)) { 127 143 MASTLOG("csw_size != sizeof(csw)\n"); 128 return E RANGE;144 return EIO; 129 145 } 130 146 131 147 if (csw.dCSWTag != tag) { 132 148 MASTLOG("csw.dCSWTag != tag\n"); 133 return E BADCHECKSUM;149 return EIO; 134 150 } 135 151 … … 137 153 * Determine the actual return value from the CSW. 138 154 */ 139 if (csw.dCSWStatus != 0) { 140 MASTLOG("csw.dCSWStatus != 0\n"); 141 // FIXME: better error code 142 // FIXME: distinguish 0x01 and 0x02 143 return EXDEV; 155 switch (csw.dCSWStatus) { 156 case cbs_passed: 157 cmd->status = CMDS_GOOD; 158 break; 159 case cbs_failed: 160 MASTLOG("Command failed\n"); 161 cmd->status = CMDS_FAILED; 162 break; 163 case cbs_phase_error: 164 MASTLOG("Phase error\n"); 165 retval = EIO; 166 break; 167 default: 168 retval = EIO; 169 break; 144 170 } 145 171 … … 147 173 if (residue > dbuf_size) { 148 174 MASTLOG("residue > dbuf_size\n"); 149 return E RANGE;175 return EIO; 150 176 } 151 177 … … 158 184 */ 159 185 160 if (xferred_size != NULL) 161 *xferred_size = dbuf_size - residue; 162 163 return EOK; 164 } 165 166 /** Perform data-in command. 167 * 168 * @param mfun Mass storage function 169 * @param tag Command block wrapper tag (automatically compared with 170 * answer) 171 * @param cmd CDB (Command Descriptor) 172 * @param cmd_size CDB length in bytes 173 * @param dbuf Data receive buffer 174 * @param dbuf_size Data receive buffer size in bytes 175 * @param proc_size Number of bytes actually processed by device 176 * 177 * @return Error code 178 */ 179 int usb_massstor_data_in(usbmast_fun_t *mfun, uint32_t tag, const void *cmd, 180 size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size) 181 { 182 return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_IN, 183 dbuf, dbuf_size, proc_size); 184 } 185 186 /** Perform data-out command. 187 * 188 * @param mfun Mass storage function 189 * @param tag Command block wrapper tag (automatically compared with 190 * answer) 191 * @param cmd CDB (Command Descriptor) 192 * @param cmd_size CDB length in bytes 193 * @param data Command data 194 * @param data_size Size of @a data in bytes 195 * @param proc_size Number of bytes actually processed by device 196 * 197 * @return Error code 198 */ 199 int usb_massstor_data_out(usbmast_fun_t *mfun, uint32_t tag, const void *cmd, 200 size_t cmd_size, const void *data, size_t data_size, size_t *proc_size) 201 { 202 return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_OUT, 203 (void *) data, data_size, proc_size); 186 if (ddir == USB_DIRECTION_IN) 187 cmd->rcvd_size = dbuf_size - residue; 188 189 return retval; 204 190 } 205 191 -
uspace/drv/bus/usb/usbmast/bo_trans.h
r6c69d19 r00c2de63 47 47 #define BULK_OUT_EP 1 48 48 49 extern int usb_massstor_data_in(usbmast_fun_t *, uint32_t, const void *, 50 size_t, void *, size_t, size_t *); 51 extern int usb_massstor_data_out(usbmast_fun_t *, uint32_t, const void *, 52 size_t, const void *, size_t, size_t *); 49 typedef enum cmd_status { 50 CMDS_GOOD, 51 CMDS_FAILED 52 } cmd_status_t; 53 54 /** SCSI command. 55 * 56 * Contains (a subset of) the input and output arguments of SCSI 57 * Execute Command procedure call (see SAM-4 chapter 5.1) 58 */ 59 typedef struct { 60 /* 61 * Related to IN fields 62 */ 63 64 /** Command Descriptor Block */ 65 void *cdb; 66 /** CDB size in bytes */ 67 size_t cdb_size; 68 69 /** Outgoing data */ 70 const void *data_out; 71 /** Size of outgoing data in bytes */ 72 size_t data_out_size; 73 74 /* 75 * Related to OUT fields 76 */ 77 78 /** Buffer for incoming data */ 79 void *data_in; 80 /** Size of input buffer in bytes */ 81 size_t data_in_size; 82 83 /** Number of bytes actually received */ 84 size_t rcvd_size; 85 86 /** Status */ 87 cmd_status_t status; 88 } scsi_cmd_t; 89 90 extern int usb_massstor_cmd(usbmast_fun_t *, uint32_t, scsi_cmd_t *); 53 91 extern int usb_massstor_reset(usbmast_dev_t *); 54 92 extern void usb_massstor_reset_recovery(usbmast_dev_t *); -
uspace/drv/bus/usb/usbmast/cmdw.h
r6c69d19 r00c2de63 57 57 } __attribute__((packed)) usb_massstor_csw_t; 58 58 59 enum cmd_block_status { 60 cbs_passed = 0x00, 61 cbs_failed = 0x01, 62 cbs_phase_error = 0x02 63 }; 64 59 65 extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t, 60 66 usb_direction_t, uint8_t, uint8_t, const uint8_t *); -
uspace/drv/bus/usb/usbmast/scsi_ms.c
r6c69d19 r00c2de63 61 61 } 62 62 63 static void usbmast_dump_sense(scsi_sense_data_t *sense_buf) 64 { 65 unsigned sense_key; 66 67 sense_key = sense_buf->flags_key & 0x0f; 68 printf("Got sense data. Sense key: 0x%x (%s), ASC 0x%02x, " 69 "ASCQ 0x%02x.\n", sense_key, 70 scsi_get_sense_key_str(sense_key), 71 sense_buf->additional_code, 72 sense_buf->additional_cqual); 73 } 74 75 /** Run SCSI command. 76 * 77 * Run command and repeat in case of unit attention. 78 * XXX This is too simplified. 79 */ 80 static int usbmast_run_cmd(usbmast_fun_t *mfun, scsi_cmd_t *cmd) 81 { 82 uint8_t sense_key; 83 scsi_sense_data_t sense_buf; 84 int rc; 85 86 do { 87 rc = usb_massstor_cmd(mfun, 0xDEADBEEF, cmd); 88 if (rc != EOK) { 89 usb_log_error("Inquiry transport failed, device %s: %s.\n", 90 mfun->mdev->ddf_dev->name, str_error(rc)); 91 return rc; 92 } 93 94 if (cmd->status == CMDS_GOOD) 95 return EOK; 96 97 usb_log_error("SCSI command failed, device %s.\n", 98 mfun->mdev->ddf_dev->name); 99 100 rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf)); 101 if (rc != EOK) { 102 usb_log_error("Failed to read sense data.\n"); 103 return EIO; 104 } 105 106 /* Dump sense data to log */ 107 usbmast_dump_sense(&sense_buf); 108 109 /* Get sense key */ 110 sense_key = sense_buf.flags_key & 0x0f; 111 112 if (sense_key == SCSI_SK_UNIT_ATTENTION) { 113 printf("Got unit attention. Re-trying command.\n"); 114 } 115 116 } while (sense_key == SCSI_SK_UNIT_ATTENTION); 117 118 /* Command status is not good, nevertheless transport succeeded. */ 119 return EOK; 120 } 121 63 122 /** Perform SCSI Inquiry command on USB mass storage device. 64 123 * … … 70 129 { 71 130 scsi_std_inquiry_data_t inq_data; 72 s ize_t response_len;131 scsi_cmd_t cmd; 73 132 scsi_cdb_inquiry_t cdb; 74 133 int rc; … … 78 137 cdb.alloc_len = host2uint16_t_be(sizeof(inq_data)); 79 138 80 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 81 sizeof(cdb), &inq_data, sizeof(inq_data), &response_len); 139 memset(&cmd, 0, sizeof(cmd)); 140 cmd.cdb = &cdb; 141 cmd.cdb_size = sizeof(cdb); 142 cmd.data_in = &inq_data; 143 cmd.data_in_size = sizeof(inq_data); 144 145 rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd); 82 146 83 147 if (rc != EOK) { 84 usb_log_error("Inquiry failed, device %s: %s.\n", 85 mfun->mdev->ddf_dev->name, str_error(rc)); 86 return rc; 87 } 88 89 if (response_len < SCSI_STD_INQUIRY_DATA_MIN_SIZE) { 148 usb_log_error("Inquiry transport failed, device %s: %s.\n", 149 mfun->mdev->ddf_dev->name, str_error(rc)); 150 return rc; 151 } 152 153 if (cmd.status != CMDS_GOOD) { 154 usb_log_error("Inquiry command failed, device %s.\n", 155 mfun->mdev->ddf_dev->name); 156 return EIO; 157 } 158 159 if (cmd.rcvd_size < SCSI_STD_INQUIRY_DATA_MIN_SIZE) { 90 160 usb_log_error("SCSI Inquiry response too short (%zu).\n", 91 response_len);161 cmd.rcvd_size); 92 162 return EIO; 93 163 } … … 127 197 int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size) 128 198 { 199 scsi_cmd_t cmd; 129 200 scsi_cdb_request_sense_t cdb; 130 size_t data_len;131 201 int rc; 132 202 … … 135 205 cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE); 136 206 137 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 138 sizeof(cdb), buf, size, &data_len); 139 140 if (rc != EOK) { 207 memset(&cmd, 0, sizeof(cmd)); 208 cmd.cdb = &cdb; 209 cmd.cdb_size = sizeof(cdb); 210 cmd.data_in = buf; 211 cmd.data_in_size = size; 212 213 rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd); 214 215 if (rc != EOK || cmd.status != CMDS_GOOD) { 141 216 usb_log_error("Request Sense failed, device %s: %s.\n", 142 217 mfun->mdev->ddf_dev->name, str_error(rc)); … … 144 219 } 145 220 146 if ( data_len< SCSI_SENSE_DATA_MIN_SIZE) {221 if (cmd.rcvd_size < SCSI_SENSE_DATA_MIN_SIZE) { 147 222 /* The missing bytes should be considered to be zeroes. */ 148 memset((uint8_t *)buf + data_len, 0,149 SCSI_SENSE_DATA_MIN_SIZE - data_len);223 memset((uint8_t *)buf + cmd.rcvd_size, 0, 224 SCSI_SENSE_DATA_MIN_SIZE - cmd.rcvd_size); 150 225 } 151 226 … … 164 239 uint32_t *block_size) 165 240 { 241 scsi_cmd_t cmd; 166 242 scsi_cdb_read_capacity_10_t cdb; 167 243 scsi_read_capacity_10_data_t data; 168 size_t data_len;169 244 int rc; 170 245 … … 172 247 cdb.op_code = SCSI_CMD_READ_CAPACITY_10; 173 248 174 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 175 sizeof(cdb), &data, sizeof(data), &data_len); 249 memset(&cmd, 0, sizeof(cmd)); 250 cmd.cdb = &cdb; 251 cmd.cdb_size = sizeof(cdb); 252 cmd.data_in = &data; 253 cmd.data_in_size = sizeof(data); 254 255 rc = usbmast_run_cmd(mfun, &cmd); 176 256 177 257 if (rc != EOK) { 178 usb_log_error("Read Capacity (10) failed, device %s: %s.\n", 179 mfun->mdev->ddf_dev->name, str_error(rc)); 180 return rc; 181 } 182 183 if (data_len < sizeof(data)) { 258 usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n", 259 mfun->mdev->ddf_dev->name, str_error(rc)); 260 return rc; 261 } 262 263 if (cmd.status != CMDS_GOOD) { 264 usb_log_error("Read Capacity (10) command failed, device %s.\n", 265 mfun->mdev->ddf_dev->name); 266 return EIO; 267 } 268 269 if (cmd.rcvd_size < sizeof(data)) { 184 270 usb_log_error("SCSI Read Capacity response too short (%zu).\n", 185 data_len);271 cmd.rcvd_size); 186 272 return EIO; 187 273 } … … 203 289 int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf) 204 290 { 205 scsi_cdb_read_12_t cdb; 206 size_t data_len; 207 int rc; 208 209 /* XXX Need softstate to store block size. */ 291 scsi_cmd_t cmd; 292 scsi_cdb_read_10_t cdb; 293 int rc; 210 294 211 295 if (ba > UINT32_MAX) 212 296 return ELIMIT; 213 297 214 if ( (uint64_t)nblocks * mfun->block_size > UINT32_MAX)298 if (nblocks > UINT16_MAX) 215 299 return ELIMIT; 216 300 217 301 memset(&cdb, 0, sizeof(cdb)); 218 cdb.op_code = SCSI_CMD_READ_1 2;302 cdb.op_code = SCSI_CMD_READ_10; 219 303 cdb.lba = host2uint32_t_be(ba); 220 cdb.xfer_len = host2uint32_t_be(nblocks); 221 222 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 223 sizeof(cdb), buf, nblocks * mfun->block_size, &data_len); 304 cdb.xfer_len = host2uint16_t_be(nblocks); 305 306 memset(&cmd, 0, sizeof(cmd)); 307 cmd.cdb = &cdb; 308 cmd.cdb_size = sizeof(cdb); 309 cmd.data_in = buf; 310 cmd.data_in_size = nblocks * mfun->block_size; 311 312 rc = usbmast_run_cmd(mfun, &cmd); 224 313 225 314 if (rc != EOK) { 226 usb_log_error("Read (12) failed, device %s: %s.\n", 227 mfun->mdev->ddf_dev->name, str_error(rc)); 228 return rc; 229 } 230 231 if (data_len < nblocks * mfun->block_size) { 315 usb_log_error("Read (10) transport failed, device %s: %s.\n", 316 mfun->mdev->ddf_dev->name, str_error(rc)); 317 return rc; 318 } 319 320 if (cmd.status != CMDS_GOOD) { 321 usb_log_error("Read (10) command failed, device %s.\n", 322 mfun->mdev->ddf_dev->name); 323 return EIO; 324 } 325 326 if (cmd.rcvd_size < nblocks * mfun->block_size) { 232 327 usb_log_error("SCSI Read response too short (%zu).\n", 233 data_len);328 cmd.rcvd_size); 234 329 return EIO; 235 330 } … … 250 345 const void *data) 251 346 { 252 scsi_c db_write_12_t cdb;253 s ize_t sent_len;347 scsi_cmd_t cmd; 348 scsi_cdb_write_10_t cdb; 254 349 int rc; 255 350 … … 257 352 return ELIMIT; 258 353 259 if ( (uint64_t)nblocks * mfun->block_size > UINT32_MAX)354 if (nblocks > UINT16_MAX) 260 355 return ELIMIT; 261 356 262 357 memset(&cdb, 0, sizeof(cdb)); 263 cdb.op_code = SCSI_CMD_WRITE_1 2;358 cdb.op_code = SCSI_CMD_WRITE_10; 264 359 cdb.lba = host2uint32_t_be(ba); 265 cdb.xfer_len = host2uint32_t_be(nblocks); 266 267 rc = usb_massstor_data_out(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 268 sizeof(cdb), data, nblocks * mfun->block_size, &sent_len); 360 cdb.xfer_len = host2uint16_t_be(nblocks); 361 362 memset(&cmd, 0, sizeof(cmd)); 363 cmd.cdb = &cdb; 364 cmd.cdb_size = sizeof(cdb); 365 cmd.data_out = data; 366 cmd.data_out_size = nblocks * mfun->block_size; 367 368 rc = usbmast_run_cmd(mfun, &cmd); 269 369 270 370 if (rc != EOK) { 271 usb_log_error("Write (1 2)failed, device %s: %s.\n",272 mfun->mdev->ddf_dev->name, str_error(rc)); 273 return rc; 274 } 275 276 if ( sent_len < nblocks * mfun->block_size) {277 usb_log_error(" SCSI Write not all bytes transferred (%zu).\n",278 sent_len);371 usb_log_error("Write (10) transport failed, device %s: %s.\n", 372 mfun->mdev->ddf_dev->name, str_error(rc)); 373 return rc; 374 } 375 376 if (cmd.status != CMDS_GOOD) { 377 usb_log_error("Write (10) command failed, device %s.\n", 378 mfun->mdev->ddf_dev->name); 279 379 return EIO; 280 380 }
Note:
See TracChangeset
for help on using the changeset viewer.
