aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/serverworks.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-07-09 17:17:53 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-07-09 17:17:53 -0400
commitb740d8846e2e184909e9f74d4ad9d67ae0e084ea (patch)
treefe3fa46985ac9b82ae012fe58542ff5e513990d8 /drivers/ide/pci/serverworks.c
parent71d441ddb51941d9d8279bdc858f965711b85c14 (diff)
serverworks: always tune CSB6
Switch the driver to always program DMA/PIO timings and set device transfer mode instead of trusting BIOS on CSB6 controllers (libata pata_serverworks.c driver is also doing things this way and there were no problems reported so far). While doing conversion I noticed that the old code had many issues: * the code was assuming that hwif->dma_status is always valid (which obviously isn't true if hwif->dma_base == NULL) * value of "(ultra_timing >> (4*unit)) & ~(0xF0)" expression wasn't checked to fit into udma_modes[5] * code validating DMA timings didn't validate corresponding PIO timings * extra CSB5 PIO register wasn't validated et all * hwif->ide_dma_off_quietly() is always called before ide_set_dma() (which in turn calls hwif->speedproc() method - svwks_tune_chipset() in this case) so the code depending on DMA capable bit of DMA status to be set was never executed (=> the code was never validating DMA timings despite actually enabling DMA if the PIO timings were OK!) * on resume driver dependend entirely on BIOS to restore timings and set transfer mode on the device While at it: There is no need to read PIO/MWDMA timings now so don't do it. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Diffstat (limited to 'drivers/ide/pci/serverworks.c')
-rw-r--r--drivers/ide/pci/serverworks.c77
1 files changed, 2 insertions, 75 deletions
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index d9c4fd1ae996..09a7aedf63ac 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/drivers/ide/pci/serverworks.c Version 0.11 Jun 2 2007 2 * linux/drivers/ide/pci/serverworks.c Version 0.20 Jun 3 2007
3 * 3 *
4 * Copyright (C) 1998-2000 Michel Aubry 4 * Copyright (C) 1998-2000 Michel Aubry
5 * Copyright (C) 1998-2000 Andrzej Krzysztofowicz 5 * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -151,84 +151,11 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
151 if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 && 151 if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
152 drive->media == ide_disk && speed >= XFER_UDMA_0) 152 drive->media == ide_disk && speed >= XFER_UDMA_0)
153 BUG(); 153 BUG();
154 154
155 pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
156 pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
157 pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); 155 pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
158 pci_read_config_word(dev, 0x4A, &csb5_pio); 156 pci_read_config_word(dev, 0x4A, &csb5_pio);
159 pci_read_config_byte(dev, 0x54, &ultra_enable); 157 pci_read_config_byte(dev, 0x54, &ultra_enable);
160 158
161 /* If we are in RAID mode (eg AMI MegaIDE) then we can't it
162 turns out trust the firmware configuration */
163
164 if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
165 goto oem_setup_failed;
166
167 /* Per Specified Design by OEM, and ASIC Architect */
168 if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
169 (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
170 if (!drive->init_speed) {
171 u8 dma_stat = inb(hwif->dma_status);
172
173 if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
174 ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
175 drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
176 return 0;
177 } else if ((dma_timing) &&
178 ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
179 u8 dmaspeed;
180
181 switch (dma_timing & 0x77) {
182 case 0x20:
183 dmaspeed = XFER_MW_DMA_2;
184 break;
185 case 0x21:
186 dmaspeed = XFER_MW_DMA_1;
187 break;
188 case 0x77:
189 dmaspeed = XFER_MW_DMA_0;
190 break;
191 default:
192 goto dma_pio;
193 }
194
195 drive->current_speed = drive->init_speed = dmaspeed;
196 return 0;
197 }
198dma_pio:
199 if (pio_timing) {
200 u8 piospeed;
201
202 switch (pio_timing & 0x7f) {
203 case 0x20:
204 piospeed = XFER_PIO_4;
205 break;
206 case 0x22:
207 piospeed = XFER_PIO_3;
208 break;
209 case 0x34:
210 piospeed = XFER_PIO_2;
211 break;
212 case 0x47:
213 piospeed = XFER_PIO_1;
214 break;
215 case 0x5d:
216 piospeed = XFER_PIO_0;
217 break;
218 default:
219 goto oem_setup_failed;
220 }
221
222 drive->current_speed = drive->init_speed = piospeed;
223 return 0;
224 }
225 }
226 }
227
228oem_setup_failed:
229
230 pio_timing = 0;
231 dma_timing = 0;
232 ultra_timing &= ~(0x0F << (4*unit)); 159 ultra_timing &= ~(0x0F << (4*unit));
233 ultra_enable &= ~(0x01 << drive->dn); 160 ultra_enable &= ~(0x01 << drive->dn);
234 csb5_pio &= ~(0x0F << (4*drive->dn)); 161 csb5_pio &= ~(0x0F << (4*drive->dn));