aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-lib.c')
-rw-r--r--drivers/ide/ide-lib.c125
1 files changed, 18 insertions, 107 deletions
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 68719314df3f..4557fc5a3ea3 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -69,123 +69,34 @@ char *ide_xfer_verbose (u8 xfer_rate)
69EXPORT_SYMBOL(ide_xfer_verbose); 69EXPORT_SYMBOL(ide_xfer_verbose);
70 70
71/** 71/**
72 * ide_dma_speed - compute DMA speed 72 * ide_rate_filter - filter transfer mode
73 * @drive: drive 73 * @drive: IDE device
74 * @mode: modes available
75 *
76 * Checks the drive capabilities and returns the speed to use
77 * for the DMA transfer. Returns 0 if the drive is incapable
78 * of DMA transfers.
79 */
80
81u8 ide_dma_speed(ide_drive_t *drive, u8 mode)
82{
83 struct hd_driveid *id = drive->id;
84 ide_hwif_t *hwif = HWIF(drive);
85 u8 ultra_mask, mwdma_mask, swdma_mask;
86 u8 speed = 0;
87
88 if (drive->media != ide_disk && hwif->atapi_dma == 0)
89 return 0;
90
91 /* Capable of UltraDMA modes? */
92 ultra_mask = id->dma_ultra & hwif->ultra_mask;
93
94 if (!(id->field_valid & 4))
95 mode = 0; /* fallback to MW/SW DMA if no UltraDMA */
96
97 switch (mode) {
98 case 4:
99 if (ultra_mask & 0x40) {
100 speed = XFER_UDMA_6;
101 break;
102 }
103 case 3:
104 if (ultra_mask & 0x20) {
105 speed = XFER_UDMA_5;
106 break;
107 }
108 case 2:
109 if (ultra_mask & 0x10) {
110 speed = XFER_UDMA_4;
111 break;
112 }
113 if (ultra_mask & 0x08) {
114 speed = XFER_UDMA_3;
115 break;
116 }
117 case 1:
118 if (ultra_mask & 0x04) {
119 speed = XFER_UDMA_2;
120 break;
121 }
122 if (ultra_mask & 0x02) {
123 speed = XFER_UDMA_1;
124 break;
125 }
126 if (ultra_mask & 0x01) {
127 speed = XFER_UDMA_0;
128 break;
129 }
130 case 0:
131 mwdma_mask = id->dma_mword & hwif->mwdma_mask;
132
133 if (mwdma_mask & 0x04) {
134 speed = XFER_MW_DMA_2;
135 break;
136 }
137 if (mwdma_mask & 0x02) {
138 speed = XFER_MW_DMA_1;
139 break;
140 }
141 if (mwdma_mask & 0x01) {
142 speed = XFER_MW_DMA_0;
143 break;
144 }
145
146 swdma_mask = id->dma_1word & hwif->swdma_mask;
147
148 if (swdma_mask & 0x04) {
149 speed = XFER_SW_DMA_2;
150 break;
151 }
152 if (swdma_mask & 0x02) {
153 speed = XFER_SW_DMA_1;
154 break;
155 }
156 if (swdma_mask & 0x01) {
157 speed = XFER_SW_DMA_0;
158 break;
159 }
160 }
161
162 return speed;
163}
164EXPORT_SYMBOL(ide_dma_speed);
165
166
167/**
168 * ide_rate_filter - return best speed for mode
169 * @mode: modes available
170 * @speed: desired speed 74 * @speed: desired speed
171 * 75 *
172 * Given the available DMA/UDMA mode this function returns 76 * Given the available transfer modes this function returns
173 * the best available speed at or below the speed requested. 77 * the best available speed at or below the speed requested.
78 *
79 * FIXME: filter also PIO/SWDMA/MWDMA modes
174 */ 80 */
175 81
176u8 ide_rate_filter (u8 mode, u8 speed) 82u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
177{ 83{
178#ifdef CONFIG_BLK_DEV_IDEDMA 84#ifdef CONFIG_BLK_DEV_IDEDMA
179 static u8 speed_max[] = { 85 ide_hwif_t *hwif = drive->hwif;
180 XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, 86 u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2;
181 XFER_UDMA_5, XFER_UDMA_6 87
182 }; 88 if (hwif->udma_filter)
89 mask = hwif->udma_filter(drive);
90
91 if ((mask & 0x78) && (eighty_ninty_three(drive) == 0))
92 mask &= 0x07;
93
94 if (mask)
95 mode = fls(mask) - 1 + XFER_UDMA_0;
183 96
184// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); 97// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed);
185 98
186 /* So that we remember to update this if new modes appear */ 99 return min(speed, mode);
187 BUG_ON(mode > 4);
188 return min(speed, speed_max[mode]);
189#else /* !CONFIG_BLK_DEV_IDEDMA */ 100#else /* !CONFIG_BLK_DEV_IDEDMA */
190 return min(speed, (u8)XFER_PIO_4); 101 return min(speed, (u8)XFER_PIO_4);
191#endif /* CONFIG_BLK_DEV_IDEDMA */ 102#endif /* CONFIG_BLK_DEV_IDEDMA */