diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-07-19 19:11:56 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-07-19 19:11:56 -0400 |
commit | 1880a8d7f2d0587e657e3292166003636067b7ea (patch) | |
tree | 94ab0c3404fb45f73fc18dc2fa8d6ab268c9b803 /drivers/ide/pci/serverworks.c | |
parent | a5d8c5c834d3cabf4b7b477c3f6ee923c25026fc (diff) |
serverworks: always tune PIO
* Always set ->autotune so PIO gets correctly auto-tuned (previously
->autotune was only set when ->dma_base wasn't available, however
->ide_dma_check()/->speedproc() was always trying to tune PIO when
tuning DMA).
* Move code responsible for programming chipset for PIO mode from
svwks_tune_chipset() to svwks_tune_pio(). Don't tune PIO when tuning
DMA (this is no longer needed since ->autotune is always set now).
* Handle PIO modes early in svwks_tune_chipset() so DMA configuration
registers don't get cleared when programming PIO mode.
* Bump driver version.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci/serverworks.c')
-rw-r--r-- | drivers/ide/pci/serverworks.c | 76 |
1 files changed, 36 insertions, 40 deletions
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index 809deb92bc11..011245246b1f 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.20 Jun 3 2007 | 2 | * linux/drivers/ide/pci/serverworks.c Version 0.21 Jun 16 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 |
@@ -123,23 +123,45 @@ static u8 svwks_csb_check (struct pci_dev *dev) | |||
123 | } | 123 | } |
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | |||
127 | static void svwks_tune_pio(ide_drive_t *drive, const u8 pio) | ||
128 | { | ||
129 | static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; | ||
130 | static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 }; | ||
131 | |||
132 | struct pci_dev *dev = drive->hwif->pci_dev; | ||
133 | |||
134 | pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]); | ||
135 | |||
136 | if (svwks_csb_check(dev)) { | ||
137 | u16 csb_pio = 0; | ||
138 | |||
139 | pci_read_config_word(dev, 0x4a, &csb_pio); | ||
140 | |||
141 | csb_pio &= ~(0x0f << (4 * drive->dn)); | ||
142 | csb_pio |= (pio << (4 * drive->dn)); | ||
143 | |||
144 | pci_write_config_word(dev, 0x4a, csb_pio); | ||
145 | } | ||
146 | } | ||
147 | |||
126 | static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) | 148 | static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) |
127 | { | 149 | { |
128 | static const u8 udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; | 150 | static const u8 udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; |
129 | static const u8 dma_modes[] = { 0x77, 0x21, 0x20 }; | 151 | static const u8 dma_modes[] = { 0x77, 0x21, 0x20 }; |
130 | static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; | ||
131 | static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 }; | ||
132 | static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 }; | 152 | static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 }; |
133 | 153 | ||
134 | ide_hwif_t *hwif = HWIF(drive); | 154 | ide_hwif_t *hwif = HWIF(drive); |
135 | struct pci_dev *dev = hwif->pci_dev; | 155 | struct pci_dev *dev = hwif->pci_dev; |
136 | u8 speed = ide_rate_filter(drive, xferspeed); | 156 | u8 speed = ide_rate_filter(drive, xferspeed); |
137 | u8 pio = ide_get_best_pio_mode(drive, 255, 4, NULL); | ||
138 | u8 unit = (drive->select.b.unit & 0x01); | 157 | u8 unit = (drive->select.b.unit & 0x01); |
139 | u8 csb5 = svwks_csb_check(dev); | 158 | |
140 | u8 ultra_enable = 0, ultra_timing = 0; | 159 | u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0; |
141 | u8 dma_timing = 0, pio_timing = 0; | 160 | |
142 | u16 csb5_pio = 0; | 161 | if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) { |
162 | svwks_tune_pio(drive, speed - XFER_PIO_0); | ||
163 | return ide_config_drive_speed(drive, speed); | ||
164 | } | ||
143 | 165 | ||
144 | /* If we are about to put a disk into UDMA mode we screwed up. | 166 | /* If we are about to put a disk into UDMA mode we screwed up. |
145 | Our code assumes we never _ever_ do this on an OSB4 */ | 167 | Our code assumes we never _ever_ do this on an OSB4 */ |
@@ -149,31 +171,15 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) | |||
149 | BUG(); | 171 | BUG(); |
150 | 172 | ||
151 | pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); | 173 | pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); |
152 | pci_read_config_word(dev, 0x4A, &csb5_pio); | ||
153 | pci_read_config_byte(dev, 0x54, &ultra_enable); | 174 | pci_read_config_byte(dev, 0x54, &ultra_enable); |
154 | 175 | ||
155 | ultra_timing &= ~(0x0F << (4*unit)); | 176 | ultra_timing &= ~(0x0F << (4*unit)); |
156 | ultra_enable &= ~(0x01 << drive->dn); | 177 | ultra_enable &= ~(0x01 << drive->dn); |
157 | csb5_pio &= ~(0x0F << (4*drive->dn)); | ||
158 | 178 | ||
159 | switch(speed) { | 179 | switch(speed) { |
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 | pio_timing |= pio_modes[speed - XFER_PIO_0]; | ||
166 | csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn)); | ||
167 | break; | ||
168 | |||
169 | case XFER_MW_DMA_2: | 180 | case XFER_MW_DMA_2: |
170 | case XFER_MW_DMA_1: | 181 | case XFER_MW_DMA_1: |
171 | case XFER_MW_DMA_0: | 182 | case XFER_MW_DMA_0: |
172 | /* | ||
173 | * TODO: always setup PIO mode so this won't be needed | ||
174 | */ | ||
175 | pio_timing |= pio_modes[pio]; | ||
176 | csb5_pio |= (pio << (4*drive->dn)); | ||
177 | dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; | 183 | dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; |
178 | break; | 184 | break; |
179 | 185 | ||
@@ -183,11 +189,6 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) | |||
183 | case XFER_UDMA_2: | 189 | case XFER_UDMA_2: |
184 | case XFER_UDMA_1: | 190 | case XFER_UDMA_1: |
185 | case XFER_UDMA_0: | 191 | case XFER_UDMA_0: |
186 | /* | ||
187 | * TODO: always setup PIO mode so this won't be needed | ||
188 | */ | ||
189 | pio_timing |= pio_modes[pio]; | ||
190 | csb5_pio |= (pio << (4*drive->dn)); | ||
191 | dma_timing |= dma_modes[2]; | 192 | dma_timing |= dma_modes[2]; |
192 | ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); | 193 | ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); |
193 | ultra_enable |= (0x01 << drive->dn); | 194 | ultra_enable |= (0x01 << drive->dn); |
@@ -195,10 +196,6 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) | |||
195 | break; | 196 | break; |
196 | } | 197 | } |
197 | 198 | ||
198 | pci_write_config_byte(dev, drive_pci[drive->dn], pio_timing); | ||
199 | if (csb5) | ||
200 | pci_write_config_word(dev, 0x4A, csb5_pio); | ||
201 | |||
202 | pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); | 199 | pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); |
203 | pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); | 200 | pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); |
204 | pci_write_config_byte(dev, 0x54, ultra_enable); | 201 | pci_write_config_byte(dev, 0x54, ultra_enable); |
@@ -209,7 +206,8 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) | |||
209 | static void svwks_tune_drive (ide_drive_t *drive, u8 pio) | 206 | static void svwks_tune_drive (ide_drive_t *drive, u8 pio) |
210 | { | 207 | { |
211 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | 208 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); |
212 | (void)svwks_tune_chipset(drive, XFER_PIO_0 + pio); | 209 | svwks_tune_pio(drive, pio); |
210 | (void)ide_config_drive_speed(drive, XFER_PIO_0 + pio); | ||
213 | } | 211 | } |
214 | 212 | ||
215 | static int svwks_config_drive_xfer_rate (ide_drive_t *drive) | 213 | static int svwks_config_drive_xfer_rate (ide_drive_t *drive) |
@@ -407,11 +405,11 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) | |||
407 | 405 | ||
408 | hwif->autodma = 0; | 406 | hwif->autodma = 0; |
409 | 407 | ||
410 | if (!hwif->dma_base) { | 408 | hwif->drives[0].autotune = 1; |
411 | hwif->drives[0].autotune = 1; | 409 | hwif->drives[1].autotune = 1; |
412 | hwif->drives[1].autotune = 1; | 410 | |
411 | if (!hwif->dma_base) | ||
413 | return; | 412 | return; |
414 | } | ||
415 | 413 | ||
416 | hwif->ide_dma_check = &svwks_config_drive_xfer_rate; | 414 | hwif->ide_dma_check = &svwks_config_drive_xfer_rate; |
417 | if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { | 415 | if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { |
@@ -424,8 +422,6 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) | |||
424 | dma_stat = inb(hwif->dma_status); | 422 | dma_stat = inb(hwif->dma_status); |
425 | hwif->drives[0].autodma = (dma_stat & 0x20); | 423 | hwif->drives[0].autodma = (dma_stat & 0x20); |
426 | hwif->drives[1].autodma = (dma_stat & 0x40); | 424 | hwif->drives[1].autodma = (dma_stat & 0x40); |
427 | hwif->drives[0].autotune = (!(dma_stat & 0x20)); | ||
428 | hwif->drives[1].autotune = (!(dma_stat & 0x40)); | ||
429 | } | 425 | } |
430 | 426 | ||
431 | static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) | 427 | static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) |