diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-08-29 19:24:43 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-29 19:24:43 -0400 |
commit | 76b2bf9b4dee2fb32ef17f5c84a99ce481a14be2 (patch) | |
tree | 49cd36d6e980044c2a88f2c14cdc9259e0f0f1b4 /drivers/scsi/libata-scsi.c | |
parent | 2fca877b68b2b4fc5b94277858a1bedd46017cde (diff) | |
parent | 8f3d17fb7bcb7c255197d11469fb5e9695c9d2f4 (diff) |
Merge libata branch 'chs-support' to latest upstream kernel.
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 112 |
1 files changed, 91 insertions, 21 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 954d1bca3b2a..f8ddc2a29e9a 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) |
@@ -598,7 +663,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
598 | } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { | 663 | } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { |
599 | block |= ((u64)scsicmd[2]) << 8; | 664 | block |= ((u64)scsicmd[2]) << 8; |
600 | block |= ((u64)scsicmd[3]); | 665 | block |= ((u64)scsicmd[3]); |
666 | |||
601 | n_block |= ((u32)scsicmd[4]); | 667 | n_block |= ((u32)scsicmd[4]); |
668 | if (!n_block) | ||
669 | n_block = 256; | ||
602 | 670 | ||
603 | VPRINTK("six-byte command\n"); | 671 | VPRINTK("six-byte command\n"); |
604 | } else if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) { | 672 | } else if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) { |
@@ -1509,6 +1577,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) | |||
1509 | case VERIFY: | 1577 | case VERIFY: |
1510 | case VERIFY_16: | 1578 | case VERIFY_16: |
1511 | return ata_scsi_verify_xlat; | 1579 | return ata_scsi_verify_xlat; |
1580 | case START_STOP: | ||
1581 | return ata_scsi_start_stop_xlat; | ||
1512 | } | 1582 | } |
1513 | 1583 | ||
1514 | return NULL; | 1584 | return NULL; |