diff options
| -rw-r--r-- | drivers/ide/pci/siimage.c | 137 |
1 files changed, 39 insertions, 98 deletions
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 1c3e35487893..5304fc5c616a 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/ide/pci/siimage.c Version 1.12 Mar 10 2007 | 2 | * linux/drivers/ide/pci/siimage.c Version 1.15 Jun 29 2007 |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> | 4 | * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> |
| 5 | * Copyright (C) 2003 Red Hat <alan@redhat.com> | 5 | * Copyright (C) 2003 Red Hat <alan@redhat.com> |
| 6 | * Copyright (C) 2007 MontaVista Software, Inc. | 6 | * Copyright (C) 2007 MontaVista Software, Inc. |
| 7 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | ||
| 7 | * | 8 | * |
| 8 | * May be copied or modified under the terms of the GNU General Public License | 9 | * May be copied or modified under the terms of the GNU General Public License |
| 9 | * | 10 | * |
| @@ -31,6 +32,10 @@ | |||
| 31 | * unplugging/replugging the virtual CD interface when the DRAC is reset. | 32 | * unplugging/replugging the virtual CD interface when the DRAC is reset. |
| 32 | * This often causes drivers/ide/siimage to panic but is ok with the rather | 33 | * This often causes drivers/ide/siimage to panic but is ok with the rather |
| 33 | * smarter code in libata. | 34 | * smarter code in libata. |
| 35 | * | ||
| 36 | * TODO: | ||
| 37 | * - IORDY fixes | ||
| 38 | * - VDMA support | ||
| 34 | */ | 39 | */ |
| 35 | 40 | ||
| 36 | #include <linux/types.h> | 41 | #include <linux/types.h> |
| @@ -160,82 +165,45 @@ out: | |||
| 160 | } | 165 | } |
| 161 | 166 | ||
| 162 | /** | 167 | /** |
| 163 | * siimage_taskfile_timing - turn timing data to a mode | 168 | * sil_tune_pio - tune a drive |
| 164 | * @hwif: interface to query | ||
| 165 | * | ||
| 166 | * Read the timing data for the interface and return the | ||
| 167 | * mode that is being used. | ||
| 168 | */ | ||
| 169 | |||
| 170 | static byte siimage_taskfile_timing (ide_hwif_t *hwif) | ||
| 171 | { | ||
| 172 | u16 timing = 0x328a; | ||
| 173 | unsigned long addr = siimage_selreg(hwif, 2); | ||
| 174 | |||
| 175 | if (hwif->mmio) | ||
| 176 | timing = hwif->INW(addr); | ||
| 177 | else | ||
| 178 | pci_read_config_word(hwif->pci_dev, addr, &timing); | ||
| 179 | |||
| 180 | switch (timing) { | ||
| 181 | case 0x10c1: return 4; | ||
| 182 | case 0x10c3: return 3; | ||
| 183 | case 0x1104: | ||
| 184 | case 0x1281: return 2; | ||
| 185 | case 0x2283: return 1; | ||
| 186 | case 0x328a: | ||
| 187 | default: return 0; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | /** | ||
| 192 | * simmage_tuneproc - tune a drive | ||
| 193 | * @drive: drive to tune | 169 | * @drive: drive to tune |
| 194 | * @mode_wanted: the target operating mode | 170 | * @pio: the desired PIO mode |
| 195 | * | 171 | * |
| 196 | * Load the timing settings for this device mode into the | 172 | * Load the timing settings for this device mode into the |
| 197 | * controller. If we are in PIO mode 3 or 4 turn on IORDY | 173 | * controller. If we are in PIO mode 3 or 4 turn on IORDY |
| 198 | * monitoring (bit 9). The TF timing is bits 31:16 | 174 | * monitoring (bit 9). The TF timing is bits 31:16 |
| 199 | */ | 175 | */ |
| 200 | 176 | ||
| 201 | static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) | 177 | static void sil_tune_pio(ide_drive_t *drive, u8 pio) |
| 202 | { | 178 | { |
| 179 | const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; | ||
| 180 | const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; | ||
| 181 | |||
| 203 | ide_hwif_t *hwif = HWIF(drive); | 182 | ide_hwif_t *hwif = HWIF(drive); |
| 183 | ide_drive_t *pair = &hwif->drives[drive->dn ^ 1]; | ||
| 204 | u32 speedt = 0; | 184 | u32 speedt = 0; |
| 205 | u16 speedp = 0; | 185 | u16 speedp = 0; |
| 206 | unsigned long addr = siimage_seldev(drive, 0x04); | 186 | unsigned long addr = siimage_seldev(drive, 0x04); |
| 207 | unsigned long tfaddr = siimage_selreg(hwif, 0x02); | 187 | unsigned long tfaddr = siimage_selreg(hwif, 0x02); |
| 208 | 188 | u8 tf_pio = pio; | |
| 209 | /* cheat for now and use the docs */ | 189 | |
| 210 | switch (mode_wanted) { | 190 | /* trim *taskfile* PIO to the slowest of the master/slave */ |
| 211 | case 4: | 191 | if (pair->present) { |
| 212 | speedp = 0x10c1; | 192 | u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL); |
| 213 | speedt = 0x10c1; | 193 | |
| 214 | break; | 194 | if (pair_pio < tf_pio) |
| 215 | case 3: | 195 | tf_pio = pair_pio; |
| 216 | speedp = 0x10c3; | ||
| 217 | speedt = 0x10c3; | ||
| 218 | break; | ||
| 219 | case 2: | ||
| 220 | speedp = 0x1104; | ||
| 221 | speedt = 0x1281; | ||
| 222 | break; | ||
| 223 | case 1: | ||
| 224 | speedp = 0x2283; | ||
| 225 | speedt = 0x2283; | ||
| 226 | break; | ||
| 227 | case 0: | ||
| 228 | default: | ||
| 229 | speedp = 0x328a; | ||
| 230 | speedt = 0x328a; | ||
| 231 | break; | ||
| 232 | } | 196 | } |
| 233 | 197 | ||
| 198 | /* cheat for now and use the docs */ | ||
| 199 | speedp = data_speed[pio]; | ||
| 200 | speedt = tf_speed[tf_pio]; | ||
| 201 | |||
| 234 | if (hwif->mmio) { | 202 | if (hwif->mmio) { |
| 235 | hwif->OUTW(speedp, addr); | 203 | hwif->OUTW(speedp, addr); |
| 236 | hwif->OUTW(speedt, tfaddr); | 204 | hwif->OUTW(speedt, tfaddr); |
| 237 | /* Now set up IORDY */ | 205 | /* Now set up IORDY */ |
| 238 | if(mode_wanted == 3 || mode_wanted == 4) | 206 | if (pio > 2) |
| 239 | hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); | 207 | hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); |
| 240 | else | 208 | else |
| 241 | hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); | 209 | hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); |
| @@ -245,42 +213,17 @@ static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) | |||
| 245 | pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); | 213 | pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); |
| 246 | speedp &= ~0x200; | 214 | speedp &= ~0x200; |
| 247 | /* Set IORDY for mode 3 or 4 */ | 215 | /* Set IORDY for mode 3 or 4 */ |
| 248 | if(mode_wanted == 3 || mode_wanted == 4) | 216 | if (pio > 2) |
| 249 | speedp |= 0x200; | 217 | speedp |= 0x200; |
| 250 | pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); | 218 | pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); |
| 251 | } | 219 | } |
| 252 | } | 220 | } |
| 253 | 221 | ||
| 254 | /** | 222 | static void sil_tuneproc(ide_drive_t *drive, u8 pio) |
| 255 | * config_siimage_chipset_for_pio - set drive timings | ||
| 256 | * @drive: drive to tune | ||
| 257 | * @speed we want | ||
| 258 | * | ||
| 259 | * Compute the best pio mode we can for a given device. Also honour | ||
| 260 | * the timings for the driver when dealing with mixed devices. Some | ||
| 261 | * of this is ugly but its all wrapped up here | ||
| 262 | * | ||
| 263 | * The SI680 can also do VDMA - we need to start using that | ||
| 264 | * | ||
| 265 | * FIXME: we use the BIOS channel timings to avoid driving the task | ||
| 266 | * files too fast at the disk. We need to compute the master/slave | ||
| 267 | * drive PIO mode properly so that we can up the speed on a hotplug | ||
| 268 | * system. | ||
| 269 | */ | ||
| 270 | |||
| 271 | static void config_siimage_chipset_for_pio (ide_drive_t *drive, byte set_speed) | ||
| 272 | { | 223 | { |
| 273 | u8 channel_timings = siimage_taskfile_timing(HWIF(drive)); | 224 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); |
| 274 | u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); | 225 | sil_tune_pio(drive, pio); |
| 275 | 226 | (void)ide_config_drive_speed(drive, XFER_PIO_0 + pio); | |
| 276 | /* WARNING PIO timing mess is going to happen b/w devices, argh */ | ||
| 277 | if ((channel_timings != set_pio) && (set_pio > channel_timings)) | ||
| 278 | set_pio = channel_timings; | ||
| 279 | |||
| 280 | siimage_tuneproc(drive, set_pio); | ||
| 281 | speed = XFER_PIO_0 + set_pio; | ||
| 282 | if (set_speed) | ||
| 283 | (void) ide_config_drive_speed(drive, speed); | ||
| 284 | } | 227 | } |
| 285 | 228 | ||
| 286 | /** | 229 | /** |
| @@ -335,7 +278,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) | |||
| 335 | case XFER_PIO_2: | 278 | case XFER_PIO_2: |
| 336 | case XFER_PIO_1: | 279 | case XFER_PIO_1: |
| 337 | case XFER_PIO_0: | 280 | case XFER_PIO_0: |
| 338 | siimage_tuneproc(drive, (speed - XFER_PIO_0)); | 281 | sil_tune_pio(drive, speed - XFER_PIO_0); |
| 339 | mode |= ((unit) ? 0x10 : 0x01); | 282 | mode |= ((unit) ? 0x10 : 0x01); |
| 340 | break; | 283 | break; |
| 341 | case XFER_MW_DMA_2: | 284 | case XFER_MW_DMA_2: |
| @@ -343,7 +286,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) | |||
| 343 | case XFER_MW_DMA_0: | 286 | case XFER_MW_DMA_0: |
| 344 | multi = dma[speed - XFER_MW_DMA_0]; | 287 | multi = dma[speed - XFER_MW_DMA_0]; |
| 345 | mode |= ((unit) ? 0x20 : 0x02); | 288 | mode |= ((unit) ? 0x20 : 0x02); |
| 346 | config_siimage_chipset_for_pio(drive, 0); | ||
| 347 | break; | 289 | break; |
| 348 | case XFER_UDMA_6: | 290 | case XFER_UDMA_6: |
| 349 | case XFER_UDMA_5: | 291 | case XFER_UDMA_5: |
| @@ -356,7 +298,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) | |||
| 356 | ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) : | 298 | ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) : |
| 357 | (ultra5[speed - XFER_UDMA_0])); | 299 | (ultra5[speed - XFER_UDMA_0])); |
| 358 | mode |= ((unit) ? 0x30 : 0x03); | 300 | mode |= ((unit) ? 0x30 : 0x03); |
| 359 | config_siimage_chipset_for_pio(drive, 0); | ||
| 360 | break; | 301 | break; |
| 361 | default: | 302 | default: |
| 362 | return 1; | 303 | return 1; |
| @@ -390,7 +331,7 @@ static int siimage_config_drive_for_dma (ide_drive_t *drive) | |||
| 390 | return 0; | 331 | return 0; |
| 391 | 332 | ||
| 392 | if (ide_use_fast_pio(drive)) | 333 | if (ide_use_fast_pio(drive)) |
| 393 | config_siimage_chipset_for_pio(drive, 1); | 334 | sil_tuneproc(drive, 255); |
| 394 | 335 | ||
| 395 | return -1; | 336 | return -1; |
| 396 | } | 337 | } |
| @@ -961,7 +902,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) | |||
| 961 | 902 | ||
| 962 | hwif->resetproc = &siimage_reset; | 903 | hwif->resetproc = &siimage_reset; |
| 963 | hwif->speedproc = &siimage_tune_chipset; | 904 | hwif->speedproc = &siimage_tune_chipset; |
| 964 | hwif->tuneproc = &siimage_tuneproc; | 905 | hwif->tuneproc = &sil_tuneproc; |
| 965 | hwif->reset_poll = &siimage_reset_poll; | 906 | hwif->reset_poll = &siimage_reset_poll; |
| 966 | hwif->pre_reset = &siimage_pre_reset; | 907 | hwif->pre_reset = &siimage_pre_reset; |
| 967 | hwif->udma_filter = &sil_udma_filter; | 908 | hwif->udma_filter = &sil_udma_filter; |
| @@ -976,11 +917,11 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) | |||
| 976 | first = 0; | 917 | first = 0; |
| 977 | } | 918 | } |
| 978 | } | 919 | } |
| 979 | if (!hwif->dma_base) { | 920 | |
| 980 | hwif->drives[0].autotune = 1; | 921 | hwif->drives[0].autotune = hwif->drives[1].autotune = 1; |
| 981 | hwif->drives[1].autotune = 1; | 922 | |
| 923 | if (hwif->dma_base == 0) | ||
| 982 | return; | 924 | return; |
| 983 | } | ||
| 984 | 925 | ||
| 985 | hwif->ultra_mask = 0x7f; | 926 | hwif->ultra_mask = 0x7f; |
| 986 | hwif->mwdma_mask = 0x07; | 927 | hwif->mwdma_mask = 0x07; |
