This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / ide / ide-iops.c
index 2d9b028..1ee780e 100644 (file)
 #include <linux/delay.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
-#include <linux/bitops.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/bitops.h>
 
 /*
  *     Conventional PIO operations for ATA devices
@@ -674,15 +674,44 @@ EXPORT_SYMBOL(ide_wait_stat);
  */
 u8 eighty_ninty_three (ide_drive_t *drive)
 {
-       if(HWIF(drive)->udma_four == 0)
-               return 0;
-       if (!(drive->id->hw_config & 0x6000))
+#if 0
+       if (!HWIF(drive)->udma_four)
                return 0;
+
+       if (drive->id->major_rev_num) {
+               int hssbd = 0;
+               int i;
+               /*
+                * Determine highest Supported SPEC
+                */
+               for (i=1; i<=15; i++)
+                       if (drive->id->major_rev_num & (1<<i))
+                               hssbd++;
+
+               switch (hssbd) {
+                       case 7:
+                       case 6:
+                       case 5:
+               /* ATA-4 and older do not support above Ultra 33 */
+                       default:
+                               return 0;
+               }
+       }
+
+       return ((u8) (
 #ifndef CONFIG_IDEDMA_IVB
-       if(!(drive->id->hw_config & 0x4000))
-               return 0;
+               (drive->id->hw_config & 0x4000) &&
 #endif /* CONFIG_IDEDMA_IVB */
-       return 1;
+                (drive->id->hw_config & 0x6000)) ? 1 : 0);
+
+#else
+
+       return ((u8) ((HWIF(drive)->udma_four) &&
+#ifndef CONFIG_IDEDMA_IVB
+                       (drive->id->hw_config & 0x4000) &&
+#endif /* CONFIG_IDEDMA_IVB */
+                       (drive->id->hw_config & 0x6000)) ? 1 : 0);
+#endif
 }
 
 EXPORT_SYMBOL(eighty_ninty_three);
@@ -712,6 +741,8 @@ int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
        return 0;
 }
 
+EXPORT_SYMBOL(ide_ata66_check);
+
 /*
  * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
  * 1 : Safe to update drive->id DMA registers.
@@ -730,8 +761,9 @@ int set_transfer (ide_drive_t *drive, ide_task_t *args)
        return 0;
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static u8 ide_auto_reduce_xfer (ide_drive_t *drive)
+EXPORT_SYMBOL(set_transfer);
+
+u8 ide_auto_reduce_xfer (ide_drive_t *drive)
 {
        if (!drive->crc_count)
                return drive->current_speed;
@@ -755,7 +787,8 @@ static u8 ide_auto_reduce_xfer (ide_drive_t *drive)
                default:                return XFER_PIO_4;
        }
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+EXPORT_SYMBOL(ide_auto_reduce_xfer);
 
 /*
  * Update the 
@@ -830,6 +863,8 @@ int ide_driveid_update (ide_drive_t *drive)
 #endif
 }
 
+EXPORT_SYMBOL(ide_driveid_update);
+
 /*
  * Similar to ide_wait_stat(), except it never calls ide_error internally.
  * This is a kludge to handle the new ide_config_drive_speed() function,
@@ -840,11 +875,6 @@ int ide_driveid_update (ide_drive_t *drive)
  * It is gone..........
  *
  * const char *msg == consider adding for verbose errors.
- *
- * Beware. If we timed out from a series of CRC errors and the timer
- * expiry caused a switch to PIO mode and we take an IRQ as the drive times
- * out about the same moment we may be entering this function with a
- * pending interrupt. 
  */
 int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
 {
@@ -862,20 +892,20 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
 
        /*
         * Don't use ide_wait_cmd here - it will
-        * attempt to set_geometry and recalibrate, We can't
-        * do that here as we may be in the IRQ handler already
-        *
-         * Select the drive, and issue the SETFEATURES command in
-         * polled mode.
+        * attempt to set_geometry and recalibrate,
+        * but for some reason these don't work at
+        * this point (lost interrupt).
+        */
+        /*
+         * Select the drive, and issue the SETFEATURES command
          */
        disable_irq_nosync(hwif->irq);
        
        /*
-        *      We race against the running IRQ here if
+        *      FIXME: we race against the running IRQ here if
         *      this is called from non IRQ context. If we use
-        *      disable_irq() we hang on the error path. Instead we
-        *      must let the core code know the hwif is doing a polling
-        *      recovery.
+        *      disable_irq() we hang on the error path. Work
+        *      is needed.
         */
         
        udelay(1);
@@ -886,43 +916,23 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
                hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
        hwif->OUTB(speed, IDE_NSECTOR_REG);
        hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG);
-       hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
-       /* The status bits are not valid for 400nS */
-       udelay(1);
-       
-       /* Drive status is now valid which means we can allow interrupts
-          to occur as they will see the drive as busy and will not
-          interfere erroneously. IRQ's for this drive will also be off
-          providing control and quirks allow for it */
-          
-       if ((IDE_CONTROL_REG) && drive->quirk_list == 2)
+       hwif->OUTB(WIN_SETFEATURES, IDE_COMMAND_REG);
+       if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
                hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
        udelay(1);
-       
-       /*
-        * Tell the interrupt layer that we are doing polled recovery.
-        * Eventually this should use the same mechanism do_reset does
-        * internally.
-        */
-        
-       hwif->polling = 1;
-       
        /*
         * Wait for drive to become non-BUSY
         */
        if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
-               unsigned long timeout;
-               /* FIXME */
-/*             spin_unlock_irq(&ide_lock); */
+               unsigned long flags, timeout;
+               local_irq_set(flags);
                timeout = jiffies + WAIT_CMD;
                while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
                        if (time_after(jiffies, timeout))
                                break;
                }
-/*             spin_lock_irq(&ide_lock); */
+               local_irq_restore(flags);
        }
-       
-       hwif->polling = 0;
 
        /*
         * Allow status to settle, then read it again.
@@ -994,7 +1004,7 @@ EXPORT_SYMBOL(ide_config_drive_speed);
  *
  * See also ide_execute_command
  */
-static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
+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);
@@ -1010,6 +1020,8 @@ static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
        add_timer(&hwgroup->timer);
 }
 
+EXPORT_SYMBOL(__ide_set_handler);
+
 void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
                      unsigned int timeout, ide_expiry_t *expiry)
 {