X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fide%2Fide-dma.c;h=ead141e2db9e2d12213daaa5d746fe178a05724d;hb=5a6248cac22a77588f81c7473cfd03d250cc5b56;hp=08e7cd043bccc9f9a7937276431f25130b3d7509;hpb=2aa6eb313e57a8254b17e60b8bb5e0a2570d7776;p=linux-2.6 diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 08e7cd043b..ead141e2db 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -119,15 +119,17 @@ static const struct drive_list_entry drive_blacklist [] = { { "HITACHI CDR-8335" , "ALL" }, { "HITACHI CDR-8435" , "ALL" }, { "Toshiba CD-ROM XM-6202B" , "ALL" }, + { "TOSHIBA CD-ROM XM-1702BC", "ALL" }, { "CD-532E-A" , "ALL" }, { "E-IDE CD-ROM CR-840", "ALL" }, { "CD-ROM Drive/F5A", "ALL" }, { "WPI CDD-820", "ALL" }, { "SAMSUNG CD-ROM SC-148C", "ALL" }, { "SAMSUNG CD-ROM SC", "ALL" }, - { "SanDisk SDP3B-64" , "ALL" }, { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, { "_NEC DV5800A", "ALL" }, + { "SAMSUNG CD-ROM SN-124", "N001" }, + { "Seagate STT20000A", "ALL" }, { NULL , NULL } }; @@ -670,40 +672,105 @@ int __ide_dma_good_drive (ide_drive_t *drive) EXPORT_SYMBOL(__ide_dma_good_drive); -int ide_use_dma(ide_drive_t *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) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = drive->hwif; + unsigned int mask = 0; + + switch(base) { + case XFER_UDMA_0: + if ((id->field_valid & 4) == 0) + break; + + mask = id->dma_ultra & hwif->ultra_mask; + + if (hwif->udma_filter) + mask &= hwif->udma_filter(drive); + + 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; + break; + case XFER_SW_DMA_0: + if (id->field_valid & 2) + mask = id->dma_1word & hwif->swdma_mask; + break; + default: + BUG(); + break; + } + + return mask; +} + +/** + * ide_max_dma_mode - compute DMA speed + * @drive: IDE device + * + * Checks the drive capabilities and returns the speed to use + * for the DMA transfer. Returns 0 if the drive is incapable + * of DMA transfers. + */ + +u8 ide_max_dma_mode(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned int mask; + int x, i; + u8 mode = 0; - if ((id->capability & 1) == 0 || drive->autodma == 0) + if (drive->media != ide_disk && hwif->atapi_dma == 0) + return 0; + + for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { + mask = ide_get_mode_mask(drive, xfer_mode_bases[i]); + x = fls(mask) - 1; + if (x >= 0) { + mode = xfer_mode_bases[i] + x; + break; + } + } + + printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); + + return mode; +} + +EXPORT_SYMBOL_GPL(ide_max_dma_mode); + +int ide_tune_dma(ide_drive_t *drive) +{ + u8 speed; + + if ((drive->id->capability & 1) == 0 || drive->autodma == 0) return 0; /* consult the list of known "bad" drives */ if (__ide_dma_bad_drive(drive)) return 0; - /* capable of UltraDMA modes */ - if (id->field_valid & 4) { - if (hwif->ultra_mask & id->dma_ultra) - return 1; - } + speed = ide_max_dma_mode(drive); - /* capable of regular DMA modes */ - if (id->field_valid & 2) { - if (hwif->mwdma_mask & id->dma_mword) - return 1; - if (hwif->swdma_mask & id->dma_1word) - return 1; - } + if (!speed) + return 0; - /* consult the list of known "good" drives */ - if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150) - return 1; + if (drive->hwif->speedproc(drive, speed)) + return 0; - return 0; + return 1; } -EXPORT_SYMBOL_GPL(ide_use_dma); +EXPORT_SYMBOL_GPL(ide_tune_dma); void ide_dma_verbose(ide_drive_t *drive) { @@ -767,7 +834,7 @@ int ide_set_dma(ide_drive_t *drive) switch(rc) { case -1: /* DMA needs to be disabled */ hwif->dma_off_quietly(drive); - return 0; + return -1; case 0: /* DMA needs to be enabled */ return hwif->ide_dma_on(drive); case 1: /* DMA setting cannot be changed */