2 Copyright © 2004-2018, The AROS Development Team. All rights reserved
5 Desc: Generic PCI-DMA ATA controller driver
9 #include <aros/debug.h>
11 #include <proto/exec.h>
13 /* We want all other bases obtained from our base */
16 #include <devices/scsidisk.h>
17 #include <exec/exec.h>
19 #include "interface_dma.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 static LONG
dma_Setup(APTR addr
, ULONG len
, BOOL read
, struct PRDEntry
* array
)
28 ULONG rem
= 0, flg
= read
? DMA_ReadFromRAM
: 0;
29 volatile ULONG tmp
= 0;
33 D(bug("[ATA:PCI] 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
41 phy_mem
= (IPTR
)CachePreDMA(addr
, (ULONG
*)&tmp
, flg
);
43 D(bug("[ATA:PCI] 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
];
52 * check if we're crossing the magic 64k boundary:
57 * politely say what sucks
59 if (phy_mem
> 0xffffffffull
|| (phy_mem
+ tmp
) > 0xffffffffull
)
61 D(bug("[ATA:PCI] dma_Setup: ERROR: ATA DMA POINTERS BEYOND MAXIMUM ALLOWED ADDRESS!\n"));
66 D(bug("[ATA:PCI] dma_Setup: ERROR: ATA DMA PRD TABLE SIZE TOO LARGE\n"));
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);
78 * update PRD with address and remainder
80 D(bug("[ATA:PCI] dma_Setup: Inserting into PRD Table: %p / %d @ %p\n", phy_mem
, rem
, array
));
81 array
->prde_Address
= AROS_LONG2LE(phy_mem
);
82 array
->prde_Length
= AROS_LONG2LE((rem
& 0xffff));
97 array
->prde_Length
|= AROS_LONG2LE(PRDE_EOT
);
99 D(bug("[ATA:PCI] dma_Setup: PRD Table set - %u items in total.\n", items
));
107 BOOL
dma_SetupPRDSize(struct dma_data
*unit
, APTR buffer
, IPTR size
, BOOL read
)
111 volatile ULONG length
;
113 items
= dma_Setup(buffer
, size
, read
, unit
->ab_PRD
);
118 length
= items
* sizeof(struct PRDEntry
);
120 prd_phys
= (IPTR
)CachePreDMA(unit
->ab_PRD
, (ULONG
*)&length
, DMA_ReadFromRAM
);
122 outl(prd_phys
, dma_PRD
+ unit
->au_DMAPort
);
123 outb(read
? DMA_WRITE
: DMA_READ
, dma_Command
+ unit
->au_DMAPort
); /* inverse logic */
128 void dma_Cleanup(struct dma_data
*unit
, APTR addr
, IPTR len
, BOOL read
)
132 port_t port
= dma_Command
+ unit
->au_DMAPort
;
134 /* Stop DMA engine */
135 outb(inb(port
) & ~DMA_START
, port
);
137 flg
= read
? DMA_ReadFromRAM
: 0;
141 CachePostDMA(addr
, (ULONG
*)&tmp
, flg
);
142 addr
= &((UBYTE
*)addr
)[tmp
];
148 VOID
dma_StartDMA(struct dma_data
*unit
)
150 port_t port
= dma_Command
+ unit
->au_DMAPort
;
152 outb(inb(port
) | DMA_START
, port
);
155 ULONG
dma_CheckErr(struct dma_data
*unit
)
157 UBYTE stat
= inb(dma_Status
+ unit
->au_DMAPort
);
159 return (stat
& DMAF_Error
) ? HFERR_DMA
: 0;
162 const APTR dma_FuncTable
[]=