Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds
[sfrench/cifs-2.6.git] / drivers / ide / ide-lib.c
index 7ddb11828731e816ea9c6acafe382906bb0b81a5..8afce4ceea310c6e47eea9ff1c715bdb39916591 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -72,75 +71,96 @@ EXPORT_SYMBOL(ide_xfer_verbose);
 /**
  *     ide_dma_speed   -       compute DMA speed
  *     @drive: drive
- *     @mode; intended mode
+ *     @mode:  modes available
  *
  *     Checks the drive capabilities and returns the speed to use
- *     for the transfer. Returns -1 if the requested mode is unknown
- *     (eg PIO)
+ *     for the DMA transfer.  Returns 0 if the drive is incapable
+ *     of DMA transfers.
  */
  
 u8 ide_dma_speed(ide_drive_t *drive, u8 mode)
 {
        struct hd_driveid *id   = drive->id;
        ide_hwif_t *hwif        = HWIF(drive);
+       u8 ultra_mask, mwdma_mask, swdma_mask;
        u8 speed = 0;
 
        if (drive->media != ide_disk && hwif->atapi_dma == 0)
                return 0;
 
-       switch(mode) {
-               case 0x04:
-                       if ((id->dma_ultra & 0x0040) &&
-                           (id->dma_ultra & hwif->ultra_mask))
-                               { speed = XFER_UDMA_6; break; }
-               case 0x03:
-                       if ((id->dma_ultra & 0x0020) &&
-                           (id->dma_ultra & hwif->ultra_mask))
-                               { speed = XFER_UDMA_5; break; }
-               case 0x02:
-                       if ((id->dma_ultra & 0x0010) &&
-                           (id->dma_ultra & hwif->ultra_mask))
-                               { speed = XFER_UDMA_4; break; }
-                       if ((id->dma_ultra & 0x0008) &&
-                           (id->dma_ultra & hwif->ultra_mask))
-                               { speed = XFER_UDMA_3; break; }
-               case 0x01:
-                       if ((id->dma_ultra & 0x0004) &&
-                           (id->dma_ultra & hwif->ultra_mask))
-                               { speed = XFER_UDMA_2; break; }
-                       if ((id->dma_ultra & 0x0002) &&
-                           (id->dma_ultra & hwif->ultra_mask))
-                               { speed = XFER_UDMA_1; break; }
-                       if ((id->dma_ultra & 0x0001) &&
-                           (id->dma_ultra & hwif->ultra_mask))
-                               { speed = XFER_UDMA_0; break; }
-               case 0x00:
-                       if ((id->dma_mword & 0x0004) &&
-                           (id->dma_mword & hwif->mwdma_mask))
-                               { speed = XFER_MW_DMA_2; break; }
-                       if ((id->dma_mword & 0x0002) &&
-                           (id->dma_mword & hwif->mwdma_mask))
-                               { speed = XFER_MW_DMA_1; break; }
-                       if ((id->dma_mword & 0x0001) &&
-                           (id->dma_mword & hwif->mwdma_mask))
-                               { speed = XFER_MW_DMA_0; break; }
-                       if ((id->dma_1word & 0x0004) &&
-                           (id->dma_1word & hwif->swdma_mask))
-                               { speed = XFER_SW_DMA_2; break; }
-                       if ((id->dma_1word & 0x0002) &&
-                           (id->dma_1word & hwif->swdma_mask))
-                               { speed = XFER_SW_DMA_1; break; }
-                       if ((id->dma_1word & 0x0001) &&
-                           (id->dma_1word & hwif->swdma_mask))
-                               { speed = XFER_SW_DMA_0; break; }
-       }
+       /* Capable of UltraDMA modes? */
+       ultra_mask = id->dma_ultra & hwif->ultra_mask;
+
+       if (!(id->field_valid & 4))
+               mode = 0;       /* fallback to MW/SW DMA if no UltraDMA */
+
+       switch (mode) {
+       case 4:
+               if (ultra_mask & 0x40) {
+                       speed = XFER_UDMA_6;
+                       break;
+               }
+       case 3:
+               if (ultra_mask & 0x20) {
+                       speed = XFER_UDMA_5;
+                       break;
+               }
+       case 2:
+               if (ultra_mask & 0x10) {
+                       speed = XFER_UDMA_4;
+                       break;
+               }
+               if (ultra_mask & 0x08) {
+                       speed = XFER_UDMA_3;
+                       break;
+               }
+       case 1:
+               if (ultra_mask & 0x04) {
+                       speed = XFER_UDMA_2;
+                       break;
+               }
+               if (ultra_mask & 0x02) {
+                       speed = XFER_UDMA_1;
+                       break;
+               }
+               if (ultra_mask & 0x01) {
+                       speed = XFER_UDMA_0;
+                       break;
+               }
+       case 0:
+               mwdma_mask = id->dma_mword & hwif->mwdma_mask;
+
+               if (mwdma_mask & 0x04) {
+                       speed = XFER_MW_DMA_2;
+                       break;
+               }
+               if (mwdma_mask & 0x02) {
+                       speed = XFER_MW_DMA_1;
+                       break;
+               }
+               if (mwdma_mask & 0x01) {
+                       speed = XFER_MW_DMA_0;
+                       break;
+               }
 
-//     printk("%s: %s: mode 0x%02x, speed 0x%02x\n",
-//             __FUNCTION__, drive->name, mode, speed);
+               swdma_mask = id->dma_1word & hwif->swdma_mask;
+
+               if (swdma_mask & 0x04) {
+                       speed = XFER_SW_DMA_2;
+                       break;
+               }
+               if (swdma_mask & 0x02) {
+                       speed = XFER_SW_DMA_1;
+                       break;
+               }
+               if (swdma_mask & 0x01) {
+                       speed = XFER_SW_DMA_0;
+                       break;
+               }
+       }
 
        return speed;
 }
-
 EXPORT_SYMBOL(ide_dma_speed);
 
 
@@ -185,6 +205,21 @@ int ide_dma_enable (ide_drive_t *drive)
 
 EXPORT_SYMBOL(ide_dma_enable);
 
+int ide_use_fast_pio(ide_drive_t *drive)
+{
+       struct hd_driveid *id = drive->id;
+
+       if ((id->capability & 1) && drive->autodma)
+               return 1;
+
+       if ((id->capability & 8) || (id->field_valid & 2))
+               return 1;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_use_fast_pio);
+
 /*
  * Standard (generic) timings for PIO modes, from ATA2 specification.
  * These timings are for access to the IDE data port register *only*.
@@ -329,7 +364,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
        int use_iordy = 0;
        struct hd_driveid* id = drive->id;
        int overridden  = 0;
-       int blacklisted = 0;
 
        if (mode_wanted != 255) {
                pio_mode = mode_wanted;
@@ -337,7 +371,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
                pio_mode = 0;
        } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
                overridden = 1;
-               blacklisted = 1;
                use_iordy = (pio_mode > 2);
        } else {
                pio_mode = id->tPIO;
@@ -389,7 +422,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
                d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time;
                d->use_iordy = use_iordy;
                d->overridden = overridden;
-               d->blacklisted = blacklisted;
        }
        return pio_mode;
 }
@@ -442,8 +474,6 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
                return -1;
 }
 
-EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
-
 static void ide_dump_opcode(ide_drive_t *drive)
 {
        struct request *rq;
@@ -457,13 +487,14 @@ static void ide_dump_opcode(ide_drive_t *drive)
        spin_unlock(&ide_lock);
        if (!rq)
                return;
-       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+       if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
+           rq->cmd_type == REQ_TYPE_ATA_TASK) {
                char *args = rq->buffer;
                if (args) {
                        opcode = args[0];
                        found = 1;
                }
-       } else if (rq->flags & REQ_DRIVE_TASKFILE) {
+       } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
                ide_task_t *args = rq->special;
                if (args) {
                        task_struct_t *tf = (task_struct_t *) args->tfRegister;