aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-03-24 18:22:46 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-03-24 18:22:46 -0400
commit7eeaaaa52285d5e6cb79f515e99c591dcb9d04fe (patch)
tree02513d82b19d9b00faaf268ce60a312cbe3a1389 /drivers
parent11938c929022bb92b1a42f5e1289524a1e465dc0 (diff)
ide: move xfer mode tuning code to ide-xfer-mode.c
* Move xfer mode tuning code to ide-xfer-mode.c. * Add CONFIG_IDE_XFER_MODE config option to be selected by host drivers that support xfer mode tuning. * Add CONFIG_IDE_XFER_MODE=n static inline versions of ide_set_pio() and ide_set_xfer_rate(). * Make IDE_TIMINGS and BLK_DEV_IDEDMA config options select IDE_XFER_MODE, also add explicit selects for few host drivers that need it. * Build/link ide-xfer-mode.o and ide-pio-blacklist.o (it is needed only by ide-xfer-mode.o) only if CONFIG_IDE_XFER_MODE=y. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/Kconfig8
-rw-r--r--drivers/ide/Makefile4
-rw-r--r--drivers/ide/ide-lib.c240
-rw-r--r--drivers/ide/ide-xfer-mode.c246
4 files changed, 256 insertions, 242 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 5ea3bfad172a..640c99207242 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -56,8 +56,12 @@ if IDE
56 56
57comment "Please see Documentation/ide/ide.txt for help/info on IDE drives" 57comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
58 58
59config IDE_XFER_MODE
60 bool
61
59config IDE_TIMINGS 62config IDE_TIMINGS
60 bool 63 bool
64 select IDE_XFER_MODE
61 65
62config IDE_ATAPI 66config IDE_ATAPI
63 bool 67 bool
@@ -698,6 +702,7 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST
698config BLK_DEV_IDE_AU1XXX 702config BLK_DEV_IDE_AU1XXX
699 bool "IDE for AMD Alchemy Au1200" 703 bool "IDE for AMD Alchemy Au1200"
700 depends on SOC_AU1200 704 depends on SOC_AU1200
705 select IDE_XFER_MODE
701choice 706choice
702 prompt "IDE Mode for AMD Alchemy Au1200" 707 prompt "IDE Mode for AMD Alchemy Au1200"
703 default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA 708 default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
@@ -871,6 +876,7 @@ config BLK_DEV_ALI14XX
871 876
872config BLK_DEV_DTC2278 877config BLK_DEV_DTC2278
873 tristate "DTC-2278 support" 878 tristate "DTC-2278 support"
879 select IDE_XFER_MODE
874 select IDE_LEGACY 880 select IDE_LEGACY
875 help 881 help
876 This driver is enabled at runtime using the "dtc2278.probe" kernel 882 This driver is enabled at runtime using the "dtc2278.probe" kernel
@@ -902,6 +908,7 @@ config BLK_DEV_QD65XX
902 908
903config BLK_DEV_UMC8672 909config BLK_DEV_UMC8672
904 tristate "UMC-8672 support" 910 tristate "UMC-8672 support"
911 select IDE_XFER_MODE
905 select IDE_LEGACY 912 select IDE_LEGACY
906 help 913 help
907 This driver is enabled at runtime using the "umc8672.probe" kernel 914 This driver is enabled at runtime using the "umc8672.probe" kernel
@@ -915,5 +922,6 @@ endif
915config BLK_DEV_IDEDMA 922config BLK_DEV_IDEDMA
916 def_bool BLK_DEV_IDEDMA_SFF || \ 923 def_bool BLK_DEV_IDEDMA_SFF || \
917 BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA 924 BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
925 select IDE_XFER_MODE
918 926
919endif # IDE 927endif # IDE
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 83a970ee4bfe..d0976e6ee090 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -5,10 +5,10 @@
5EXTRA_CFLAGS += -Idrivers/ide 5EXTRA_CFLAGS += -Idrivers/ide
6 6
7ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ 7ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
8 ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o \ 8 ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o
9 ide-sysfs.o ide-devsets.o
10 9
11# core IDE code 10# core IDE code
11ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o
12ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o 12ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
13ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o 13ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
14ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o 14ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 09526a0de734..f6c683dd2987 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -5,163 +5,6 @@
5#include <linux/ide.h> 5#include <linux/ide.h>
6#include <linux/bitops.h> 6#include <linux/bitops.h>
7 7
8static const char *udma_str[] =
9 { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
10 "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
11static const char *mwdma_str[] =
12 { "MWDMA0", "MWDMA1", "MWDMA2" };
13static const char *swdma_str[] =
14 { "SWDMA0", "SWDMA1", "SWDMA2" };
15static const char *pio_str[] =
16 { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
17
18/**
19 * ide_xfer_verbose - return IDE mode names
20 * @mode: transfer mode
21 *
22 * Returns a constant string giving the name of the mode
23 * requested.
24 */
25
26const char *ide_xfer_verbose(u8 mode)
27{
28 const char *s;
29 u8 i = mode & 0xf;
30
31 if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
32 s = udma_str[i];
33 else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
34 s = mwdma_str[i];
35 else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
36 s = swdma_str[i];
37 else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
38 s = pio_str[i & 0x7];
39 else if (mode == XFER_PIO_SLOW)
40 s = "PIO SLOW";
41 else
42 s = "XFER ERROR";
43
44 return s;
45}
46EXPORT_SYMBOL(ide_xfer_verbose);
47
48/**
49 * ide_rate_filter - filter transfer mode
50 * @drive: IDE device
51 * @speed: desired speed
52 *
53 * Given the available transfer modes this function returns
54 * the best available speed at or below the speed requested.
55 *
56 * TODO: check device PIO capabilities
57 */
58
59static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
60{
61 ide_hwif_t *hwif = drive->hwif;
62 u8 mode = ide_find_dma_mode(drive, speed);
63
64 if (mode == 0) {
65 if (hwif->pio_mask)
66 mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
67 else
68 mode = XFER_PIO_4;
69 }
70
71/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
72
73 return min(speed, mode);
74}
75
76/**
77 * ide_get_best_pio_mode - get PIO mode from drive
78 * @drive: drive to consider
79 * @mode_wanted: preferred mode
80 * @max_mode: highest allowed mode
81 *
82 * This routine returns the recommended PIO settings for a given drive,
83 * based on the drive->id information and the ide_pio_blacklist[].
84 *
85 * Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
86 * This is used by most chipset support modules when "auto-tuning".
87 */
88
89u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
90{
91 u16 *id = drive->id;
92 int pio_mode = -1, overridden = 0;
93
94 if (mode_wanted != 255)
95 return min_t(u8, mode_wanted, max_mode);
96
97 if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
98 pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
99
100 if (pio_mode != -1) {
101 printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
102 } else {
103 pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
104 if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
105 pio_mode = 2;
106 overridden = 1;
107 }
108
109 if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
110 if (ata_id_has_iordy(id)) {
111 if (id[ATA_ID_PIO_MODES] & 7) {
112 overridden = 0;
113 if (id[ATA_ID_PIO_MODES] & 4)
114 pio_mode = 5;
115 else if (id[ATA_ID_PIO_MODES] & 2)
116 pio_mode = 4;
117 else
118 pio_mode = 3;
119 }
120 }
121 }
122
123 if (overridden)
124 printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
125 drive->name);
126 }
127
128 if (pio_mode > max_mode)
129 pio_mode = max_mode;
130
131 return pio_mode;
132}
133EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
134
135/* req_pio == "255" for auto-tune */
136void ide_set_pio(ide_drive_t *drive, u8 req_pio)
137{
138 ide_hwif_t *hwif = drive->hwif;
139 const struct ide_port_ops *port_ops = hwif->port_ops;
140 u8 host_pio, pio;
141
142 if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
143 (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
144 return;
145
146 BUG_ON(hwif->pio_mask == 0x00);
147
148 host_pio = fls(hwif->pio_mask) - 1;
149
150 pio = ide_get_best_pio_mode(drive, req_pio, host_pio);
151
152 /*
153 * TODO:
154 * - report device max PIO mode
155 * - check req_pio != 255 against device max PIO mode
156 */
157 printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n",
158 drive->name, host_pio, req_pio,
159 req_pio == 255 ? "(auto-tune)" : "", pio);
160
161 (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
162}
163EXPORT_SYMBOL_GPL(ide_set_pio);
164
165/** 8/**
166 * ide_toggle_bounce - handle bounce buffering 9 * ide_toggle_bounce - handle bounce buffering
167 * @drive: drive to update 10 * @drive: drive to update
@@ -188,89 +31,6 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
188 blk_queue_bounce_limit(drive->queue, addr); 31 blk_queue_bounce_limit(drive->queue, addr);
189} 32}
190 33
191int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
192{
193 ide_hwif_t *hwif = drive->hwif;
194 const struct ide_port_ops *port_ops = hwif->port_ops;
195
196 if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
197 return 0;
198
199 if (port_ops == NULL || port_ops->set_pio_mode == NULL)
200 return -1;
201
202 /*
203 * TODO: temporary hack for some legacy host drivers that didn't
204 * set transfer mode on the device in ->set_pio_mode method...
205 */
206 if (port_ops->set_dma_mode == NULL) {
207 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
208 return 0;
209 }
210
211 if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
212 if (ide_config_drive_speed(drive, mode))
213 return -1;
214 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
215 return 0;
216 } else {
217 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
218 return ide_config_drive_speed(drive, mode);
219 }
220}
221
222int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
223{
224 ide_hwif_t *hwif = drive->hwif;
225 const struct ide_port_ops *port_ops = hwif->port_ops;
226
227 if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
228 return 0;
229
230 if (port_ops == NULL || port_ops->set_dma_mode == NULL)
231 return -1;
232
233 if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
234 if (ide_config_drive_speed(drive, mode))
235 return -1;
236 port_ops->set_dma_mode(drive, mode);
237 return 0;
238 } else {
239 port_ops->set_dma_mode(drive, mode);
240 return ide_config_drive_speed(drive, mode);
241 }
242}
243EXPORT_SYMBOL_GPL(ide_set_dma_mode);
244
245/**
246 * ide_set_xfer_rate - set transfer rate
247 * @drive: drive to set
248 * @rate: speed to attempt to set
249 *
250 * General helper for setting the speed of an IDE device. This
251 * function knows about user enforced limits from the configuration
252 * which ->set_pio_mode/->set_dma_mode does not.
253 */
254
255int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
256{
257 ide_hwif_t *hwif = drive->hwif;
258 const struct ide_port_ops *port_ops = hwif->port_ops;
259
260 if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
261 (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
262 return -1;
263
264 rate = ide_rate_filter(drive, rate);
265
266 BUG_ON(rate < XFER_PIO_0);
267
268 if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
269 return ide_set_pio_mode(drive, rate);
270
271 return ide_set_dma_mode(drive, rate);
272}
273
274static void ide_dump_opcode(ide_drive_t *drive) 34static void ide_dump_opcode(ide_drive_t *drive)
275{ 35{
276 struct request *rq = drive->hwif->rq; 36 struct request *rq = drive->hwif->rq;
diff --git a/drivers/ide/ide-xfer-mode.c b/drivers/ide/ide-xfer-mode.c
new file mode 100644
index 000000000000..6910f6a257e8
--- /dev/null
+++ b/drivers/ide/ide-xfer-mode.c
@@ -0,0 +1,246 @@
1#include <linux/types.h>
2#include <linux/string.h>
3#include <linux/kernel.h>
4#include <linux/interrupt.h>
5#include <linux/ide.h>
6#include <linux/bitops.h>
7
8static const char *udma_str[] =
9 { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
10 "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
11static const char *mwdma_str[] =
12 { "MWDMA0", "MWDMA1", "MWDMA2" };
13static const char *swdma_str[] =
14 { "SWDMA0", "SWDMA1", "SWDMA2" };
15static const char *pio_str[] =
16 { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
17
18/**
19 * ide_xfer_verbose - return IDE mode names
20 * @mode: transfer mode
21 *
22 * Returns a constant string giving the name of the mode
23 * requested.
24 */
25
26const char *ide_xfer_verbose(u8 mode)
27{
28 const char *s;
29 u8 i = mode & 0xf;
30
31 if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
32 s = udma_str[i];
33 else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
34 s = mwdma_str[i];
35 else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
36 s = swdma_str[i];
37 else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
38 s = pio_str[i & 0x7];
39 else if (mode == XFER_PIO_SLOW)
40 s = "PIO SLOW";
41 else
42 s = "XFER ERROR";
43
44 return s;
45}
46EXPORT_SYMBOL(ide_xfer_verbose);
47
48/**
49 * ide_get_best_pio_mode - get PIO mode from drive
50 * @drive: drive to consider
51 * @mode_wanted: preferred mode
52 * @max_mode: highest allowed mode
53 *
54 * This routine returns the recommended PIO settings for a given drive,
55 * based on the drive->id information and the ide_pio_blacklist[].
56 *
57 * Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
58 * This is used by most chipset support modules when "auto-tuning".
59 */
60
61u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
62{
63 u16 *id = drive->id;
64 int pio_mode = -1, overridden = 0;
65
66 if (mode_wanted != 255)
67 return min_t(u8, mode_wanted, max_mode);
68
69 if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
70 pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
71
72 if (pio_mode != -1) {
73 printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
74 } else {
75 pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
76 if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
77 pio_mode = 2;
78 overridden = 1;
79 }
80
81 if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
82 if (ata_id_has_iordy(id)) {
83 if (id[ATA_ID_PIO_MODES] & 7) {
84 overridden = 0;
85 if (id[ATA_ID_PIO_MODES] & 4)
86 pio_mode = 5;
87 else if (id[ATA_ID_PIO_MODES] & 2)
88 pio_mode = 4;
89 else
90 pio_mode = 3;
91 }
92 }
93 }
94
95 if (overridden)
96 printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
97 drive->name);
98 }
99
100 if (pio_mode > max_mode)
101 pio_mode = max_mode;
102
103 return pio_mode;
104}
105EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
106
107int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
108{
109 ide_hwif_t *hwif = drive->hwif;
110 const struct ide_port_ops *port_ops = hwif->port_ops;
111
112 if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
113 return 0;
114
115 if (port_ops == NULL || port_ops->set_pio_mode == NULL)
116 return -1;
117
118 /*
119 * TODO: temporary hack for some legacy host drivers that didn't
120 * set transfer mode on the device in ->set_pio_mode method...
121 */
122 if (port_ops->set_dma_mode == NULL) {
123 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
124 return 0;
125 }
126
127 if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
128 if (ide_config_drive_speed(drive, mode))
129 return -1;
130 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
131 return 0;
132 } else {
133 port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
134 return ide_config_drive_speed(drive, mode);
135 }
136}
137
138int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
139{
140 ide_hwif_t *hwif = drive->hwif;
141 const struct ide_port_ops *port_ops = hwif->port_ops;
142
143 if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
144 return 0;
145
146 if (port_ops == NULL || port_ops->set_dma_mode == NULL)
147 return -1;
148
149 if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
150 if (ide_config_drive_speed(drive, mode))
151 return -1;
152 port_ops->set_dma_mode(drive, mode);
153 return 0;
154 } else {
155 port_ops->set_dma_mode(drive, mode);
156 return ide_config_drive_speed(drive, mode);
157 }
158}
159EXPORT_SYMBOL_GPL(ide_set_dma_mode);
160
161/* req_pio == "255" for auto-tune */
162void ide_set_pio(ide_drive_t *drive, u8 req_pio)
163{
164 ide_hwif_t *hwif = drive->hwif;
165 const struct ide_port_ops *port_ops = hwif->port_ops;
166 u8 host_pio, pio;
167
168 if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
169 (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
170 return;
171
172 BUG_ON(hwif->pio_mask == 0x00);
173
174 host_pio = fls(hwif->pio_mask) - 1;
175
176 pio = ide_get_best_pio_mode(drive, req_pio, host_pio);
177
178 /*
179 * TODO:
180 * - report device max PIO mode
181 * - check req_pio != 255 against device max PIO mode
182 */
183 printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n",
184 drive->name, host_pio, req_pio,
185 req_pio == 255 ? "(auto-tune)" : "", pio);
186
187 (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
188}
189EXPORT_SYMBOL_GPL(ide_set_pio);
190
191/**
192 * ide_rate_filter - filter transfer mode
193 * @drive: IDE device
194 * @speed: desired speed
195 *
196 * Given the available transfer modes this function returns
197 * the best available speed at or below the speed requested.
198 *
199 * TODO: check device PIO capabilities
200 */
201
202static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
203{
204 ide_hwif_t *hwif = drive->hwif;
205 u8 mode = ide_find_dma_mode(drive, speed);
206
207 if (mode == 0) {
208 if (hwif->pio_mask)
209 mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
210 else
211 mode = XFER_PIO_4;
212 }
213
214/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
215
216 return min(speed, mode);
217}
218
219/**
220 * ide_set_xfer_rate - set transfer rate
221 * @drive: drive to set
222 * @rate: speed to attempt to set
223 *
224 * General helper for setting the speed of an IDE device. This
225 * function knows about user enforced limits from the configuration
226 * which ->set_pio_mode/->set_dma_mode does not.
227 */
228
229int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
230{
231 ide_hwif_t *hwif = drive->hwif;
232 const struct ide_port_ops *port_ops = hwif->port_ops;
233
234 if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
235 (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
236 return -1;
237
238 rate = ide_rate_filter(drive, rate);
239
240 BUG_ON(rate < XFER_PIO_0);
241
242 if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
243 return ide_set_pio_mode(drive, rate);
244
245 return ide_set_dma_mode(drive, rate);
246}