2 Copyright © 2004-2011, 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
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>
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
));
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
)
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
);
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
);
151 ATA_OUT(DMA_WRITE
, dma_Command
, unit
->au_DMAPort
); /* inverse logic */
153 ATA_OUT(DMA_READ
, dma_Command
, unit
->au_DMAPort
);
157 VOID
dma_Cleanup(APTR addr
, ULONG len
, BOOL read
)
160 ULONG flg
= read
? DMA_ReadFromRAM
: 0;
162 D(bug("[ATA ] dma_Cleanup(%p, %d bytes)\n", addr
, len
));
167 CachePostDMA(addr
, &tmp
, flg
);
168 addr
= &((UBYTE
*)addr
)[tmp
];
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
);