|
|
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:
1.1.1.6 ! root 183: /* Control registers. */
1.1 root 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:
1.1.1.6 ! root 404: struct dma_context_metadata meta;
! 405: bool send_context = true;
! 406:
1.1 root 407: if (ctrl->channels[c].eol)
408: return 0;
409:
410: do {
1.1.1.6 ! root 411: bool out_eop;
1.1.1.2 root 412: D(printf("ch=%d buf=%x after=%x\n",
1.1 root 413: c,
414: (uint32_t)ctrl->channels[c].current_d.buf,
1.1.1.2 root 415: (uint32_t)ctrl->channels[c].current_d.after));
1.1 root 416:
1.1.1.6 ! root 417: if (send_context) {
! 418: if (ctrl->channels[c].client->client.metadata_push) {
! 419: meta.metadata = ctrl->channels[c].current_d.md;
! 420: ctrl->channels[c].client->client.metadata_push(
! 421: ctrl->channels[c].client->client.opaque,
! 422: &meta);
! 423: }
! 424: send_context = false;
! 425: }
! 426:
1.1 root 427: channel_load_d(ctrl, c);
428: saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
429: len = (uint32_t)(unsigned long)
430: ctrl->channels[c].current_d.after;
431: len -= saved_data_buf;
432:
433: if (len > sizeof buf)
434: len = sizeof buf;
435: cpu_physical_memory_read (saved_data_buf, buf, len);
436:
1.1.1.6 ! root 437: out_eop = ((saved_data_buf + len) ==
! 438: ctrl->channels[c].current_d.after) &&
! 439: ctrl->channels[c].current_d.out_eop;
! 440:
! 441: D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
! 442: saved_data_buf, len, out_eop));
1.1 root 443:
444: if (ctrl->channels[c].client->client.push)
445: ctrl->channels[c].client->client.push(
446: ctrl->channels[c].client->client.opaque,
1.1.1.6 ! root 447: buf, len, out_eop);
1.1 root 448: else
449: printf("WARNING: DMA ch%d dataloss,"
450: " no attached client.\n", c);
451:
452: saved_data_buf += len;
453:
454: if (saved_data_buf == (uint32_t)(unsigned long)
455: ctrl->channels[c].current_d.after) {
456: /* Done. Step to next. */
457: if (ctrl->channels[c].current_d.out_eop) {
1.1.1.6 ! root 458: send_context = true;
1.1 root 459: }
460: if (ctrl->channels[c].current_d.intr) {
461: /* data intr. */
462: D(printf("signal intr %d eol=%d\n",
463: len, ctrl->channels[c].current_d.eol));
464: ctrl->channels[c].regs[R_INTR] |= (1 << 2);
465: channel_update_irq(ctrl, c);
466: }
467: channel_store_d(ctrl, c);
468: if (ctrl->channels[c].current_d.eol) {
469: D(printf("channel %d EOL\n", c));
470: ctrl->channels[c].eol = 1;
471:
472: /* Mark the context as disabled. */
473: ctrl->channels[c].current_c.dis = 1;
474: channel_store_c(ctrl, c);
475:
476: channel_stop(ctrl, c);
477: } else {
478: ctrl->channels[c].regs[RW_SAVED_DATA] =
479: (uint32_t)(unsigned long)ctrl->
480: channels[c].current_d.next;
481: /* Load new descriptor. */
482: channel_load_d(ctrl, c);
483: saved_data_buf = (uint32_t)(unsigned long)
484: ctrl->channels[c].current_d.buf;
485: }
486:
487: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
488: saved_data_buf;
489: D(dump_d(c, &ctrl->channels[c].current_d));
490: }
491: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
492: } while (!ctrl->channels[c].eol);
493: return 1;
494: }
495:
496: static int channel_in_process(struct fs_dma_ctrl *ctrl, int c,
497: unsigned char *buf, int buflen, int eop)
498: {
499: uint32_t len;
500: uint32_t saved_data_buf;
501:
502: if (ctrl->channels[c].eol == 1)
503: return 0;
504:
505: channel_load_d(ctrl, c);
506: saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
507: len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after;
508: len -= saved_data_buf;
509:
510: if (len > buflen)
511: len = buflen;
512:
513: cpu_physical_memory_write (saved_data_buf, buf, len);
514: saved_data_buf += len;
515:
516: if (saved_data_buf ==
517: (uint32_t)(unsigned long)ctrl->channels[c].current_d.after
518: || eop) {
519: uint32_t r_intr = ctrl->channels[c].regs[R_INTR];
520:
521: D(printf("in dscr end len=%d\n",
522: ctrl->channels[c].current_d.after
523: - ctrl->channels[c].current_d.buf));
1.1.1.2 root 524: ctrl->channels[c].current_d.after = saved_data_buf;
1.1 root 525:
526: /* Done. Step to next. */
527: if (ctrl->channels[c].current_d.intr) {
528: /* TODO: signal eop to the client. */
529: /* data intr. */
530: ctrl->channels[c].regs[R_INTR] |= 3;
531: }
532: if (eop) {
533: ctrl->channels[c].current_d.in_eop = 1;
534: ctrl->channels[c].regs[R_INTR] |= 8;
535: }
536: if (r_intr != ctrl->channels[c].regs[R_INTR])
537: channel_update_irq(ctrl, c);
538:
539: channel_store_d(ctrl, c);
540: D(dump_d(c, &ctrl->channels[c].current_d));
541:
542: if (ctrl->channels[c].current_d.eol) {
543: D(printf("channel %d EOL\n", c));
544: ctrl->channels[c].eol = 1;
545:
546: /* Mark the context as disabled. */
547: ctrl->channels[c].current_c.dis = 1;
548: channel_store_c(ctrl, c);
549:
550: channel_stop(ctrl, c);
551: } else {
552: ctrl->channels[c].regs[RW_SAVED_DATA] =
553: (uint32_t)(unsigned long)ctrl->
554: channels[c].current_d.next;
555: /* Load new descriptor. */
556: channel_load_d(ctrl, c);
557: saved_data_buf = (uint32_t)(unsigned long)
558: ctrl->channels[c].current_d.buf;
559: }
560: }
561:
562: ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
563: return len;
564: }
565:
566: static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c)
567: {
568: if (ctrl->channels[c].client->client.pull) {
569: ctrl->channels[c].client->client.pull(
570: ctrl->channels[c].client->client.opaque);
571: return 1;
572: } else
573: return 0;
574: }
575:
576: static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr)
577: {
1.1.1.2 root 578: hw_error("Unsupported short raccess. reg=" TARGET_FMT_plx "\n", addr);
1.1 root 579: return 0;
580: }
581:
1.1.1.5 root 582: static uint64_t
583: dma_read(void *opaque, target_phys_addr_t addr, unsigned int size)
1.1 root 584: {
585: struct fs_dma_ctrl *ctrl = opaque;
586: int c;
587: uint32_t r = 0;
588:
1.1.1.5 root 589: if (size != 4) {
590: dma_rinvalid(opaque, addr);
591: }
592:
1.1 root 593: /* Make addr relative to this channel and bounded to nr regs. */
594: c = fs_channel(addr);
595: addr &= 0xff;
596: addr >>= 2;
597: switch (addr)
598: {
599: case RW_STAT:
600: r = ctrl->channels[c].state & 7;
601: r |= ctrl->channels[c].eol << 5;
602: r |= ctrl->channels[c].stream_cmd_src << 8;
603: break;
604:
605: default:
606: r = ctrl->channels[c].regs[addr];
1.1.1.2 root 607: D(printf ("%s c=%d addr=" TARGET_FMT_plx "\n",
1.1 root 608: __func__, c, addr));
609: break;
610: }
611: return r;
612: }
613:
614: static void
615: dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
616: {
1.1.1.2 root 617: hw_error("Unsupported short waccess. reg=" TARGET_FMT_plx "\n", addr);
1.1 root 618: }
619:
620: static void
621: dma_update_state(struct fs_dma_ctrl *ctrl, int c)
622: {
1.1.1.5 root 623: if (ctrl->channels[c].regs[RW_CFG] & 2)
624: ctrl->channels[c].state = STOPPED;
625: if (!(ctrl->channels[c].regs[RW_CFG] & 1))
626: ctrl->channels[c].state = RST;
1.1 root 627: }
628:
629: static void
1.1.1.5 root 630: dma_write(void *opaque, target_phys_addr_t addr,
631: uint64_t val64, unsigned int size)
1.1 root 632: {
633: struct fs_dma_ctrl *ctrl = opaque;
1.1.1.5 root 634: uint32_t value = val64;
1.1 root 635: int c;
636:
1.1.1.5 root 637: if (size != 4) {
638: dma_winvalid(opaque, addr, value);
639: }
640:
1.1 root 641: /* Make addr relative to this channel and bounded to nr regs. */
642: c = fs_channel(addr);
643: addr &= 0xff;
644: addr >>= 2;
645: switch (addr)
646: {
647: case RW_DATA:
648: ctrl->channels[c].regs[addr] = value;
649: break;
650:
651: case RW_CFG:
652: ctrl->channels[c].regs[addr] = value;
653: dma_update_state(ctrl, c);
654: break;
655: case RW_CMD:
656: /* continue. */
657: if (value & ~1)
658: printf("Invalid store to ch=%d RW_CMD %x\n",
659: c, value);
660: ctrl->channels[c].regs[addr] = value;
661: channel_continue(ctrl, c);
662: break;
663:
664: case RW_SAVED_DATA:
665: case RW_SAVED_DATA_BUF:
666: case RW_GROUP:
667: case RW_GROUP_DOWN:
668: ctrl->channels[c].regs[addr] = value;
669: break;
670:
671: case RW_ACK_INTR:
672: case RW_INTR_MASK:
673: ctrl->channels[c].regs[addr] = value;
674: channel_update_irq(ctrl, c);
675: if (addr == RW_ACK_INTR)
676: ctrl->channels[c].regs[RW_ACK_INTR] = 0;
677: break;
678:
679: case RW_STREAM_CMD:
680: if (value & ~1023)
681: printf("Invalid store to ch=%d "
682: "RW_STREAMCMD %x\n",
683: c, value);
684: ctrl->channels[c].regs[addr] = value;
685: D(printf("stream_cmd ch=%d\n", c));
686: channel_stream_cmd(ctrl, c, value);
687: break;
688:
689: default:
1.1.1.2 root 690: D(printf ("%s c=%d " TARGET_FMT_plx "\n",
691: __func__, c, addr));
1.1 root 692: break;
693: }
694: }
695:
1.1.1.5 root 696: static const MemoryRegionOps dma_ops = {
697: .read = dma_read,
698: .write = dma_write,
699: .endianness = DEVICE_NATIVE_ENDIAN,
700: .valid = {
701: .min_access_size = 1,
702: .max_access_size = 4
703: }
1.1 root 704: };
705:
706: static int etraxfs_dmac_run(void *opaque)
707: {
708: struct fs_dma_ctrl *ctrl = opaque;
709: int i;
710: int p = 0;
711:
712: for (i = 0;
713: i < ctrl->nr_channels;
714: i++)
715: {
716: if (ctrl->channels[i].state == RUNNING)
717: {
718: if (ctrl->channels[i].input) {
719: p += channel_in_run(ctrl, i);
720: } else {
721: p += channel_out_run(ctrl, i);
722: }
723: }
724: }
725: return p;
726: }
727:
728: int etraxfs_dmac_input(struct etraxfs_dma_client *client,
729: void *buf, int len, int eop)
730: {
731: return channel_in_process(client->ctrl, client->channel,
732: buf, len, eop);
733: }
734:
735: /* Connect an IRQ line with a channel. */
736: void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input)
737: {
738: struct fs_dma_ctrl *ctrl = opaque;
1.1.1.2 root 739: ctrl->channels[c].irq = *line;
1.1 root 740: ctrl->channels[c].input = input;
741: }
742:
743: void etraxfs_dmac_connect_client(void *opaque, int c,
744: struct etraxfs_dma_client *cl)
745: {
746: struct fs_dma_ctrl *ctrl = opaque;
747: cl->ctrl = ctrl;
748: cl->channel = c;
749: ctrl->channels[c].client = cl;
750: }
751:
752:
753: static void DMA_run(void *opaque)
754: {
755: struct fs_dma_ctrl *etraxfs_dmac = opaque;
756: int p = 1;
757:
1.1.1.5 root 758: if (runstate_is_running())
1.1 root 759: p = etraxfs_dmac_run(etraxfs_dmac);
760:
761: if (p)
762: qemu_bh_schedule_idle(etraxfs_dmac->bh);
763: }
764:
1.1.1.2 root 765: void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels)
1.1 root 766: {
767: struct fs_dma_ctrl *ctrl = NULL;
768:
1.1.1.5 root 769: ctrl = g_malloc0(sizeof *ctrl);
1.1 root 770:
771: ctrl->bh = qemu_bh_new(DMA_run, ctrl);
772:
773: ctrl->nr_channels = nr_channels;
1.1.1.5 root 774: ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
775:
776: memory_region_init_io(&ctrl->mmio, &dma_ops, ctrl, "etraxfs-dma",
777: nr_channels * 0x2000);
778: memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
1.1 root 779:
780: return ctrl;
781: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.