root / hw / soc_dma.c @ 4870852c
History | View | Annotate | Download (11.7 kB)
1 | afbb5194 | balrog | /*
|
---|---|---|---|
2 | afbb5194 | balrog | * On-chip DMA controller framework.
|
3 | afbb5194 | balrog | *
|
4 | afbb5194 | balrog | * Copyright (C) 2008 Nokia Corporation
|
5 | afbb5194 | balrog | * Written by Andrzej Zaborowski <andrew@openedhand.com>
|
6 | afbb5194 | balrog | *
|
7 | afbb5194 | balrog | * This program is free software; you can redistribute it and/or
|
8 | afbb5194 | balrog | * modify it under the terms of the GNU General Public License as
|
9 | afbb5194 | balrog | * published by the Free Software Foundation; either version 2 or
|
10 | afbb5194 | balrog | * (at your option) version 3 of the License.
|
11 | afbb5194 | balrog | *
|
12 | afbb5194 | balrog | * This program is distributed in the hope that it will be useful,
|
13 | afbb5194 | balrog | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | afbb5194 | balrog | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15 | afbb5194 | balrog | * GNU General Public License for more details.
|
16 | afbb5194 | balrog | *
|
17 | fad6cb1a | aurel32 | * You should have received a copy of the GNU General Public License along
|
18 | fad6cb1a | aurel32 | * with this program; if not, write to the Free Software Foundation, Inc.,
|
19 | fad6cb1a | aurel32 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
20 | afbb5194 | balrog | */
|
21 | afbb5194 | balrog | #include "qemu-common.h" |
22 | afbb5194 | balrog | #include "qemu-timer.h" |
23 | afbb5194 | balrog | #include "soc_dma.h" |
24 | afbb5194 | balrog | |
25 | b1d8e52e | blueswir1 | static void transfer_mem2mem(struct soc_dma_ch_s *ch) |
26 | afbb5194 | balrog | { |
27 | afbb5194 | balrog | memcpy(ch->paddr[0], ch->paddr[1], ch->bytes); |
28 | afbb5194 | balrog | ch->paddr[0] += ch->bytes;
|
29 | afbb5194 | balrog | ch->paddr[1] += ch->bytes;
|
30 | afbb5194 | balrog | } |
31 | afbb5194 | balrog | |
32 | b1d8e52e | blueswir1 | static void transfer_mem2fifo(struct soc_dma_ch_s *ch) |
33 | afbb5194 | balrog | { |
34 | afbb5194 | balrog | ch->io_fn[1](ch->io_opaque[1], ch->paddr[0], ch->bytes); |
35 | afbb5194 | balrog | ch->paddr[0] += ch->bytes;
|
36 | afbb5194 | balrog | } |
37 | afbb5194 | balrog | |
38 | b1d8e52e | blueswir1 | static void transfer_fifo2mem(struct soc_dma_ch_s *ch) |
39 | afbb5194 | balrog | { |
40 | afbb5194 | balrog | ch->io_fn[0](ch->io_opaque[0], ch->paddr[1], ch->bytes); |
41 | afbb5194 | balrog | ch->paddr[1] += ch->bytes;
|
42 | afbb5194 | balrog | } |
43 | afbb5194 | balrog | |
44 | afbb5194 | balrog | /* This is further optimisable but isn't very important because often
|
45 | afbb5194 | balrog | * DMA peripherals forbid this kind of transfers and even when they don't,
|
46 | afbb5194 | balrog | * oprating systems may not need to use them. */
|
47 | afbb5194 | balrog | static void *fifo_buf; |
48 | afbb5194 | balrog | static int fifo_size; |
49 | b1d8e52e | blueswir1 | static void transfer_fifo2fifo(struct soc_dma_ch_s *ch) |
50 | afbb5194 | balrog | { |
51 | d4066479 | balrog | if (ch->bytes > fifo_size)
|
52 | 2137b4cc | ths | fifo_buf = qemu_realloc(fifo_buf, fifo_size = ch->bytes); |
53 | afbb5194 | balrog | |
54 | afbb5194 | balrog | /* Implement as transfer_fifo2linear + transfer_linear2fifo. */
|
55 | afbb5194 | balrog | ch->io_fn[0](ch->io_opaque[0], fifo_buf, ch->bytes); |
56 | afbb5194 | balrog | ch->io_fn[1](ch->io_opaque[1], fifo_buf, ch->bytes); |
57 | afbb5194 | balrog | } |
58 | afbb5194 | balrog | |
59 | afbb5194 | balrog | struct dma_s {
|
60 | afbb5194 | balrog | struct soc_dma_s soc;
|
61 | afbb5194 | balrog | int chnum;
|
62 | afbb5194 | balrog | uint64_t ch_enable_mask; |
63 | afbb5194 | balrog | int64_t channel_freq; |
64 | afbb5194 | balrog | int enabled_count;
|
65 | afbb5194 | balrog | |
66 | afbb5194 | balrog | struct memmap_entry_s {
|
67 | afbb5194 | balrog | enum soc_dma_port_type type;
|
68 | afbb5194 | balrog | target_phys_addr_t addr; |
69 | afbb5194 | balrog | union {
|
70 | afbb5194 | balrog | struct {
|
71 | afbb5194 | balrog | void *opaque;
|
72 | afbb5194 | balrog | soc_dma_io_t fn; |
73 | afbb5194 | balrog | int out;
|
74 | afbb5194 | balrog | } fifo; |
75 | afbb5194 | balrog | struct {
|
76 | afbb5194 | balrog | void *base;
|
77 | afbb5194 | balrog | size_t size; |
78 | afbb5194 | balrog | } mem; |
79 | afbb5194 | balrog | } u; |
80 | afbb5194 | balrog | } *memmap; |
81 | afbb5194 | balrog | int memmap_size;
|
82 | afbb5194 | balrog | |
83 | afbb5194 | balrog | struct soc_dma_ch_s ch[0]; |
84 | afbb5194 | balrog | }; |
85 | afbb5194 | balrog | |
86 | afbb5194 | balrog | static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, int delay_bytes) |
87 | afbb5194 | balrog | { |
88 | afbb5194 | balrog | int64_t now = qemu_get_clock(vm_clock); |
89 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) ch->dma; |
90 | afbb5194 | balrog | |
91 | afbb5194 | balrog | qemu_mod_timer(ch->timer, now + delay_bytes / dma->channel_freq); |
92 | afbb5194 | balrog | } |
93 | afbb5194 | balrog | |
94 | afbb5194 | balrog | static void soc_dma_ch_run(void *opaque) |
95 | afbb5194 | balrog | { |
96 | afbb5194 | balrog | struct soc_dma_ch_s *ch = (struct soc_dma_ch_s *) opaque; |
97 | afbb5194 | balrog | |
98 | afbb5194 | balrog | ch->running = 1;
|
99 | afbb5194 | balrog | ch->dma->setup_fn(ch); |
100 | afbb5194 | balrog | ch->transfer_fn(ch); |
101 | afbb5194 | balrog | ch->running = 0;
|
102 | afbb5194 | balrog | |
103 | afbb5194 | balrog | if (ch->enable)
|
104 | afbb5194 | balrog | soc_dma_ch_schedule(ch, ch->bytes); |
105 | afbb5194 | balrog | ch->bytes = 0;
|
106 | afbb5194 | balrog | } |
107 | afbb5194 | balrog | |
108 | afbb5194 | balrog | static inline struct memmap_entry_s *soc_dma_lookup(struct dma_s *dma, |
109 | afbb5194 | balrog | target_phys_addr_t addr) |
110 | afbb5194 | balrog | { |
111 | afbb5194 | balrog | struct memmap_entry_s *lo;
|
112 | afbb5194 | balrog | int hi;
|
113 | afbb5194 | balrog | |
114 | afbb5194 | balrog | lo = dma->memmap; |
115 | afbb5194 | balrog | hi = dma->memmap_size; |
116 | afbb5194 | balrog | |
117 | afbb5194 | balrog | while (hi > 1) { |
118 | afbb5194 | balrog | hi /= 2;
|
119 | afbb5194 | balrog | if (lo[hi].addr <= addr)
|
120 | afbb5194 | balrog | lo += hi; |
121 | afbb5194 | balrog | } |
122 | afbb5194 | balrog | |
123 | afbb5194 | balrog | return lo;
|
124 | afbb5194 | balrog | } |
125 | afbb5194 | balrog | |
126 | afbb5194 | balrog | static inline enum soc_dma_port_type soc_dma_ch_update_type( |
127 | afbb5194 | balrog | struct soc_dma_ch_s *ch, int port) |
128 | afbb5194 | balrog | { |
129 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) ch->dma; |
130 | afbb5194 | balrog | struct memmap_entry_s *entry = soc_dma_lookup(dma, ch->vaddr[port]);
|
131 | afbb5194 | balrog | |
132 | afbb5194 | balrog | if (entry->type == soc_dma_port_fifo) {
|
133 | afbb5194 | balrog | while (entry < dma->memmap + dma->memmap_size &&
|
134 | afbb5194 | balrog | entry->u.fifo.out != port) |
135 | afbb5194 | balrog | entry ++; |
136 | afbb5194 | balrog | if (entry->addr != ch->vaddr[port] || entry->u.fifo.out != port)
|
137 | afbb5194 | balrog | return soc_dma_port_other;
|
138 | afbb5194 | balrog | |
139 | afbb5194 | balrog | if (ch->type[port] != soc_dma_access_const)
|
140 | afbb5194 | balrog | return soc_dma_port_other;
|
141 | afbb5194 | balrog | |
142 | afbb5194 | balrog | ch->io_fn[port] = entry->u.fifo.fn; |
143 | afbb5194 | balrog | ch->io_opaque[port] = entry->u.fifo.opaque; |
144 | afbb5194 | balrog | return soc_dma_port_fifo;
|
145 | afbb5194 | balrog | } else if (entry->type == soc_dma_port_mem) { |
146 | afbb5194 | balrog | if (entry->addr > ch->vaddr[port] ||
|
147 | afbb5194 | balrog | entry->addr + entry->u.mem.size <= ch->vaddr[port]) |
148 | afbb5194 | balrog | return soc_dma_port_other;
|
149 | afbb5194 | balrog | |
150 | afbb5194 | balrog | /* TODO: support constant memory address for source port as used for
|
151 | afbb5194 | balrog | * drawing solid rectangles by PalmOS(R). */
|
152 | afbb5194 | balrog | if (ch->type[port] != soc_dma_access_const)
|
153 | afbb5194 | balrog | return soc_dma_port_other;
|
154 | afbb5194 | balrog | |
155 | afbb5194 | balrog | ch->paddr[port] = (uint8_t *) entry->u.mem.base + |
156 | afbb5194 | balrog | (ch->vaddr[port] - entry->addr); |
157 | afbb5194 | balrog | /* TODO: save bytes left to the end of the mapping somewhere so we
|
158 | afbb5194 | balrog | * can check we're not reading beyond it. */
|
159 | afbb5194 | balrog | return soc_dma_port_mem;
|
160 | afbb5194 | balrog | } else
|
161 | afbb5194 | balrog | return soc_dma_port_other;
|
162 | afbb5194 | balrog | } |
163 | afbb5194 | balrog | |
164 | afbb5194 | balrog | void soc_dma_ch_update(struct soc_dma_ch_s *ch) |
165 | afbb5194 | balrog | { |
166 | afbb5194 | balrog | enum soc_dma_port_type src, dst;
|
167 | afbb5194 | balrog | |
168 | afbb5194 | balrog | src = soc_dma_ch_update_type(ch, 0);
|
169 | afbb5194 | balrog | if (src == soc_dma_port_other) {
|
170 | afbb5194 | balrog | ch->update = 0;
|
171 | afbb5194 | balrog | ch->transfer_fn = ch->dma->transfer_fn; |
172 | afbb5194 | balrog | return;
|
173 | afbb5194 | balrog | } |
174 | afbb5194 | balrog | dst = soc_dma_ch_update_type(ch, 1);
|
175 | afbb5194 | balrog | |
176 | afbb5194 | balrog | /* TODO: use src and dst as array indices. */
|
177 | afbb5194 | balrog | if (src == soc_dma_port_mem && dst == soc_dma_port_mem)
|
178 | afbb5194 | balrog | ch->transfer_fn = transfer_mem2mem; |
179 | afbb5194 | balrog | else if (src == soc_dma_port_mem && dst == soc_dma_port_fifo) |
180 | afbb5194 | balrog | ch->transfer_fn = transfer_mem2fifo; |
181 | afbb5194 | balrog | else if (src == soc_dma_port_fifo && dst == soc_dma_port_mem) |
182 | afbb5194 | balrog | ch->transfer_fn = transfer_fifo2mem; |
183 | afbb5194 | balrog | else if (src == soc_dma_port_fifo && dst == soc_dma_port_fifo) |
184 | afbb5194 | balrog | ch->transfer_fn = transfer_fifo2fifo; |
185 | afbb5194 | balrog | else
|
186 | afbb5194 | balrog | ch->transfer_fn = ch->dma->transfer_fn; |
187 | afbb5194 | balrog | |
188 | afbb5194 | balrog | ch->update = (dst != soc_dma_port_other); |
189 | afbb5194 | balrog | } |
190 | afbb5194 | balrog | |
191 | afbb5194 | balrog | static void soc_dma_ch_freq_update(struct dma_s *s) |
192 | afbb5194 | balrog | { |
193 | afbb5194 | balrog | if (s->enabled_count)
|
194 | afbb5194 | balrog | /* We completely ignore channel priorities and stuff */
|
195 | afbb5194 | balrog | s->channel_freq = s->soc.freq / s->enabled_count; |
196 | afbb5194 | balrog | else
|
197 | afbb5194 | balrog | /* TODO: Signal that we want to disable the functional clock and let
|
198 | afbb5194 | balrog | * the platform code decide what to do with it, i.e. check that
|
199 | afbb5194 | balrog | * auto-idle is enabled in the clock controller and if we are stopping
|
200 | afbb5194 | balrog | * the clock, do the same with any parent clocks that had only one
|
201 | afbb5194 | balrog | * user keeping them on and auto-idle enabled. */;
|
202 | afbb5194 | balrog | } |
203 | afbb5194 | balrog | |
204 | afbb5194 | balrog | void soc_dma_set_request(struct soc_dma_ch_s *ch, int level) |
205 | afbb5194 | balrog | { |
206 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) ch->dma; |
207 | afbb5194 | balrog | |
208 | afbb5194 | balrog | dma->enabled_count += level - ch->enable; |
209 | afbb5194 | balrog | |
210 | afbb5194 | balrog | if (level)
|
211 | afbb5194 | balrog | dma->ch_enable_mask |= 1 << ch->num;
|
212 | afbb5194 | balrog | else
|
213 | afbb5194 | balrog | dma->ch_enable_mask &= ~(1 << ch->num);
|
214 | afbb5194 | balrog | |
215 | afbb5194 | balrog | if (level != ch->enable) {
|
216 | afbb5194 | balrog | soc_dma_ch_freq_update(dma); |
217 | afbb5194 | balrog | ch->enable = level; |
218 | afbb5194 | balrog | |
219 | afbb5194 | balrog | if (!ch->enable)
|
220 | afbb5194 | balrog | qemu_del_timer(ch->timer); |
221 | afbb5194 | balrog | else if (!ch->running) |
222 | afbb5194 | balrog | soc_dma_ch_run(ch); |
223 | afbb5194 | balrog | else
|
224 | afbb5194 | balrog | soc_dma_ch_schedule(ch, 1);
|
225 | afbb5194 | balrog | } |
226 | afbb5194 | balrog | } |
227 | afbb5194 | balrog | |
228 | afbb5194 | balrog | void soc_dma_reset(struct soc_dma_s *soc) |
229 | afbb5194 | balrog | { |
230 | afbb5194 | balrog | struct dma_s *s = (struct dma_s *) soc; |
231 | afbb5194 | balrog | |
232 | afbb5194 | balrog | s->soc.drqbmp = 0;
|
233 | afbb5194 | balrog | s->ch_enable_mask = 0;
|
234 | afbb5194 | balrog | s->enabled_count = 0;
|
235 | afbb5194 | balrog | soc_dma_ch_freq_update(s); |
236 | afbb5194 | balrog | } |
237 | afbb5194 | balrog | |
238 | afbb5194 | balrog | /* TODO: take a functional-clock argument */
|
239 | afbb5194 | balrog | struct soc_dma_s *soc_dma_init(int n) |
240 | afbb5194 | balrog | { |
241 | afbb5194 | balrog | int i;
|
242 | afbb5194 | balrog | struct dma_s *s = qemu_mallocz(sizeof(*s) + n * sizeof(*s->ch)); |
243 | afbb5194 | balrog | |
244 | afbb5194 | balrog | s->chnum = n; |
245 | afbb5194 | balrog | s->soc.ch = s->ch; |
246 | afbb5194 | balrog | for (i = 0; i < n; i ++) { |
247 | afbb5194 | balrog | s->ch[i].dma = &s->soc; |
248 | afbb5194 | balrog | s->ch[i].num = i; |
249 | afbb5194 | balrog | s->ch[i].timer = qemu_new_timer(vm_clock, soc_dma_ch_run, &s->ch[i]); |
250 | afbb5194 | balrog | } |
251 | afbb5194 | balrog | |
252 | afbb5194 | balrog | soc_dma_reset(&s->soc); |
253 | d4066479 | balrog | fifo_size = 0;
|
254 | afbb5194 | balrog | |
255 | afbb5194 | balrog | return &s->soc;
|
256 | afbb5194 | balrog | } |
257 | afbb5194 | balrog | |
258 | afbb5194 | balrog | void soc_dma_port_add_fifo(struct soc_dma_s *soc, target_phys_addr_t virt_base, |
259 | afbb5194 | balrog | soc_dma_io_t fn, void *opaque, int out) |
260 | afbb5194 | balrog | { |
261 | afbb5194 | balrog | struct memmap_entry_s *entry;
|
262 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) soc; |
263 | afbb5194 | balrog | |
264 | 2137b4cc | ths | dma->memmap = qemu_realloc(dma->memmap, sizeof(*entry) *
|
265 | afbb5194 | balrog | (dma->memmap_size + 1));
|
266 | afbb5194 | balrog | entry = soc_dma_lookup(dma, virt_base); |
267 | afbb5194 | balrog | |
268 | afbb5194 | balrog | if (dma->memmap_size) {
|
269 | afbb5194 | balrog | if (entry->type == soc_dma_port_mem) {
|
270 | afbb5194 | balrog | if (entry->addr <= virt_base &&
|
271 | afbb5194 | balrog | entry->addr + entry->u.mem.size > virt_base) { |
272 | afbb5194 | balrog | fprintf(stderr, "%s: FIFO at " TARGET_FMT_lx
|
273 | afbb5194 | balrog | " collides with RAM region at " TARGET_FMT_lx
|
274 | afbb5194 | balrog | "-" TARGET_FMT_lx "\n", __FUNCTION__, |
275 | afbb5194 | balrog | (target_ulong) virt_base, |
276 | afbb5194 | balrog | (target_ulong) entry->addr, (target_ulong) |
277 | afbb5194 | balrog | (entry->addr + entry->u.mem.size)); |
278 | afbb5194 | balrog | exit(-1);
|
279 | afbb5194 | balrog | } |
280 | afbb5194 | balrog | |
281 | afbb5194 | balrog | if (entry->addr <= virt_base)
|
282 | afbb5194 | balrog | entry ++; |
283 | afbb5194 | balrog | } else
|
284 | afbb5194 | balrog | while (entry < dma->memmap + dma->memmap_size &&
|
285 | afbb5194 | balrog | entry->addr <= virt_base) { |
286 | afbb5194 | balrog | if (entry->addr == virt_base && entry->u.fifo.out == out) {
|
287 | afbb5194 | balrog | fprintf(stderr, "%s: FIFO at " TARGET_FMT_lx
|
288 | afbb5194 | balrog | " collides FIFO at " TARGET_FMT_lx "\n", |
289 | afbb5194 | balrog | __FUNCTION__, (target_ulong) virt_base, |
290 | afbb5194 | balrog | (target_ulong) entry->addr); |
291 | afbb5194 | balrog | exit(-1);
|
292 | afbb5194 | balrog | } |
293 | afbb5194 | balrog | |
294 | afbb5194 | balrog | entry ++; |
295 | afbb5194 | balrog | } |
296 | afbb5194 | balrog | |
297 | afbb5194 | balrog | memmove(entry + 1, entry,
|
298 | afbb5194 | balrog | (uint8_t *) (dma->memmap + dma->memmap_size ++) - |
299 | afbb5194 | balrog | (uint8_t *) entry); |
300 | afbb5194 | balrog | } else
|
301 | afbb5194 | balrog | dma->memmap_size ++; |
302 | afbb5194 | balrog | |
303 | afbb5194 | balrog | entry->addr = virt_base; |
304 | afbb5194 | balrog | entry->type = soc_dma_port_fifo; |
305 | afbb5194 | balrog | entry->u.fifo.fn = fn; |
306 | afbb5194 | balrog | entry->u.fifo.opaque = opaque; |
307 | afbb5194 | balrog | entry->u.fifo.out = out; |
308 | afbb5194 | balrog | } |
309 | afbb5194 | balrog | |
310 | afbb5194 | balrog | void soc_dma_port_add_mem(struct soc_dma_s *soc, uint8_t *phys_base, |
311 | afbb5194 | balrog | target_phys_addr_t virt_base, size_t size) |
312 | afbb5194 | balrog | { |
313 | afbb5194 | balrog | struct memmap_entry_s *entry;
|
314 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) soc; |
315 | afbb5194 | balrog | |
316 | 2137b4cc | ths | dma->memmap = qemu_realloc(dma->memmap, sizeof(*entry) *
|
317 | afbb5194 | balrog | (dma->memmap_size + 1));
|
318 | afbb5194 | balrog | entry = soc_dma_lookup(dma, virt_base); |
319 | afbb5194 | balrog | |
320 | afbb5194 | balrog | if (dma->memmap_size) {
|
321 | afbb5194 | balrog | if (entry->type == soc_dma_port_mem) {
|
322 | afbb5194 | balrog | if ((entry->addr >= virt_base && entry->addr < virt_base + size) ||
|
323 | afbb5194 | balrog | (entry->addr <= virt_base && |
324 | afbb5194 | balrog | entry->addr + entry->u.mem.size > virt_base)) { |
325 | afbb5194 | balrog | fprintf(stderr, "%s: RAM at " TARGET_FMT_lx "-" TARGET_FMT_lx |
326 | afbb5194 | balrog | " collides with RAM region at " TARGET_FMT_lx
|
327 | afbb5194 | balrog | "-" TARGET_FMT_lx "\n", __FUNCTION__, |
328 | afbb5194 | balrog | (target_ulong) virt_base, |
329 | afbb5194 | balrog | (target_ulong) (virt_base + size), |
330 | afbb5194 | balrog | (target_ulong) entry->addr, (target_ulong) |
331 | afbb5194 | balrog | (entry->addr + entry->u.mem.size)); |
332 | afbb5194 | balrog | exit(-1);
|
333 | afbb5194 | balrog | } |
334 | afbb5194 | balrog | |
335 | afbb5194 | balrog | if (entry->addr <= virt_base)
|
336 | afbb5194 | balrog | entry ++; |
337 | afbb5194 | balrog | } else {
|
338 | afbb5194 | balrog | if (entry->addr >= virt_base &&
|
339 | afbb5194 | balrog | entry->addr < virt_base + size) { |
340 | afbb5194 | balrog | fprintf(stderr, "%s: RAM at " TARGET_FMT_lx "-" TARGET_FMT_lx |
341 | afbb5194 | balrog | " collides with FIFO at " TARGET_FMT_lx
|
342 | afbb5194 | balrog | "\n", __FUNCTION__,
|
343 | afbb5194 | balrog | (target_ulong) virt_base, |
344 | afbb5194 | balrog | (target_ulong) (virt_base + size), |
345 | afbb5194 | balrog | (target_ulong) entry->addr); |
346 | afbb5194 | balrog | exit(-1);
|
347 | afbb5194 | balrog | } |
348 | afbb5194 | balrog | |
349 | afbb5194 | balrog | while (entry < dma->memmap + dma->memmap_size &&
|
350 | afbb5194 | balrog | entry->addr <= virt_base) |
351 | afbb5194 | balrog | entry ++; |
352 | afbb5194 | balrog | } |
353 | afbb5194 | balrog | |
354 | afbb5194 | balrog | memmove(entry + 1, entry,
|
355 | afbb5194 | balrog | (uint8_t *) (dma->memmap + dma->memmap_size ++) - |
356 | afbb5194 | balrog | (uint8_t *) entry); |
357 | afbb5194 | balrog | } else
|
358 | afbb5194 | balrog | dma->memmap_size ++; |
359 | afbb5194 | balrog | |
360 | afbb5194 | balrog | entry->addr = virt_base; |
361 | afbb5194 | balrog | entry->type = soc_dma_port_mem; |
362 | afbb5194 | balrog | entry->u.mem.base = phys_base; |
363 | afbb5194 | balrog | entry->u.mem.size = size; |
364 | afbb5194 | balrog | } |
365 | afbb5194 | balrog | |
366 | afbb5194 | balrog | /* TODO: port removal for ports like PCMCIA memory */ |