diff options
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 119 |
1 files changed, 98 insertions, 21 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 6a75ec2187fd..346eb36b1e31 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -1,25 +1,36 @@ | |||
1 | /* | 1 | /* |
2 | libata-scsi.c - helper library for ATA | 2 | * libata-scsi.c - helper library for ATA |
3 | 3 | * | |
4 | Copyright 2003-2004 Red Hat, Inc. All rights reserved. | 4 | * Maintained by: Jeff Garzik <jgarzik@pobox.com> |
5 | Copyright 2003-2004 Jeff Garzik | 5 | * Please ALWAYS copy linux-ide@vger.kernel.org |
6 | 6 | * on emails. | |
7 | The contents of this file are subject to the Open | 7 | * |
8 | Software License version 1.1 that can be found at | 8 | * Copyright 2003-2004 Red Hat, Inc. All rights reserved. |
9 | http://www.opensource.org/licenses/osl-1.1.txt and is included herein | 9 | * Copyright 2003-2004 Jeff Garzik |
10 | by reference. | 10 | * |
11 | 11 | * | |
12 | Alternatively, the contents of this file may be used under the terms | 12 | * This program is free software; you can redistribute it and/or modify |
13 | of the GNU General Public License version 2 (the "GPL") as distributed | 13 | * it under the terms of the GNU General Public License as published by |
14 | in the kernel source COPYING file, in which case the provisions of | 14 | * the Free Software Foundation; either version 2, or (at your option) |
15 | the GPL are applicable instead of the above. If you wish to allow | 15 | * any later version. |
16 | the use of your version of this file only under the terms of the | 16 | * |
17 | GPL and not to allow others to use your version of this file under | 17 | * This program is distributed in the hope that it will be useful, |
18 | the OSL, indicate your decision by deleting the provisions above and | 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | replace them with the notice and other provisions required by the GPL. | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | If you do not delete the provisions above, a recipient may use your | 20 | * GNU General Public License for more details. |
21 | version of this file under either the OSL or the GPL. | 21 | * |
22 | 22 | * You should have received a copy of the GNU General Public License | |
23 | * along with this program; see the file COPYING. If not, write to | ||
24 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | * | ||
27 | * libata documentation is available via 'make {ps|pdf}docs', | ||
28 | * as Documentation/DocBook/libata.* | ||
29 | * | ||
30 | * Hardware documentation available from | ||
31 | * - http://www.t10.org/ | ||
32 | * - http://www.t13.org/ | ||
33 | * | ||
23 | */ | 34 | */ |
24 | 35 | ||
25 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
@@ -392,6 +403,60 @@ int ata_scsi_error(struct Scsi_Host *host) | |||
392 | } | 403 | } |
393 | 404 | ||
394 | /** | 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 | /** | ||
395 | * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command | 460 | * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command |
396 | * @qc: Storage for translated ATA taskfile | 461 | * @qc: Storage for translated ATA taskfile |
397 | * @scsicmd: SCSI command to translate (ignored) | 462 | * @scsicmd: SCSI command to translate (ignored) |
@@ -576,11 +641,19 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
576 | tf->lbah = scsicmd[3]; | 641 | tf->lbah = scsicmd[3]; |
577 | 642 | ||
578 | 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; | ||
579 | return 0; | 646 | return 0; |
580 | } | 647 | } |
581 | 648 | ||
582 | if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { | 649 | if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { |
583 | 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 | |||
584 | tf->lbal = scsicmd[3]; | 657 | tf->lbal = scsicmd[3]; |
585 | tf->lbam = scsicmd[2]; | 658 | tf->lbam = scsicmd[2]; |
586 | tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */ | 659 | tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */ |
@@ -620,6 +693,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
620 | tf->lbah = scsicmd[7]; | 693 | tf->lbah = scsicmd[7]; |
621 | 694 | ||
622 | 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; | ||
623 | return 0; | 698 | return 0; |
624 | } | 699 | } |
625 | 700 | ||
@@ -1435,6 +1510,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) | |||
1435 | case VERIFY: | 1510 | case VERIFY: |
1436 | case VERIFY_16: | 1511 | case VERIFY_16: |
1437 | return ata_scsi_verify_xlat; | 1512 | return ata_scsi_verify_xlat; |
1513 | case START_STOP: | ||
1514 | return ata_scsi_start_stop_xlat; | ||
1438 | } | 1515 | } |
1439 | 1516 | ||
1440 | return NULL; | 1517 | return NULL; |