2 Copyright © 2004-2013, The AROS Development Team. All rights reserved
5 Desc: Generic PCI-DMA ATA controller driver
9 #include <aros/debug.h>
10 #include <devices/scsidisk.h>
11 #include <exec/exec.h>
12 #include <proto/exec.h>
14 #include "interface_dma.h"
17 * Prepare PRD entries for sectors transfer. This function assumes that no one
18 * else will even touch PRD. It should be however truth, as for given bus all
19 * ATA accesses are protected with a semaphore.
21 static LONG
dma_Setup(APTR addr
, ULONG len
, BOOL read
, struct PRDEntry
* array
)
23 ULONG tmp
= 0, rem
= 0;
24 ULONG flg
= read
? DMA_ReadFromRAM
: 0;
28 D(bug("[PCI-ATA] dma_Setup(addr %p, len %d, PRDEntry @ %p for %s)\n", addr
, len
, array
, read
? "READ" : "WRITE"));
31 * in future you may have to put this in prd construction procedure
36 phy_mem
= (IPTR
)CachePreDMA(addr
, &tmp
, flg
);
38 D(bug("[PCI-ATA] dma_Setup: Translating V:%p > P:%p (%ld bytes)\n", addr
, phy_mem
, tmp
));
40 * update all addresses for the next call
42 addr
= &((UBYTE
*)addr
)[tmp
];
47 * check if we're crossing the magic 64k boundary:
52 * politely say what sucks
54 if (phy_mem
> 0xffffffffull
)
56 D(bug("[PCI-ATA] dma_Setup: ERROR: ATA DMA POINTERS BEYOND MAXIMUM ALLOWED ADDRESS!\n"));
61 D(bug("[PCI-ATA] dma_Setup: ERROR: ATA DMA PRD TABLE SIZE TOO LARGE\n"));
66 * calculate remainder and see if it is larger of the current memory block.
67 * if smaller, adjust its size.
69 rem
= 0x10000 - (phy_mem
& 0xffff);
73 * update PRD with address and remainder
75 D(bug("[PCI-ATA] dma_Setup: Inserting into PRD Table: %p / %d @ %p\n", phy_mem
, rem
, array
));
76 array
->prde_Address
= AROS_LONG2LE(phy_mem
);
77 array
->prde_Length
= AROS_LONG2LE((rem
& 0xffff));
92 array
->prde_Length
|= AROS_LONG2LE(PRDE_EOT
);
94 D(bug("[PCI-ATA] dma_Setup: PRD Table set - %u items in total.\n", items
));
102 BOOL
dma_SetupPRDSize(struct dma_data
*unit
, APTR buffer
, IPTR size
, BOOL read
)
108 items
= dma_Setup(buffer
, size
, read
, unit
->ab_PRD
);
113 length
= items
* sizeof(struct PRDEntry
);
115 prd_phys
= (IPTR
)CachePreDMA(unit
->ab_PRD
, &length
, DMA_ReadFromRAM
);
117 outl(prd_phys
, dma_PRD
+ unit
->au_DMAPort
);
118 outb(read
? DMA_WRITE
: DMA_READ
, dma_Command
+ unit
->au_DMAPort
); /* inverse logic */
123 void dma_Cleanup(struct dma_data
*unit
, APTR addr
, IPTR len
, BOOL read
)
126 port_t port
= dma_Command
+ unit
->au_DMAPort
;
128 /* Stop DMA engine */
129 outb(inb(port
) & ~DMA_START
, port
);
131 flg
= read
? DMA_ReadFromRAM
: 0;
135 CachePostDMA(addr
, &tmp
, flg
);
136 addr
= &((UBYTE
*)addr
)[tmp
];
142 VOID
dma_StartDMA(struct dma_data
*unit
)
144 port_t port
= dma_Command
+ unit
->au_DMAPort
;
146 outb(inb(port
) | DMA_START
, port
);
149 ULONG
dma_CheckErr(struct dma_data
*unit
)
151 UBYTE stat
= inb(dma_Status
+ unit
->au_DMAPort
);
153 return (stat
& DMAF_Error
) ? HFERR_DMA
: 0;
156 const APTR dma_FuncTable
[]=