diff options
Diffstat (limited to 'drivers/ide/ide-lib.c')
| -rw-r--r-- | drivers/ide/ide-lib.c | 132 | 
1 files changed, 25 insertions, 107 deletions
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 68719314df3f..3be3c69383f2 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c  | |||
| @@ -69,123 +69,41 @@ char *ide_xfer_verbose (u8 xfer_rate) | |||
| 69 | EXPORT_SYMBOL(ide_xfer_verbose); | 69 | EXPORT_SYMBOL(ide_xfer_verbose); | 
| 70 | 70 | ||
| 71 | /** | 71 | /** | 
| 72 | * ide_dma_speed - compute DMA speed | 72 | * ide_rate_filter - filter transfer mode | 
| 73 | * @drive: drive | 73 | * @drive: IDE device | 
| 74 | * @mode: modes available | ||
| 75 | * | ||
| 76 | * Checks the drive capabilities and returns the speed to use | ||
| 77 | * for the DMA transfer. Returns 0 if the drive is incapable | ||
| 78 | * of DMA transfers. | ||
| 79 | */ | ||
| 80 | |||
| 81 | u8 ide_dma_speed(ide_drive_t *drive, u8 mode) | ||
| 82 | { | ||
| 83 | struct hd_driveid *id = drive->id; | ||
| 84 | ide_hwif_t *hwif = HWIF(drive); | ||
| 85 | u8 ultra_mask, mwdma_mask, swdma_mask; | ||
| 86 | u8 speed = 0; | ||
| 87 | |||
| 88 | if (drive->media != ide_disk && hwif->atapi_dma == 0) | ||
| 89 | return 0; | ||
| 90 | |||
| 91 | /* Capable of UltraDMA modes? */ | ||
| 92 | ultra_mask = id->dma_ultra & hwif->ultra_mask; | ||
| 93 | |||
| 94 | if (!(id->field_valid & 4)) | ||
| 95 | mode = 0; /* fallback to MW/SW DMA if no UltraDMA */ | ||
| 96 | |||
| 97 | switch (mode) { | ||
| 98 | case 4: | ||
| 99 | if (ultra_mask & 0x40) { | ||
| 100 | speed = XFER_UDMA_6; | ||
| 101 | break; | ||
| 102 | } | ||
| 103 | case 3: | ||
| 104 | if (ultra_mask & 0x20) { | ||
| 105 | speed = XFER_UDMA_5; | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | case 2: | ||
| 109 | if (ultra_mask & 0x10) { | ||
| 110 | speed = XFER_UDMA_4; | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | if (ultra_mask & 0x08) { | ||
| 114 | speed = XFER_UDMA_3; | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | case 1: | ||
| 118 | if (ultra_mask & 0x04) { | ||
| 119 | speed = XFER_UDMA_2; | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | if (ultra_mask & 0x02) { | ||
| 123 | speed = XFER_UDMA_1; | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | if (ultra_mask & 0x01) { | ||
| 127 | speed = XFER_UDMA_0; | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | case 0: | ||
| 131 | mwdma_mask = id->dma_mword & hwif->mwdma_mask; | ||
| 132 | |||
| 133 | if (mwdma_mask & 0x04) { | ||
| 134 | speed = XFER_MW_DMA_2; | ||
| 135 | break; | ||
| 136 | } | ||
| 137 | if (mwdma_mask & 0x02) { | ||
| 138 | speed = XFER_MW_DMA_1; | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | if (mwdma_mask & 0x01) { | ||
| 142 | speed = XFER_MW_DMA_0; | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | |||
| 146 | swdma_mask = id->dma_1word & hwif->swdma_mask; | ||
| 147 | |||
| 148 | if (swdma_mask & 0x04) { | ||
| 149 | speed = XFER_SW_DMA_2; | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | if (swdma_mask & 0x02) { | ||
| 153 | speed = XFER_SW_DMA_1; | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | if (swdma_mask & 0x01) { | ||
| 157 | speed = XFER_SW_DMA_0; | ||
| 158 | break; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | return speed; | ||
| 163 | } | ||
| 164 | EXPORT_SYMBOL(ide_dma_speed); | ||
| 165 | |||
| 166 | |||
| 167 | /** | ||
| 168 | * ide_rate_filter - return best speed for mode | ||
| 169 | * @mode: modes available | ||
| 170 | * @speed: desired speed | 74 | * @speed: desired speed | 
| 171 | * | 75 | * | 
| 172 | * Given the available DMA/UDMA mode this function returns | 76 | * Given the available transfer modes this function returns | 
| 173 | * the best available speed at or below the speed requested. | 77 | * the best available speed at or below the speed requested. | 
| 78 | * | ||
| 79 | * FIXME: filter also PIO/SWDMA/MWDMA modes | ||
| 174 | */ | 80 | */ | 
| 175 | 81 | ||
| 176 | u8 ide_rate_filter (u8 mode, u8 speed) | 82 | u8 ide_rate_filter(ide_drive_t *drive, u8 speed) | 
| 177 | { | 83 | { | 
| 178 | #ifdef CONFIG_BLK_DEV_IDEDMA | 84 | #ifdef CONFIG_BLK_DEV_IDEDMA | 
| 179 | static u8 speed_max[] = { | 85 | ide_hwif_t *hwif = drive->hwif; | 
| 180 | XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, | 86 | u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; | 
| 181 | XFER_UDMA_5, XFER_UDMA_6 | 87 | |
| 182 | }; | 88 | if (hwif->udma_filter) | 
| 89 | mask = hwif->udma_filter(drive); | ||
| 90 | |||
| 91 | /* | ||
| 92 | * TODO: speed > XFER_UDMA_2 extra check is needed to avoid false | ||
| 93 | * cable warning from eighty_ninty_three(), moving ide_rate_filter() | ||
| 94 | * calls from ->speedproc to core code will make this hack go away | ||
| 95 | */ | ||
| 96 | if (speed > XFER_UDMA_2) { | ||
| 97 | if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) | ||
| 98 | mask &= 0x07; | ||
| 99 | } | ||
| 100 | |||
| 101 | if (mask) | ||
| 102 | mode = fls(mask) - 1 + XFER_UDMA_0; | ||
| 183 | 103 | ||
| 184 | // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); | 104 | // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); | 
| 185 | 105 | ||
| 186 | /* So that we remember to update this if new modes appear */ | 106 | return min(speed, mode); | 
| 187 | BUG_ON(mode > 4); | ||
| 188 | return min(speed, speed_max[mode]); | ||
| 189 | #else /* !CONFIG_BLK_DEV_IDEDMA */ | 107 | #else /* !CONFIG_BLK_DEV_IDEDMA */ | 
| 190 | return min(speed, (u8)XFER_PIO_4); | 108 | return min(speed, (u8)XFER_PIO_4); | 
| 191 | #endif /* CONFIG_BLK_DEV_IDEDMA */ | 109 | #endif /* CONFIG_BLK_DEV_IDEDMA */ | 
