make the linux-ppc packags be in synch with other platforms
[tangerine.git] / arch / common / ata.device / dma_generic.c
blob2552d9c0d3540f43303196593f1106e3d4f4da06
1 /*
2 Copyright © 2004-2006, The AROS Development Team. All rights reserved
3 $Id$
5 Desc:
6 Lang: English
7 */
8 /*
9 * CHANGELOG:
10 * DATE NAME ENTRY
11 * ---------- ------------------ -------------------------------------------------------------------
12 * 2008-01-25 T. Wiszkowski Rebuilt, rearranged and partially fixed 60% of the code here
13 * Enabled implementation to scan for other PCI IDE controllers
14 * Implemented ATAPI Packet Support for both read and write
15 * Corrected ATAPI DMA handling
16 * Fixed major IDE enumeration bugs severely handicapping transfers with more than one controller
17 * Compacted source and implemented major ATA support procedure
18 * Improved DMA and Interrupt management
19 * Removed obsolete code
20 * 2008-04-03 M. Schulz inb, outb and outl are not used directly anymore. Instead, the ata_* macros are taken.
21 * PRD should be set in little endian mode up (at least I guess so...)
22 * 2008-04-07 M. Schulz Once PRD is ready one has to clear data caches. PRD might still be in cache only on
23 * writeback systems otherwise
26 #define DEBUG 0
27 #include <aros/debug.h>
29 #include <exec/types.h>
30 #include <exec/exec.h>
31 #include <exec/resident.h>
32 #include <utility/utility.h>
33 #include <dos/bptr.h>
35 #include <proto/exec.h>
37 #include "ata.h"
40 Prepare PRD entries for sectors transfer. This function assumes, that noone
41 else will even touch PRD. It should be however truth, as for given bus all
42 ATA accesses are protected with a semaphore.
44 VOID dma_SetupPRD(struct ata_Unit *unit, APTR buffer, ULONG sectors, BOOL io)
46 dma_SetupPRDSize(unit, buffer, sectors << unit->au_SectorShift, io);
49 VOID dma_SetupPRDSize(struct ata_Unit *unit, APTR buffer, ULONG size, BOOL io)
51 struct PRDEntry *prd = unit->au_Bus->ab_PRD;
52 IPTR ptr = (IPTR)buffer;
53 int i;
55 D(bug("[DMA] Setup PRD for %d bytes at %x\n",
56 size, ptr));
58 /*
59 The first PRD address is the buffer pointer self, doesn't have to be
60 aligned to 64K boundary
62 prd[0].prde_Address = AROS_LONG2LE(ptr);
65 All other PRD addresses are the next 64K pages, until the page address
66 is bigger as the highest address used
68 for (i=1; i < PRD_MAX; i++)
70 prd[i].prde_Address = AROS_LONG2LE((AROS_LE2LONG(prd[i-1].prde_Address) & 0xffff0000) + 0x00010000);
71 prd[i].prde_Length = 0;
72 if (AROS_LE2LONG(prd[i].prde_Address) > ptr + size)
73 break;
76 if (size <= AROS_LE2LONG(prd[1].prde_Address) - AROS_LE2LONG(prd[0].prde_Address))
78 prd[0].prde_Length = AROS_LONG2LE(size);
79 size = 0;
81 else
83 prd[0].prde_Length = AROS_LONG2LE(AROS_LE2LONG(prd[1].prde_Address) - AROS_LE2LONG(prd[0].prde_Address));
84 size -= AROS_LE2LONG(prd[0].prde_Length);
87 prd[0].prde_Length &= AROS_LONG2LE(0x0000ffff);
89 i = 1;
91 while(size >= 65536)
93 prd[i].prde_Length = 0; /* 64KB in one PRD */
94 size -= 65536;
95 i++;
98 if (size > 0)
100 prd[i].prde_Length = AROS_LONG2LE(size);
101 i++;
104 prd[i-1].prde_Length |= AROS_LONG2LE(0x80000000);
106 CacheClearE(&prd[0], (i) * sizeof(struct PRDEntry), CACRF_ClearD);
108 ata_outl((ULONG)prd, dma_PRD, unit->au_DMAPort);
109 ata_out(ata_in(dma_Status, unit->au_DMAPort) | DMAF_Error | DMAF_Interrupt, dma_Status, unit->au_DMAPort);
112 If io set to TRUE, then sectors are read, when set to FALSE, they are written
114 if (io)
115 ata_out(DMA_WRITE, dma_Command, unit->au_DMAPort);
116 else
117 ata_out(DMA_READ, dma_Command, unit->au_DMAPort);
120 VOID dma_StartDMA(struct ata_Unit *unit)
122 ata_in(dma_Command, unit->au_DMAPort);
123 ata_in(dma_Status, unit->au_DMAPort);
124 ata_out(ata_in(dma_Command, unit->au_DMAPort) | DMA_START, dma_Command, unit->au_DMAPort);
125 ata_in(dma_Command, unit->au_DMAPort);
126 ata_in(dma_Status, unit->au_DMAPort);
129 VOID dma_StopDMA(struct ata_Unit *unit)
131 ata_in(dma_Command, unit->au_DMAPort);
132 ata_in(dma_Status, unit->au_DMAPort);
133 ata_out(ata_in(dma_Command, unit->au_DMAPort) & ~DMA_START, dma_Command, unit->au_DMAPort);
134 ata_in(dma_Command, unit->au_DMAPort);
135 ata_in(dma_Status, unit->au_DMAPort);
136 ata_out(ata_in(dma_Status, unit->au_DMAPort) | DMAF_Error | DMAF_Interrupt, dma_Status, unit->au_DMAPort);