diff options
-rw-r--r-- | drivers/usb/storage/realtek_cr.c | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 232167ad4781..f664c865e71e 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c | |||
@@ -293,6 +293,52 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, | |||
293 | return USB_STOR_TRANSPORT_ERROR; | 293 | return USB_STOR_TRANSPORT_ERROR; |
294 | } | 294 | } |
295 | 295 | ||
296 | static int rts51x_bulk_transport_special(struct us_data *us, u8 lun, | ||
297 | u8 *cmd, int cmd_len, u8 *buf, int buf_len, | ||
298 | enum dma_data_direction dir, int *act_len) | ||
299 | { | ||
300 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
301 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | ||
302 | int result; | ||
303 | unsigned int cswlen; | ||
304 | unsigned int cbwlen = US_BULK_CB_WRAP_LEN; | ||
305 | |||
306 | /* set up the command wrapper */ | ||
307 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
308 | bcb->DataTransferLength = cpu_to_le32(buf_len); | ||
309 | bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0; | ||
310 | bcb->Tag = ++us->tag; | ||
311 | bcb->Lun = lun; | ||
312 | bcb->Length = cmd_len; | ||
313 | |||
314 | /* copy the command payload */ | ||
315 | memset(bcb->CDB, 0, sizeof(bcb->CDB)); | ||
316 | memcpy(bcb->CDB, cmd, bcb->Length); | ||
317 | |||
318 | /* send it to out endpoint */ | ||
319 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
320 | bcb, cbwlen, NULL); | ||
321 | if (result != USB_STOR_XFER_GOOD) | ||
322 | return USB_STOR_TRANSPORT_ERROR; | ||
323 | |||
324 | /* DATA STAGE */ | ||
325 | /* send/receive data payload, if there is any */ | ||
326 | |||
327 | if (buf && buf_len) { | ||
328 | unsigned int pipe = (dir == DMA_FROM_DEVICE) ? | ||
329 | us->recv_bulk_pipe : us->send_bulk_pipe; | ||
330 | result = usb_stor_bulk_transfer_buf(us, pipe, | ||
331 | buf, buf_len, NULL); | ||
332 | if (result == USB_STOR_XFER_ERROR) | ||
333 | return USB_STOR_TRANSPORT_ERROR; | ||
334 | } | ||
335 | |||
336 | /* get CSW for device status */ | ||
337 | result = usb_bulk_msg(us->pusb_dev, us->recv_bulk_pipe, bcs, | ||
338 | US_BULK_CS_WRAP_LEN, &cswlen, 250); | ||
339 | return result; | ||
340 | } | ||
341 | |||
296 | /* Determine what the maximum LUN supported is */ | 342 | /* Determine what the maximum LUN supported is */ |
297 | static int rts51x_get_max_lun(struct us_data *us) | 343 | static int rts51x_get_max_lun(struct us_data *us) |
298 | { | 344 | { |
@@ -459,6 +505,29 @@ static int enable_oscillator(struct us_data *us) | |||
459 | return 0; | 505 | return 0; |
460 | } | 506 | } |
461 | 507 | ||
508 | static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) | ||
509 | { | ||
510 | int retval; | ||
511 | u16 addr = 0xFE47; | ||
512 | u8 cmnd[12] = {0}; | ||
513 | |||
514 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __FUNCTION__, addr, len); | ||
515 | |||
516 | cmnd[0] = 0xF0; | ||
517 | cmnd[1] = 0x0E; | ||
518 | cmnd[2] = (u8)(addr >> 8); | ||
519 | cmnd[3] = (u8)addr; | ||
520 | cmnd[4] = (u8)(len >> 8); | ||
521 | cmnd[5] = (u8)len; | ||
522 | |||
523 | retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL); | ||
524 | if (retval != USB_STOR_TRANSPORT_GOOD) { | ||
525 | return -EIO; | ||
526 | } | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
462 | static int do_config_autodelink(struct us_data *us, int enable, int force) | 531 | static int do_config_autodelink(struct us_data *us, int enable, int force) |
463 | { | 532 | { |
464 | int retval; | 533 | int retval; |
@@ -479,7 +548,8 @@ static int do_config_autodelink(struct us_data *us, int enable, int force) | |||
479 | 548 | ||
480 | US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); | 549 | US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); |
481 | 550 | ||
482 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 551 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
552 | retval = __do_config_autodelink(us, &value, 1); | ||
483 | if (retval < 0) | 553 | if (retval < 0) |
484 | return -EIO; | 554 | return -EIO; |
485 | 555 | ||
@@ -511,7 +581,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
511 | 581 | ||
512 | SET_BIT(value, 7); | 582 | SET_BIT(value, 7); |
513 | 583 | ||
514 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 584 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
585 | retval = __do_config_autodelink(us, &value, 1); | ||
515 | if (retval < 0) | 586 | if (retval < 0) |
516 | return -EIO; | 587 | return -EIO; |
517 | 588 | ||
@@ -532,7 +603,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
532 | CLR_BIT(value, 7); | 603 | CLR_BIT(value, 7); |
533 | } | 604 | } |
534 | 605 | ||
535 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 606 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
607 | retval = __do_config_autodelink(us, &value, 1); | ||
536 | if (retval < 0) | 608 | if (retval < 0) |
537 | return -EIO; | 609 | return -EIO; |
538 | 610 | ||
@@ -609,7 +681,8 @@ static int config_autodelink_before_power_down(struct us_data *us) | |||
609 | if (CHECK_ID(chip, 0x0138, 0x3882)) | 681 | if (CHECK_ID(chip, 0x0138, 0x3882)) |
610 | SET_BIT(value, 2); | 682 | SET_BIT(value, 2); |
611 | 683 | ||
612 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 684 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
685 | retval = __do_config_autodelink(us, &value, 1); | ||
613 | if (retval < 0) | 686 | if (retval < 0) |
614 | return -EIO; | 687 | return -EIO; |
615 | } | 688 | } |