ide: rework the code for selecting the best DMA transfer mode (v3)
Depends on the "ide: fix UDMA/MWDMA/SWDMA masks" patch. * add ide_hwif_t.udma_filter hook for filtering UDMA mask (use it in alim15x3, hpt366, siimage and serverworks drivers) * add ide_max_dma_mode() for finding best DMA mode for the device (loosely based on some older libata-core.c code) * convert ide_dma_speed() users to use ide_max_dma_mode() * make ide_rate_filter() take "ide_drive_t *drive" as an argument instead of "u8 mode" and teach it to how to use UDMA mask to do filtering * use ide_rate_filter() in hpt366 driver * remove no longer needed ide_dma_speed() and *_ratemask() * unexport eighty_ninty_three() v2: * rename ->filter_udma_mask to ->udma_filter [ Suggested by Sergei Shtylyov <sshtylyov@ru.mvista.com>. ] v3: * updated for scc_pata driver (fixes XFER_UDMA_6 filtering for user-space originated transfer mode change requests when 100MHz clock is used) Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
This commit is contained in:
@@ -69,123 +69,34 @@ char *ide_xfer_verbose (u8 xfer_rate)
|
||||
EXPORT_SYMBOL(ide_xfer_verbose);
|
||||
|
||||
/**
|
||||
* ide_dma_speed - compute DMA speed
|
||||
* @drive: drive
|
||||
* @mode: modes available
|
||||
*
|
||||
* 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_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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/**
|
||||
* ide_rate_filter - return best speed for mode
|
||||
* @mode: modes available
|
||||
* ide_rate_filter - filter transfer mode
|
||||
* @drive: IDE device
|
||||
* @speed: desired speed
|
||||
*
|
||||
* Given the available DMA/UDMA mode this function returns
|
||||
* Given the available transfer modes this function returns
|
||||
* the best available speed at or below the speed requested.
|
||||
*
|
||||
* FIXME: filter also PIO/SWDMA/MWDMA modes
|
||||
*/
|
||||
|
||||
u8 ide_rate_filter (u8 mode, u8 speed)
|
||||
u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA
|
||||
static u8 speed_max[] = {
|
||||
XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4,
|
||||
XFER_UDMA_5, XFER_UDMA_6
|
||||
};
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2;
|
||||
|
||||
if (hwif->udma_filter)
|
||||
mask = hwif->udma_filter(drive);
|
||||
|
||||
if ((mask & 0x78) && (eighty_ninty_three(drive) == 0))
|
||||
mask &= 0x07;
|
||||
|
||||
if (mask)
|
||||
mode = fls(mask) - 1 + XFER_UDMA_0;
|
||||
|
||||
// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed);
|
||||
|
||||
/* So that we remember to update this if new modes appear */
|
||||
BUG_ON(mode > 4);
|
||||
return min(speed, speed_max[mode]);
|
||||
return min(speed, mode);
|
||||
#else /* !CONFIG_BLK_DEV_IDEDMA */
|
||||
return min(speed, (u8)XFER_PIO_4);
|
||||
#endif /* CONFIG_BLK_DEV_IDEDMA */
|
||||
|
Reference in New Issue
Block a user