diff options
Diffstat (limited to 'drivers/usb/storage/realtek_cr.c')
-rw-r--r-- | drivers/usb/storage/realtek_cr.c | 116 |
1 files changed, 107 insertions, 9 deletions
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 6fd13068481b..0ce5f79197e7 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c | |||
@@ -292,6 +292,52 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, | |||
292 | return USB_STOR_TRANSPORT_ERROR; | 292 | return USB_STOR_TRANSPORT_ERROR; |
293 | } | 293 | } |
294 | 294 | ||
295 | static int rts51x_bulk_transport_special(struct us_data *us, u8 lun, | ||
296 | u8 *cmd, int cmd_len, u8 *buf, int buf_len, | ||
297 | enum dma_data_direction dir, int *act_len) | ||
298 | { | ||
299 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | ||
300 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | ||
301 | int result; | ||
302 | unsigned int cswlen; | ||
303 | unsigned int cbwlen = US_BULK_CB_WRAP_LEN; | ||
304 | |||
305 | /* set up the command wrapper */ | ||
306 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
307 | bcb->DataTransferLength = cpu_to_le32(buf_len); | ||
308 | bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0; | ||
309 | bcb->Tag = ++us->tag; | ||
310 | bcb->Lun = lun; | ||
311 | bcb->Length = cmd_len; | ||
312 | |||
313 | /* copy the command payload */ | ||
314 | memset(bcb->CDB, 0, sizeof(bcb->CDB)); | ||
315 | memcpy(bcb->CDB, cmd, bcb->Length); | ||
316 | |||
317 | /* send it to out endpoint */ | ||
318 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
319 | bcb, cbwlen, NULL); | ||
320 | if (result != USB_STOR_XFER_GOOD) | ||
321 | return USB_STOR_TRANSPORT_ERROR; | ||
322 | |||
323 | /* DATA STAGE */ | ||
324 | /* send/receive data payload, if there is any */ | ||
325 | |||
326 | if (buf && buf_len) { | ||
327 | unsigned int pipe = (dir == DMA_FROM_DEVICE) ? | ||
328 | us->recv_bulk_pipe : us->send_bulk_pipe; | ||
329 | result = usb_stor_bulk_transfer_buf(us, pipe, | ||
330 | buf, buf_len, NULL); | ||
331 | if (result == USB_STOR_XFER_ERROR) | ||
332 | return USB_STOR_TRANSPORT_ERROR; | ||
333 | } | ||
334 | |||
335 | /* get CSW for device status */ | ||
336 | result = usb_bulk_msg(us->pusb_dev, us->recv_bulk_pipe, bcs, | ||
337 | US_BULK_CS_WRAP_LEN, &cswlen, 250); | ||
338 | return result; | ||
339 | } | ||
340 | |||
295 | /* Determine what the maximum LUN supported is */ | 341 | /* Determine what the maximum LUN supported is */ |
296 | static int rts51x_get_max_lun(struct us_data *us) | 342 | static int rts51x_get_max_lun(struct us_data *us) |
297 | { | 343 | { |
@@ -319,6 +365,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
319 | { | 365 | { |
320 | int retval; | 366 | int retval; |
321 | u8 cmnd[12] = { 0 }; | 367 | u8 cmnd[12] = { 0 }; |
368 | u8 *buf; | ||
369 | |||
370 | buf = kmalloc(len, GFP_NOIO); | ||
371 | if (buf == NULL) | ||
372 | return USB_STOR_TRANSPORT_ERROR; | ||
322 | 373 | ||
323 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); | 374 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); |
324 | 375 | ||
@@ -330,10 +381,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
330 | cmnd[5] = (u8) len; | 381 | cmnd[5] = (u8) len; |
331 | 382 | ||
332 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, | 383 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, |
333 | data, len, DMA_FROM_DEVICE, NULL); | 384 | buf, len, DMA_FROM_DEVICE, NULL); |
334 | if (retval != USB_STOR_TRANSPORT_GOOD) | 385 | if (retval != USB_STOR_TRANSPORT_GOOD) { |
386 | kfree(buf); | ||
335 | return -EIO; | 387 | return -EIO; |
388 | } | ||
336 | 389 | ||
390 | memcpy(data, buf, len); | ||
391 | kfree(buf); | ||
337 | return 0; | 392 | return 0; |
338 | } | 393 | } |
339 | 394 | ||
@@ -341,6 +396,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
341 | { | 396 | { |
342 | int retval; | 397 | int retval; |
343 | u8 cmnd[12] = { 0 }; | 398 | u8 cmnd[12] = { 0 }; |
399 | u8 *buf; | ||
400 | |||
401 | buf = kmalloc(len, GFP_NOIO); | ||
402 | if (buf == NULL) | ||
403 | return USB_STOR_TRANSPORT_ERROR; | ||
404 | memcpy(buf, data, len); | ||
344 | 405 | ||
345 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); | 406 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); |
346 | 407 | ||
@@ -352,7 +413,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) | |||
352 | cmnd[5] = (u8) len; | 413 | cmnd[5] = (u8) len; |
353 | 414 | ||
354 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, | 415 | retval = rts51x_bulk_transport(us, 0, cmnd, 12, |
355 | data, len, DMA_TO_DEVICE, NULL); | 416 | buf, len, DMA_TO_DEVICE, NULL); |
417 | kfree(buf); | ||
356 | if (retval != USB_STOR_TRANSPORT_GOOD) | 418 | if (retval != USB_STOR_TRANSPORT_GOOD) |
357 | return -EIO; | 419 | return -EIO; |
358 | 420 | ||
@@ -364,6 +426,11 @@ static int rts51x_read_status(struct us_data *us, | |||
364 | { | 426 | { |
365 | int retval; | 427 | int retval; |
366 | u8 cmnd[12] = { 0 }; | 428 | u8 cmnd[12] = { 0 }; |
429 | u8 *buf; | ||
430 | |||
431 | buf = kmalloc(len, GFP_NOIO); | ||
432 | if (buf == NULL) | ||
433 | return USB_STOR_TRANSPORT_ERROR; | ||
367 | 434 | ||
368 | US_DEBUGP("%s, lun = %d\n", __func__, lun); | 435 | US_DEBUGP("%s, lun = %d\n", __func__, lun); |
369 | 436 | ||
@@ -371,10 +438,14 @@ static int rts51x_read_status(struct us_data *us, | |||
371 | cmnd[1] = 0x09; | 438 | cmnd[1] = 0x09; |
372 | 439 | ||
373 | retval = rts51x_bulk_transport(us, lun, cmnd, 12, | 440 | retval = rts51x_bulk_transport(us, lun, cmnd, 12, |
374 | status, len, DMA_FROM_DEVICE, actlen); | 441 | buf, len, DMA_FROM_DEVICE, actlen); |
375 | if (retval != USB_STOR_TRANSPORT_GOOD) | 442 | if (retval != USB_STOR_TRANSPORT_GOOD) { |
443 | kfree(buf); | ||
376 | return -EIO; | 444 | return -EIO; |
445 | } | ||
377 | 446 | ||
447 | memcpy(status, buf, len); | ||
448 | kfree(buf); | ||
378 | return 0; | 449 | return 0; |
379 | } | 450 | } |
380 | 451 | ||
@@ -433,6 +504,29 @@ static int enable_oscillator(struct us_data *us) | |||
433 | return 0; | 504 | return 0; |
434 | } | 505 | } |
435 | 506 | ||
507 | static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) | ||
508 | { | ||
509 | int retval; | ||
510 | u16 addr = 0xFE47; | ||
511 | u8 cmnd[12] = {0}; | ||
512 | |||
513 | US_DEBUGP("%s, addr = 0x%x, len = %d\n", __FUNCTION__, addr, len); | ||
514 | |||
515 | cmnd[0] = 0xF0; | ||
516 | cmnd[1] = 0x0E; | ||
517 | cmnd[2] = (u8)(addr >> 8); | ||
518 | cmnd[3] = (u8)addr; | ||
519 | cmnd[4] = (u8)(len >> 8); | ||
520 | cmnd[5] = (u8)len; | ||
521 | |||
522 | retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL); | ||
523 | if (retval != USB_STOR_TRANSPORT_GOOD) { | ||
524 | return -EIO; | ||
525 | } | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
436 | static int do_config_autodelink(struct us_data *us, int enable, int force) | 530 | static int do_config_autodelink(struct us_data *us, int enable, int force) |
437 | { | 531 | { |
438 | int retval; | 532 | int retval; |
@@ -453,7 +547,8 @@ static int do_config_autodelink(struct us_data *us, int enable, int force) | |||
453 | 547 | ||
454 | US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); | 548 | US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); |
455 | 549 | ||
456 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 550 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
551 | retval = __do_config_autodelink(us, &value, 1); | ||
457 | if (retval < 0) | 552 | if (retval < 0) |
458 | return -EIO; | 553 | return -EIO; |
459 | 554 | ||
@@ -485,7 +580,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
485 | 580 | ||
486 | SET_BIT(value, 7); | 581 | SET_BIT(value, 7); |
487 | 582 | ||
488 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 583 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
584 | retval = __do_config_autodelink(us, &value, 1); | ||
489 | if (retval < 0) | 585 | if (retval < 0) |
490 | return -EIO; | 586 | return -EIO; |
491 | 587 | ||
@@ -506,7 +602,8 @@ static int config_autodelink_after_power_on(struct us_data *us) | |||
506 | CLR_BIT(value, 7); | 602 | CLR_BIT(value, 7); |
507 | } | 603 | } |
508 | 604 | ||
509 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 605 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
606 | retval = __do_config_autodelink(us, &value, 1); | ||
510 | if (retval < 0) | 607 | if (retval < 0) |
511 | return -EIO; | 608 | return -EIO; |
512 | 609 | ||
@@ -583,7 +680,8 @@ static int config_autodelink_before_power_down(struct us_data *us) | |||
583 | if (CHECK_ID(chip, 0x0138, 0x3882)) | 680 | if (CHECK_ID(chip, 0x0138, 0x3882)) |
584 | SET_BIT(value, 2); | 681 | SET_BIT(value, 2); |
585 | 682 | ||
586 | retval = rts51x_write_mem(us, 0xFE47, &value, 1); | 683 | /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */ |
684 | retval = __do_config_autodelink(us, &value, 1); | ||
587 | if (retval < 0) | 685 | if (retval < 0) |
588 | return -EIO; | 686 | return -EIO; |
589 | } | 687 | } |