powerpc/mm: Fix handling of _PAGE_COHERENT in BAT setup code
[safe/jmp/linux-2.6] / drivers / ide / ide-iops.c
index ee44878..753b92e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2000-2002    Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2003         Red Hat <alan@redhat.com>
+ *  Copyright (C) 2003         Red Hat
  *
  */
 
@@ -105,15 +105,6 @@ u8 ide_read_altstatus(ide_hwif_t *hwif)
 }
 EXPORT_SYMBOL_GPL(ide_read_altstatus);
 
-u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
-{
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
-               return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               return inb(hwif->dma_base + ATA_DMA_STATUS);
-}
-EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
-
 void ide_set_irq(ide_hwif_t *hwif, int on)
 {
        u8 ctl = ATA_DEVCTL_OBS;
@@ -181,7 +172,7 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
                tf_outb(tf->lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               tf_outb((tf->device & HIHI) | drive->select.all,
+               tf_outb((tf->device & HIHI) | drive->select,
                         io_ports->device_addr);
 }
 EXPORT_SYMBOL_GPL(ide_tf_load);
@@ -388,7 +379,6 @@ const struct ide_tp_ops default_tp_ops = {
        .exec_command           = ide_exec_command,
        .read_status            = ide_read_status,
        .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
 
        .set_irq                = ide_set_irq,
 
@@ -451,24 +441,20 @@ EXPORT_SYMBOL(ide_fixstring);
  */
 int drive_is_ready (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif        = drive->hwif;
        u8 stat                 = 0;
 
        if (drive->waiting_for_dma)
                return hwif->dma_ops->dma_test_irq(drive);
 
-#if 0
-       /* need to guarantee 400ns since last command was issued */
-       udelay(1);
-#endif
-
        /*
         * We do a passive status test under shared PCI interrupts on
         * cards that truly share the ATA side interrupt, but may also share
         * an interrupt with another pci card/device.  We make no assumptions
         * about possible isa-pnp and pci-pnp issues yet.
         */
-       if (hwif->io_ports.ctl_addr)
+       if (hwif->io_ports.ctl_addr &&
+           (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
                stat = hwif->tp_ops->read_altstatus(hwif);
        else
                /* Note: this may clear a pending IRQ!! */
@@ -507,7 +493,8 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
        stat = tp_ops->read_status(hwif);
 
        if (stat & ATA_BUSY) {
-               local_irq_set(flags);
+               local_save_flags(flags);
+               local_irq_enable_in_hardirq();
                timeout += jiffies;
                while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) {
                        if (time_after(jiffies, timeout)) {
@@ -610,6 +597,7 @@ static const struct drive_list_entry ivb_list[] = {
        { "TSSTcorp CDDVDW SH-S202N"    , "SB01"        },
        { "TSSTcorp CDDVDW SH-S202H"    , "SB00"        },
        { "TSSTcorp CDDVDW SH-S202H"    , "SB01"        },
+       { "SAMSUNG SP0822N"             , "WA100-10"    },
        { NULL                          , NULL          }
 };
 
@@ -630,7 +618,7 @@ u8 eighty_ninty_three (ide_drive_t *drive)
                printk(KERN_DEBUG "%s: skipping word 93 validity check\n",
                                  drive->name);
 
-       if (ide_dev_is_sata(id) && !ivb)
+       if (ata_id_is_sata(id) && !ivb)
                return 1;
 
        if (hwif->cbl != ATA_CBL_PATA80 && !ivb)
@@ -647,7 +635,7 @@ u8 eighty_ninty_three (ide_drive_t *drive)
                return 1;
 
 no_80w:
-       if (drive->udma33_warned == 1)
+       if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED)
                return 0;
 
        printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
@@ -655,7 +643,7 @@ no_80w:
                            drive->name,
                            hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
 
-       drive->udma33_warned = 1;
+       drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED;
 
        return 0;
 }
@@ -693,7 +681,7 @@ int ide_driveid_update(ide_drive_t *drive)
        }
        local_irq_save(flags);
        SELECT_MASK(drive, 0);
-       id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+       id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
        if (!id) {
                local_irq_restore(flags);
                return 0;
@@ -711,7 +699,7 @@ int ide_driveid_update(ide_drive_t *drive)
 
        kfree(id);
 
-       if (drive->using_dma && ide_id_dma_bug(drive))
+       if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive))
                ide_dma_off(drive);
 
        return 1;
@@ -755,7 +743,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
         
        udelay(1);
        SELECT_DRIVE(drive);
-       SELECT_MASK(drive, 0);
+       SELECT_MASK(drive, 1);
        udelay(1);
        tp_ops->set_irq(hwif, 0);
 
@@ -790,7 +778,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 
  skip:
 #ifdef CONFIG_BLK_DEV_IDEDMA
-       if (speed >= XFER_SW_DMA_0 && drive->using_dma)
+       if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA))
                hwif->dma_ops->dma_host_set(drive, 1);
        else if (hwif->dma_ops) /* check if host supports DMA */
                ide_dma_off_quietly(drive);
@@ -825,23 +813,25 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
                      unsigned int timeout, ide_expiry_t *expiry)
 {
-       ide_hwgroup_t *hwgroup = HWGROUP(drive);
-
-       BUG_ON(hwgroup->handler);
-       hwgroup->handler        = handler;
-       hwgroup->expiry         = expiry;
-       hwgroup->timer.expires  = jiffies + timeout;
-       hwgroup->req_gen_timer  = hwgroup->req_gen;
-       add_timer(&hwgroup->timer);
+       ide_hwif_t *hwif = drive->hwif;
+
+       BUG_ON(hwif->handler);
+       hwif->handler           = handler;
+       hwif->expiry            = expiry;
+       hwif->timer.expires     = jiffies + timeout;
+       hwif->req_gen_timer     = hwif->req_gen;
+       add_timer(&hwif->timer);
 }
 
 void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
                      unsigned int timeout, ide_expiry_t *expiry)
 {
+       ide_hwif_t *hwif = drive->hwif;
        unsigned long flags;
-       spin_lock_irqsave(&ide_lock, flags);
+
+       spin_lock_irqsave(&hwif->lock, flags);
        __ide_set_handler(drive, handler, timeout, expiry);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&hwif->lock, flags);
 }
 
 EXPORT_SYMBOL(ide_set_handler);
@@ -863,10 +853,10 @@ EXPORT_SYMBOL(ide_set_handler);
 void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
                         unsigned timeout, ide_expiry_t *expiry)
 {
+       ide_hwif_t *hwif = drive->hwif;
        unsigned long flags;
-       ide_hwif_t *hwif = HWIF(drive);
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&hwif->lock, flags);
        __ide_set_handler(drive, handler, timeout, expiry);
        hwif->tp_ops->exec_command(hwif, cmd);
        /*
@@ -876,7 +866,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
         * FIXME: we could skip this delay with care on non shared devices
         */
        ndelay(400);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&hwif->lock, flags);
 }
 EXPORT_SYMBOL(ide_execute_command);
 
@@ -885,16 +875,16 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
        ide_hwif_t *hwif = drive->hwif;
        unsigned long flags;
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&hwif->lock, flags);
        hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
        ndelay(400);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&hwif->lock, flags);
 }
 EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
 
 static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
 {
-       struct request *rq = drive->hwif->hwgroup->rq;
+       struct request *rq = drive->hwif->rq;
 
        if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
                ide_end_request(drive, err ? err : 1, 0);
@@ -912,7 +902,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *, int);
 static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       ide_hwgroup_t *hwgroup = hwif->hwgroup;
        u8 stat;
 
        SELECT_DRIVE(drive);
@@ -922,24 +911,43 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
        if (OK_STAT(stat, 0, ATA_BUSY))
                printk("%s: ATAPI reset complete\n", drive->name);
        else {
-               if (time_before(jiffies, hwgroup->poll_timeout)) {
+               if (time_before(jiffies, hwif->poll_timeout)) {
                        ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
                        /* continue polling */
                        return ide_started;
                }
                /* end of polling */
-               hwgroup->polling = 0;
+               hwif->polling = 0;
                printk("%s: ATAPI reset timed-out, status=0x%02x\n",
                                drive->name, stat);
                /* do it the old fashioned way */
                return do_reset1(drive, 1);
        }
        /* done polling */
-       hwgroup->polling = 0;
+       hwif->polling = 0;
        ide_complete_drive_reset(drive, 0);
        return ide_stopped;
 }
 
+static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
+{
+       static const char *err_master_vals[] =
+               { NULL, "passed", "formatter device error",
+                 "sector buffer error", "ECC circuitry error",
+                 "controlling MPU error" };
+
+       u8 err_master = err & 0x7f;
+
+       printk(KERN_ERR "%s: reset: master: ", hwif->name);
+       if (err_master && err_master < 6)
+               printk(KERN_CONT "%s", err_master_vals[err_master]);
+       else
+               printk(KERN_CONT "error (0x%02x?)", err);
+       if (err & 0x80)
+               printk(KERN_CONT "; slave: failed");
+       printk(KERN_CONT "\n");
+}
+
 /*
  * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
  * during an ide reset operation. If the drives have not yet responded,
@@ -948,8 +956,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
  */
 static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
 {
-       ide_hwgroup_t *hwgroup  = HWGROUP(drive);
-       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        const struct ide_port_ops *port_ops = hwif->port_ops;
        u8 tmp;
        int err = 0;
@@ -966,7 +973,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
        tmp = hwif->tp_ops->read_status(hwif);
 
        if (!OK_STAT(tmp, 0, ATA_BUSY)) {
-               if (time_before(jiffies, hwgroup->poll_timeout)) {
+               if (time_before(jiffies, hwif->poll_timeout)) {
                        ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
                        /* continue polling */
                        return ide_started;
@@ -975,36 +982,19 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
                drive->failures++;
                err = -EIO;
        } else  {
-               printk("%s: reset: ", hwif->name);
                tmp = ide_read_error(drive);
 
                if (tmp == 1) {
-                       printk("success\n");
+                       printk(KERN_INFO "%s: reset: success\n", hwif->name);
                        drive->failures = 0;
                } else {
+                       ide_reset_report_error(hwif, tmp);
                        drive->failures++;
-                       printk("master: ");
-                       switch (tmp & 0x7f) {
-                               case 1: printk("passed");
-                                       break;
-                               case 2: printk("formatter device error");
-                                       break;
-                               case 3: printk("sector buffer error");
-                                       break;
-                               case 4: printk("ECC circuitry error");
-                                       break;
-                               case 5: printk("controlling MPU error");
-                                       break;
-                               default:printk("error (0x%02x?)", tmp);
-                       }
-                       if (tmp & 0x80)
-                               printk("; slave: failed");
-                       printk("\n");
                        err = -EIO;
                }
        }
 out:
-       hwgroup->polling = 0;   /* done polling */
+       hwif->polling = 0;      /* done polling */
        ide_complete_drive_reset(drive, err);
        return ide_stopped;
 }
@@ -1016,9 +1006,14 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
        drive->special.all = 0;
        drive->special.b.set_geometry = legacy;
        drive->special.b.recalibrate  = legacy;
+
        drive->mult_count = 0;
-       if (!drive->keep_settings && !drive->using_dma)
+       drive->dev_flags &= ~IDE_DFLAG_PARKED;
+
+       if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
+           (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
                drive->mult_req = 0;
+
        if (drive->mult_req != drive->mult_count)
                drive->special.b.set_multmode = 1;
 }
@@ -1030,18 +1025,18 @@ static void pre_reset(ide_drive_t *drive)
        if (drive->media == ide_disk)
                ide_disk_pre_reset(drive);
        else
-               drive->post_reset = 1;
+               drive->dev_flags |= IDE_DFLAG_POST_RESET;
 
-       if (drive->using_dma) {
+       if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
                if (drive->crc_count)
                        ide_check_dma_crc(drive);
                else
                        ide_dma_off(drive);
        }
 
-       if (!drive->keep_settings) {
-               if (!drive->using_dma) {
-                       drive->unmask = 0;
+       if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
+               if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
+                       drive->dev_flags &= ~IDE_DFLAG_UNMASK;
                        drive->io_32bit = 0;
                }
                return;
@@ -1072,24 +1067,19 @@ static void pre_reset(ide_drive_t *drive)
  */
 static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
 {
-       unsigned int unit;
-       unsigned long flags;
-       ide_hwif_t *hwif;
-       ide_hwgroup_t *hwgroup;
-       struct ide_io_ports *io_ports;
-       const struct ide_tp_ops *tp_ops;
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        const struct ide_port_ops *port_ops;
+       ide_drive_t *tdrive;
+       unsigned long flags, timeout;
+       int i;
+       DEFINE_WAIT(wait);
 
-       spin_lock_irqsave(&ide_lock, flags);
-       hwif = HWIF(drive);
-       hwgroup = HWGROUP(drive);
-
-       io_ports = &hwif->io_ports;
-
-       tp_ops = hwif->tp_ops;
+       spin_lock_irqsave(&hwif->lock, flags);
 
        /* We must not reset with running handlers */
-       BUG_ON(hwgroup->handler != NULL);
+       BUG_ON(hwif->handler != NULL);
 
        /* For an ATAPI device, first try an ATAPI SRST. */
        if (drive->media != ide_disk && !do_not_try_atapi) {
@@ -1098,22 +1088,45 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
                udelay (20);
                tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
                ndelay(400);
-               hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-               hwgroup->polling = 1;
+               hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+               hwif->polling = 1;
                __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
-               spin_unlock_irqrestore(&ide_lock, flags);
+               spin_unlock_irqrestore(&hwif->lock, flags);
                return ide_started;
        }
 
+       /* We must not disturb devices in the IDE_DFLAG_PARKED state. */
+       do {
+               unsigned long now;
+
+               prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
+               timeout = jiffies;
+               ide_port_for_each_dev(i, tdrive, hwif) {
+                       if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
+                           tdrive->dev_flags & IDE_DFLAG_PARKED &&
+                           time_after(tdrive->sleep, timeout))
+                               timeout = tdrive->sleep;
+               }
+
+               now = jiffies;
+               if (time_before_eq(timeout, now))
+                       break;
+
+               spin_unlock_irqrestore(&hwif->lock, flags);
+               timeout = schedule_timeout_uninterruptible(timeout - now);
+               spin_lock_irqsave(&hwif->lock, flags);
+       } while (timeout);
+       finish_wait(&ide_park_wq, &wait);
+
        /*
         * First, reset any device state data we were maintaining
         * for any of the drives on this interface.
         */
-       for (unit = 0; unit < MAX_DRIVES; ++unit)
-               pre_reset(&hwif->drives[unit]);
+       ide_port_for_each_dev(i, tdrive, hwif)
+               pre_reset(tdrive);
 
        if (io_ports->ctl_addr == 0) {
-               spin_unlock_irqrestore(&ide_lock, flags);
+               spin_unlock_irqrestore(&hwif->lock, flags);
                ide_complete_drive_reset(drive, -ENXIO);
                return ide_stopped;
        }
@@ -1136,8 +1149,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
        tp_ops->set_irq(hwif, drive->quirk_list == 2);
        /* more than enough time */
        udelay(10);
-       hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-       hwgroup->polling = 1;
+       hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+       hwif->polling = 1;
        __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
 
        /*
@@ -1149,7 +1162,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
        if (port_ops && port_ops->resetproc)
                port_ops->resetproc(drive);
 
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&hwif->lock, flags);
        return ide_started;
 }
 
@@ -1193,6 +1206,3 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
        }
        return -EBUSY;
 }
-
-EXPORT_SYMBOL_GPL(ide_wait_not_busy);
-