2 Copyright © 2004-2009, The AROS Development Team. All rights reserved
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
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>
35 #include <proto/exec.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;
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
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
];
70 * check if we're crossing the magic 64k boundary:
75 * politely say what sucks
77 if (phy_mem
> 0xffffffffull
)
79 bug("[ATA ] dma_Setup: ERROR: ATA DMA POINTERS BEYOND MAXIMUM ALLOWED ADDRESS!\n");
84 bug("[ATA ] dma_Setup: ERROR: ATA DMA PRD TABLE SIZE TOO LARGE\n");
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);
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));
115 array
->prde_Length
|= AROS_LONG2LE(PRDE_EOT
);
117 D(bug("[ATA ] dma_Setup: PRD Table set - %ld items in total.\n", items
));
125 BOOL
dma_SetupPRD(struct ata_Unit
*unit
, APTR buffer
, ULONG sectors
, BOOL io
)
127 return dma_SetupPRDSize(unit
, buffer
, sectors
<< unit
->au_SectorShift
, io
);
130 BOOL
dma_SetupPRDSize(struct ata_Unit
*unit
, APTR buffer
, ULONG size
, BOOL read
)
134 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"));
136 items
= dma_Setup(buffer
, size
, read
, unit
->au_Bus
->ab_PRD
);
141 CacheClearE(unit
->au_Bus
->ab_PRD
, items
* sizeof(struct PRDEntry
), CACRF_ClearD
);
143 ata_outl((ULONG
)unit
->au_Bus
->ab_PRD
, dma_PRD
, unit
->au_DMAPort
);
146 ata_out(DMA_WRITE
, dma_Command
, unit
->au_DMAPort
); /* inverse logic */
148 ata_out(DMA_READ
, dma_Command
, unit
->au_DMAPort
);
152 VOID
dma_Cleanup(APTR addr
, ULONG len
, BOOL read
)
155 ULONG flg
= read
? DMA_ReadFromRAM
: 0;
157 D(bug("[ATA ] dma_Cleanup(%p, %d bytes)\n", addr
, len
));
162 CachePostDMA(addr
, &tmp
, flg
);
163 addr
= &((UBYTE
*)addr
)[tmp
];
169 VOID
dma_StartDMA(struct ata_Unit
*unit
)
171 D(bug("[ATA%02ld] dma_StartDMA()\n", unit
->au_UnitNum
));
172 ata_out(ata_in(dma_Command
, unit
->au_DMAPort
) | DMA_START
, dma_Command
, unit
->au_DMAPort
);
175 VOID
dma_StopDMA(struct ata_Unit
*unit
)
177 D(bug("[ATA%02ld] dma_StopDMA()\n", unit
->au_UnitNum
));
178 ata_out(ata_in(dma_Command
, unit
->au_DMAPort
) & ~DMA_START
, dma_Command
, unit
->au_DMAPort
);