aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r--drivers/scsi/libata-scsi.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index c6aeab1630e..346eb36b1e3 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -403,6 +403,60 @@ int ata_scsi_error(struct Scsi_Host *host)
403} 403}
404 404
405/** 405/**
406 * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
407 * @qc: Storage for translated ATA taskfile
408 * @scsicmd: SCSI command to translate
409 *
410 * Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
411 * (to start). Perhaps these commands should be preceded by
412 * CHECK POWER MODE to see what power mode the device is already in.
413 * [See SAT revision 5 at www.t10.org]
414 *
415 * LOCKING:
416 * spin_lock_irqsave(host_set lock)
417 *
418 * RETURNS:
419 * Zero on success, non-zero on error.
420 */
421
422static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
423 u8 *scsicmd)
424{
425 struct ata_taskfile *tf = &qc->tf;
426
427 tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
428 tf->protocol = ATA_PROT_NODATA;
429 if (scsicmd[1] & 0x1) {
430 ; /* ignore IMMED bit, violates sat-r05 */
431 }
432 if (scsicmd[4] & 0x2)
433 return 1; /* LOEJ bit set not supported */
434 if (((scsicmd[4] >> 4) & 0xf) != 0)
435 return 1; /* power conditions not supported */
436 if (scsicmd[4] & 0x1) {
437 tf->nsect = 1; /* 1 sector, lba=0 */
438 tf->lbah = 0x0;
439 tf->lbam = 0x0;
440 tf->lbal = 0x0;
441 tf->device |= ATA_LBA;
442 tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
443 } else {
444 tf->nsect = 0; /* time period value (0 implies now) */
445 tf->command = ATA_CMD_STANDBY;
446 /* Consider: ATA STANDBY IMMEDIATE command */
447 }
448 /*
449 * Standby and Idle condition timers could be implemented but that
450 * would require libata to implement the Power condition mode page
451 * and allow the user to change it. Changing mode pages requires
452 * MODE SELECT to be implemented.
453 */
454
455 return 0;
456}
457
458
459/**
406 * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command 460 * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
407 * @qc: Storage for translated ATA taskfile 461 * @qc: Storage for translated ATA taskfile
408 * @scsicmd: SCSI command to translate (ignored) 462 * @scsicmd: SCSI command to translate (ignored)
@@ -587,11 +641,19 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
587 tf->lbah = scsicmd[3]; 641 tf->lbah = scsicmd[3];
588 642
589 VPRINTK("ten-byte command\n"); 643 VPRINTK("ten-byte command\n");
644 if (qc->nsect == 0) /* we don't support length==0 cmds */
645 return 1;
590 return 0; 646 return 0;
591 } 647 }
592 648
593 if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { 649 if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
594 qc->nsect = tf->nsect = scsicmd[4]; 650 qc->nsect = tf->nsect = scsicmd[4];
651 if (!qc->nsect) {
652 qc->nsect = 256;
653 if (lba48)
654 tf->hob_nsect = 1;
655 }
656
595 tf->lbal = scsicmd[3]; 657 tf->lbal = scsicmd[3];
596 tf->lbam = scsicmd[2]; 658 tf->lbam = scsicmd[2];
597 tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */ 659 tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
@@ -631,6 +693,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
631 tf->lbah = scsicmd[7]; 693 tf->lbah = scsicmd[7];
632 694
633 VPRINTK("sixteen-byte command\n"); 695 VPRINTK("sixteen-byte command\n");
696 if (qc->nsect == 0) /* we don't support length==0 cmds */
697 return 1;
634 return 0; 698 return 0;
635 } 699 }
636 700
@@ -1446,6 +1510,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
1446 case VERIFY: 1510 case VERIFY:
1447 case VERIFY_16: 1511 case VERIFY_16:
1448 return ata_scsi_verify_xlat; 1512 return ata_scsi_verify_xlat;
1513 case START_STOP:
1514 return ata_scsi_start_stop_xlat;
1449 } 1515 }
1450 1516
1451 return NULL; 1517 return NULL;