diff options
Diffstat (limited to 'drivers/usb/storage/isd200.c')
-rw-r--r-- | drivers/usb/storage/isd200.c | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 49ba6c0ff1e8..178e8c2a8a2f 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | #include <linux/hdreg.h> | 50 | #include <linux/hdreg.h> |
51 | #include <linux/ide.h> | 51 | #include <linux/ide.h> |
52 | #include <linux/scatterlist.h> | ||
52 | 53 | ||
53 | #include <scsi/scsi.h> | 54 | #include <scsi/scsi.h> |
54 | #include <scsi/scsi_cmnd.h> | 55 | #include <scsi/scsi_cmnd.h> |
@@ -287,6 +288,7 @@ struct isd200_info { | |||
287 | /* maximum number of LUNs supported */ | 288 | /* maximum number of LUNs supported */ |
288 | unsigned char MaxLUNs; | 289 | unsigned char MaxLUNs; |
289 | struct scsi_cmnd srb; | 290 | struct scsi_cmnd srb; |
291 | struct scatterlist sg; | ||
290 | }; | 292 | }; |
291 | 293 | ||
292 | 294 | ||
@@ -398,6 +400,31 @@ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb) | |||
398 | * Transport routines | 400 | * Transport routines |
399 | ***********************************************************************/ | 401 | ***********************************************************************/ |
400 | 402 | ||
403 | /************************************************************************** | ||
404 | * isd200_set_srb(), isd200_srb_set_bufflen() | ||
405 | * | ||
406 | * Two helpers to facilitate in initialization of scsi_cmnd structure | ||
407 | * Will need to change when struct scsi_cmnd changes | ||
408 | */ | ||
409 | static void isd200_set_srb(struct isd200_info *info, | ||
410 | enum dma_data_direction dir, void* buff, unsigned bufflen) | ||
411 | { | ||
412 | struct scsi_cmnd *srb = &info->srb; | ||
413 | |||
414 | if (buff) | ||
415 | sg_init_one(&info->sg, buff, bufflen); | ||
416 | |||
417 | srb->sc_data_direction = dir; | ||
418 | srb->request_buffer = buff ? &info->sg : NULL; | ||
419 | srb->request_bufflen = bufflen; | ||
420 | srb->use_sg = buff ? 1 : 0; | ||
421 | } | ||
422 | |||
423 | static void isd200_srb_set_bufflen(struct scsi_cmnd *srb, unsigned bufflen) | ||
424 | { | ||
425 | srb->request_bufflen = bufflen; | ||
426 | } | ||
427 | |||
401 | 428 | ||
402 | /************************************************************************** | 429 | /************************************************************************** |
403 | * isd200_action | 430 | * isd200_action |
@@ -432,9 +459,7 @@ static int isd200_action( struct us_data *us, int action, | |||
432 | ata.generic.RegisterSelect = | 459 | ata.generic.RegisterSelect = |
433 | REG_CYLINDER_LOW | REG_CYLINDER_HIGH | | 460 | REG_CYLINDER_LOW | REG_CYLINDER_HIGH | |
434 | REG_STATUS | REG_ERROR; | 461 | REG_STATUS | REG_ERROR; |
435 | srb->sc_data_direction = DMA_FROM_DEVICE; | 462 | isd200_set_srb(info, DMA_FROM_DEVICE, pointer, value); |
436 | srb->request_buffer = pointer; | ||
437 | srb->request_bufflen = value; | ||
438 | break; | 463 | break; |
439 | 464 | ||
440 | case ACTION_ENUM: | 465 | case ACTION_ENUM: |
@@ -444,7 +469,7 @@ static int isd200_action( struct us_data *us, int action, | |||
444 | ACTION_SELECT_5; | 469 | ACTION_SELECT_5; |
445 | ata.generic.RegisterSelect = REG_DEVICE_HEAD; | 470 | ata.generic.RegisterSelect = REG_DEVICE_HEAD; |
446 | ata.write.DeviceHeadByte = value; | 471 | ata.write.DeviceHeadByte = value; |
447 | srb->sc_data_direction = DMA_NONE; | 472 | isd200_set_srb(info, DMA_NONE, NULL, 0); |
448 | break; | 473 | break; |
449 | 474 | ||
450 | case ACTION_RESET: | 475 | case ACTION_RESET: |
@@ -453,7 +478,7 @@ static int isd200_action( struct us_data *us, int action, | |||
453 | ACTION_SELECT_3|ACTION_SELECT_4; | 478 | ACTION_SELECT_3|ACTION_SELECT_4; |
454 | ata.generic.RegisterSelect = REG_DEVICE_CONTROL; | 479 | ata.generic.RegisterSelect = REG_DEVICE_CONTROL; |
455 | ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; | 480 | ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; |
456 | srb->sc_data_direction = DMA_NONE; | 481 | isd200_set_srb(info, DMA_NONE, NULL, 0); |
457 | break; | 482 | break; |
458 | 483 | ||
459 | case ACTION_REENABLE: | 484 | case ACTION_REENABLE: |
@@ -462,7 +487,7 @@ static int isd200_action( struct us_data *us, int action, | |||
462 | ACTION_SELECT_3|ACTION_SELECT_4; | 487 | ACTION_SELECT_3|ACTION_SELECT_4; |
463 | ata.generic.RegisterSelect = REG_DEVICE_CONTROL; | 488 | ata.generic.RegisterSelect = REG_DEVICE_CONTROL; |
464 | ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; | 489 | ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; |
465 | srb->sc_data_direction = DMA_NONE; | 490 | isd200_set_srb(info, DMA_NONE, NULL, 0); |
466 | break; | 491 | break; |
467 | 492 | ||
468 | case ACTION_SOFT_RESET: | 493 | case ACTION_SOFT_RESET: |
@@ -471,21 +496,20 @@ static int isd200_action( struct us_data *us, int action, | |||
471 | ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; | 496 | ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; |
472 | ata.write.DeviceHeadByte = info->DeviceHead; | 497 | ata.write.DeviceHeadByte = info->DeviceHead; |
473 | ata.write.CommandByte = WIN_SRST; | 498 | ata.write.CommandByte = WIN_SRST; |
474 | srb->sc_data_direction = DMA_NONE; | 499 | isd200_set_srb(info, DMA_NONE, NULL, 0); |
475 | break; | 500 | break; |
476 | 501 | ||
477 | case ACTION_IDENTIFY: | 502 | case ACTION_IDENTIFY: |
478 | US_DEBUGP(" isd200_action(IDENTIFY)\n"); | 503 | US_DEBUGP(" isd200_action(IDENTIFY)\n"); |
479 | ata.generic.RegisterSelect = REG_COMMAND; | 504 | ata.generic.RegisterSelect = REG_COMMAND; |
480 | ata.write.CommandByte = WIN_IDENTIFY; | 505 | ata.write.CommandByte = WIN_IDENTIFY; |
481 | srb->sc_data_direction = DMA_FROM_DEVICE; | 506 | isd200_set_srb(info, DMA_FROM_DEVICE, info->id, |
482 | srb->request_buffer = (void *) info->id; | 507 | sizeof(struct hd_driveid)); |
483 | srb->request_bufflen = sizeof(struct hd_driveid); | ||
484 | break; | 508 | break; |
485 | 509 | ||
486 | default: | 510 | default: |
487 | US_DEBUGP("Error: Undefined action %d\n",action); | 511 | US_DEBUGP("Error: Undefined action %d\n",action); |
488 | break; | 512 | return ISD200_ERROR; |
489 | } | 513 | } |
490 | 514 | ||
491 | memcpy(srb->cmnd, &ata, sizeof(ata.generic)); | 515 | memcpy(srb->cmnd, &ata, sizeof(ata.generic)); |
@@ -590,7 +614,7 @@ static void isd200_invoke_transport( struct us_data *us, | |||
590 | return; | 614 | return; |
591 | } | 615 | } |
592 | 616 | ||
593 | if ((srb->resid > 0) && | 617 | if ((scsi_get_resid(srb) > 0) && |
594 | !((srb->cmnd[0] == REQUEST_SENSE) || | 618 | !((srb->cmnd[0] == REQUEST_SENSE) || |
595 | (srb->cmnd[0] == INQUIRY) || | 619 | (srb->cmnd[0] == INQUIRY) || |
596 | (srb->cmnd[0] == MODE_SENSE) || | 620 | (srb->cmnd[0] == MODE_SENSE) || |
@@ -1217,7 +1241,6 @@ static int isd200_get_inquiry_data( struct us_data *us ) | |||
1217 | return(retStatus); | 1241 | return(retStatus); |
1218 | } | 1242 | } |
1219 | 1243 | ||
1220 | |||
1221 | /************************************************************************** | 1244 | /************************************************************************** |
1222 | * isd200_scsi_to_ata | 1245 | * isd200_scsi_to_ata |
1223 | * | 1246 | * |
@@ -1266,7 +1289,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, | |||
1266 | ataCdb->generic.TransferBlockSize = 1; | 1289 | ataCdb->generic.TransferBlockSize = 1; |
1267 | ataCdb->generic.RegisterSelect = REG_COMMAND; | 1290 | ataCdb->generic.RegisterSelect = REG_COMMAND; |
1268 | ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; | 1291 | ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; |
1269 | srb->request_bufflen = 0; | 1292 | isd200_srb_set_bufflen(srb, 0); |
1270 | } else { | 1293 | } else { |
1271 | US_DEBUGP(" Media Status not supported, just report okay\n"); | 1294 | US_DEBUGP(" Media Status not supported, just report okay\n"); |
1272 | srb->result = SAM_STAT_GOOD; | 1295 | srb->result = SAM_STAT_GOOD; |
@@ -1284,7 +1307,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, | |||
1284 | ataCdb->generic.TransferBlockSize = 1; | 1307 | ataCdb->generic.TransferBlockSize = 1; |
1285 | ataCdb->generic.RegisterSelect = REG_COMMAND; | 1308 | ataCdb->generic.RegisterSelect = REG_COMMAND; |
1286 | ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; | 1309 | ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; |
1287 | srb->request_bufflen = 0; | 1310 | isd200_srb_set_bufflen(srb, 0); |
1288 | } else { | 1311 | } else { |
1289 | US_DEBUGP(" Media Status not supported, just report okay\n"); | 1312 | US_DEBUGP(" Media Status not supported, just report okay\n"); |
1290 | srb->result = SAM_STAT_GOOD; | 1313 | srb->result = SAM_STAT_GOOD; |
@@ -1390,7 +1413,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, | |||
1390 | ataCdb->generic.RegisterSelect = REG_COMMAND; | 1413 | ataCdb->generic.RegisterSelect = REG_COMMAND; |
1391 | ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ? | 1414 | ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ? |
1392 | WIN_DOORLOCK : WIN_DOORUNLOCK; | 1415 | WIN_DOORLOCK : WIN_DOORUNLOCK; |
1393 | srb->request_bufflen = 0; | 1416 | isd200_srb_set_bufflen(srb, 0); |
1394 | } else { | 1417 | } else { |
1395 | US_DEBUGP(" Not removeable media, just report okay\n"); | 1418 | US_DEBUGP(" Not removeable media, just report okay\n"); |
1396 | srb->result = SAM_STAT_GOOD; | 1419 | srb->result = SAM_STAT_GOOD; |
@@ -1416,7 +1439,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, | |||
1416 | ataCdb->generic.TransferBlockSize = 1; | 1439 | ataCdb->generic.TransferBlockSize = 1; |
1417 | ataCdb->generic.RegisterSelect = REG_COMMAND; | 1440 | ataCdb->generic.RegisterSelect = REG_COMMAND; |
1418 | ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; | 1441 | ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; |
1419 | srb->request_bufflen = 0; | 1442 | isd200_srb_set_bufflen(srb, 0); |
1420 | } else { | 1443 | } else { |
1421 | US_DEBUGP(" Nothing to do, just report okay\n"); | 1444 | US_DEBUGP(" Nothing to do, just report okay\n"); |
1422 | srb->result = SAM_STAT_GOOD; | 1445 | srb->result = SAM_STAT_GOOD; |
@@ -1525,7 +1548,7 @@ int isd200_Initialization(struct us_data *us) | |||
1525 | 1548 | ||
1526 | void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) | 1549 | void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) |
1527 | { | 1550 | { |
1528 | int sendToTransport = 1; | 1551 | int sendToTransport = 1, orig_bufflen; |
1529 | union ata_cdb ataCdb; | 1552 | union ata_cdb ataCdb; |
1530 | 1553 | ||
1531 | /* Make sure driver was initialized */ | 1554 | /* Make sure driver was initialized */ |
@@ -1533,11 +1556,14 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) | |||
1533 | if (us->extra == NULL) | 1556 | if (us->extra == NULL) |
1534 | US_DEBUGP("ERROR Driver not initialized\n"); | 1557 | US_DEBUGP("ERROR Driver not initialized\n"); |
1535 | 1558 | ||
1536 | /* Convert command */ | 1559 | scsi_set_resid(srb, 0); |
1537 | srb->resid = 0; | 1560 | /* scsi_bufflen might change in protocol translation to ata */ |
1561 | orig_bufflen = scsi_bufflen(srb); | ||
1538 | sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb); | 1562 | sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb); |
1539 | 1563 | ||
1540 | /* send the command to the transport layer */ | 1564 | /* send the command to the transport layer */ |
1541 | if (sendToTransport) | 1565 | if (sendToTransport) |
1542 | isd200_invoke_transport(us, srb, &ataCdb); | 1566 | isd200_invoke_transport(us, srb, &ataCdb); |
1567 | |||
1568 | isd200_srb_set_bufflen(srb, orig_bufflen); | ||
1543 | } | 1569 | } |