powerpc/mm: Fix handling of _PAGE_COHERENT in BAT setup code
[safe/jmp/linux-2.6] / drivers / ide / ide-iops.c
index 91182eb..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;
@@ -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          }
 };
 
@@ -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);
 
@@ -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,20 +911,20 @@ 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;
 }
@@ -967,8 +956,7 @@ static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
  */
 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;
@@ -985,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;
@@ -1006,7 +994,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
                }
        }
 out:
-       hwgroup->polling = 0;   /* done polling */
+       hwif->polling = 0;      /* done polling */
        ide_complete_drive_reset(drive, err);
        return ide_stopped;
 }
@@ -1020,6 +1008,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
        drive->special.b.recalibrate  = legacy;
 
        drive->mult_count = 0;
+       drive->dev_flags &= ~IDE_DFLAG_PARKED;
 
        if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
            (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
@@ -1078,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) {
@@ -1104,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;
        }
@@ -1142,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);
 
        /*
@@ -1155,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;
 }
 
@@ -1199,6 +1206,3 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
        }
        return -EBUSY;
 }
-
-EXPORT_SYMBOL_GPL(ide_wait_not_busy);
-