29
ch->paddr[1] += ch->bytes;
30
}
31
32
-static void transfer_mem2fifo(struct soc_dma_ch_s *ch)
33
-{
34
- ch->io_fn[1](ch->io_opaque[1], ch->paddr[0], ch->bytes);
35
- ch->paddr[0] += ch->bytes;
36
-}
37
-
38
-static void transfer_fifo2mem(struct soc_dma_ch_s *ch)
39
-{
40
- ch->io_fn[0](ch->io_opaque[0], ch->paddr[1], ch->bytes);
41
- ch->paddr[1] += ch->bytes;
42
-}
43
-
44
-/* This is further optimisable but isn't very important because often
45
- * DMA peripherals forbid this kind of transfers and even when they don't,
46
- * oprating systems may not need to use them. */
47
-static void *fifo_buf;
48
-static int fifo_size;
49
-static void transfer_fifo2fifo(struct soc_dma_ch_s *ch)
50
-{
51
- if (ch->bytes > fifo_size)
52
- fifo_buf = g_realloc(fifo_buf, fifo_size = ch->bytes);
53
-
54
- /* Implement as transfer_fifo2linear + transfer_linear2fifo. */
55
- ch->io_fn[0](ch->io_opaque[0], fifo_buf, ch->bytes);
56
- ch->io_fn[1](ch->io_opaque[1], fifo_buf, ch->bytes);
57
-}
58
-
32
struct dma_s {
33
struct soc_dma_s soc;
34
int chnum;
40
enum soc_dma_port_type type;
41
hwaddr addr;
42
union {
70
- struct {
71
- void *opaque;
72
- soc_dma_io_t fn;
73
- int out;
74
- } fifo;
43
struct {
44
void *base;
45
size_t size;
97
struct dma_s *dma = (struct dma_s *) ch->dma;
98
struct memmap_entry_s *entry = soc_dma_lookup(dma, ch->vaddr[port]);
99
132
- if (entry->type == soc_dma_port_fifo) {
133
- while (entry < dma->memmap + dma->memmap_size &&
134
- entry->u.fifo.out != port)
135
- entry ++;
136
- if (entry->addr != ch->vaddr[port] || entry->u.fifo.out != port)
137
- return soc_dma_port_other;
138
-
139
- if (ch->type[port] != soc_dma_access_const)
140
- return soc_dma_port_other;
141
-
142
- ch->io_fn[port] = entry->u.fifo.fn;
143
- ch->io_opaque[port] = entry->u.fifo.opaque;
144
- return soc_dma_port_fifo;
145
- } else if (entry->type == soc_dma_port_mem) {
100
+ if (entry->type == soc_dma_port_mem) {
101
if (entry->addr > ch->vaddr[port] ||
102
entry->addr + entry->u.mem.size <= ch->vaddr[port])
103
return soc_dma_port_other;
128
}
129
dst = soc_dma_ch_update_type(ch, 1);
130
176
- /* TODO: use src and dst as array indices. */
131
if (src == soc_dma_port_mem && dst == soc_dma_port_mem)
132
ch->transfer_fn = transfer_mem2mem;
179
- else if (src == soc_dma_port_mem && dst == soc_dma_port_fifo)
180
- ch->transfer_fn = transfer_mem2fifo;
181
- else if (src == soc_dma_port_fifo && dst == soc_dma_port_mem)
182
- ch->transfer_fn = transfer_fifo2mem;
183
- else if (src == soc_dma_port_fifo && dst == soc_dma_port_fifo)
184
- ch->transfer_fn = transfer_fifo2fifo;
133
else
134
ch->transfer_fn = ch->dma->transfer_fn;
135
199
}
200
201
soc_dma_reset(&s->soc);
254
- fifo_size = 0;
202
203
return &s->soc;
204
}
205
259
-void soc_dma_port_add_fifo(struct soc_dma_s *soc, hwaddr virt_base,
260
- soc_dma_io_t fn, void *opaque, int out)
261
-{
262
- struct memmap_entry_s *entry;
263
- struct dma_s *dma = (struct dma_s *) soc;
264
-
265
- dma->memmap = g_realloc(dma->memmap, sizeof(*entry) *
266
- (dma->memmap_size + 1));
267
- entry = soc_dma_lookup(dma, virt_base);
268
-
269
- if (dma->memmap_size) {
270
- if (entry->type == soc_dma_port_mem) {
271
- if (entry->addr <= virt_base &&
272
- entry->addr + entry->u.mem.size > virt_base) {
273
- error_report("%s: FIFO at %"PRIx64
274
- " collides with RAM region at %"PRIx64
275
- "-%"PRIx64, __func__,
276
- virt_base, entry->addr,
277
- (entry->addr + entry->u.mem.size));
278
- exit(-1);
279
- }
280
-
281
- if (entry->addr <= virt_base)
282
- entry ++;
283
- } else
284
- while (entry < dma->memmap + dma->memmap_size &&
285
- entry->addr <= virt_base) {
286
- if (entry->addr == virt_base && entry->u.fifo.out == out) {
287
- error_report("%s: FIFO at %"PRIx64
288
- " collides FIFO at %"PRIx64,
289
- __func__, virt_base, entry->addr);
290
- exit(-1);
291
- }
292
-
293
- entry ++;
294
- }
295
-
296
- memmove(entry + 1, entry,
297
- (uint8_t *) (dma->memmap + dma->memmap_size ++) -
298
- (uint8_t *) entry);
299
- } else
300
- dma->memmap_size ++;
301
-
302
- entry->addr = virt_base;
303
- entry->type = soc_dma_port_fifo;
304
- entry->u.fifo.fn = fn;
305
- entry->u.fifo.opaque = opaque;
306
- entry->u.fifo.out = out;
307
-}
308
-
206
void soc_dma_port_add_mem(struct soc_dma_s *soc, uint8_t *phys_base,
207
hwaddr virt_base, size_t size)
208
{