Added 'Resident' field to ensure that the handler is included in the
[AROS.git] / rom / devs / ata / dma_generic.c
blobd3a70ea7060646df20d4bef081474c3f17407e30
1 /*
2 Copyright © 2004-2012, The AROS Development Team. All rights reserved
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include <aros/debug.h>
11 #include <exec/types.h>
12 #include <exec/exec.h>
13 #include <exec/resident.h>
14 #include <utility/utility.h>
15 #include <dos/bptr.h>
17 #include <proto/exec.h>
19 #include "ata.h"
22 Prepare PRD entries for sectors transfer. This function assumes that no one
23 else will even touch PRD. It should be however truth, as for given bus all
24 ATA accesses are protected with a semaphore.
26 LONG dma_Setup(APTR addr, ULONG len, BOOL read, struct PRDEntry* array)
28 ULONG tmp = 0, rem = 0;
29 ULONG flg = read ? DMA_ReadFromRAM : 0;
30 IPTR phy_mem;
31 LONG items = 0;
33 D(bug("[ATA ] dma_Setup(addr %p, len %d, PRDEntry @ %p for %s)\n", addr, len, array, read ? "READ" : "WRITE"));
36 * in future you may have to put this in prd construction procedure
38 while (0 < len)
40 tmp = len;
41 phy_mem = (IPTR)CachePreDMA(addr, &tmp, flg);
43 D(bug("[ATA ] dma_Setup: Translating V:%p > P:%p (%ld bytes)\n", addr, phy_mem, tmp));
45 * update all addresses for the next call
47 addr = &((UBYTE*)addr)[tmp];
48 len -= tmp;
49 flg |= DMA_Continue;
51 /*
52 * check if we're crossing the magic 64k boundary:
54 while (0 < tmp)
57 * politely say what sucks
59 if (phy_mem > 0xffffffffull)
61 bug("[ATA ] dma_Setup: ERROR: ATA DMA POINTERS BEYOND MAXIMUM ALLOWED ADDRESS!\n");
62 return 0;
64 if (items > PRD_MAX)
66 bug("[ATA ] dma_Setup: ERROR: ATA DMA PRD TABLE SIZE TOO LARGE\n");
67 return 0;
71 * calculate remainder and see if it is larger of the current memory block.
72 * if smaller, adjust its size.
74 rem = 0x10000 - (phy_mem & 0xffff);
75 if (rem > tmp)
76 rem = tmp;
78 * update PRD with address and remainder
80 D(bug("[ATA ] dma_Setup: Inserting into PRD Table: %p / %ld @ %p\n", phy_mem, rem, array));
81 array->prde_Address = AROS_LONG2LE(phy_mem);
82 array->prde_Length = AROS_LONG2LE((rem & 0xffff));
83 ++array;
84 ++items;
87 * update locals ;-)
89 phy_mem += rem;
90 tmp -= rem;
94 if (items > 0)
96 --array;
97 array->prde_Length |= AROS_LONG2LE(PRDE_EOT);
99 D(bug("[ATA ] dma_Setup: PRD Table set - %ld items in total.\n", items));
102 * PRD table all set.
104 return items;
108 BOOL dma_SetupPRD(struct ata_Unit *unit, APTR buffer, ULONG sectors, BOOL io)
110 return dma_SetupPRDSize(unit, buffer, sectors << unit->au_SectorShift, io);
113 BOOL dma_SetupPRDSize(struct ata_Unit *unit, APTR buffer, ULONG size, BOOL read)
115 LONG items = 0;
116 IPTR prd_phys;
117 ULONG length;
119 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"));
121 items = dma_Setup(buffer, size, read, unit->au_Bus->ab_PRD);
123 if (0 == items)
124 return FALSE;
126 length = items * sizeof(struct PRDEntry);
128 prd_phys = (IPTR)CachePreDMA(unit->au_Bus->ab_PRD, &length, DMA_ReadFromRAM);
130 ATA_OUTL(prd_phys, dma_PRD, unit->au_DMAPort);
132 if (read)
133 ATA_OUT(DMA_WRITE, dma_Command, unit->au_DMAPort); /* inverse logic */
134 else
135 ATA_OUT(DMA_READ, dma_Command, unit->au_DMAPort);
136 return TRUE;
139 VOID dma_Cleanup(APTR addr, ULONG len, BOOL read)
141 ULONG tmp = 0;
142 ULONG flg = read ? DMA_ReadFromRAM : 0;
144 D(bug("[ATA ] dma_Cleanup(%p, %d bytes)\n", addr, len));
146 while (len > 0)
148 tmp = len;
149 CachePostDMA(addr, &tmp, flg);
150 addr = &((UBYTE*)addr)[tmp];
151 len -= tmp;
152 flg |= DMA_Continue;
156 VOID dma_StartDMA(struct ata_Unit *unit)
158 D(bug("[ATA%02ld] dma_StartDMA()\n", unit->au_UnitNum));
159 ATA_OUT(ATA_IN(dma_Command, unit->au_DMAPort) | DMA_START, dma_Command, unit->au_DMAPort);
162 VOID dma_StopDMA(struct ata_Unit *unit)
164 D(bug("[ATA%02ld] dma_StopDMA()\n", unit->au_UnitNum));
165 ATA_OUT(ATA_IN(dma_Command, unit->au_DMAPort) & ~DMA_START, dma_Command, unit->au_DMAPort);