diff options
Diffstat (limited to 'drivers/ide/pci/sc1200.c')
-rw-r--r-- | drivers/ide/pci/sc1200.c | 161 |
1 files changed, 77 insertions, 84 deletions
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index b5ae0c50e216..523363c93794 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c | |||
@@ -1,7 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/ide/pci/sc1200.c Version 0.91 28-Jan-2003 | 2 | * linux/drivers/ide/pci/sc1200.c Version 0.94 Mar 10 2007 |
3 | * | 3 | * |
4 | * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> | 4 | * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> |
5 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | ||
6 | * | ||
5 | * May be copied or modified under the terms of the GNU General Public License | 7 | * May be copied or modified under the terms of the GNU General Public License |
6 | * | 8 | * |
7 | * Development of this chipset driver was funded | 9 | * Development of this chipset driver was funded |
@@ -93,64 +95,50 @@ static const unsigned int sc1200_pio_timings[4][5] = | |||
93 | */ | 95 | */ |
94 | //#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) | 96 | //#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) |
95 | 97 | ||
96 | static int sc1200_autoselect_dma_mode (ide_drive_t *drive) | 98 | static void sc1200_tunepio(ide_drive_t *drive, u8 pio) |
97 | { | 99 | { |
98 | int udma_ok = 1, mode = 0; | 100 | ide_hwif_t *hwif = drive->hwif; |
99 | ide_hwif_t *hwif = HWIF(drive); | 101 | struct pci_dev *pdev = hwif->pci_dev; |
100 | int unit = drive->select.b.unit; | 102 | unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0; |
101 | ide_drive_t *mate = &hwif->drives[unit^1]; | 103 | |
102 | struct hd_driveid *id = drive->id; | 104 | pci_read_config_dword(pdev, basereg + 4, &format); |
103 | 105 | format = (format >> 31) & 1; | |
104 | /* | 106 | if (format) |
105 | * The SC1200 specifies that two drives sharing a cable cannot | 107 | format += sc1200_get_pci_clock(); |
106 | * mix UDMA/MDMA. It has to be one or the other, for the pair, | 108 | pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3), |
107 | * though different timings can still be chosen for each drive. | 109 | sc1200_pio_timings[format][pio]); |
108 | * We could set the appropriate timing bits on the fly, | ||
109 | * but that might be a bit confusing. So, for now we statically | ||
110 | * handle this requirement by looking at our mate drive to see | ||
111 | * what it is capable of, before choosing a mode for our own drive. | ||
112 | */ | ||
113 | if (mate->present) { | ||
114 | struct hd_driveid *mateid = mate->id; | ||
115 | if (mateid && (mateid->capability & 1) && !__ide_dma_bad_drive(mate)) { | ||
116 | if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) | ||
117 | udma_ok = 1; | ||
118 | else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) | ||
119 | udma_ok = 0; | ||
120 | else | ||
121 | udma_ok = 1; | ||
122 | } | ||
123 | } | ||
124 | /* | ||
125 | * Now see what the current drive is capable of, | ||
126 | * selecting UDMA only if the mate said it was ok. | ||
127 | */ | ||
128 | if (id && (id->capability & 1) && hwif->autodma && !__ide_dma_bad_drive(drive)) { | ||
129 | if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { | ||
130 | if (id->dma_ultra & 4) | ||
131 | mode = XFER_UDMA_2; | ||
132 | else if (id->dma_ultra & 2) | ||
133 | mode = XFER_UDMA_1; | ||
134 | else if (id->dma_ultra & 1) | ||
135 | mode = XFER_UDMA_0; | ||
136 | } | ||
137 | if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { | ||
138 | if (id->dma_mword & 4) | ||
139 | mode = XFER_MW_DMA_2; | ||
140 | else if (id->dma_mword & 2) | ||
141 | mode = XFER_MW_DMA_1; | ||
142 | else if (id->dma_mword & 1) | ||
143 | mode = XFER_MW_DMA_0; | ||
144 | } | ||
145 | } | ||
146 | return mode; | ||
147 | } | 110 | } |
148 | 111 | ||
149 | /* | 112 | /* |
150 | * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes | 113 | * The SC1200 specifies that two drives sharing a cable cannot mix |
151 | * for both the chipset and drive. | 114 | * UDMA/MDMA. It has to be one or the other, for the pair, though |
115 | * different timings can still be chosen for each drive. We could | ||
116 | * set the appropriate timing bits on the fly, but that might be | ||
117 | * a bit confusing. So, for now we statically handle this requirement | ||
118 | * by looking at our mate drive to see what it is capable of, before | ||
119 | * choosing a mode for our own drive. | ||
152 | */ | 120 | */ |
153 | static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | 121 | static u8 sc1200_udma_filter(ide_drive_t *drive) |
122 | { | ||
123 | ide_hwif_t *hwif = drive->hwif; | ||
124 | ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1]; | ||
125 | struct hd_driveid *mateid = mate->id; | ||
126 | u8 mask = hwif->ultra_mask; | ||
127 | |||
128 | if (mate->present == 0) | ||
129 | goto out; | ||
130 | |||
131 | if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { | ||
132 | if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) | ||
133 | goto out; | ||
134 | if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) | ||
135 | mask = 0; | ||
136 | } | ||
137 | out: | ||
138 | return mask; | ||
139 | } | ||
140 | |||
141 | static int sc1200_tune_chipset(ide_drive_t *drive, u8 mode) | ||
154 | { | 142 | { |
155 | ide_hwif_t *hwif = HWIF(drive); | 143 | ide_hwif_t *hwif = HWIF(drive); |
156 | int unit = drive->select.b.unit; | 144 | int unit = drive->select.b.unit; |
@@ -158,20 +146,26 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
158 | unsigned short pci_clock; | 146 | unsigned short pci_clock; |
159 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; | 147 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; |
160 | 148 | ||
161 | /* | 149 | mode = ide_rate_filter(drive, mode); |
162 | * Default to DMA-off in case we run into trouble here. | ||
163 | */ | ||
164 | hwif->dma_off_quietly(drive); /* turn off DMA while we fiddle */ | ||
165 | outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ | ||
166 | 150 | ||
167 | /* | 151 | /* |
168 | * Tell the drive to switch to the new mode; abort on failure. | 152 | * Tell the drive to switch to the new mode; abort on failure. |
169 | */ | 153 | */ |
170 | if (!mode || sc1200_set_xfer_mode(drive, mode)) { | 154 | if (sc1200_set_xfer_mode(drive, mode)) { |
171 | printk("SC1200: set xfer mode failure\n"); | 155 | printk("SC1200: set xfer mode failure\n"); |
172 | return 1; /* failure */ | 156 | return 1; /* failure */ |
173 | } | 157 | } |
174 | 158 | ||
159 | switch (mode) { | ||
160 | case XFER_PIO_4: | ||
161 | case XFER_PIO_3: | ||
162 | case XFER_PIO_2: | ||
163 | case XFER_PIO_1: | ||
164 | case XFER_PIO_0: | ||
165 | sc1200_tunepio(drive, mode - XFER_PIO_0); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
175 | pci_clock = sc1200_get_pci_clock(); | 169 | pci_clock = sc1200_get_pci_clock(); |
176 | 170 | ||
177 | /* | 171 | /* |
@@ -224,11 +218,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
224 | case PCI_CLK_66: timings = 0x00015151; break; | 218 | case PCI_CLK_66: timings = 0x00015151; break; |
225 | } | 219 | } |
226 | break; | 220 | break; |
227 | } | 221 | default: |
228 | 222 | BUG(); | |
229 | if (timings == 0) { | 223 | break; |
230 | printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock); | ||
231 | return 1; /* failure */ | ||
232 | } | 224 | } |
233 | 225 | ||
234 | if (unit == 0) { /* are we configuring drive0? */ | 226 | if (unit == 0) { /* are we configuring drive0? */ |
@@ -239,8 +231,6 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
239 | pci_write_config_dword(hwif->pci_dev, basereg+12, timings); | 231 | pci_write_config_dword(hwif->pci_dev, basereg+12, timings); |
240 | } | 232 | } |
241 | 233 | ||
242 | outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ | ||
243 | |||
244 | return 0; /* success */ | 234 | return 0; /* success */ |
245 | } | 235 | } |
246 | 236 | ||
@@ -250,7 +240,10 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
250 | */ | 240 | */ |
251 | static int sc1200_config_dma (ide_drive_t *drive) | 241 | static int sc1200_config_dma (ide_drive_t *drive) |
252 | { | 242 | { |
253 | return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive)); | 243 | if (ide_tune_dma(drive)) |
244 | return 0; | ||
245 | |||
246 | return 1; | ||
254 | } | 247 | } |
255 | 248 | ||
256 | 249 | ||
@@ -290,10 +283,11 @@ static int sc1200_ide_dma_end (ide_drive_t *drive) | |||
290 | static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ | 283 | static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ |
291 | { | 284 | { |
292 | ide_hwif_t *hwif = HWIF(drive); | 285 | ide_hwif_t *hwif = HWIF(drive); |
293 | unsigned int format; | ||
294 | static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; | ||
295 | int mode = -1; | 286 | int mode = -1; |
296 | 287 | ||
288 | /* | ||
289 | * bad abuse of ->tuneproc interface | ||
290 | */ | ||
297 | switch (pio) { | 291 | switch (pio) { |
298 | case 200: mode = XFER_UDMA_0; break; | 292 | case 200: mode = XFER_UDMA_0; break; |
299 | case 201: mode = XFER_UDMA_1; break; | 293 | case 201: mode = XFER_UDMA_1; break; |
@@ -304,20 +298,17 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au | |||
304 | } | 298 | } |
305 | if (mode != -1) { | 299 | if (mode != -1) { |
306 | printk("SC1200: %s: changing (U)DMA mode\n", drive->name); | 300 | printk("SC1200: %s: changing (U)DMA mode\n", drive->name); |
307 | (void)sc1200_config_dma2(drive, mode); | 301 | hwif->dma_off_quietly(drive); |
302 | if (sc1200_tune_chipset(drive, mode) == 0) | ||
303 | hwif->dma_host_on(drive); | ||
308 | return; | 304 | return; |
309 | } | 305 | } |
310 | 306 | ||
311 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | 307 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); |
312 | printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); | 308 | printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); |
313 | if (!sc1200_set_xfer_mode(drive, modes[pio])) { | 309 | |
314 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; | 310 | if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0) |
315 | pci_read_config_dword (hwif->pci_dev, basereg+4, &format); | 311 | sc1200_tunepio(drive, pio); |
316 | format = (format >> 31) & 1; | ||
317 | if (format) | ||
318 | format += sc1200_get_pci_clock(); | ||
319 | pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]); | ||
320 | } | ||
321 | } | 312 | } |
322 | 313 | ||
323 | #ifdef CONFIG_PM | 314 | #ifdef CONFIG_PM |
@@ -438,12 +429,12 @@ static int sc1200_resume (struct pci_dev *dev) | |||
438 | for (d = 0; d < MAX_DRIVES; ++d) { | 429 | for (d = 0; d < MAX_DRIVES; ++d) { |
439 | ide_drive_t *drive = &(hwif->drives[d]); | 430 | ide_drive_t *drive = &(hwif->drives[d]); |
440 | if (drive->present && !__ide_dma_bad_drive(drive)) { | 431 | if (drive->present && !__ide_dma_bad_drive(drive)) { |
441 | int was_using_dma = drive->using_dma; | 432 | int enable_dma = drive->using_dma; |
442 | hwif->dma_off_quietly(drive); | 433 | hwif->dma_off_quietly(drive); |
443 | sc1200_config_dma(drive); | 434 | if (sc1200_config_dma(drive)) |
444 | if (!was_using_dma && drive->using_dma) { | 435 | enable_dma = 0; |
445 | hwif->dma_off_quietly(drive); | 436 | if (enable_dma) |
446 | } | 437 | hwif->dma_host_on(drive); |
447 | } | 438 | } |
448 | } | 439 | } |
449 | } | 440 | } |
@@ -461,11 +452,13 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) | |||
461 | hwif->serialized = hwif->mate->serialized = 1; | 452 | hwif->serialized = hwif->mate->serialized = 1; |
462 | hwif->autodma = 0; | 453 | hwif->autodma = 0; |
463 | if (hwif->dma_base) { | 454 | if (hwif->dma_base) { |
455 | hwif->udma_filter = sc1200_udma_filter; | ||
464 | hwif->ide_dma_check = &sc1200_config_dma; | 456 | hwif->ide_dma_check = &sc1200_config_dma; |
465 | hwif->ide_dma_end = &sc1200_ide_dma_end; | 457 | hwif->ide_dma_end = &sc1200_ide_dma_end; |
466 | if (!noautodma) | 458 | if (!noautodma) |
467 | hwif->autodma = 1; | 459 | hwif->autodma = 1; |
468 | hwif->tuneproc = &sc1200_tuneproc; | 460 | hwif->tuneproc = &sc1200_tuneproc; |
461 | hwif->speedproc = &sc1200_tune_chipset; | ||
469 | } | 462 | } |
470 | hwif->atapi_dma = 1; | 463 | hwif->atapi_dma = 1; |
471 | hwif->ultra_mask = 0x07; | 464 | hwif->ultra_mask = 0x07; |