aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-dma.c')
-rw-r--r--drivers/ide/ide-dma.c73
1 files changed, 30 insertions, 43 deletions
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 83885ba0496c..4d212b867c35 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -153,8 +153,11 @@ EXPORT_SYMBOL_GPL(ide_build_sglist);
153 * 153 *
154 * ide_build_dmatable() prepares a dma request. We map the command 154 * ide_build_dmatable() prepares a dma request. We map the command
155 * to get the pci bus addresses of the buffers and then build up 155 * to get the pci bus addresses of the buffers and then build up
156 * the PRD table that the IDE layer wants to be fed. The code 156 * the PRD table that the IDE layer wants to be fed.
157 * knows about the 64K wrap bug in the CS5530. 157 *
158 * Most chipsets correctly interpret a length of 0x0000 as 64KB,
159 * but at least one (e.g. CS5530) misinterprets it as zero (!).
160 * So we break the 64KB entry into two 32KB entries instead.
158 * 161 *
159 * Returns the number of built PRD entries if all went okay, 162 * Returns the number of built PRD entries if all went okay,
160 * returns 0 otherwise. 163 * returns 0 otherwise.
@@ -171,15 +174,12 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
171 int i; 174 int i;
172 struct scatterlist *sg; 175 struct scatterlist *sg;
173 176
174 hwif->sg_nents = i = ide_build_sglist(drive, rq); 177 hwif->sg_nents = ide_build_sglist(drive, rq);
175 178 if (hwif->sg_nents == 0)
176 if (!i)
177 return 0; 179 return 0;
178 180
179 sg = hwif->sg_table; 181 for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
180 while (i) { 182 u32 cur_addr, cur_len, xcount, bcount;
181 u32 cur_addr;
182 u32 cur_len;
183 183
184 cur_addr = sg_dma_address(sg); 184 cur_addr = sg_dma_address(sg);
185 cur_len = sg_dma_len(sg); 185 cur_len = sg_dma_len(sg);
@@ -191,40 +191,27 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
191 */ 191 */
192 192
193 while (cur_len) { 193 while (cur_len) {
194 if (count++ >= PRD_ENTRIES) { 194 if (count++ >= PRD_ENTRIES)
195 printk(KERN_ERR "%s: DMA table too small\n", drive->name);
196 goto use_pio_instead; 195 goto use_pio_instead;
197 } else { 196
198 u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); 197 bcount = 0x10000 - (cur_addr & 0xffff);
199 198 if (bcount > cur_len)
200 if (bcount > cur_len) 199 bcount = cur_len;
201 bcount = cur_len; 200 *table++ = cpu_to_le32(cur_addr);
202 *table++ = cpu_to_le32(cur_addr); 201 xcount = bcount & 0xffff;
203 xcount = bcount & 0xffff; 202 if (is_trm290)
204 if (is_trm290) 203 xcount = ((xcount >> 2) - 1) << 16;
205 xcount = ((xcount >> 2) - 1) << 16; 204 if (xcount == 0x0000) {
206 else if (xcount == 0x0000) { 205 if (count++ >= PRD_ENTRIES)
207 /* 206 goto use_pio_instead;
208 * Most chipsets correctly interpret a length of 0x0000 as 64KB, 207 *table++ = cpu_to_le32(0x8000);
209 * but at least one (e.g. CS5530) misinterprets it as zero (!). 208 *table++ = cpu_to_le32(cur_addr + 0x8000);
210 * So here we break the 64KB entry into two 32KB entries instead. 209 xcount = 0x8000;
211 */
212 if (count++ >= PRD_ENTRIES) {
213 printk(KERN_ERR "%s: DMA table too small\n", drive->name);
214 goto use_pio_instead;
215 }
216 *table++ = cpu_to_le32(0x8000);
217 *table++ = cpu_to_le32(cur_addr + 0x8000);
218 xcount = 0x8000;
219 }
220 *table++ = cpu_to_le32(xcount);
221 cur_addr += bcount;
222 cur_len -= bcount;
223 } 210 }
211 *table++ = cpu_to_le32(xcount);
212 cur_addr += bcount;
213 cur_len -= bcount;
224 } 214 }
225
226 sg = sg_next(sg);
227 i--;
228 } 215 }
229 216
230 if (count) { 217 if (count) {
@@ -233,14 +220,14 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
233 return count; 220 return count;
234 } 221 }
235 222
236 printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
237
238use_pio_instead: 223use_pio_instead:
224 printk(KERN_ERR "%s: %s\n", drive->name,
225 count ? "DMA table too small" : "empty DMA table?");
226
239 ide_destroy_dmatable(drive); 227 ide_destroy_dmatable(drive);
240 228
241 return 0; /* revert to PIO for this request */ 229 return 0; /* revert to PIO for this request */
242} 230}
243
244EXPORT_SYMBOL_GPL(ide_build_dmatable); 231EXPORT_SYMBOL_GPL(ide_build_dmatable);
245#endif 232#endif
246 233