]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/scsi/libata-scsi.c
Merge libata branch 'chs-support' to latest upstream kernel.
[linux-2.6.git] / drivers / scsi / libata-scsi.c
index 954d1bca3b2a4616df8cfae13ec7882a798bb287..f8ddc2a29e9a744cd32b50a059da6e7430730734 100644 (file)
@@ -1,25 +1,36 @@
 /*
-   libata-scsi.c - helper library for ATA
-
-   Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
-   Copyright 2003-2004 Jeff Garzik
-
-   The contents of this file are subject to the Open
-   Software License version 1.1 that can be found at
-   http://www.opensource.org/licenses/osl-1.1.txt and is included herein
-   by reference.
-
-   Alternatively, the contents of this file may be used under the terms
-   of the GNU General Public License version 2 (the "GPL") as distributed
-   in the kernel source COPYING file, in which case the provisions of
-   the GPL are applicable instead of the above.  If you wish to allow
-   the use of your version of this file only under the terms of the
-   GPL and not to allow others to use your version of this file under
-   the OSL, indicate your decision by deleting the provisions above and
-   replace them with the notice and other provisions required by the GPL.
-   If you do not delete the provisions above, a recipient may use your
-   version of this file under either the OSL or the GPL.
-
+ *  libata-scsi.c - helper library for ATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+ *  Copyright 2003-2004 Jeff Garzik
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *  libata documentation is available via 'make {ps|pdf}docs',
+ *  as Documentation/DocBook/libata.*
+ *
+ *  Hardware documentation available from
+ *  - http://www.t10.org/
+ *  - http://www.t13.org/
+ *
  */
 
 #include <linux/kernel.h>
@@ -391,6 +402,60 @@ int ata_scsi_error(struct Scsi_Host *host)
        return 0;
 }
 
+/**
+ *     ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
+ *     @qc: Storage for translated ATA taskfile
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
+ *     (to start). Perhaps these commands should be preceded by
+ *     CHECK POWER MODE to see what power mode the device is already in.
+ *     [See SAT revision 5 at www.t10.org]
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
+                                            u8 *scsicmd)
+{
+       struct ata_taskfile *tf = &qc->tf;
+
+       tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+       tf->protocol = ATA_PROT_NODATA;
+       if (scsicmd[1] & 0x1) {
+               ;       /* ignore IMMED bit, violates sat-r05 */
+       }
+       if (scsicmd[4] & 0x2)
+               return 1;       /* LOEJ bit set not supported */
+       if (((scsicmd[4] >> 4) & 0xf) != 0)
+               return 1;       /* power conditions not supported */
+       if (scsicmd[4] & 0x1) {
+               tf->nsect = 1;  /* 1 sector, lba=0 */
+               tf->lbah = 0x0;
+               tf->lbam = 0x0;
+               tf->lbal = 0x0;
+               tf->device |= ATA_LBA;
+               tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
+       } else {
+               tf->nsect = 0;  /* time period value (0 implies now) */
+               tf->command = ATA_CMD_STANDBY;
+               /* Consider: ATA STANDBY IMMEDIATE command */
+       }
+       /*
+        * Standby and Idle condition timers could be implemented but that
+        * would require libata to implement the Power condition mode page
+        * and allow the user to change it. Changing mode pages requires
+        * MODE SELECT to be implemented.
+        */
+
+       return 0;
+}
+
+
 /**
  *     ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
  *     @qc: Storage for translated ATA taskfile
@@ -598,7 +663,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
                block |= ((u64)scsicmd[2]) << 8;
                block |= ((u64)scsicmd[3]);
+
                n_block |= ((u32)scsicmd[4]);
+               if (!n_block)
+                       n_block = 256;
        
                VPRINTK("six-byte command\n");
        } 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)
        case VERIFY:
        case VERIFY_16:
                return ata_scsi_verify_xlat;
+       case START_STOP:
+               return ata_scsi_start_stop_xlat;
        }
 
        return NULL;