Fixed capitalisation typo.
[AROS.git] / rom / devs / ata / dma_generic.c
blob357e553ecfe69096c51120dd041aa9e9b75b2eda
1 /*
2 Copyright © 2004-2011, The AROS Development Team. All rights reserved
3 $Id$
5 Desc:
6 Lang: English
7 */
8 /*
9 * PARTIAL 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
24 * 2011-05-19 P. Fedin The Big rework. Separated bus-specific code. Made 64-bit-friendly.
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 no one
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 LONG dma_Setup(APTR addr, ULONG len, BOOL read, struct PRDEntry* array)
46 ULONG tmp = 0, rem = 0;
47 ULONG flg = read ? DMA_ReadFromRAM : 0;
48 IPTR phy_mem;
49 LONG items = 0;
51 D(bug("[ATA ] dma_Setup(addr %p, len %d, PRDEntry @ %p for %s)\n", addr, len, array, read ? "READ" : "WRITE"));
54 * in future you may have to put this in prd construction procedure
56 while (0 < len)
58 tmp = len;
59 phy_mem = (IPTR)CachePreDMA(addr, &tmp, flg);
61 D(bug("[ATA ] dma_Setup: Translating V:%p > P:%p (%ld bytes)\n", addr, phy_mem, tmp));
63 * update all addresses for the next call
65 addr = &((UBYTE*)addr)[tmp];
66 len -= tmp;
67 flg |= DMA_Continue;
69 /*
70 * check if we're crossing the magic 64k boundary:
72 while (0 < tmp)
75 * politely say what sucks
77 if (phy_mem > 0xffffffffull)
79 bug("[ATA ] dma_Setup: ERROR: ATA DMA POINTERS BEYOND MAXIMUM ALLOWED ADDRESS!\n");
80 return 0;
82 if (items > PRD_MAX)
84 bug("[ATA ] dma_Setup: ERROR: ATA DMA PRD TABLE SIZE TOO LARGE\n");
85 return 0;
89 * calculate remainder and see if it is larger of the current memory block.
90 * if smaller, adjust its size.
92 rem = 0x10000 - (phy_mem & 0xffff);
93 if (rem > tmp)
94 rem = tmp;
96 * update PRD with address and remainder
98 D(bug("[ATA ] dma_Setup: Inserting into PRD Table: %p / %ld @ %p\n", phy_mem, rem, array));
99 array->prde_Address = AROS_LONG2LE(phy_mem);
100 array->prde_Length = AROS_LONG2LE((rem & 0xffff));
101 ++array;
102 ++items;
105 * update locals ;-)
107 phy_mem += rem;
108 tmp -= rem;
112 if (items > 0)
114 --array;
115 array->prde_Length |= AROS_LONG2LE(PRDE_EOT);
117 D(bug("[ATA ] dma_Setup: PRD Table set - %ld items in total.\n", items));
120 * PRD table all set.
122 return items;
126 BOOL dma_SetupPRD(struct ata_Unit *unit, APTR buffer, ULONG sectors, BOOL io)
128 return dma_SetupPRDSize(unit, buffer, sectors << unit->au_SectorShift, io);
131 BOOL dma_SetupPRDSize(struct ata_Unit *unit, APTR buffer, ULONG size, BOOL read)
133 LONG items = 0;
134 IPTR prd_phys;
135 ULONG length;
137 D(bug("[ATA%02ld] dma_SetupPRDSize(buffer @ %p, %ld bytes, PRD @ %x for %s)\n", unit->au_UnitNum, buffer, size, unit->au_Bus->ab_PRD, read ? "READ" : "WRITE"));
139 items = dma_Setup(buffer, size, read, unit->au_Bus->ab_PRD);
141 if (0 == items)
142 return FALSE;
144 length = items * sizeof(struct PRDEntry);
146 prd_phys = (IPTR)CachePreDMA(unit->au_Bus->ab_PRD, &length, DMA_ReadFromRAM);
148 ATA_OUTL(prd_phys, dma_PRD, unit->au_DMAPort);
150 if (read)
151 ATA_OUT(DMA_WRITE, dma_Command, unit->au_DMAPort); /* inverse logic */
152 else
153 ATA_OUT(DMA_READ, dma_Command, unit->au_DMAPort);
154 return TRUE;
157 VOID dma_Cleanup(APTR addr, ULONG len, BOOL read)
159 ULONG tmp = 0;
160 ULONG flg = read ? DMA_ReadFromRAM : 0;
162 D(bug("[ATA ] dma_Cleanup(%p, %d bytes)\n", addr, len));
164 while (len > 0)
166 tmp = len;
167 CachePostDMA(addr, &tmp, flg);
168 addr = &((UBYTE*)addr)[tmp];
169 len -= tmp;
170 flg |= DMA_Continue;
174 VOID dma_StartDMA(struct ata_Unit *unit)
176 D(bug("[ATA%02ld] dma_StartDMA()\n", unit->au_UnitNum));
177 ATA_OUT(ATA_IN(dma_Command, unit->au_DMAPort) | DMA_START, dma_Command, unit->au_DMAPort);
180 VOID dma_StopDMA(struct ata_Unit *unit)
182 D(bug("[ATA%02ld] dma_StopDMA()\n", unit->au_UnitNum));
183 ATA_OUT(ATA_IN(dma_Command, unit->au_DMAPort) & ~DMA_START, dma_Command, unit->au_DMAPort);