diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-08-29 15:59:42 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-29 15:59:42 -0400 |
commit | 70d374ea9907036e15574a5ce89219edd5baee10 (patch) | |
tree | b858bb4a841eb91b1d91b41c33698d05fa7bfb37 /drivers/scsi/libata-scsi.c | |
parent | aa7e16d6b88b3b38db0d2ee49ed5e44e7b2045ec (diff) | |
parent | bf4e70e54cf31dcca48d279c7f7e71328eebe749 (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index c6aeab1630ee..346eb36b1e31 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 | |||
422 | static 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; |