revert between 56095 -> 55830 in arch
[AROS.git] / rom / hidds / ata_pci / interface_dma.c
blob4f1857ae5d415bc0910dd8111b478c3268f585af
1 /*
2 Copyright © 2004-2018, The AROS Development Team. All rights reserved
3 $Id$
5 Desc: Generic PCI-DMA ATA controller driver
6 Lang: English
7 */
9 #include <aros/debug.h>
11 #include <proto/exec.h>
13 /* We want all other bases obtained from our base */
14 #define __NOLIBBASE__
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;
30 LONG items = 0;
31 IPTR phy_mem;
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
38 while (0 < len)
40 tmp = len;
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];
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 || (phy_mem + tmp) > 0xffffffffull)
61 D(bug("[ATA:PCI] dma_Setup: ERROR: ATA DMA POINTERS BEYOND MAXIMUM ALLOWED ADDRESS!\n"));
62 return 0;
64 if (items > PRD_MAX)
66 D(bug("[ATA:PCI] 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: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));
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:PCI] dma_Setup: PRD Table set - %u items in total.\n", items));
102 * PRD table all set.
104 return items;
107 BOOL dma_SetupPRDSize(struct dma_data *unit, APTR buffer, IPTR size, BOOL read)
109 LONG items = 0;
110 IPTR prd_phys;
111 volatile ULONG length;
113 items = dma_Setup(buffer, size, read, unit->ab_PRD);
115 if (0 == items)
116 return FALSE;
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 */
125 return TRUE;
128 void dma_Cleanup(struct dma_data *unit, APTR addr, IPTR len, BOOL read)
130 volatile ULONG tmp;
131 ULONG flg;
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;
138 while (len > 0)
140 tmp = len;
141 CachePostDMA(addr, (ULONG *)&tmp, flg);
142 addr = &((UBYTE*)addr)[tmp];
143 len -= tmp;
144 flg |= DMA_Continue;
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[]=
164 dma_SetupPRDSize,
165 dma_StartDMA,
166 dma_Cleanup,
167 dma_CheckErr,
168 (APTR)-1