aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-15 18:51:43 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-15 18:51:43 -0400
commit5fd216bbb277b645109a889c489e13a7aafbc304 (patch)
tree9ab2016779ea6e49dff6aa49299bbc37f5381406 /drivers/ide
parent793a97228d3da876f42b7fb4d4a52cc8cc86dc81 (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')
-rw-r--r--drivers/ide/pci/cs5530.c120
-rw-r--r--drivers/ide/pci/sc1200.c86
2 files changed, 89 insertions, 117 deletions
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index b2d7c132ef4b..845500115f3c 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -1,10 +1,10 @@
1/* 1/*
2 * linux/drivers/ide/pci/cs5530.c Version 0.7 Sept 10, 2002 2 * linux/drivers/ide/pci/cs5530.c Version 0.71 Mar 10 2007
3 * 3 *
4 * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> 4 * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
5 * Ditto of GNU General Public License.
6 *
7 * Copyright (C) 2000 Mark Lord <mlord@pobox.com> 5 * Copyright (C) 2000 Mark Lord <mlord@pobox.com>
6 * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
7 *
8 * May be copied or modified under the terms of the GNU General Public License 8 * May be copied or modified under the terms of the GNU General Public License
9 * 9 *
10 * Development of this chipset driver was funded 10 * Development of this chipset driver was funded
@@ -88,79 +88,66 @@ static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autot
88} 88}
89 89
90/** 90/**
91 * cs5530_config_dma - select/set DMA and UDMA modes 91 * cs5530_udma_filter - UDMA filter
92 * @drive: drive
93 *
94 * cs5530_udma_filter() does UDMA mask filtering for the given drive
95 * taking into the consideration capabilities of the mate device.
96 *
97 * The CS5530 specifies that two drives sharing a cable cannot mix
98 * UDMA/MDMA. It has to be one or the other, for the pair, though
99 * different timings can still be chosen for each drive. We could
100 * set the appropriate timing bits on the fly, but that might be
101 * a bit confusing. So, for now we statically handle this requirement
102 * by looking at our mate drive to see what it is capable of, before
103 * choosing a mode for our own drive.
104 *
105 * Note: This relies on the fact we never fail from UDMA to MWDMA2
106 * but instead drop to PIO.
107 */
108
109static u8 cs5530_udma_filter(ide_drive_t *drive)
110{
111 ide_hwif_t *hwif = drive->hwif;
112 ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
113 struct hd_driveid *mateid = mate->id;
114 u8 mask = hwif->ultra_mask;
115
116 if (mate->present == 0)
117 goto out;
118
119 if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
120 if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
121 goto out;
122 if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
123 mask = 0;
124 }
125out:
126 return mask;
127}
128
129/**
130 * cs5530_config_dma - set DMA/UDMA mode
92 * @drive: drive to tune 131 * @drive: drive to tune
93 * 132 *
94 * cs5530_config_dma() handles selection/setting of DMA/UDMA modes 133 * cs5530_config_dma() handles setting of DMA/UDMA mode
95 * for both the chipset and drive. The CS5530 has limitations about 134 * for both the chipset and drive.
96 * mixing DMA/UDMA on the same cable.
97 */ 135 */
98 136
99static int cs5530_config_dma (ide_drive_t *drive) 137static int cs5530_config_dma(ide_drive_t *drive)
100{ 138{
101 int udma_ok = 1, mode = 0; 139 ide_hwif_t *hwif = drive->hwif;
102 ide_hwif_t *hwif = HWIF(drive); 140 unsigned int reg, timings = 0;
103 int unit = drive->select.b.unit; 141 unsigned long basereg;
104 ide_drive_t *mate = &hwif->drives[unit^1]; 142 u8 unit = drive->dn & 1, mode = 0;
105 struct hd_driveid *id = drive->id;
106 unsigned int reg, timings = 0;
107 unsigned long basereg;
108 143
109 /* 144 /*
110 * Default to DMA-off in case we run into trouble here. 145 * Default to DMA-off in case we run into trouble here.
111 */ 146 */
112 hwif->dma_off_quietly(drive); 147 hwif->dma_off_quietly(drive);
113 148
114 /* 149 if (ide_use_dma(drive))
115 * The CS5530 specifies that two drives sharing a cable cannot 150 mode = ide_max_dma_mode(drive);
116 * mix UDMA/MDMA. It has to be one or the other, for the pair,
117 * though different timings can still be chosen for each drive.
118 * We could set the appropriate timing bits on the fly,
119 * but that might be a bit confusing. So, for now we statically
120 * handle this requirement by looking at our mate drive to see
121 * what it is capable of, before choosing a mode for our own drive.
122 *
123 * Note: This relies on the fact we never fail from UDMA to MWDMA_2
124 * but instead drop to PIO
125 */
126 if (mate->present) {
127 struct hd_driveid *mateid = mate->id;
128 if (mateid && (mateid->capability & 1) &&
129 !__ide_dma_bad_drive(mate)) {
130 if ((mateid->field_valid & 4) &&
131 (mateid->dma_ultra & 7))
132 udma_ok = 1;
133 else if ((mateid->field_valid & 2) &&
134 (mateid->dma_mword & 7))
135 udma_ok = 0;
136 else
137 udma_ok = 1;
138 }
139 }
140
141 /*
142 * Now see what the current drive is capable of,
143 * selecting UDMA only if the mate said it was ok.
144 */
145 if (id && (id->capability & 1) && drive->autodma &&
146 !__ide_dma_bad_drive(drive)) {
147 if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
148 if (id->dma_ultra & 4)
149 mode = XFER_UDMA_2;
150 else if (id->dma_ultra & 2)
151 mode = XFER_UDMA_1;
152 else if (id->dma_ultra & 1)
153 mode = XFER_UDMA_0;
154 }
155 if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
156 if (id->dma_mword & 4)
157 mode = XFER_MW_DMA_2;
158 else if (id->dma_mword & 2)
159 mode = XFER_MW_DMA_1;
160 else if (id->dma_mword & 1)
161 mode = XFER_MW_DMA_0;
162 }
163 }
164 151
165 /* 152 /*
166 * Tell the drive to switch to the new mode; abort on failure. 153 * Tell the drive to switch to the new mode; abort on failure.
@@ -332,6 +319,7 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
332 hwif->ultra_mask = 0x07; 319 hwif->ultra_mask = 0x07;
333 hwif->mwdma_mask = 0x07; 320 hwif->mwdma_mask = 0x07;
334 321
322 hwif->udma_filter = cs5530_udma_filter;
335 hwif->ide_dma_check = &cs5530_config_dma; 323 hwif->ide_dma_check = &cs5530_config_dma;
336 if (!noautodma) 324 if (!noautodma)
337 hwif->autodma = 1; 325 hwif->autodma = 1;
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
96static 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 */
107static 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; 123out:
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 */
251static int sc1200_config_dma (ide_drive_t *drive) 229static 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)