diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-07-09 17:17:53 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-07-09 17:17:53 -0400 |
commit | b740d8846e2e184909e9f74d4ad9d67ae0e084ea (patch) | |
tree | fe3fa46985ac9b82ae012fe58542ff5e513990d8 | |
parent | 71d441ddb51941d9d8279bdc858f965711b85c14 (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>
-rw-r--r-- | drivers/ide/pci/serverworks.c | 77 |
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 | } | ||
198 | dma_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 | |||
228 | oem_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)); |