]> err.no Git - linux-2.6/blobdiff - drivers/ide/ide-dma.c
pcmcia: use DMA_MASK_NONE for the default for all pcmcia devices
[linux-2.6] / drivers / ide / ide-dma.c
index 5fe1d72ab4514e97a5dbcc5c3c1ea6183cd46324..b453211ee0fc1364cebe09be3bd0296bf6500207 100644 (file)
@@ -134,25 +134,6 @@ static const struct drive_list_entry drive_blacklist [] = {
 
 };
 
-/**
- *     ide_in_drive_list       -       look for drive in black/white list
- *     @id: drive identifier
- *     @drive_table: list to inspect
- *
- *     Look for a drive in the blacklist and the whitelist tables
- *     Returns 1 if the drive is found in the table.
- */
-
-int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
-{
-       for ( ; drive_table->id_model ; drive_table++)
-               if ((!strcmp(drive_table->id_model, id->model)) &&
-                   (!drive_table->id_firmware ||
-                    strstr(id->fw_rev, drive_table->id_firmware)))
-                       return 1;
-       return 0;
-}
-
 /**
  *     ide_dma_intr    -       IDE DMA interrupt handler
  *     @drive: the drive the interrupt is for
@@ -188,6 +169,11 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
 
 EXPORT_SYMBOL_GPL(ide_dma_intr);
 
+static int ide_dma_good_drive(ide_drive_t *drive)
+{
+       return ide_in_drive_list(drive->id, drive_whitelist);
+}
+
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
  *     ide_build_sglist        -       map IDE scatter gather for DMA I/O
@@ -349,9 +335,17 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
  
 static int config_drive_for_dma (ide_drive_t *drive)
 {
+       ide_hwif_t *hwif = drive->hwif;
        struct hd_driveid *id = drive->id;
 
-       if ((id->capability & 1) && drive->hwif->autodma) {
+       /* consult the list of known "bad" drives */
+       if (__ide_dma_bad_drive(drive))
+               return -1;
+
+       if (drive->media != ide_disk && hwif->atapi_dma == 0)
+               return -1;
+
+       if ((id->capability & 1) && drive->autodma) {
                /*
                 * Enable DMA on any drive that has
                 * UltraDMA (mode 0/1/2/3/4/5/6) enabled
@@ -368,7 +362,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
                                return 0;
 
                /* Consult the list of known "good" drives */
-               if (__ide_dma_good_drive(drive))
+               if (ide_dma_good_drive(drive))
                        return 0;
        }
 
@@ -513,20 +507,6 @@ int __ide_dma_on (ide_drive_t *drive)
 
 EXPORT_SYMBOL(__ide_dma_on);
 
-/**
- *     __ide_dma_check         -       check DMA setup
- *     @drive: drive to check
- *
- *     Don't use - due for extermination
- */
-int __ide_dma_check (ide_drive_t *drive)
-{
-       return config_drive_for_dma(drive);
-}
-
-EXPORT_SYMBOL(__ide_dma_check);
-
 /**
  *     ide_dma_setup   -       begin a DMA phase
  *     @drive: target device
@@ -664,21 +644,13 @@ int __ide_dma_bad_drive (ide_drive_t *drive)
 
 EXPORT_SYMBOL(__ide_dma_bad_drive);
 
-int __ide_dma_good_drive (ide_drive_t *drive)
-{
-       struct hd_driveid *id = drive->id;
-       return ide_in_drive_list(id, drive_whitelist);
-}
-
-EXPORT_SYMBOL(__ide_dma_good_drive);
-
 static const u8 xfer_mode_bases[] = {
        XFER_UDMA_0,
        XFER_MW_DMA_0,
        XFER_SW_DMA_0,
 };
 
-static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
+static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
 {
        struct hd_driveid *id = drive->id;
        ide_hwif_t *hwif = drive->hwif;
@@ -689,17 +661,28 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
                if ((id->field_valid & 4) == 0)
                        break;
 
-               mask = id->dma_ultra & hwif->ultra_mask;
-
                if (hwif->udma_filter)
-                       mask &= hwif->udma_filter(drive);
+                       mask = hwif->udma_filter(drive);
+               else
+                       mask = hwif->ultra_mask;
+               mask &= id->dma_ultra;
 
-               if ((mask & 0x78) && (eighty_ninty_three(drive) == 0))
-                       mask &= 0x07;
+               /*
+                * avoid false cable warning from eighty_ninty_three()
+                */
+               if (req_mode > XFER_UDMA_2) {
+                       if ((mask & 0x78) && (eighty_ninty_three(drive) == 0))
+                               mask &= 0x07;
+               }
                break;
        case XFER_MW_DMA_0:
-               if (id->field_valid & 2)
-                       mask = id->dma_mword & hwif->mwdma_mask;
+               if ((id->field_valid & 2) == 0)
+                       break;
+               if (hwif->mdma_filter)
+                       mask = hwif->mdma_filter(drive);
+               else
+                       mask = hwif->mwdma_mask;
+               mask &= id->dma_mword;
                break;
        case XFER_SW_DMA_0:
                if (id->field_valid & 2) {
@@ -728,15 +711,18 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
 }
 
 /**
- *     ide_max_dma_mode        -       compute DMA speed
+ *     ide_find_dma_mode       -       compute DMA speed
  *     @drive: IDE device
+ *     @req_mode: requested mode
+ *
+ *     Checks the drive/host capabilities and finds the speed to use for
+ *     the DMA transfer.  The speed is then limited by the requested mode.
  *
- *     Checks the drive capabilities and returns the speed to use
- *     for the DMA transfer.  Returns 0 if the drive is incapable
- *     of DMA transfers.
+ *     Returns 0 if the drive/host combination is incapable of DMA transfers
+ *     or if the requested mode is not a DMA mode.
  */
 
-u8 ide_max_dma_mode(ide_drive_t *drive)
+u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
 {
        ide_hwif_t *hwif = drive->hwif;
        unsigned int mask;
@@ -747,7 +733,9 @@ u8 ide_max_dma_mode(ide_drive_t *drive)
                return 0;
 
        for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) {
-               mask = ide_get_mode_mask(drive, xfer_mode_bases[i]);
+               if (req_mode < xfer_mode_bases[i])
+                       continue;
+               mask = ide_get_mode_mask(drive, xfer_mode_bases[i], req_mode);
                x = fls(mask) - 1;
                if (x >= 0) {
                        mode = xfer_mode_bases[i] + x;
@@ -755,12 +743,20 @@ u8 ide_max_dma_mode(ide_drive_t *drive)
                }
        }
 
+       if (hwif->chipset == ide_acorn && mode == 0) {
+               /*
+                * is this correct?
+                */
+               if (ide_dma_good_drive(drive) && drive->id->eide_dma_time < 150)
+                       mode = XFER_MW_DMA_1;
+       }
+
        printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode);
 
-       return mode;
+       return min(mode, req_mode);
 }
 
-EXPORT_SYMBOL_GPL(ide_max_dma_mode);
+EXPORT_SYMBOL_GPL(ide_find_dma_mode);
 
 int ide_tune_dma(ide_drive_t *drive)
 {
@@ -778,7 +774,10 @@ int ide_tune_dma(ide_drive_t *drive)
        if (!speed)
                return 0;
 
-       if (drive->hwif->speedproc(drive, speed))
+       if (drive->hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+               return 0;
+
+       if (ide_set_dma_mode(drive, speed))
                return 0;
 
        return 1;
@@ -1021,7 +1020,7 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
        if (!hwif->dma_host_on)
                hwif->dma_host_on = &ide_dma_host_on;
        if (!hwif->ide_dma_check)
-               hwif->ide_dma_check = &__ide_dma_check;
+               hwif->ide_dma_check = &config_drive_for_dma;
        if (!hwif->dma_setup)
                hwif->dma_setup = &ide_dma_setup;
        if (!hwif->dma_exec_cmd)