diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-15 18:51:43 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-15 18:51:43 -0400 |
commit | 5fd216bbb277b645109a889c489e13a7aafbc304 (patch) | |
tree | 9ab2016779ea6e49dff6aa49299bbc37f5381406 /drivers/ide/pci/sc1200.c | |
parent | 793a97228d3da876f42b7fb4d4a52cc8cc86dc81 (diff) |
cs5530/sc1200: add ->udma_filter methods
CS5530/SC1200 specifies that two drives on the same cable cannot mix
UDMA/MDMA. Add {cs5530,sc1200}_udma_filter() to handle this. This also
makes it possible to remove open-coded best DMA mode selection and use
standard ide_use_dma()/ide_max_dma_mode() helpers. While at it bump
version numbers.
There should be no functionality changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci/sc1200.c')
-rw-r--r-- | drivers/ide/pci/sc1200.c | 86 |
1 files changed, 35 insertions, 51 deletions
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index b5ae0c50e216..c0254b5e7d92 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.92 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,57 +95,33 @@ 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 | /* |
99 | * The SC1200 specifies that two drives sharing a cable cannot mix | ||
100 | * UDMA/MDMA. It has to be one or the other, for the pair, though | ||
101 | * different timings can still be chosen for each drive. We could | ||
102 | * set the appropriate timing bits on the fly, but that might be | ||
103 | * a bit confusing. So, for now we statically handle this requirement | ||
104 | * by looking at our mate drive to see what it is capable of, before | ||
105 | * choosing a mode for our own drive. | ||
106 | */ | ||
107 | static u8 sc1200_udma_filter(ide_drive_t *drive) | ||
97 | { | 108 | { |
98 | int udma_ok = 1, mode = 0; | 109 | ide_hwif_t *hwif = drive->hwif; |
99 | ide_hwif_t *hwif = HWIF(drive); | 110 | ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1]; |
100 | int unit = drive->select.b.unit; | 111 | struct hd_driveid *mateid = mate->id; |
101 | ide_drive_t *mate = &hwif->drives[unit^1]; | 112 | u8 mask = hwif->ultra_mask; |
102 | struct hd_driveid *id = drive->id; | 113 | |
103 | 114 | if (mate->present == 0) | |
104 | /* | 115 | goto out; |
105 | * The SC1200 specifies that two drives sharing a cable cannot | 116 | |
106 | * mix UDMA/MDMA. It has to be one or the other, for the pair, | 117 | if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) { |
107 | * though different timings can still be chosen for each drive. | 118 | if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) |
108 | * We could set the appropriate timing bits on the fly, | 119 | goto out; |
109 | * but that might be a bit confusing. So, for now we statically | 120 | if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) |
110 | * handle this requirement by looking at our mate drive to see | 121 | mask = 0; |
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 | } | 122 | } |
146 | return mode; | 123 | out: |
124 | return mask; | ||
147 | } | 125 | } |
148 | 126 | ||
149 | /* | 127 | /* |
@@ -250,7 +228,12 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
250 | */ | 228 | */ |
251 | static int sc1200_config_dma (ide_drive_t *drive) | 229 | static int sc1200_config_dma (ide_drive_t *drive) |
252 | { | 230 | { |
253 | return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive)); | 231 | u8 mode = 0; |
232 | |||
233 | if (ide_use_dma(drive)) | ||
234 | mode = ide_max_dma_mode(drive); | ||
235 | |||
236 | return sc1200_config_dma2(drive, mode); | ||
254 | } | 237 | } |
255 | 238 | ||
256 | 239 | ||
@@ -461,6 +444,7 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) | |||
461 | hwif->serialized = hwif->mate->serialized = 1; | 444 | hwif->serialized = hwif->mate->serialized = 1; |
462 | hwif->autodma = 0; | 445 | hwif->autodma = 0; |
463 | if (hwif->dma_base) { | 446 | if (hwif->dma_base) { |
447 | hwif->udma_filter = sc1200_udma_filter; | ||
464 | hwif->ide_dma_check = &sc1200_config_dma; | 448 | hwif->ide_dma_check = &sc1200_config_dma; |
465 | hwif->ide_dma_end = &sc1200_ide_dma_end; | 449 | hwif->ide_dma_end = &sc1200_ide_dma_end; |
466 | if (!noautodma) | 450 | if (!noautodma) |