|
|
1.1 root 1: /*
2: * QEMU ETRAX DMA Controller.
3: *
4: * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
24: #include <stdio.h>
25: #include <sys/time.h>
26: #include "hw.h"
1.1.1.5 ! root 27: #include "exec-memory.h"
1.1 root 28: #include "qemu-common.h"
29: #include "sysemu.h"
30:
31: #include "etraxfs_dma.h"
32:
33: #define D(x)
34:
35: #define RW_DATA (0x0 / 4)
36: #define RW_SAVED_DATA (0x58 / 4)
37: #define RW_SAVED_DATA_BUF (0x5c / 4)
38: #define RW_GROUP (0x60 / 4)
39: #define RW_GROUP_DOWN (0x7c / 4)
40: #define RW_CMD (0x80 / 4)
41: #define RW_CFG (0x84 / 4)
42: #define RW_STAT (0x88 / 4)
43: #define RW_INTR_MASK (0x8c / 4)
44: #define RW_ACK_INTR (0x90 / 4)
45: #define R_INTR (0x94 / 4)
46: #define R_MASKED_INTR (0x98 / 4)
47: #define RW_STREAM_CMD (0x9c / 4)
48:
49: #define DMA_REG_MAX (0x100 / 4)
50:
51: /* descriptors */
52:
53: // ------------------------------------------------------------ dma_descr_group
54: typedef struct dma_descr_group {
1.1.1.2 root 55: uint32_t next;
1.1 root 56: unsigned eol : 1;
57: unsigned tol : 1;
58: unsigned bol : 1;
59: unsigned : 1;
60: unsigned intr : 1;
61: unsigned : 2;
62: unsigned en : 1;
63: unsigned : 7;
64: unsigned dis : 1;
65: unsigned md : 16;
66: struct dma_descr_group *up;
67: union {
68: struct dma_descr_context *context;
69: struct dma_descr_group *group;
70: } down;
71: } dma_descr_group;
72:
73: // ---------------------------------------------------------- dma_descr_context
74: typedef struct dma_descr_context {
1.1.1.2 root 75: uint32_t next;
1.1 root 76: unsigned eol : 1;
77: unsigned : 3;
78: unsigned intr : 1;
79: unsigned : 1;
80: unsigned store_mode : 1;
81: unsigned en : 1;
82: unsigned : 7;
83: unsigned dis : 1;
84: unsigned md0 : 16;
85: unsigned md1;
86: unsigned md2;
87: unsigned md3;
88: unsigned md4;
1.1.1.2 root 89: uint32_t saved_data;
90: uint32_t saved_data_buf;
1.1 root 91: } dma_descr_context;
92:
93: // ------------------------------------------------------------- dma_descr_data
94: typedef struct dma_descr_data {
1.1.1.2 root 95: uint32_t next;
96: uint32_t buf;
1.1 root 97: unsigned eol : 1;
98: unsigned : 2;
99: unsigned out_eop : 1;
100: unsigned intr : 1;
101: unsigned wait : 1;
102: unsigned : 2;
103: unsigned : 3;
104: unsigned in_eop : 1;
105: unsigned : 4;
106: unsigned md : 16;
1.1.1.2 root 107: uint32_t after;
1.1 root 108: } dma_descr_data;
109:
110: /* Constants */
111: enum {
112: regk_dma_ack_pkt = 0x00000100,
113: regk_dma_anytime = 0x00000001,
114: regk_dma_array = 0x00000008,
115: regk_dma_burst = 0x00000020,
116: regk_dma_client = 0x00000002,
117: regk_dma_copy_next = 0x00000010,
118: regk_dma_copy_up = 0x00000020,
119: regk_dma_data_at_eol = 0x00000001,
120: regk_dma_dis_c = 0x00000010,
121: regk_dma_dis_g = 0x00000020,
122: regk_dma_idle = 0x00000001,
123: regk_dma_intern = 0x00000004,
124: regk_dma_load_c = 0x00000200,
125: regk_dma_load_c_n = 0x00000280,
126: regk_dma_load_c_next = 0x00000240,
127: regk_dma_load_d = 0x00000140,
128: regk_dma_load_g = 0x00000300,
129: regk_dma_load_g_down = 0x000003c0,
130: regk_dma_load_g_next = 0x00000340,
131: regk_dma_load_g_up = 0x00000380,
132: regk_dma_next_en = 0x00000010,
133: regk_dma_next_pkt = 0x00000010,
134: regk_dma_no = 0x00000000,
135: regk_dma_only_at_wait = 0x00000000,
136: regk_dma_restore = 0x00000020,
137: regk_dma_rst = 0x00000001,
138: regk_dma_running = 0x00000004,
139: regk_dma_rw_cfg_default = 0x00000000,
140: regk_dma_rw_cmd_default = 0x00000000,
141: regk_dma_rw_intr_mask_default = 0x00000000,
142: regk_dma_rw_stat_default = 0x00000101,
143: regk_dma_rw_stream_cmd_default = 0x00000000,
144: regk_dma_save_down = 0x00000020,
145: regk_dma_save_up = 0x00000020,
146: regk_dma_set_reg = 0x00000050,
147: regk_dma_set_w_size1 = 0x00000190,
148: regk_dma_set_w_size2 = 0x000001a0,
149: regk_dma_set_w_size4 = 0x000001c0,
150: regk_dma_stopped = 0x00000002,
151: regk_dma_store_c = 0x00000002,
152: regk_dma_store_descr = 0x00000000,
153: regk_dma_store_g = 0x00000004,
154: regk_dma_store_md = 0x00000001,
155: regk_dma_sw = 0x00000008,
156: regk_dma_update_down = 0x00000020,
157: regk_dma_yes = 0x00000001
158: };
159:
160: enum dma_ch_state
161: {
162: RST = 1,
163: STOPPED = 2,
164: RUNNING = 4
165: };
166:
167: struct fs_dma_channel
168: {
1.1.1.2 root 169: qemu_irq irq;
1.1 root 170: struct etraxfs_dma_client *client;
171:
172: /* Internal status. */
173: int stream_cmd_src;
174: enum dma_ch_state state;
175:
176: unsigned int input : 1;
177: unsigned int eol : 1;
178:
179: struct dma_descr_group current_g;
180: struct dma_descr_context current_c;
181: struct dma_descr_data current_d;
182:
183: /* Controll registers. */
184: uint32_t regs[DMA_REG_MAX];
185: };
186:
187: struct fs_dma_ctrl
188: {
1.1.1.5 ! root 189: MemoryRegion mmio;
1.1 root 190: int nr_channels;
191: struct fs_dma_channel *channels;
192:
193: QEMUBH *bh;
194: };
195:
196: static void DMA_run(void *opaque);
197: static int channel_out_run(struct fs_dma_ctrl *ctrl, int c);
198:
199: static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg)
200: {
201: return ctrl->channels[c].regs[reg];
202: }
203:
204: static inline int channel_stopped(struct fs_dma_ctrl *ctrl, int c)
205: {
206: return channel_reg(ctrl, c, RW_CFG) & 2;
207: }
208:
209: static inline int channel_en(struct fs_dma_ctrl *ctrl, int c)
210: {
211: return (channel_reg(ctrl, c, RW_CFG) & 1)
212: && ctrl->channels[c].client;
213: }
214:
215: static inline int fs_channel(target_phys_addr_t addr)
216: {
217: /* Every channel has a 0x2000 ctrl register map. */
218: return addr >> 13;
219: }
220:
221: #ifdef USE_THIS_DEAD_CODE
222: static void channel_load_g(struct fs_dma_ctrl *ctrl, int c)
223: {
224: target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP);
225:
226: /* Load and decode. FIXME: handle endianness. */
227: cpu_physical_memory_read (addr,
228: (void *) &ctrl->channels[c].current_g,
229: sizeof ctrl->channels[c].current_g);
230: }
231:
232: static void dump_c(int ch, struct dma_descr_context *c)
233: {
234: printf("%s ch=%d\n", __func__, ch);
1.1.1.2 root 235: printf("next=%x\n", c->next);
236: printf("saved_data=%x\n", c->saved_data);
237: printf("saved_data_buf=%x\n", c->saved_data_buf);
1.1 root 238: printf("eol=%x\n", (uint32_t) c->eol);
239: }
240:
241: static void dump_d(int ch, struct dma_descr_data *d)
242: {
243: printf("%s ch=%d\n", __func__, ch);
1.1.1.2 root 244: printf("next=%x\n", d->next);
245: printf("buf=%x\n", d->buf);
246: printf("after=%x\n", d->after);
1.1 root 247: printf("intr=%x\n", (uint32_t) d->intr);
248: printf("out_eop=%x\n", (uint32_t) d->out_eop);
249: printf("in_eop=%x\n", (uint32_t) d->in_eop);
250: printf("eol=%x\n", (uint32_t) d->eol);
251: }
252: #endif
253:
254: static void channel_load_c(struct fs_dma_ctrl *ctrl, int c)
255: {
256: target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
257:
258: /* Load and decode. FIXME: handle endianness. */
259: cpu_physical_memory_read (addr,
260: (void *) &ctrl->channels[c].current_c,
261: sizeof ctrl->channels[c].current_c);
262:
263: D(dump_c(c, &ctrl->channels[c].current_c));
264: /* I guess this should update the current pos. */
265: ctrl->channels[c].regs[RW_SAVED_DATA] =
266: (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data;
267: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
268: (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data_buf;
269: }
270:
271: static void channel_load_d(struct fs_dma_ctrl *ctrl, int c)
272: {
273: target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);
274:
275: /* Load and decode. FIXME: handle endianness. */
1.1.1.2 root 276: D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
1.1 root 277: cpu_physical_memory_read (addr,
278: (void *) &ctrl->channels[c].current_d,
279: sizeof ctrl->channels[c].current_d);
280:
281: D(dump_d(c, &ctrl->channels[c].current_d));
282: ctrl->channels[c].regs[RW_DATA] = addr;
283: }
284:
285: static void channel_store_c(struct fs_dma_ctrl *ctrl, int c)
286: {
287: target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
288:
289: /* Encode and store. FIXME: handle endianness. */
1.1.1.2 root 290: D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
1.1 root 291: D(dump_d(c, &ctrl->channels[c].current_d));
292: cpu_physical_memory_write (addr,
293: (void *) &ctrl->channels[c].current_c,
294: sizeof ctrl->channels[c].current_c);
295: }
296:
297: static void channel_store_d(struct fs_dma_ctrl *ctrl, int c)
298: {
299: target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);
300:
301: /* Encode and store. FIXME: handle endianness. */
1.1.1.2 root 302: D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
1.1 root 303: cpu_physical_memory_write (addr,
304: (void *) &ctrl->channels[c].current_d,
305: sizeof ctrl->channels[c].current_d);
306: }
307:
308: static inline void channel_stop(struct fs_dma_ctrl *ctrl, int c)
309: {
310: /* FIXME: */
311: }
312:
313: static inline void channel_start(struct fs_dma_ctrl *ctrl, int c)
314: {
315: if (ctrl->channels[c].client)
316: {
317: ctrl->channels[c].eol = 0;
318: ctrl->channels[c].state = RUNNING;
319: if (!ctrl->channels[c].input)
320: channel_out_run(ctrl, c);
321: } else
322: printf("WARNING: starting DMA ch %d with no client\n", c);
323:
324: qemu_bh_schedule_idle(ctrl->bh);
325: }
326:
327: static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
328: {
329: if (!channel_en(ctrl, c)
330: || channel_stopped(ctrl, c)
331: || ctrl->channels[c].state != RUNNING
332: /* Only reload the current data descriptor if it has eol set. */
333: || !ctrl->channels[c].current_d.eol) {
334: D(printf("continue failed ch=%d state=%d stopped=%d en=%d eol=%d\n",
335: c, ctrl->channels[c].state,
336: channel_stopped(ctrl, c),
337: channel_en(ctrl,c),
338: ctrl->channels[c].eol));
339: D(dump_d(c, &ctrl->channels[c].current_d));
340: return;
341: }
342:
343: /* Reload the current descriptor. */
344: channel_load_d(ctrl, c);
345:
346: /* If the current descriptor cleared the eol flag and we had already
347: reached eol state, do the continue. */
348: if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) {
1.1.1.2 root 349: D(printf("continue %d ok %x\n", c,
1.1 root 350: ctrl->channels[c].current_d.next));
351: ctrl->channels[c].regs[RW_SAVED_DATA] =
352: (uint32_t)(unsigned long)ctrl->channels[c].current_d.next;
353: channel_load_d(ctrl, c);
354: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
355: (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
356:
357: channel_start(ctrl, c);
358: }
359: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
360: (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
361: }
362:
363: static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
364: {
365: unsigned int cmd = v & ((1 << 10) - 1);
366:
367: D(printf("%s ch=%d cmd=%x\n",
368: __func__, c, cmd));
369: if (cmd & regk_dma_load_d) {
370: channel_load_d(ctrl, c);
371: if (cmd & regk_dma_burst)
372: channel_start(ctrl, c);
373: }
374:
375: if (cmd & regk_dma_load_c) {
376: channel_load_c(ctrl, c);
377: }
378: }
379:
380: static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c)
381: {
382: D(printf("%s %d\n", __func__, c));
383: ctrl->channels[c].regs[R_INTR] &=
384: ~(ctrl->channels[c].regs[RW_ACK_INTR]);
385:
386: ctrl->channels[c].regs[R_MASKED_INTR] =
387: ctrl->channels[c].regs[R_INTR]
388: & ctrl->channels[c].regs[RW_INTR_MASK];
389:
390: D(printf("%s: chan=%d masked_intr=%x\n", __func__,
391: c,
392: ctrl->channels[c].regs[R_MASKED_INTR]));
393:
1.1.1.2 root 394: qemu_set_irq(ctrl->channels[c].irq,
395: !!ctrl->channels[c].regs[R_MASKED_INTR]);
1.1 root 396: }
397:
398: static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
399: {
400: uint32_t len;
401: uint32_t saved_data_buf;
402: unsigned char buf[2 * 1024];
403:
404: if (ctrl->channels[c].eol)
405: return 0;
406:
407: do {
1.1.1.2 root 408: D(printf("ch=%d buf=%x after=%x\n",
1.1 root 409: c,
410: (uint32_t)ctrl->channels[c].current_d.buf,
1.1.1.2 root 411: (uint32_t)ctrl->channels[c].current_d.after));
1.1 root 412:
413: channel_load_d(ctrl, c);
414: saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
415: len = (uint32_t)(unsigned long)
416: ctrl->channels[c].current_d.after;
417: len -= saved_data_buf;
418:
419: if (len > sizeof buf)
420: len = sizeof buf;
421: cpu_physical_memory_read (saved_data_buf, buf, len);
422:
423: D(printf("channel %d pushes %x %u bytes\n", c,
424: saved_data_buf, len));
425:
426: if (ctrl->channels[c].client->client.push)
427: ctrl->channels[c].client->client.push(
428: ctrl->channels[c].client->client.opaque,
429: buf, len);
430: else
431: printf("WARNING: DMA ch%d dataloss,"
432: " no attached client.\n", c);
433:
434: saved_data_buf += len;
435:
436: if (saved_data_buf == (uint32_t)(unsigned long)
437: ctrl->channels[c].current_d.after) {
438: /* Done. Step to next. */
439: if (ctrl->channels[c].current_d.out_eop) {
440: /* TODO: signal eop to the client. */
441: D(printf("signal eop\n"));
442: }
443: if (ctrl->channels[c].current_d.intr) {
444: /* TODO: signal eop to the client. */
445: /* data intr. */
446: D(printf("signal intr %d eol=%d\n",
447: len, ctrl->channels[c].current_d.eol));
448: ctrl->channels[c].regs[R_INTR] |= (1 << 2);
449: channel_update_irq(ctrl, c);
450: }
451: channel_store_d(ctrl, c);
452: if (ctrl->channels[c].current_d.eol) {
453: D(printf("channel %d EOL\n", c));
454: ctrl->channels[c].eol = 1;
455:
456: /* Mark the context as disabled. */
457: ctrl->channels[c].current_c.dis = 1;
458: channel_store_c(ctrl, c);
459:
460: channel_stop(ctrl, c);
461: } else {
462: ctrl->channels[c].regs[RW_SAVED_DATA] =
463: (uint32_t)(unsigned long)ctrl->
464: channels[c].current_d.next;
465: /* Load new descriptor. */
466: channel_load_d(ctrl, c);
467: saved_data_buf = (uint32_t)(unsigned long)
468: ctrl->channels[c].current_d.buf;
469: }
470:
471: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
472: saved_data_buf;
473: D(dump_d(c, &ctrl->channels[c].current_d));
474: }
475: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
476: } while (!ctrl->channels[c].eol);
477: return 1;
478: }
479:
480: static int channel_in_process(struct fs_dma_ctrl *ctrl, int c,
481: unsigned char *buf, int buflen, int eop)
482: {
483: uint32_t len;
484: uint32_t saved_data_buf;
485:
486: if (ctrl->channels[c].eol == 1)
487: return 0;
488:
489: channel_load_d(ctrl, c);
490: saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
491: len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after;
492: len -= saved_data_buf;
493:
494: if (len > buflen)
495: len = buflen;
496:
497: cpu_physical_memory_write (saved_data_buf, buf, len);
498: saved_data_buf += len;
499:
500: if (saved_data_buf ==
501: (uint32_t)(unsigned long)ctrl->channels[c].current_d.after
502: || eop) {
503: uint32_t r_intr = ctrl->channels[c].regs[R_INTR];
504:
505: D(printf("in dscr end len=%d\n",
506: ctrl->channels[c].current_d.after
507: - ctrl->channels[c].current_d.buf));
1.1.1.2 root 508: ctrl->channels[c].current_d.after = saved_data_buf;
1.1 root 509:
510: /* Done. Step to next. */
511: if (ctrl->channels[c].current_d.intr) {
512: /* TODO: signal eop to the client. */
513: /* data intr. */
514: ctrl->channels[c].regs[R_INTR] |= 3;
515: }
516: if (eop) {
517: ctrl->channels[c].current_d.in_eop = 1;
518: ctrl->channels[c].regs[R_INTR] |= 8;
519: }
520: if (r_intr != ctrl->channels[c].regs[R_INTR])
521: channel_update_irq(ctrl, c);
522:
523: channel_store_d(ctrl, c);
524: D(dump_d(c, &ctrl->channels[c].current_d));
525:
526: if (ctrl->channels[c].current_d.eol) {
527: D(printf("channel %d EOL\n", c));
528: ctrl->channels[c].eol = 1;
529:
530: /* Mark the context as disabled. */
531: ctrl->channels[c].current_c.dis = 1;
532: channel_store_c(ctrl, c);
533:
534: channel_stop(ctrl, c);
535: } else {
536: ctrl->channels[c].regs[RW_SAVED_DATA] =
537: (uint32_t)(unsigned long)ctrl->
538: channels[c].current_d.next;
539: /* Load new descriptor. */
540: channel_load_d(ctrl, c);
541: saved_data_buf = (uint32_t)(unsigned long)
542: ctrl->channels[c].current_d.buf;
543: }
544: }
545:
546: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
547: return len;
548: }
549:
550: static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c)
551: {
552: if (ctrl->channels[c].client->client.pull) {
553: ctrl->channels[c].client->client.pull(
554: ctrl->channels[c].client->client.opaque);
555: return 1;
556: } else
557: return 0;
558: }
559:
560: static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr)
561: {
1.1.1.2 root 562: hw_error("Unsupported short raccess. reg=" TARGET_FMT_plx "\n", addr);
1.1 root 563: return 0;
564: }
565:
1.1.1.5 ! root 566: static uint64_t
! 567: dma_read(void *opaque, target_phys_addr_t addr, unsigned int size)
1.1 root 568: {
569: struct fs_dma_ctrl *ctrl = opaque;
570: int c;
571: uint32_t r = 0;
572:
1.1.1.5 ! root 573: if (size != 4) {
! 574: dma_rinvalid(opaque, addr);
! 575: }
! 576:
1.1 root 577: /* Make addr relative to this channel and bounded to nr regs. */
578: c = fs_channel(addr);
579: addr &= 0xff;
580: addr >>= 2;
581: switch (addr)
582: {
583: case RW_STAT:
584: r = ctrl->channels[c].state & 7;
585: r |= ctrl->channels[c].eol << 5;
586: r |= ctrl->channels[c].stream_cmd_src << 8;
587: break;
588:
589: default:
590: r = ctrl->channels[c].regs[addr];
1.1.1.2 root 591: D(printf ("%s c=%d addr=" TARGET_FMT_plx "\n",
1.1 root 592: __func__, c, addr));
593: break;
594: }
595: return r;
596: }
597:
598: static void
599: dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
600: {
1.1.1.2 root 601: hw_error("Unsupported short waccess. reg=" TARGET_FMT_plx "\n", addr);
1.1 root 602: }
603:
604: static void
605: dma_update_state(struct fs_dma_ctrl *ctrl, int c)
606: {
1.1.1.5 ! root 607: if (ctrl->channels[c].regs[RW_CFG] & 2)
! 608: ctrl->channels[c].state = STOPPED;
! 609: if (!(ctrl->channels[c].regs[RW_CFG] & 1))
! 610: ctrl->channels[c].state = RST;
1.1 root 611: }
612:
613: static void
1.1.1.5 ! root 614: dma_write(void *opaque, target_phys_addr_t addr,
! 615: uint64_t val64, unsigned int size)
1.1 root 616: {
617: struct fs_dma_ctrl *ctrl = opaque;
1.1.1.5 ! root 618: uint32_t value = val64;
1.1 root 619: int c;
620:
1.1.1.5 ! root 621: if (size != 4) {
! 622: dma_winvalid(opaque, addr, value);
! 623: }
! 624:
1.1 root 625: /* Make addr relative to this channel and bounded to nr regs. */
626: c = fs_channel(addr);
627: addr &= 0xff;
628: addr >>= 2;
629: switch (addr)
630: {
631: case RW_DATA:
632: ctrl->channels[c].regs[addr] = value;
633: break;
634:
635: case RW_CFG:
636: ctrl->channels[c].regs[addr] = value;
637: dma_update_state(ctrl, c);
638: break;
639: case RW_CMD:
640: /* continue. */
641: if (value & ~1)
642: printf("Invalid store to ch=%d RW_CMD %x\n",
643: c, value);
644: ctrl->channels[c].regs[addr] = value;
645: channel_continue(ctrl, c);
646: break;
647:
648: case RW_SAVED_DATA:
649: case RW_SAVED_DATA_BUF:
650: case RW_GROUP:
651: case RW_GROUP_DOWN:
652: ctrl->channels[c].regs[addr] = value;
653: break;
654:
655: case RW_ACK_INTR:
656: case RW_INTR_MASK:
657: ctrl->channels[c].regs[addr] = value;
658: channel_update_irq(ctrl, c);
659: if (addr == RW_ACK_INTR)
660: ctrl->channels[c].regs[RW_ACK_INTR] = 0;
661: break;
662:
663: case RW_STREAM_CMD:
664: if (value & ~1023)
665: printf("Invalid store to ch=%d "
666: "RW_STREAMCMD %x\n",
667: c, value);
668: ctrl->channels[c].regs[addr] = value;
669: D(printf("stream_cmd ch=%d\n", c));
670: channel_stream_cmd(ctrl, c, value);
671: break;
672:
673: default:
1.1.1.2 root 674: D(printf ("%s c=%d " TARGET_FMT_plx "\n",
675: __func__, c, addr));
1.1 root 676: break;
677: }
678: }
679:
1.1.1.5 ! root 680: static const MemoryRegionOps dma_ops = {
! 681: .read = dma_read,
! 682: .write = dma_write,
! 683: .endianness = DEVICE_NATIVE_ENDIAN,
! 684: .valid = {
! 685: .min_access_size = 1,
! 686: .max_access_size = 4
! 687: }
1.1 root 688: };
689:
690: static int etraxfs_dmac_run(void *opaque)
691: {
692: struct fs_dma_ctrl *ctrl = opaque;
693: int i;
694: int p = 0;
695:
696: for (i = 0;
697: i < ctrl->nr_channels;
698: i++)
699: {
700: if (ctrl->channels[i].state == RUNNING)
701: {
702: if (ctrl->channels[i].input) {
703: p += channel_in_run(ctrl, i);
704: } else {
705: p += channel_out_run(ctrl, i);
706: }
707: }
708: }
709: return p;
710: }
711:
712: int etraxfs_dmac_input(struct etraxfs_dma_client *client,
713: void *buf, int len, int eop)
714: {
715: return channel_in_process(client->ctrl, client->channel,
716: buf, len, eop);
717: }
718:
719: /* Connect an IRQ line with a channel. */
720: void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input)
721: {
722: struct fs_dma_ctrl *ctrl = opaque;
1.1.1.2 root 723: ctrl->channels[c].irq = *line;
1.1 root 724: ctrl->channels[c].input = input;
725: }
726:
727: void etraxfs_dmac_connect_client(void *opaque, int c,
728: struct etraxfs_dma_client *cl)
729: {
730: struct fs_dma_ctrl *ctrl = opaque;
731: cl->ctrl = ctrl;
732: cl->channel = c;
733: ctrl->channels[c].client = cl;
734: }
735:
736:
737: static void DMA_run(void *opaque)
738: {
739: struct fs_dma_ctrl *etraxfs_dmac = opaque;
740: int p = 1;
741:
1.1.1.5 ! root 742: if (runstate_is_running())
1.1 root 743: p = etraxfs_dmac_run(etraxfs_dmac);
744:
745: if (p)
746: qemu_bh_schedule_idle(etraxfs_dmac->bh);
747: }
748:
1.1.1.2 root 749: void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels)
1.1 root 750: {
751: struct fs_dma_ctrl *ctrl = NULL;
752:
1.1.1.5 ! root 753: ctrl = g_malloc0(sizeof *ctrl);
1.1 root 754:
755: ctrl->bh = qemu_bh_new(DMA_run, ctrl);
756:
757: ctrl->nr_channels = nr_channels;
1.1.1.5 ! root 758: ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
! 759:
! 760: memory_region_init_io(&ctrl->mmio, &dma_ops, ctrl, "etraxfs-dma",
! 761: nr_channels * 0x2000);
! 762: memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
1.1 root 763:
764: return ctrl;
765: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.