diff options
Diffstat (limited to 'drivers/ide/ide-dma-sff.c')
-rw-r--r-- | drivers/ide/ide-dma-sff.c | 105 |
1 files changed, 53 insertions, 52 deletions
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c index cac431f0df17..123d393658af 100644 --- a/drivers/ide/ide-dma-sff.c +++ b/drivers/ide/ide-dma-sff.c | |||
@@ -50,6 +50,27 @@ int config_drive_for_dma(ide_drive_t *drive) | |||
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
52 | 52 | ||
53 | u8 ide_dma_sff_read_status(ide_hwif_t *hwif) | ||
54 | { | ||
55 | unsigned long addr = hwif->dma_base + ATA_DMA_STATUS; | ||
56 | |||
57 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
58 | return readb((void __iomem *)addr); | ||
59 | else | ||
60 | return inb(addr); | ||
61 | } | ||
62 | EXPORT_SYMBOL_GPL(ide_dma_sff_read_status); | ||
63 | |||
64 | static void ide_dma_sff_write_status(ide_hwif_t *hwif, u8 val) | ||
65 | { | ||
66 | unsigned long addr = hwif->dma_base + ATA_DMA_STATUS; | ||
67 | |||
68 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
69 | writeb(val, (void __iomem *)addr); | ||
70 | else | ||
71 | outb(val, addr); | ||
72 | } | ||
73 | |||
53 | /** | 74 | /** |
54 | * ide_dma_host_set - Enable/disable DMA on a host | 75 | * ide_dma_host_set - Enable/disable DMA on a host |
55 | * @drive: drive to control | 76 | * @drive: drive to control |
@@ -62,18 +83,14 @@ void ide_dma_host_set(ide_drive_t *drive, int on) | |||
62 | { | 83 | { |
63 | ide_hwif_t *hwif = drive->hwif; | 84 | ide_hwif_t *hwif = drive->hwif; |
64 | u8 unit = drive->dn & 1; | 85 | u8 unit = drive->dn & 1; |
65 | u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); | 86 | u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); |
66 | 87 | ||
67 | if (on) | 88 | if (on) |
68 | dma_stat |= (1 << (5 + unit)); | 89 | dma_stat |= (1 << (5 + unit)); |
69 | else | 90 | else |
70 | dma_stat &= ~(1 << (5 + unit)); | 91 | dma_stat &= ~(1 << (5 + unit)); |
71 | 92 | ||
72 | if (hwif->host_flags & IDE_HFLAG_MMIO) | 93 | ide_dma_sff_write_status(hwif, dma_stat); |
73 | writeb(dma_stat, | ||
74 | (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)); | ||
75 | else | ||
76 | outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS); | ||
77 | } | 94 | } |
78 | EXPORT_SYMBOL_GPL(ide_dma_host_set); | 95 | EXPORT_SYMBOL_GPL(ide_dma_host_set); |
79 | 96 | ||
@@ -98,10 +115,10 @@ int ide_build_dmatable(ide_drive_t *drive, struct request *rq) | |||
98 | { | 115 | { |
99 | ide_hwif_t *hwif = drive->hwif; | 116 | ide_hwif_t *hwif = drive->hwif; |
100 | __le32 *table = (__le32 *)hwif->dmatable_cpu; | 117 | __le32 *table = (__le32 *)hwif->dmatable_cpu; |
101 | unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0; | ||
102 | unsigned int count = 0; | 118 | unsigned int count = 0; |
103 | int i; | 119 | int i; |
104 | struct scatterlist *sg; | 120 | struct scatterlist *sg; |
121 | u8 is_trm290 = !!(hwif->host_flags & IDE_HFLAG_TRM290); | ||
105 | 122 | ||
106 | hwif->sg_nents = ide_build_sglist(drive, rq); | 123 | hwif->sg_nents = ide_build_sglist(drive, rq); |
107 | if (hwif->sg_nents == 0) | 124 | if (hwif->sg_nents == 0) |
@@ -175,16 +192,11 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable); | |||
175 | int ide_dma_setup(ide_drive_t *drive) | 192 | int ide_dma_setup(ide_drive_t *drive) |
176 | { | 193 | { |
177 | ide_hwif_t *hwif = drive->hwif; | 194 | ide_hwif_t *hwif = drive->hwif; |
178 | struct request *rq = hwif->hwgroup->rq; | 195 | struct request *rq = hwif->rq; |
179 | unsigned int reading; | 196 | unsigned int reading = rq_data_dir(rq) ? 0 : ATA_DMA_WR; |
180 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 197 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
181 | u8 dma_stat; | 198 | u8 dma_stat; |
182 | 199 | ||
183 | if (rq_data_dir(rq)) | ||
184 | reading = 0; | ||
185 | else | ||
186 | reading = 1 << 3; | ||
187 | |||
188 | /* fall back to pio! */ | 200 | /* fall back to pio! */ |
189 | if (!ide_build_dmatable(drive, rq)) { | 201 | if (!ide_build_dmatable(drive, rq)) { |
190 | ide_map_sg(drive, rq); | 202 | ide_map_sg(drive, rq); |
@@ -192,7 +204,7 @@ int ide_dma_setup(ide_drive_t *drive) | |||
192 | } | 204 | } |
193 | 205 | ||
194 | /* PRD table */ | 206 | /* PRD table */ |
195 | if (hwif->host_flags & IDE_HFLAG_MMIO) | 207 | if (mmio) |
196 | writel(hwif->dmatable_dma, | 208 | writel(hwif->dmatable_dma, |
197 | (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS)); | 209 | (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS)); |
198 | else | 210 | else |
@@ -205,14 +217,10 @@ int ide_dma_setup(ide_drive_t *drive) | |||
205 | outb(reading, hwif->dma_base + ATA_DMA_CMD); | 217 | outb(reading, hwif->dma_base + ATA_DMA_CMD); |
206 | 218 | ||
207 | /* read DMA status for INTR & ERROR flags */ | 219 | /* read DMA status for INTR & ERROR flags */ |
208 | dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); | 220 | dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); |
209 | 221 | ||
210 | /* clear INTR & ERROR flags */ | 222 | /* clear INTR & ERROR flags */ |
211 | if (mmio) | 223 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); |
212 | writeb(dma_stat | 6, | ||
213 | (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)); | ||
214 | else | ||
215 | outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS); | ||
216 | 224 | ||
217 | drive->waiting_for_dma = 1; | 225 | drive->waiting_for_dma = 1; |
218 | return 0; | 226 | return 0; |
@@ -236,7 +244,7 @@ EXPORT_SYMBOL_GPL(ide_dma_setup); | |||
236 | static int dma_timer_expiry(ide_drive_t *drive) | 244 | static int dma_timer_expiry(ide_drive_t *drive) |
237 | { | 245 | { |
238 | ide_hwif_t *hwif = drive->hwif; | 246 | ide_hwif_t *hwif = drive->hwif; |
239 | u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); | 247 | u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); |
240 | 248 | ||
241 | printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n", | 249 | printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n", |
242 | drive->name, __func__, dma_stat); | 250 | drive->name, __func__, dma_stat); |
@@ -244,16 +252,15 @@ static int dma_timer_expiry(ide_drive_t *drive) | |||
244 | if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */ | 252 | if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */ |
245 | return WAIT_CMD; | 253 | return WAIT_CMD; |
246 | 254 | ||
247 | hwif->hwgroup->expiry = NULL; /* one free ride for now */ | 255 | hwif->expiry = NULL; /* one free ride for now */ |
248 | 256 | ||
249 | /* 1 dmaing, 2 error, 4 intr */ | 257 | if (dma_stat & ATA_DMA_ERR) /* ERROR */ |
250 | if (dma_stat & 2) /* ERROR */ | ||
251 | return -1; | 258 | return -1; |
252 | 259 | ||
253 | if (dma_stat & 1) /* DMAing */ | 260 | if (dma_stat & ATA_DMA_ACTIVE) /* DMAing */ |
254 | return WAIT_CMD; | 261 | return WAIT_CMD; |
255 | 262 | ||
256 | if (dma_stat & 4) /* Got an Interrupt */ | 263 | if (dma_stat & ATA_DMA_INTR) /* Got an Interrupt */ |
257 | return WAIT_CMD; | 264 | return WAIT_CMD; |
258 | 265 | ||
259 | return 0; /* Status is unknown -- reset the bus */ | 266 | return 0; /* Status is unknown -- reset the bus */ |
@@ -279,12 +286,11 @@ void ide_dma_start(ide_drive_t *drive) | |||
279 | */ | 286 | */ |
280 | if (hwif->host_flags & IDE_HFLAG_MMIO) { | 287 | if (hwif->host_flags & IDE_HFLAG_MMIO) { |
281 | dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); | 288 | dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); |
282 | /* start DMA */ | 289 | writeb(dma_cmd | ATA_DMA_START, |
283 | writeb(dma_cmd | 1, | ||
284 | (void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); | 290 | (void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); |
285 | } else { | 291 | } else { |
286 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); | 292 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); |
287 | outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD); | 293 | outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD); |
288 | } | 294 | } |
289 | 295 | ||
290 | wmb(); | 296 | wmb(); |
@@ -295,37 +301,35 @@ EXPORT_SYMBOL_GPL(ide_dma_start); | |||
295 | int ide_dma_end(ide_drive_t *drive) | 301 | int ide_dma_end(ide_drive_t *drive) |
296 | { | 302 | { |
297 | ide_hwif_t *hwif = drive->hwif; | 303 | ide_hwif_t *hwif = drive->hwif; |
298 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 304 | u8 dma_stat = 0, dma_cmd = 0, mask; |
299 | u8 dma_stat = 0, dma_cmd = 0; | ||
300 | 305 | ||
301 | drive->waiting_for_dma = 0; | 306 | drive->waiting_for_dma = 0; |
302 | 307 | ||
303 | if (mmio) { | 308 | /* stop DMA */ |
304 | /* get DMA command mode */ | 309 | if (hwif->host_flags & IDE_HFLAG_MMIO) { |
305 | dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); | 310 | dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); |
306 | /* stop DMA */ | 311 | writeb(dma_cmd & ~ATA_DMA_START, |
307 | writeb(dma_cmd & ~1, | ||
308 | (void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); | 312 | (void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); |
309 | } else { | 313 | } else { |
310 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); | 314 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); |
311 | outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); | 315 | outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD); |
312 | } | 316 | } |
313 | 317 | ||
314 | /* get DMA status */ | 318 | /* get DMA status */ |
315 | dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); | 319 | dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); |
316 | 320 | ||
317 | if (mmio) | 321 | /* clear INTR & ERROR bits */ |
318 | /* clear the INTR & ERROR bits */ | 322 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); |
319 | writeb(dma_stat | 6, | ||
320 | (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)); | ||
321 | else | ||
322 | outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS); | ||
323 | 323 | ||
324 | /* purge DMA mappings */ | 324 | /* purge DMA mappings */ |
325 | ide_destroy_dmatable(drive); | 325 | ide_destroy_dmatable(drive); |
326 | /* verify good DMA status */ | ||
327 | wmb(); | 326 | wmb(); |
328 | return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; | 327 | |
328 | /* verify good DMA status */ | ||
329 | mask = ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR; | ||
330 | if ((dma_stat & mask) != ATA_DMA_INTR) | ||
331 | return 0x10 | dma_stat; | ||
332 | return 0; | ||
329 | } | 333 | } |
330 | EXPORT_SYMBOL_GPL(ide_dma_end); | 334 | EXPORT_SYMBOL_GPL(ide_dma_end); |
331 | 335 | ||
@@ -333,13 +337,9 @@ EXPORT_SYMBOL_GPL(ide_dma_end); | |||
333 | int ide_dma_test_irq(ide_drive_t *drive) | 337 | int ide_dma_test_irq(ide_drive_t *drive) |
334 | { | 338 | { |
335 | ide_hwif_t *hwif = drive->hwif; | 339 | ide_hwif_t *hwif = drive->hwif; |
336 | u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif); | 340 | u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); |
337 | 341 | ||
338 | /* return 1 if INTR asserted */ | 342 | return (dma_stat & ATA_DMA_INTR) ? 1 : 0; |
339 | if ((dma_stat & 4) == 4) | ||
340 | return 1; | ||
341 | |||
342 | return 0; | ||
343 | } | 343 | } |
344 | EXPORT_SYMBOL_GPL(ide_dma_test_irq); | 344 | EXPORT_SYMBOL_GPL(ide_dma_test_irq); |
345 | 345 | ||
@@ -352,5 +352,6 @@ const struct ide_dma_ops sff_dma_ops = { | |||
352 | .dma_test_irq = ide_dma_test_irq, | 352 | .dma_test_irq = ide_dma_test_irq, |
353 | .dma_timeout = ide_dma_timeout, | 353 | .dma_timeout = ide_dma_timeout, |
354 | .dma_lost_irq = ide_dma_lost_irq, | 354 | .dma_lost_irq = ide_dma_lost_irq, |
355 | .dma_sff_read_status = ide_dma_sff_read_status, | ||
355 | }; | 356 | }; |
356 | EXPORT_SYMBOL_GPL(sff_dma_ops); | 357 | EXPORT_SYMBOL_GPL(sff_dma_ops); |