- Define structure pointer to NULL to make the compiler happy
[AROS.git] / rom / hidds / ata_pci / interface_dma.c
blobc1170f748b932aba02222db60cfe21e863f31738
1 /*
2 Copyright © 2004-2013, 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>
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;
25 IPTR phy_mem;
26 LONG items = 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
33 while (0 < len)
35 tmp = len;
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];
43 len -= tmp;
44 flg |= DMA_Continue;
46 /*
47 * check if we're crossing the magic 64k boundary:
49 while (0 < tmp)
52 * politely say what sucks
54 if (phy_mem > 0xffffffffull || (phy_mem + tmp) > 0xffffffffull)
56 D(bug("[PCI-ATA] dma_Setup: ERROR: ATA DMA POINTERS BEYOND MAXIMUM ALLOWED ADDRESS!\n"));
57 return 0;
59 if (items > PRD_MAX)
61 D(bug("[PCI-ATA] dma_Setup: ERROR: ATA DMA PRD TABLE SIZE TOO LARGE\n"));
62 return 0;
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);
70 if (rem > tmp)
71 rem = tmp;
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));
78 ++array;
79 ++items;
82 * update locals ;-)
84 phy_mem += rem;
85 tmp -= rem;
89 if (items > 0)
91 --array;
92 array->prde_Length |= AROS_LONG2LE(PRDE_EOT);
94 D(bug("[PCI-ATA] dma_Setup: PRD Table set - %u items in total.\n", items));
97 * PRD table all set.
99 return items;
102 BOOL dma_SetupPRDSize(struct dma_data *unit, APTR buffer, IPTR size, BOOL read)
104 LONG items = 0;
105 IPTR prd_phys;
106 ULONG length;
108 items = dma_Setup(buffer, size, read, unit->ab_PRD);
110 if (0 == items)
111 return FALSE;
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 */
120 return TRUE;
123 void dma_Cleanup(struct dma_data *unit, APTR addr, IPTR len, BOOL read)
125 ULONG tmp, flg;
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;
132 while (len > 0)
134 tmp = len;
135 CachePostDMA(addr, &tmp, flg);
136 addr = &((UBYTE*)addr)[tmp];
137 len -= tmp;
138 flg |= DMA_Continue;
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[]=
158 dma_SetupPRDSize,
159 dma_StartDMA,
160 dma_Cleanup,
161 dma_CheckErr,
162 (APTR)-1