diff options
-rw-r--r-- | drivers/ide/pci/scc_pata.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index a17f73ec577a..144938188325 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c | |||
@@ -260,6 +260,20 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed) | |||
260 | out_be32((void __iomem *)udenvt_port, reg); | 260 | out_be32((void __iomem *)udenvt_port, reg); |
261 | } | 261 | } |
262 | 262 | ||
263 | static void scc_dma_host_set(ide_drive_t *drive, int on) | ||
264 | { | ||
265 | ide_hwif_t *hwif = drive->hwif; | ||
266 | u8 unit = (drive->select.b.unit & 0x01); | ||
267 | u8 dma_stat = scc_ide_inb(hwif->dma_status); | ||
268 | |||
269 | if (on) | ||
270 | dma_stat |= (1 << (5 + unit)); | ||
271 | else | ||
272 | dma_stat &= ~(1 << (5 + unit)); | ||
273 | |||
274 | scc_ide_outb(dma_stat, hwif->dma_status); | ||
275 | } | ||
276 | |||
263 | /** | 277 | /** |
264 | * scc_ide_dma_setup - begin a DMA phase | 278 | * scc_ide_dma_setup - begin a DMA phase |
265 | * @drive: target device | 279 | * @drive: target device |
@@ -304,13 +318,45 @@ static int scc_dma_setup(ide_drive_t *drive) | |||
304 | return 0; | 318 | return 0; |
305 | } | 319 | } |
306 | 320 | ||
321 | static void scc_dma_start(ide_drive_t *drive) | ||
322 | { | ||
323 | ide_hwif_t *hwif = drive->hwif; | ||
324 | u8 dma_cmd = scc_ide_inb(hwif->dma_command); | ||
325 | |||
326 | /* start DMA */ | ||
327 | scc_ide_outb(dma_cmd | 1, hwif->dma_command); | ||
328 | hwif->dma = 1; | ||
329 | wmb(); | ||
330 | } | ||
331 | |||
332 | static int __scc_dma_end(ide_drive_t *drive) | ||
333 | { | ||
334 | ide_hwif_t *hwif = drive->hwif; | ||
335 | u8 dma_stat, dma_cmd; | ||
336 | |||
337 | drive->waiting_for_dma = 0; | ||
338 | /* get DMA command mode */ | ||
339 | dma_cmd = scc_ide_inb(hwif->dma_command); | ||
340 | /* stop DMA */ | ||
341 | scc_ide_outb(dma_cmd & ~1, hwif->dma_command); | ||
342 | /* get DMA status */ | ||
343 | dma_stat = scc_ide_inb(hwif->dma_status); | ||
344 | /* clear the INTR & ERROR bits */ | ||
345 | scc_ide_outb(dma_stat | 6, hwif->dma_status); | ||
346 | /* purge DMA mappings */ | ||
347 | ide_destroy_dmatable(drive); | ||
348 | /* verify good DMA status */ | ||
349 | hwif->dma = 0; | ||
350 | wmb(); | ||
351 | return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; | ||
352 | } | ||
307 | 353 | ||
308 | /** | 354 | /** |
309 | * scc_dma_end - Stop DMA | 355 | * scc_dma_end - Stop DMA |
310 | * @drive: IDE drive | 356 | * @drive: IDE drive |
311 | * | 357 | * |
312 | * Check and clear INT Status register. | 358 | * Check and clear INT Status register. |
313 | * Then call __ide_dma_end(). | 359 | * Then call __scc_dma_end(). |
314 | */ | 360 | */ |
315 | 361 | ||
316 | static int scc_dma_end(ide_drive_t *drive) | 362 | static int scc_dma_end(ide_drive_t *drive) |
@@ -414,7 +460,7 @@ static int scc_dma_end(ide_drive_t *drive) | |||
414 | break; | 460 | break; |
415 | } | 461 | } |
416 | 462 | ||
417 | dma_stat = __ide_dma_end(drive); | 463 | dma_stat = __scc_dma_end(drive); |
418 | if (data_loss) | 464 | if (data_loss) |
419 | dma_stat |= 2; /* emulate DMA error (to retry command) */ | 465 | dma_stat |= 2; /* emulate DMA error (to retry command) */ |
420 | return dma_stat; | 466 | return dma_stat; |
@@ -811,10 +857,10 @@ static const struct ide_port_ops scc_port_ops = { | |||
811 | }; | 857 | }; |
812 | 858 | ||
813 | static const struct ide_dma_ops scc_dma_ops = { | 859 | static const struct ide_dma_ops scc_dma_ops = { |
814 | .dma_host_set = ide_dma_host_set, | 860 | .dma_host_set = scc_dma_host_set, |
815 | .dma_setup = scc_dma_setup, | 861 | .dma_setup = scc_dma_setup, |
816 | .dma_exec_cmd = ide_dma_exec_cmd, | 862 | .dma_exec_cmd = ide_dma_exec_cmd, |
817 | .dma_start = ide_dma_start, | 863 | .dma_start = scc_dma_start, |
818 | .dma_end = scc_dma_end, | 864 | .dma_end = scc_dma_end, |
819 | .dma_test_irq = scc_dma_test_irq, | 865 | .dma_test_irq = scc_dma_test_irq, |
820 | .dma_lost_irq = ide_dma_lost_irq, | 866 | .dma_lost_irq = ide_dma_lost_irq, |