]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge libata branch 'chs-support' to latest upstream kernel.
authorJeff Garzik <jgarzik@pobox.com>
Mon, 29 Aug 2005 23:24:43 +0000 (19:24 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Mon, 29 Aug 2005 23:24:43 +0000 (19:24 -0400)
1  2 
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
include/linux/ata.h
include/linux/libata.h

index 35b61d699f3456f91ca45a2ebce0470f37ef6d1d,dee4b12b034261f4bbdf28e9b956dcb8d0d23ead..a872fad2326a2cdec69263bac3ab1f9d74f2d62b
@@@ -1,25 -1,35 +1,35 @@@
  /*
-    libata-core.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-core.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.t13.org/ and
+  *  http://www.sata-io.org/
+  *
   */
  
  #include <linux/config.h>
@@@ -52,7 -62,6 +62,7 @@@
  static unsigned int ata_busy_sleep (struct ata_port *ap,
                                    unsigned long tmout_pat,
                                    unsigned long tmout);
 +static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
  static void ata_set_mode(struct ata_port *ap);
  static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
  static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
@@@ -1118,7 -1127,7 +1128,7 @@@ static inline void ata_dump_id(struct a
  static void ata_dev_identify(struct ata_port *ap, unsigned int device)
  {
        struct ata_device *dev = &ap->device[device];
 -      unsigned int i;
 +      unsigned int major_version;
        u16 tmp;
        unsigned long xfer_modes;
        u8 status;
@@@ -1216,9 -1225,9 +1226,9 @@@ retry
         * common ATA, ATAPI feature tests
         */
  
 -      /* we require LBA and DMA support (bits 8 & 9 of word 49) */
 -      if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) {
 -              printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id);
 +      /* we require DMA support (bits 8 of word 49) */
 +      if (!ata_id_has_dma(dev->id)) {
 +              printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
                goto err_out_nosup;
        }
  
                if (!ata_id_is_ata(dev->id))    /* sanity check */
                        goto err_out_nosup;
  
 +              /* get major version */
                tmp = dev->id[ATA_ID_MAJOR_VER];
 -              for (i = 14; i >= 1; i--)
 -                      if (tmp & (1 << i))
 +              for (major_version = 14; major_version >= 1; major_version--)
 +                      if (tmp & (1 << major_version))
                                break;
  
 -              /* we require at least ATA-3 */
 -              if (i < 3) {
 -                      printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id);
 -                      goto err_out_nosup;
 -              }
 +              /*
 +               * The exact sequence expected by certain pre-ATA4 drives is:
 +               * SRST RESET
 +               * IDENTIFY
 +               * INITIALIZE DEVICE PARAMETERS
 +               * anything else..
 +               * Some drives were very specific about that exact sequence.
 +               */
 +              if (major_version < 4 || (!ata_id_has_lba(dev->id)))
 +                      ata_dev_init_params(ap, dev);
 +
 +              if (ata_id_has_lba(dev->id)) {
 +                      dev->flags |= ATA_DFLAG_LBA;
 +
 +                      if (ata_id_has_lba48(dev->id)) {
 +                              dev->flags |= ATA_DFLAG_LBA48;
 +                              dev->n_sectors = ata_id_u64(dev->id, 100);
 +                      } else {
 +                              dev->n_sectors = ata_id_u32(dev->id, 60);
 +                      }
 +
 +                      /* print device info to dmesg */
 +                      printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
 +                             ap->id, device,
 +                             major_version,
 +                             ata_mode_string(xfer_modes),
 +                             (unsigned long long)dev->n_sectors,
 +                             dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
 +              } else { 
 +                      /* CHS */
 +
 +                      /* Default translation */
 +                      dev->cylinders  = dev->id[1];
 +                      dev->heads      = dev->id[3];
 +                      dev->sectors    = dev->id[6];
 +                      dev->n_sectors  = dev->cylinders * dev->heads * dev->sectors;
 +
 +                      if (ata_id_current_chs_valid(dev->id)) {
 +                              /* Current CHS translation is valid. */
 +                              dev->cylinders = dev->id[54];
 +                              dev->heads     = dev->id[55];
 +                              dev->sectors   = dev->id[56];
 +                              
 +                              dev->n_sectors = ata_id_u32(dev->id, 57);
 +                      }
 +
 +                      /* print device info to dmesg */
 +                      printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
 +                             ap->id, device,
 +                             major_version,
 +                             ata_mode_string(xfer_modes),
 +                             (unsigned long long)dev->n_sectors,
 +                             (int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
  
 -              if (ata_id_has_lba48(dev->id)) {
 -                      dev->flags |= ATA_DFLAG_LBA48;
 -                      dev->n_sectors = ata_id_u64(dev->id, 100);
 -              } else {
 -                      dev->n_sectors = ata_id_u32(dev->id, 60);
                }
  
                ap->host->max_cmd_len = 16;
 -
 -              /* print device info to dmesg */
 -              printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
 -                     ap->id, device,
 -                     ata_mode_string(xfer_modes),
 -                     (unsigned long long)dev->n_sectors,
 -                     dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
        }
  
        /* ATAPI-specific feature tests */
@@@ -1342,12 -1314,12 +1352,12 @@@ static inline u8 ata_dev_knobble(struc
  /**
   *    ata_dev_config - Run device specific handlers and check for
   *                     SATA->PATA bridges
-  *    @ap: Bus 
+  *    @ap: Bus
   *    @i:  Device
   *
   *    LOCKING:
   */
-  
  void ata_dev_config(struct ata_port *ap, unsigned int i)
  {
        /* limit bridge transfers to udma5, 200 sectors */
@@@ -2167,54 -2139,6 +2177,54 @@@ static void ata_dev_set_xfermode(struc
        DPRINTK("EXIT\n");
  }
  
 +/**
 + *    ata_dev_init_params - Issue INIT DEV PARAMS command
 + *    @ap: Port associated with device @dev
 + *    @dev: Device to which command will be sent
 + *
 + *    LOCKING:
 + */
 +
 +static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
 +{
 +      DECLARE_COMPLETION(wait);
 +      struct ata_queued_cmd *qc;
 +      int rc;
 +      unsigned long flags;
 +      u16 sectors = dev->id[6];
 +      u16 heads   = dev->id[3];
 +
 +      /* Number of sectors per track 1-255. Number of heads 1-16 */
 +      if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
 +              return;
 +
 +      /* set up init dev params taskfile */
 +      DPRINTK("init dev params \n");
 +
 +      qc = ata_qc_new_init(ap, dev);
 +      BUG_ON(qc == NULL);
 +
 +      qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
 +      qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 +      qc->tf.protocol = ATA_PROT_NODATA;
 +      qc->tf.nsect = sectors;
 +      qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
 +
 +      qc->waiting = &wait;
 +      qc->complete_fn = ata_qc_complete_noop;
 +
 +      spin_lock_irqsave(&ap->host_set->lock, flags);
 +      rc = ata_qc_issue(qc);
 +      spin_unlock_irqrestore(&ap->host_set->lock, flags);
 +
 +      if (rc)
 +              ata_port_disable(ap);
 +      else
 +              wait_for_completion(&wait);
 +
 +      DPRINTK("EXIT\n");
 +}
 +
  /**
   *    ata_sg_clean - Unmap DMA memory associated with command
   *    @qc: Command containing DMA memory to be released
@@@ -2462,6 -2386,27 +2472,27 @@@ static int ata_sg_setup(struct ata_queu
        return 0;
  }
  
+ /**
+  *    ata_poll_qc_complete - turn irq back on and finish qc
+  *    @qc: Command to complete
+  *    @drv_stat: ATA status register content
+  *
+  *    LOCKING:
+  *    None.  (grabs host lock)
+  */
+ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+ {
+       struct ata_port *ap = qc->ap;
+       unsigned long flags;
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->flags &= ~ATA_FLAG_NOINTR;
+       ata_irq_on(ap);
+       ata_qc_complete(qc, drv_stat);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ }
  /**
   *    ata_pio_poll -
   *    @ap:
@@@ -2524,11 -2469,10 +2555,10 @@@ static void ata_pio_complete (struct at
        u8 drv_stat;
  
        /*
-        * This is purely hueristic.  This is a fast path.
-        * Sometimes when we enter, BSY will be cleared in
-        * a chk-status or two.  If not, the drive is probably seeking
-        * or something.  Snooze for a couple msecs, then
-        * chk-status again.  If still busy, fall back to
+        * This is purely heuristic.  This is a fast path.  Sometimes when
+        * we enter, BSY will be cleared in a chk-status or two.  If not,
+        * the drive is probably seeking or something.  Snooze for a couple
+        * msecs, then chk-status again.  If still busy, fall back to
         * PIO_ST_POLL state.
         */
        drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
  
        ap->pio_task_state = PIO_ST_IDLE;
  
-       ata_irq_on(ap);
-       ata_qc_complete(qc, drv_stat);
+       ata_poll_qc_complete(qc, drv_stat);
  }
  
  
@@@ -2580,6 -2522,20 +2608,20 @@@ void swap_buf_le16(u16 *buf, unsigned i
  #endif /* __BIG_ENDIAN */
  }
  
+ /**
+  *    ata_mmio_data_xfer - Transfer data by MMIO
+  *    @ap: port to read/write
+  *    @buf: data buffer
+  *    @buflen: buffer length
+  *    @do_write: read/write
+  *
+  *    Transfer data from/to the device data register by MMIO.
+  *
+  *    LOCKING:
+  *    Inherited from caller.
+  *
+  */
  static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
                               unsigned int buflen, int write_data)
  {
        u16 *buf16 = (u16 *) buf;
        void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
  
+       /* Transfer multiple of 2 bytes */
        if (write_data) {
                for (i = 0; i < words; i++)
                        writew(le16_to_cpu(buf16[i]), mmio);
                for (i = 0; i < words; i++)
                        buf16[i] = cpu_to_le16(readw(mmio));
        }
+       /* Transfer trailing 1 byte, if any. */
+       if (unlikely(buflen & 0x01)) {
+               u16 align_buf[1] = { 0 };
+               unsigned char *trailing_buf = buf + buflen - 1;
+               if (write_data) {
+                       memcpy(align_buf, trailing_buf, 1);
+                       writew(le16_to_cpu(align_buf[0]), mmio);
+               } else {
+                       align_buf[0] = cpu_to_le16(readw(mmio));
+                       memcpy(trailing_buf, align_buf, 1);
+               }
+       }
  }
  
+ /**
+  *    ata_pio_data_xfer - Transfer data by PIO
+  *    @ap: port to read/write
+  *    @buf: data buffer
+  *    @buflen: buffer length
+  *    @do_write: read/write
+  *
+  *    Transfer data from/to the device data register by PIO.
+  *
+  *    LOCKING:
+  *    Inherited from caller.
+  *
+  */
  static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
                              unsigned int buflen, int write_data)
  {
-       unsigned int dwords = buflen >> 1;
+       unsigned int words = buflen >> 1;
  
+       /* Transfer multiple of 2 bytes */
        if (write_data)
-               outsw(ap->ioaddr.data_addr, buf, dwords);
+               outsw(ap->ioaddr.data_addr, buf, words);
        else
-               insw(ap->ioaddr.data_addr, buf, dwords);
+               insw(ap->ioaddr.data_addr, buf, words);
+       /* Transfer trailing 1 byte, if any. */
+       if (unlikely(buflen & 0x01)) {
+               u16 align_buf[1] = { 0 };
+               unsigned char *trailing_buf = buf + buflen - 1;
+               if (write_data) {
+                       memcpy(align_buf, trailing_buf, 1);
+                       outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+               } else {
+                       align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+                       memcpy(trailing_buf, align_buf, 1);
+               }
+       }
  }
  
+ /**
+  *    ata_data_xfer - Transfer data from/to the data register.
+  *    @ap: port to read/write
+  *    @buf: data buffer
+  *    @buflen: buffer length
+  *    @do_write: read/write
+  *
+  *    Transfer data from/to the device data register.
+  *
+  *    LOCKING:
+  *    Inherited from caller.
+  *
+  */
  static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
                          unsigned int buflen, int do_write)
  {
                ata_pio_data_xfer(ap, buf, buflen, do_write);
  }
  
+ /**
+  *    ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
+  *    @qc: Command on going
+  *
+  *    Transfer ATA_SECT_SIZE of data from/to the ATA device.
+  *
+  *    LOCKING:
+  *    Inherited from caller.
+  */
  static void ata_pio_sector(struct ata_queued_cmd *qc)
  {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
        kunmap(page);
  }
  
+ /**
+  *    __atapi_pio_bytes - Transfer data from/to the ATAPI device.
+  *    @qc: Command on going
+  *    @bytes: number of bytes
+  *
+  *    Transfer Transfer data from/to the ATAPI device.
+  *
+  *    LOCKING:
+  *    Inherited from caller.
+  *
+  */
  static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
  {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
        unsigned char *buf;
        unsigned int offset, count;
  
-       if (qc->curbytes == qc->nbytes - bytes)
+       if (qc->curbytes + bytes >= qc->nbytes)
                ap->pio_task_state = PIO_ST_LAST;
  
  next_sg:
+       if (unlikely(qc->cursg >= qc->n_elem)) {
+               /* 
+                * The end of qc->sg is reached and the device expects
+                * more data to transfer. In order not to overrun qc->sg
+                * and fulfill length specified in the byte count register,
+                *    - for read case, discard trailing data from the device
+                *    - for write case, padding zero data to the device
+                */
+               u16 pad_buf[1] = { 0 };
+               unsigned int words = bytes >> 1;
+               unsigned int i;
+               if (words) /* warning if bytes > 1 */
+                       printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
+                              ap->id, bytes);
+               for (i = 0; i < words; i++)
+                       ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+               ap->pio_task_state = PIO_ST_LAST;
+               return;
+       }
        sg = &qc->sg[qc->cursg];
  
        page = sg->page;
  
        kunmap(page);
  
-       if (bytes) {
+       if (bytes)
                goto next_sg;
-       }
  }
  
+ /**
+  *    atapi_pio_bytes - Transfer data from/to the ATAPI device.
+  *    @qc: Command on going
+  *
+  *    Transfer Transfer data from/to the ATAPI device.
+  *
+  *    LOCKING:
+  *    Inherited from caller.
+  *
+  */
  static void atapi_pio_bytes(struct ata_queued_cmd *qc)
  {
        struct ata_port *ap = qc->ap;
@@@ -2778,9 -2847,7 +2933,7 @@@ static void ata_pio_block(struct ata_po
                if ((status & ATA_DRQ) == 0) {
                        ap->pio_task_state = PIO_ST_IDLE;
  
-                       ata_irq_on(ap);
-                       ata_qc_complete(qc, status);
+                       ata_poll_qc_complete(qc, status);
                        return;
                }
  
@@@ -2810,9 -2877,7 +2963,7 @@@ static void ata_pio_error(struct ata_po
  
        ap->pio_task_state = PIO_ST_IDLE;
  
-       ata_irq_on(ap);
-       ata_qc_complete(qc, drv_stat | ATA_ERR);
+       ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
  }
  
  static void ata_pio_task(void *_data)
@@@ -2918,8 -2983,10 +3069,10 @@@ static void atapi_request_sense(struct 
  static void ata_qc_timeout(struct ata_queued_cmd *qc)
  {
        struct ata_port *ap = qc->ap;
+       struct ata_host_set *host_set = ap->host_set;
        struct ata_device *dev = qc->dev;
        u8 host_stat = 0, drv_stat;
+       unsigned long flags;
  
        DPRINTK("ENTER\n");
  
                if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
  
                        /* finish completing original command */
+                       spin_lock_irqsave(&host_set->lock, flags);
                        __ata_qc_complete(qc);
+                       spin_unlock_irqrestore(&host_set->lock, flags);
  
                        atapi_request_sense(ap, dev, cmd);
  
                }
        }
  
+       spin_lock_irqsave(&host_set->lock, flags);
        /* hack alert!  We cannot use the supplied completion
         * function from inside the ->eh_strategy_handler() thread.
         * libata is the only user of ->eh_strategy_handler() in
                host_stat = ap->ops->bmdma_status(ap);
  
                /* before we do anything else, clear DMA-Start bit */
-               ap->ops->bmdma_stop(ap);
+               ap->ops->bmdma_stop(qc);
  
                /* fall through */
  
                ata_qc_complete(qc, drv_stat);
                break;
        }
+       spin_unlock_irqrestore(&host_set->lock, flags);
  out:
        DPRINTK("EXIT\n");
  }
@@@ -3069,12 -3143,8 +3229,12 @@@ struct ata_queued_cmd *ata_qc_new_init(
  
                ata_tf_init(ap, &qc->tf, dev->devno);
  
 -              if (dev->flags & ATA_DFLAG_LBA48)
 -                      qc->tf.flags |= ATA_TFLAG_LBA48;
 +              if (dev->flags & ATA_DFLAG_LBA) {
 +                      qc->tf.flags |= ATA_TFLAG_LBA;
 +
 +                      if (dev->flags & ATA_DFLAG_LBA48)
 +                              qc->tf.flags |= ATA_TFLAG_LBA48;
 +              }
        }
  
        return qc;
@@@ -3151,9 -3221,14 +3311,14 @@@ void ata_qc_complete(struct ata_queued_
        if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
                ata_sg_clean(qc);
  
+       /* atapi: mark qc as inactive to prevent the interrupt handler
+        * from completing the command twice later, before the error handler
+        * is called. (when rc != 0 and atapi request sense is needed)
+        */
+       qc->flags &= ~ATA_QCFLAG_ACTIVE;
        /* call completion callback */
        rc = qc->complete_fn(qc, drv_stat);
-       qc->flags &= ~ATA_QCFLAG_ACTIVE;
  
        /* if callback indicates not to complete command (non-zero),
         * return immediately
@@@ -3283,11 -3358,13 +3448,13 @@@ int ata_qc_issue_prot(struct ata_queued
                break;
  
        case ATA_PROT_ATAPI_NODATA:
+               ap->flags |= ATA_FLAG_NOINTR;
                ata_tf_to_host_nolock(ap, &qc->tf);
                queue_work(ata_wq, &ap->packet_task);
                break;
  
        case ATA_PROT_ATAPI_DMA:
+               ap->flags |= ATA_FLAG_NOINTR;
                ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
                ap->ops->bmdma_setup(qc);           /* set up bmdma */
                queue_work(ata_wq, &ap->packet_task);
@@@ -3332,7 -3409,7 +3499,7 @@@ static void ata_bmdma_setup_mmio (struc
  }
  
  /**
-  *    ata_bmdma_start - Start a PCI IDE BMDMA transaction
+  *    ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
   *    @qc: Info associated with this ATA transaction.
   *
   *    LOCKING:
@@@ -3503,7 -3580,7 +3670,7 @@@ u8 ata_bmdma_status(struct ata_port *ap
  
  /**
   *    ata_bmdma_stop - Stop PCI IDE BMDMA transfer
-  *    @ap: Port associated with this ATA transaction.
+  *    @qc: Command we are ending DMA for
   *
   *    Clears the ATA_DMA_START flag in the dma control register
   *
   *    spin_lock_irqsave(host_set lock)
   */
  
- void ata_bmdma_stop(struct ata_port *ap)
+ void ata_bmdma_stop(struct ata_queued_cmd *qc)
  {
+       struct ata_port *ap = qc->ap;
        if (ap->flags & ATA_FLAG_MMIO) {
                void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
  
@@@ -3566,7 -3644,7 +3734,7 @@@ inline unsigned int ata_host_intr (stru
                        goto idle_irq;
  
                /* before we do anything else, clear DMA-Start bit */
-               ap->ops->bmdma_stop(ap);
+               ap->ops->bmdma_stop(qc);
  
                /* fall through */
  
@@@ -3641,7 -3719,8 +3809,8 @@@ irqreturn_t ata_interrupt (int irq, voi
                struct ata_port *ap;
  
                ap = host_set->ports[i];
-               if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+               if (ap &&
+                   !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
  
                        qc = ata_qc_from_tag(ap, ap->active_tag);
@@@ -3693,19 -3772,27 +3862,27 @@@ static void atapi_packet_task(void *_da
        /* send SCSI cdb */
        DPRINTK("send cdb\n");
        assert(ap->cdb_len >= 12);
-       ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
  
-       /* if we are DMA'ing, irq handler takes over from here */
-       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
-               ap->ops->bmdma_start(qc);           /* initiate bmdma */
+       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
+           qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
+               unsigned long flags;
  
-       /* non-data commands are also handled via irq */
-       else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
-               /* do nothing */
-       }
+               /* Once we're done issuing command and kicking bmdma,
+                * irq handler takes over.  To not lose irq, we need
+                * to clear NOINTR flag before sending cdb, but
+                * interrupt handler shouldn't be invoked before we're
+                * finished.  Hence, the following locking.
+                */
+               spin_lock_irqsave(&ap->host_set->lock, flags);
+               ap->flags &= ~ATA_FLAG_NOINTR;
+               ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+               if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
+                       ap->ops->bmdma_start(qc);       /* initiate bmdma */
+               spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       } else {
+               ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
  
-       /* PIO commands are handled by polling */
-       else {
+               /* PIO commands are handled by polling */
                ap->pio_task_state = PIO_ST;
                queue_work(ata_wq, &ap->pio_task);
        }
        return;
  
  err_out:
-       ata_qc_complete(qc, ATA_ERR);
+       ata_poll_qc_complete(qc, ATA_ERR);
  }
  
  
index 954d1bca3b2a4616df8cfae13ec7882a798bb287,346eb36b1e31e0c5665269077e65ef4f11149644..f8ddc2a29e9a744cd32b50a059da6e7430730734
@@@ -1,25 -1,36 +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 +402,60 @@@ int ata_scsi_error(struct Scsi_Host *ho
        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
@@@ -439,107 -504,77 +504,107 @@@ static unsigned int ata_scsi_flush_xlat
  static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
  {
        struct ata_taskfile *tf = &qc->tf;
 +      struct ata_device *dev = qc->dev;
 +      unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
        u64 dev_sectors = qc->dev->n_sectors;
 -      u64 sect = 0;
 -      u32 n_sect = 0;
 +      u64 block = 0;
 +      u32 n_block = 0;
  
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = ATA_PROT_NODATA;
 -      tf->device |= ATA_LBA;
  
        if (scsicmd[0] == VERIFY) {
 -              sect |= ((u64)scsicmd[2]) << 24;
 -              sect |= ((u64)scsicmd[3]) << 16;
 -              sect |= ((u64)scsicmd[4]) << 8;
 -              sect |= ((u64)scsicmd[5]);
 +              block |= ((u64)scsicmd[2]) << 24;
 +              block |= ((u64)scsicmd[3]) << 16;
 +              block |= ((u64)scsicmd[4]) << 8;
 +              block |= ((u64)scsicmd[5]);
  
 -              n_sect |= ((u32)scsicmd[7]) << 8;
 -              n_sect |= ((u32)scsicmd[8]);
 +              n_block |= ((u32)scsicmd[7]) << 8;
 +              n_block |= ((u32)scsicmd[8]);
        }
  
        else if (scsicmd[0] == VERIFY_16) {
 -              sect |= ((u64)scsicmd[2]) << 56;
 -              sect |= ((u64)scsicmd[3]) << 48;
 -              sect |= ((u64)scsicmd[4]) << 40;
 -              sect |= ((u64)scsicmd[5]) << 32;
 -              sect |= ((u64)scsicmd[6]) << 24;
 -              sect |= ((u64)scsicmd[7]) << 16;
 -              sect |= ((u64)scsicmd[8]) << 8;
 -              sect |= ((u64)scsicmd[9]);
 -
 -              n_sect |= ((u32)scsicmd[10]) << 24;
 -              n_sect |= ((u32)scsicmd[11]) << 16;
 -              n_sect |= ((u32)scsicmd[12]) << 8;
 -              n_sect |= ((u32)scsicmd[13]);
 +              block |= ((u64)scsicmd[2]) << 56;
 +              block |= ((u64)scsicmd[3]) << 48;
 +              block |= ((u64)scsicmd[4]) << 40;
 +              block |= ((u64)scsicmd[5]) << 32;
 +              block |= ((u64)scsicmd[6]) << 24;
 +              block |= ((u64)scsicmd[7]) << 16;
 +              block |= ((u64)scsicmd[8]) << 8;
 +              block |= ((u64)scsicmd[9]);
 +
 +              n_block |= ((u32)scsicmd[10]) << 24;
 +              n_block |= ((u32)scsicmd[11]) << 16;
 +              n_block |= ((u32)scsicmd[12]) << 8;
 +              n_block |= ((u32)scsicmd[13]);
        }
  
        else
                return 1;
  
 -      if (!n_sect)
 +      if (!n_block)
                return 1;
 -      if (sect >= dev_sectors)
 +      if (block >= dev_sectors)
                return 1;
 -      if ((sect + n_sect) > dev_sectors)
 +      if ((block + n_block) > dev_sectors)
                return 1;
        if (lba48) {
 -              if (n_sect > (64 * 1024))
 +              if (n_block > (64 * 1024))
                        return 1;
        } else {
 -              if (n_sect > 256)
 +              if (n_block > 256)
                        return 1;
        }
  
 -      if (lba48) {
 -              tf->command = ATA_CMD_VERIFY_EXT;
 +      if (lba) {
 +              if (lba48) {
 +                      tf->command = ATA_CMD_VERIFY_EXT;
  
 -              tf->hob_nsect = (n_sect >> 8) & 0xff;
 +                      tf->hob_nsect = (n_block >> 8) & 0xff;
  
 -              tf->hob_lbah = (sect >> 40) & 0xff;
 -              tf->hob_lbam = (sect >> 32) & 0xff;
 -              tf->hob_lbal = (sect >> 24) & 0xff;
 -      } else {
 -              tf->command = ATA_CMD_VERIFY;
 +                      tf->hob_lbah = (block >> 40) & 0xff;
 +                      tf->hob_lbam = (block >> 32) & 0xff;
 +                      tf->hob_lbal = (block >> 24) & 0xff;
 +              } else {
 +                      tf->command = ATA_CMD_VERIFY;
  
 -              tf->device |= (sect >> 24) & 0xf;
 -      }
 +                      tf->device |= (block >> 24) & 0xf;
 +              }
  
 -      tf->nsect = n_sect & 0xff;
 +              tf->nsect = n_block & 0xff;
  
 -      tf->lbah = (sect >> 16) & 0xff;
 -      tf->lbam = (sect >> 8) & 0xff;
 -      tf->lbal = sect & 0xff;
 +              tf->lbah = (block >> 16) & 0xff;
 +              tf->lbam = (block >> 8) & 0xff;
 +              tf->lbal = block & 0xff;
 +
 +              tf->device |= ATA_LBA;
 +      } else {
 +              /* CHS */
 +              u32 sect, head, cyl, track;
 +
 +              /* Convert LBA to CHS */
 +              track = (u32)block / dev->sectors;
 +              cyl   = track / dev->heads;
 +              head  = track % dev->heads;
 +              sect  = (u32)block % dev->sectors + 1;
 +
 +              DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", (u32)block, track, cyl, head, sect);
 +              
 +              /* Check whether the converted CHS can fit. 
 +                 Cylinder: 0-65535 
 +                 Head: 0-15
 +                 Sector: 1-255*/
 +              if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
 +                      return 1;
 +              
 +              tf->command = ATA_CMD_VERIFY;
 +              tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
 +              tf->lbal = sect;
 +              tf->lbam = cyl;
 +              tf->lbah = cyl >> 8;
 +              tf->device |= head;
 +      }
  
        return 0;
  }
  static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
  {
        struct ata_taskfile *tf = &qc->tf;
 +      struct ata_device *dev = qc->dev;
 +      unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
 +      u64 block = 0;
 +      u32 n_block = 0;
  
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = qc->dev->xfer_protocol;
 -      tf->device |= ATA_LBA;
  
        if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
            scsicmd[0] == READ_16) {
                tf->flags |= ATA_TFLAG_WRITE;
        }
  
 +      /* Calculate the SCSI LBA and transfer length. */
        if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
 -              if (lba48) {
 -                      tf->hob_nsect = scsicmd[7];
 -                      tf->hob_lbal = scsicmd[2];
 -
 -                      qc->nsect = ((unsigned int)scsicmd[7] << 8) |
 -                                      scsicmd[8];
 -              } else {
 -                      /* if we don't support LBA48 addressing, the request
 -                       * -may- be too large. */
 -                      if ((scsicmd[2] & 0xf0) || scsicmd[7])
 -                              return 1;
 -
 -                      /* stores LBA27:24 in lower 4 bits of device reg */
 -                      tf->device |= scsicmd[2];
 -
 -                      qc->nsect = scsicmd[8];
 -              }
 +              block |= ((u64)scsicmd[2]) << 24;
 +              block |= ((u64)scsicmd[3]) << 16;
 +              block |= ((u64)scsicmd[4]) << 8;
 +              block |= ((u64)scsicmd[5]);
  
 -              tf->nsect = scsicmd[8];
 -              tf->lbal = scsicmd[5];
 -              tf->lbam = scsicmd[4];
 -              tf->lbah = scsicmd[3];
 +              n_block |= ((u32)scsicmd[7]) << 8;
 +              n_block |= ((u32)scsicmd[8]);
  
                VPRINTK("ten-byte command\n");
 -              if (qc->nsect == 0) /* we don't support length==0 cmds */
 -                      return 1;
 -              return 0;
 -      }
 -
 -      if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
 -              qc->nsect = tf->nsect = scsicmd[4];
 -              if (!qc->nsect) {
 -                      qc->nsect = 256;
 -                      if (lba48)
 -                              tf->hob_nsect = 1;
 -              }
 -
 -              tf->lbal = scsicmd[3];
 -              tf->lbam = scsicmd[2];
 -              tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
 -
 +      } 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");
 -              return 0;
 +      } else if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
 +              block |= ((u64)scsicmd[2]) << 56;
 +              block |= ((u64)scsicmd[3]) << 48;
 +              block |= ((u64)scsicmd[4]) << 40;
 +              block |= ((u64)scsicmd[5]) << 32;
 +              block |= ((u64)scsicmd[6]) << 24;
 +              block |= ((u64)scsicmd[7]) << 16;
 +              block |= ((u64)scsicmd[8]) << 8;
 +              block |= ((u64)scsicmd[9]);
 +
 +              n_block |= ((u32)scsicmd[10]) << 24;
 +              n_block |= ((u32)scsicmd[11]) << 16;
 +              n_block |= ((u32)scsicmd[12]) << 8;
 +              n_block |= ((u32)scsicmd[13]);
 +
 +              VPRINTK("sixteen-byte command\n");
 +      } else {
 +              DPRINTK("no-byte command\n");
 +              return 1;
        }
  
 -      if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
 -              /* rule out impossible LBAs and sector counts */
 -              if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
 -                      return 1;
 +      /* Check and compose ATA command */
 +      if (!n_block)
 +              /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */
 +              return 1;
  
 +      if (lba) {
                if (lba48) {
 -                      tf->hob_nsect = scsicmd[12];
 -                      tf->hob_lbal = scsicmd[6];
 -                      tf->hob_lbam = scsicmd[5];
 -                      tf->hob_lbah = scsicmd[4];
 -
 -                      qc->nsect = ((unsigned int)scsicmd[12] << 8) |
 -                                      scsicmd[13];
 -              } else {
 -                      /* once again, filter out impossible non-zero values */
 -                      if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
 -                          (scsicmd[6] & 0xf0))
 +                      /* The request -may- be too large for LBA48. */
 +                      if ((block >> 48) || (n_block > 65536))
                                return 1;
  
 -                      /* stores LBA27:24 in lower 4 bits of device reg */
 -                      tf->device |= scsicmd[6];
 +                      tf->hob_nsect = (n_block >> 8) & 0xff;
 +
 +                      tf->hob_lbah = (block >> 40) & 0xff;
 +                      tf->hob_lbam = (block >> 32) & 0xff;
 +                      tf->hob_lbal = (block >> 24) & 0xff;
 +              } else { 
 +                      /* LBA28 */
 +
 +                      /* The request -may- be too large for LBA28. */
 +                      if ((block >> 28) || (n_block > 256))
 +                              return 1;
  
 -                      qc->nsect = scsicmd[13];
 +                      tf->device |= (block >> 24) & 0xf;
                }
 +      
 +              qc->nsect = n_block;
 +              tf->nsect = n_block & 0xff;
  
 -              tf->nsect = scsicmd[13];
 -              tf->lbal = scsicmd[9];
 -              tf->lbam = scsicmd[8];
 -              tf->lbah = scsicmd[7];
 +              tf->lbah = (block >> 16) & 0xff;
 +              tf->lbam = (block >> 8) & 0xff;
 +              tf->lbal = block & 0xff;
  
 -              VPRINTK("sixteen-byte command\n");
 -              if (qc->nsect == 0) /* we don't support length==0 cmds */
 +              tf->device |= ATA_LBA;
 +      } else { 
 +              /* CHS */
 +              u32 sect, head, cyl, track;
 +
 +              /* The request -may- be too large for CHS addressing. */
 +              if ((block >> 28) || (n_block > 256))
                        return 1;
 -              return 0;
 +                      
 +              /* Convert LBA to CHS */
 +              track = (u32)block / dev->sectors;
 +              cyl   = track / dev->heads;
 +              head  = track % dev->heads;
 +              sect  = (u32)block % dev->sectors + 1;
 +
 +              DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", 
 +                      (u32)block, track, cyl, head, sect);
 +              
 +              /* Check whether the converted CHS can fit. 
 +                 Cylinder: 0-65535 
 +                 Head: 0-15
 +                 Sector: 1-255*/
 +              if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
 +                      return 1;
 +              
 +              qc->nsect = n_block;
 +              tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
 +              tf->lbal = sect;
 +              tf->lbam = cyl;
 +              tf->lbah = cyl >> 8;
 +              tf->device |= head;
        }
  
 -      DPRINTK("no-byte command\n");
 -      return 1;
 +      return 0;
  }
  
  static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
@@@ -1235,20 -1246,10 +1303,20 @@@ unsigned int ata_scsiop_read_cap(struc
  
        VPRINTK("ENTER\n");
  
 -      if (ata_id_has_lba48(args->id))
 -              n_sectors = ata_id_u64(args->id, 100);
 -      else
 -              n_sectors = ata_id_u32(args->id, 60);
 +      if (ata_id_has_lba(args->id)) {
 +              if (ata_id_has_lba48(args->id))
 +                      n_sectors = ata_id_u64(args->id, 100);
 +              else
 +                      n_sectors = ata_id_u32(args->id, 60);
 +      } else {
 +              /* CHS default translation */
 +              n_sectors = args->id[1] * args->id[3] * args->id[6];
 +
 +              if (ata_id_current_chs_valid(args->id))
 +                      /* CHS current translation */
 +                      n_sectors = ata_id_u32(args->id, 57);
 +      }
 +
        n_sectors--;            /* ATA TotalUserSectors - 1 */
  
        if (args->cmd->cmnd[0] == READ_CAPACITY) {
@@@ -1509,6 -1510,8 +1577,8 @@@ static inline ata_xlat_func_t ata_get_x
        case VERIFY:
        case VERIFY_16:
                return ata_scsi_verify_xlat;
+       case START_STOP:
+               return ata_scsi_start_stop_xlat;
        }
  
        return NULL;
diff --combined include/linux/ata.h
index 6962e26fc6dfa5a6fa046c7a5dea8a6daf76815e,a5b74efab0679ae2a1f17dd6329596bf89c531ea..85169ea9eb018bbee8f6a3253779119246399c77
@@@ -1,24 -1,29 +1,29 @@@
  
  /*
-    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.
+  *  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.t13.org/
+  *
   */
  
  #ifndef __LINUX_ATA_H__
@@@ -108,6 -113,8 +113,8 @@@ enum 
  
        /* ATA device commands */
        ATA_CMD_CHK_POWER       = 0xE5, /* check power mode */
+       ATA_CMD_STANDBY         = 0xE2, /* place in standby power mode */
+       ATA_CMD_IDLE            = 0xE3, /* place in idle power mode */
        ATA_CMD_EDD             = 0x90, /* execute device diagnostic */
        ATA_CMD_FLUSH           = 0xE7,
        ATA_CMD_FLUSH_EXT       = 0xEA,
        ATA_CMD_PACKET          = 0xA0,
        ATA_CMD_VERIFY          = 0x40,
        ATA_CMD_VERIFY_EXT      = 0x42,
 +      ATA_CMD_INIT_DEV_PARAMS = 0x91,
  
        /* SETFEATURES stuff */
        SETFEATURES_XFER        = 0x03,
        ATA_TFLAG_ISADDR        = (1 << 1), /* enable r/w to nsect/lba regs */
        ATA_TFLAG_DEVICE        = (1 << 2), /* enable r/w to device reg */
        ATA_TFLAG_WRITE         = (1 << 3), /* data dir: host->dev==1 (write) */
 +      ATA_TFLAG_LBA           = (1 << 4), /* enable LBA */
  };
  
  enum ata_tf_protocols {
@@@ -245,18 -250,6 +252,18 @@@ struct ata_taskfile 
          ((u64) (id)[(n) + 1] << 16) | \
          ((u64) (id)[(n) + 0]) )
  
 +static inline int ata_id_current_chs_valid(u16 *id)
 +{
 +      /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command 
 +         has not been issued to the device then the values of 
 +         id[54] to id[56] are vendor specific. */
 +      return (id[53] & 0x01) && /* Current translation valid */
 +              id[54] &&  /* cylinders in current translation */
 +              id[55] &&  /* heads in current translation */
 +              id[55] <= 16 &&
 +              id[56];    /* sectors in current translation */
 +}
 +
  static inline int atapi_cdb_len(u16 *dev_id)
  {
        u16 tmp = dev_id[0] & 0x3;
diff --combined include/linux/libata.h
index 973090be7fc4e863ac27e9b5844550f25b58afd1,fc05a989928898c91b4800647aa21d228cd5e5a7..7b2116ddd26a423f68e544f547fd9a595252eff7
@@@ -1,23 -1,26 +1,26 @@@
  /*
-    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.
+  *  Copyright 2003-2005 Red Hat, Inc.  All rights reserved.
+  *  Copyright 2003-2005 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.*
+  *
   */
  
  #ifndef __LINUX_LIBATA_H__
@@@ -95,7 -98,6 +98,7 @@@ enum 
        ATA_DFLAG_LBA48         = (1 << 0), /* device supports LBA48 */
        ATA_DFLAG_PIO           = (1 << 1), /* device currently in PIO mode */
        ATA_DFLAG_LOCK_SECTORS  = (1 << 2), /* don't adjust max_sectors */
 +      ATA_DFLAG_LBA           = (1 << 3), /* device supports LBA */
  
        ATA_DEV_UNKNOWN         = 0,    /* unknown device */
        ATA_DEV_ATA             = 1,    /* ATA device */
        ATA_FLAG_MMIO           = (1 << 6), /* use MMIO, not PIO */
        ATA_FLAG_SATA_RESET     = (1 << 7), /* use COMRESET */
        ATA_FLAG_PIO_DMA        = (1 << 8), /* PIO cmds via DMA */
+       ATA_FLAG_NOINTR         = (1 << 9), /* FIXME: Remove this once
+                                            * proper HSM is in place. */
  
        ATA_QCFLAG_ACTIVE       = (1 << 1), /* cmd not yet ack'd to scsi lyer */
        ATA_QCFLAG_SG           = (1 << 3), /* have s/g table? */
@@@ -279,11 -283,6 +284,11 @@@ struct ata_device 
        u8                      xfer_protocol;  /* taskfile xfer protocol */
        u8                      read_cmd;       /* opcode to use on read */
        u8                      write_cmd;      /* opcode to use on write */
 +
 +      /* for CHS addressing */
 +      u16                     cylinders;      /* Number of cylinders */
 +      u16                     heads;          /* Number of heads */
 +      u16                     sectors;        /* Number of sectors per track */
  };
  
  struct ata_port {
@@@ -369,7 -368,7 +374,7 @@@ struct ata_port_operations 
  
        void (*host_stop) (struct ata_host_set *host_set);
  
-       void (*bmdma_stop) (struct ata_port *ap);
+       void (*bmdma_stop) (struct ata_queued_cmd *qc);
        u8   (*bmdma_status) (struct ata_port *ap);
  };
  
@@@ -430,7 -429,7 +435,7 @@@ extern void ata_dev_id_string(u16 *id, 
  extern void ata_dev_config(struct ata_port *ap, unsigned int i);
  extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
  extern void ata_bmdma_start (struct ata_queued_cmd *qc);
- extern void ata_bmdma_stop(struct ata_port *ap);
+ extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
  extern u8   ata_bmdma_status(struct ata_port *ap);
  extern void ata_bmdma_irq_clear(struct ata_port *ap);
  extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
@@@ -650,7 -649,7 +655,7 @@@ static inline void scr_write(struct ata
        ap->ops->scr_write(ap, reg, val);
  }
  
- static inline void scr_write_flush(struct ata_port *ap, unsigned int reg, 
+ static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
                                   u32 val)
  {
        ap->ops->scr_write(ap, reg, val);