~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to debian/patches/linaro-patches-1.5.0/0009-omap_dma-add-scatter-gather-list-support.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
From 318ffd36247fcb10a878d796f4836ac2cdb8773f Mon Sep 17 00:00:00 2001
2
 
From: =?UTF-8?q?Juha=20Riihim=C3=A4ki?= <juha.riihimaki@nokia.com>
3
 
Date: Mon, 18 Feb 2013 16:58:24 +0000
4
 
Subject: [PATCH 09/69] omap_dma: add scatter gather list support
5
 
MIME-Version: 1.0
6
 
Content-Type: text/plain; charset=UTF-8
7
 
Content-Transfer-Encoding: 8bit
8
 
 
9
 
Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
10
 
---
11
 
 hw/dma/omap_dma.c | 411 +++++++++++++++++++++++++++++++++++-------------------
12
 
 1 file changed, 268 insertions(+), 143 deletions(-)
13
 
 
14
 
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c
15
 
index ac3963b..2b68e0d 100644
16
 
--- a/hw/dma/omap_dma.c
17
 
+++ b/hw/dma/omap_dma.c
18
 
@@ -98,6 +98,12 @@ struct omap_dma_channel_s {
19
 
     int type;
20
 
     int suspend;
21
 
     int buf_disable;
22
 
+
23
 
+    struct omap_dma_desc_linked_list_s {
24
 
+        uint32_t ptr;
25
 
+        uint32_t next;
26
 
+        uint32_t number;
27
 
+    } sgl;
28
 
 };
29
 
 
30
 
 struct omap_dma_s {
31
 
@@ -132,7 +138,10 @@ struct omap_dma_s {
32
 
 #define SYNC            (1 << 6)
33
 
 #define END_PKT_INTR   (1 << 7)
34
 
 #define TRANS_ERR_INTR (1 << 8)
35
 
+#define SV_ERR_INTR     (1 << 10)
36
 
 #define MISALIGN_INTR  (1 << 11)
37
 
+#define END_DRAIN_INTR  (1 << 12)
38
 
+#define END_SBLOCK_INTR (1 << 14)
39
 
 
40
 
 static inline void omap_dma_interrupts_update(struct omap_dma_s *s)
41
 
 {
42
 
@@ -259,6 +268,100 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s,
43
 
     }
44
 
 }
45
 
 
46
 
+static void omap_dma4_write_ch(struct omap_dma_s *s,
47
 
+                               struct omap_dma_channel_s *ch,
48
 
+                               uint32_t offset, uint32_t value);
49
 
+
50
 
+static int omap_dma_sgl_next(struct omap_dma_s *s,
51
 
+                             struct omap_dma_channel_s *ch)
52
 
+{
53
 
+    if ((ch->sgl.next >> 2) == 0x3fffffff) {
54
 
+        ch->status |= END_SBLOCK_INTR;
55
 
+        return 0;
56
 
+    }
57
 
+    int type = (ch->sgl.ptr >> 4) & 7;      /* NEXT_DESCRIPTOR_TYPE */
58
 
+    int src_valid = (ch->sgl.ptr >> 2) & 3; /* SRC_VALID */
59
 
+    int dst_valid = ch->sgl.ptr & 3;        /* DEST_VALID */
60
 
+    if (type < 1 || type > 3) {
61
 
+        hw_error("%s: unknown descriptor type %d\n", __func__, type);
62
 
+    }
63
 
+    hwaddr addr = (hwaddr)ch->sgl.next;
64
 
+    ch->sgl.ptr &= ~0xff;
65
 
+    uint8_t data[4];
66
 
+    cpu_physical_memory_read(addr, data, 4);
67
 
+    uint32_t word = ldl_p(data);
68
 
+    ch->sgl.next = word & ~3;
69
 
+    ch->sgl.ptr |= (word & 1) << 7;     /* PAUSE_LINK_LIST */
70
 
+    cpu_physical_memory_read(addr + 4, data, 4);
71
 
+    word = ldl_p(data);
72
 
+    ch->sgl.ptr |= (word >> 25) & 0x70; /* NEXT_DESCRIPTOR_TYPE */
73
 
+    ch->sgl.ptr |= (word >> 26) & 3;    /* DEST_VALID */
74
 
+    ch->sgl.ptr |= (word >> 22) & 0x0c; /* SRC_VALID */
75
 
+    ch->sgl.number = word & 0xffffff;
76
 
+    if (type == 3) {
77
 
+        ch->interrupts &= ~0x20;               /* BLOCK_IE */
78
 
+        ch->interrupts |= (word >> 23) & 0x20; /* BLOCK_IE */
79
 
+    }
80
 
+    addr += 8;
81
 
+    switch (src_valid) {
82
 
+    case 0:
83
 
+        ch->addr[0] = ch->active_set.src;
84
 
+        break;
85
 
+    case 1:
86
 
+        cpu_physical_memory_read(addr, data, 4);
87
 
+        ch->addr[0] = ldl_p(data);
88
 
+        addr += 4;
89
 
+        break;
90
 
+    case 2:
91
 
+        break;
92
 
+    default:
93
 
+        hw_error("%s: unknown src addressing mode %d\n",
94
 
+                 __func__, src_valid);
95
 
+        break;
96
 
+    }
97
 
+    switch (dst_valid) {
98
 
+    case 0:
99
 
+        ch->addr[1] = ch->active_set.dest;
100
 
+        break;
101
 
+    case 1:
102
 
+        cpu_physical_memory_read(addr, data, 4);
103
 
+        ch->addr[1] = ldl_p(data);
104
 
+        addr += 4;
105
 
+        break;
106
 
+    case 2:
107
 
+        break;
108
 
+    default:
109
 
+        hw_error("%s: unknown dest addressing mode %d\n",
110
 
+                 __func__, dst_valid);
111
 
+        break;
112
 
+    }
113
 
+    if (type == 1 || type == 2) {
114
 
+        cpu_physical_memory_read(addr, data, 4);
115
 
+        word = ldl_p(data);
116
 
+        ch->interrupts = word >> 16;
117
 
+        ch->frames = word & 0xffff;
118
 
+        cpu_physical_memory_read(addr + 4, data, 4);
119
 
+        word = ldl_p(data);
120
 
+        ch->element_index[0] = (int16_t)(word >> 16);
121
 
+        ch->element_index[1] = (int16_t)(word & 0xffff);
122
 
+        cpu_physical_memory_read(addr + 8, data, 4);
123
 
+        ch->frame_index[1] = ldl_p(data);
124
 
+        cpu_physical_memory_read(addr + 12, data, 4);
125
 
+        ch->frame_index[0] = ldl_p(data);
126
 
+        if (type == 1) {
127
 
+            cpu_physical_memory_read(addr + 16, data, 4);
128
 
+            ch->color = ldl_p(data);
129
 
+            cpu_physical_memory_read(addr + 20, data, 4);
130
 
+            omap_dma4_write_ch(s, ch, 0x10, ldl_p(data)); /* CSDP */
131
 
+            cpu_physical_memory_read(addr + 24, data, 4);
132
 
+            omap_dma4_write_ch(s, ch, 0x04, ldl_p(data)); /* CLNK_CTRL */
133
 
+            cpu_physical_memory_read(addr + 28, data, 4);
134
 
+            omap_dma4_write_ch(s, ch, 0x00, ldl_p(data)); /* CCR */
135
 
+        }
136
 
+    }
137
 
+    return 1;
138
 
+}
139
 
+
140
 
 static void omap_dma_enable_channel(struct omap_dma_s *s,
141
 
                 struct omap_dma_channel_s *ch)
142
 
 {
143
 
@@ -366,6 +469,34 @@ static void omap_dma_process_request(struct omap_dma_s *s, int request)
144
 
         omap_dma_interrupts_update(s);
145
 
 }
146
 
 
147
 
+static void omap_dma_end_of_block(struct omap_dma_s *s,
148
 
+                                  struct omap_dma_channel_s *ch)
149
 
+{
150
 
+    if (ch->omap_3_1_compatible_disable) {
151
 
+        omap_dma_disable_channel(s, ch);
152
 
+        if (ch->link_enabled) {
153
 
+            omap_dma_enable_channel(s, &s->ch[ch->link_next_ch]);
154
 
+        }
155
 
+    } else {
156
 
+        int sgl_pause = (ch->sgl.ptr >> 7) & 1; /* PAUSE_LINK_LIST */
157
 
+        if (((ch->sgl.ptr >> 8) & 3) != 1 || /* TRANSFER_MODE != linked list */
158
 
+            !omap_dma_sgl_next(s, ch) ||     /* end of list */
159
 
+            sgl_pause) {
160
 
+            if (!ch->auto_init) {
161
 
+                omap_dma_disable_channel(s, ch);
162
 
+            } else if (ch->repeat || ch->end_prog) {
163
 
+                omap_dma_channel_load(ch);
164
 
+            } else {
165
 
+                ch->waiting_end_prog = 1;
166
 
+                omap_dma_deactivate_channel(s, ch);
167
 
+            }
168
 
+        }
169
 
+    }
170
 
+
171
 
+    if (ch->interrupts & END_BLOCK_INTR)
172
 
+        ch->status |= END_BLOCK_INTR;
173
 
+}
174
 
+
175
 
 static void omap_dma_transfer_generic(struct soc_dma_ch_s *dma)
176
 
 {
177
 
     uint8_t value[4];
178
 
@@ -458,25 +589,7 @@ static void omap_dma_transfer_generic(struct soc_dma_ch_s *dma)
179
 
             if (a->frame == a->frames) {
180
 
                 /* End of Block */
181
 
                 /* Disable the channel */
182
 
-
183
 
-                if (ch->omap_3_1_compatible_disable) {
184
 
-                    omap_dma_disable_channel(s, ch);
185
 
-                    if (ch->link_enabled)
186
 
-                        omap_dma_enable_channel(s,
187
 
-                                        &s->ch[ch->link_next_ch]);
188
 
-                } else {
189
 
-                    if (!ch->auto_init)
190
 
-                        omap_dma_disable_channel(s, ch);
191
 
-                    else if (ch->repeat || ch->end_prog)
192
 
-                        omap_dma_channel_load(ch);
193
 
-                    else {
194
 
-                        ch->waiting_end_prog = 1;
195
 
-                        omap_dma_deactivate_channel(s, ch);
196
 
-                    }
197
 
-                }
198
 
-
199
 
-                if (ch->interrupts & END_BLOCK_INTR)
200
 
-                    ch->status |= END_BLOCK_INTR;
201
 
+                omap_dma_end_of_block(s, ch);
202
 
             }
203
 
         }
204
 
     } while (status == ch->status && ch->active);
205
 
@@ -507,6 +620,11 @@ static void omap_dma_transfer_setup(struct soc_dma_ch_s *dma)
206
 
 
207
 
     a = &ch->active_set;
208
 
 
209
 
+    if (((ch->sgl.ptr >> 8) & 3) == 1 && /* TRANSFER_MODE == linked list */
210
 
+        a->frame >= a->frames) {
211
 
+        omap_dma_channel_load(ch);
212
 
+    }
213
 
+
214
 
     src_p = &s->mpu->port[ch->port[0]];
215
 
     dest_p = &s->mpu->port[ch->port[1]];
216
 
     if ((!ch->constant_fill && !src_p->addr_valid(s->mpu, a->src)) ||
217
 
@@ -626,24 +744,7 @@ static void omap_dma_transfer_setup(struct soc_dma_ch_s *dma)
218
 
         if (min_elems == elements[omap_dma_intr_block]) {
219
 
             /* End of Block */
220
 
             /* Disable the channel */
221
 
-
222
 
-            if (ch->omap_3_1_compatible_disable) {
223
 
-                omap_dma_disable_channel(s, ch);
224
 
-                if (ch->link_enabled)
225
 
-                    omap_dma_enable_channel(s, &s->ch[ch->link_next_ch]);
226
 
-            } else {
227
 
-                if (!ch->auto_init)
228
 
-                    omap_dma_disable_channel(s, ch);
229
 
-                else if (ch->repeat || ch->end_prog)
230
 
-                    omap_dma_channel_load(ch);
231
 
-                else {
232
 
-                    ch->waiting_end_prog = 1;
233
 
-                    omap_dma_deactivate_channel(s, ch);
234
 
-                }
235
 
-            }
236
 
-
237
 
-            if (ch->interrupts & END_BLOCK_INTR)
238
 
-                ch->status |= END_BLOCK_INTR;
239
 
+            omap_dma_end_of_block(s, ch);
240
 
         }
241
 
 
242
 
         /* Update packet number */
243
 
@@ -747,6 +848,9 @@ void omap_dma_reset(struct soc_dma_s *dma)
244
 
         s->ch[i].priority = 0;
245
 
         s->ch[i].interleave_disabled = 0;
246
 
         s->ch[i].type = 0;
247
 
+        s->ch[i].sgl.ptr = 0;
248
 
+        s->ch[i].sgl.next = 0xfffffffc;
249
 
+        s->ch[i].sgl.number = 0;
250
 
     }
251
 
 }
252
 
 
253
 
@@ -1531,6 +1635,7 @@ static void omap_dma_write(void *opaque, hwaddr addr,
254
 
     case 0x404 ... 0x4fe:
255
 
         if (s->model <= omap_dma_3_1)
256
 
             break;
257
 
+        /* fall through */
258
 
     case 0x400:
259
 
         /* Fall through. */
260
 
         if (omap_dma_sys_write(s, addr, value))
261
 
@@ -1698,9 +1803,9 @@ static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
262
 
     uint32_t bmp, bit;
263
 
 
264
 
     for (bmp = 0, bit = 1; bit; ch ++, bit <<= 1)
265
 
-        if ((ch->status &= ch->interrupts)) {
266
 
+        if ((ch->status & ch->interrupts)) {
267
 
             bmp |= bit;
268
 
-            ch->cstatus |= ch->status;
269
 
+            ch->cstatus |= ch->status & ch->interrupts;
270
 
             ch->status = 0;
271
 
         }
272
 
     if ((s->irqstat[0] |= s->irqen[0] & bmp))
273
 
@@ -1867,96 +1972,36 @@ static uint64_t omap_dma4_read(void *opaque, hwaddr addr,
274
 
         return ch->color;
275
 
 
276
 
     case 0x50: /* DMA4_CDP */
277
 
-    case 0x54: /* DMA4_CNDP */
278
 
-    case 0x58: /* DMA4_CCDN */
279
 
-        return 0;
280
 
-
281
 
-    default:
282
 
-        OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
283
 
-        return 0;
284
 
-    }
285
 
-}
286
 
-
287
 
-static void omap_dma4_write(void *opaque, hwaddr addr,
288
 
-                            uint64_t value, unsigned size)
289
 
-{
290
 
-    struct omap_dma_s *s = (struct omap_dma_s *) opaque;
291
 
-    int chnum, irqn = 0;
292
 
-    struct omap_dma_channel_s *ch;
293
 
-
294
 
-    if (size == 1) {
295
 
-        return omap_badwidth_write16(opaque, addr, value);
296
 
-    }
297
 
-
298
 
-    switch (addr) {
299
 
-    case 0x14: /* DMA4_IRQSTATUS_L3 */
300
 
-        irqn ++;
301
 
-        /* fall through */
302
 
-    case 0x10: /* DMA4_IRQSTATUS_L2 */
303
 
-        irqn ++;
304
 
-        /* fall through */
305
 
-    case 0x0c: /* DMA4_IRQSTATUS_L1 */
306
 
-        irqn ++;
307
 
-        /* fall through */
308
 
-    case 0x08: /* DMA4_IRQSTATUS_L0 */
309
 
-        s->irqstat[irqn] &= ~value;
310
 
-        if (!s->irqstat[irqn])
311
 
-            qemu_irq_lower(s->irq[irqn]);
312
 
-        return;
313
 
-
314
 
-    case 0x24: /* DMA4_IRQENABLE_L3 */
315
 
-        irqn ++;
316
 
-        /* fall through */
317
 
-    case 0x20: /* DMA4_IRQENABLE_L2 */
318
 
-        irqn ++;
319
 
-        /* fall through */
320
 
-    case 0x1c: /* DMA4_IRQENABLE_L1 */
321
 
-        irqn ++;
322
 
-        /* fall through */
323
 
-    case 0x18: /* DMA4_IRQENABLE_L0 */
324
 
-        s->irqen[irqn] = value;
325
 
-        return;
326
 
-
327
 
-    case 0x2c: /* DMA4_OCP_SYSCONFIG */
328
 
-        if (value & 2) { /* SOFTRESET */
329
 
-            if (!cpu_is_omap3630(s->mpu)) { /* N/A on 3630GP */
330
 
-                omap_dma_reset(s->dma);
331
 
-            }
332
 
+        if (cpu_is_omap3630(s->mpu)) {
333
 
+            return ch->sgl.ptr;
334
 
         }
335
 
-        s->ocp = value & 0x3321;
336
 
-        if (((s->ocp >> 12) & 3) == 3)                         /* MIDLEMODE */
337
 
-            fprintf(stderr, "%s: invalid DMA power mode\n", __FUNCTION__);
338
 
-        return;
339
 
-
340
 
-    case 0x78: /* DMA4_GCR */
341
 
-        s->gcr = value & 0x00ff00ff;
342
 
-       if ((value & 0xff) == 0x00)             /* MAX_CHANNEL_FIFO_DEPTH */
343
 
-            fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __FUNCTION__);
344
 
-        return;
345
 
+        break;
346
 
 
347
 
-    case 0x80 ... 0xfff:
348
 
-        addr -= 0x80;
349
 
-        chnum = addr / 0x60;
350
 
-        ch = s->ch + chnum;
351
 
-        addr -= chnum * 0x60;
352
 
+    case 0x54: /* DMA4_CNDP */
353
 
+        if (cpu_is_omap3630(s->mpu)) {
354
 
+            return ch->sgl.next;
355
 
+        }
356
 
         break;
357
 
 
358
 
-    case 0x00: /* DMA4_REVISION */
359
 
-    case 0x28: /* DMA4_SYSSTATUS */
360
 
-    case 0x64: /* DMA4_CAPS_0 */
361
 
-    case 0x6c: /* DMA4_CAPS_2 */
362
 
-    case 0x70: /* DMA4_CAPS_3 */
363
 
-    case 0x74: /* DMA4_CAPS_4 */
364
 
-        OMAP_RO_REG(addr);
365
 
-        return;
366
 
+    case 0x58: /* DMA4_CCDN */
367
 
+        if (cpu_is_omap3630(s->mpu)) {
368
 
+            return ch->sgl.number;
369
 
+        }
370
 
+        break;
371
 
 
372
 
     default:
373
 
-        OMAP_BAD_REG(addr);
374
 
-        return;
375
 
+        break;
376
 
     }
377
 
 
378
 
-    /* Per-channel registers */
379
 
-    switch (addr) {
380
 
+    OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
381
 
+    return 0;
382
 
+}
383
 
+
384
 
+static void omap_dma4_write_ch(struct omap_dma_s *s,
385
 
+                               struct omap_dma_channel_s *ch,
386
 
+                               uint32_t offset, uint32_t value)
387
 
+{
388
 
+    switch (offset) {
389
 
     case 0x00: /* DMA4_CCR */
390
 
         ch->buf_disable = (value >> 25) & 1;
391
 
         ch->src_sync = (value >> 24) & 1;      /* XXX For CamDMA must be 1 */
392
 
@@ -1978,11 +2023,15 @@ static void omap_dma4_write(void *opaque, hwaddr addr,
393
 
         ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060);
394
 
         /* XXX must be 0x01 for CamDMA */
395
 
 
396
 
-        if (value & 0x0080)
397
 
-            omap_dma_enable_channel(s, ch);
398
 
-        else
399
 
+        if (value & 0x0080) {
400
 
+            if (((ch->sgl.ptr >> 8) & 3) != 1 || /* TRANSFER_MODE */
401
 
+                !(ch->sgl.ptr & (1 << 10)) ||    /* FAST */
402
 
+                omap_dma_sgl_next(s, ch)) {
403
 
+                omap_dma_enable_channel(s, ch);
404
 
+            }
405
 
+        } else {
406
 
             omap_dma_disable_channel(s, ch);
407
 
-
408
 
+        }
409
 
         break;
410
 
 
411
 
     case 0x04: /* DMA4_CLNK_CTRL */
412
 
@@ -2067,41 +2116,117 @@ static void omap_dma4_write(void *opaque, hwaddr addr,
413
 
         ch->set_update = 1;
414
 
         break;
415
 
 
416
 
-    case 0x44: /* DMA4_COLOR */
417
 
-        /* XXX only in sDMA */
418
 
-        ch->color = value;
419
 
-        break;
420
 
-
421
 
     case 0x34: /* DMA4_CSAC */
422
 
     case 0x38: /* DMA4_CDAC */
423
 
     case 0x3c: /* DMA4_CCEN */
424
 
     case 0x40: /* DMA4_CCFN */
425
 
-        /* f.ex. linux kernel writes zeroes to these registers as well
426
 
-           when performing a DMA channel reset. let's just ignore the
427
 
-           writes instead of reporting "dummy" errors */
428
 
-        /*OMAP_RO_REG(0x80 + chnum * 0x60 + addr);*/
429
 
+        /* ignore */
430
 
+        break;
431
 
+
432
 
+    case 0x44: /* DMA4_COLOR */
433
 
+        /* XXX only in sDMA */
434
 
+        ch->color = value;
435
 
         break;
436
 
 
437
 
     case 0x50: /* DMA4_CDP */
438
 
         if (cpu_is_omap3630(s->mpu)) {
439
 
-            if ((value >> 8) & 3) { /* TRANSFER_MODE */
440
 
-                hw_error("%s: linked list transfer mode not supported",
441
 
-                         __FUNCTION__);
442
 
-            }
443
 
-        } else {
444
 
-            OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
445
 
+            ch->sgl.ptr = value & 0x7ff;
446
 
         }
447
 
         break;
448
 
 
449
 
     case 0x54: /* DMA4_CNDP */
450
 
+        if (cpu_is_omap3630(s->mpu)) {
451
 
+            ch->sgl.next = value & ~3;
452
 
+        }
453
 
+        break;
454
 
+
455
 
     case 0x58: /* DMA4_CCDN */
456
 
-        if (!cpu_is_omap3630(s->mpu)) {
457
 
-            OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
458
 
+        if (cpu_is_omap3630(s->mpu)) {
459
 
+            ch->sgl.number = value & 0xffff;
460
 
         }
461
 
         break;
462
 
 
463
 
     default:
464
 
-        OMAP_BAD_REG(0x80 + chnum * 0x60 + addr);
465
 
+        fprintf(stderr, "%s: unknown register 0x%x\n",
466
 
+                __func__, offset + 0x80);
467
 
+        break;
468
 
+    }
469
 
+}
470
 
+
471
 
+static void omap_dma4_write(void *opaque, hwaddr addr,
472
 
+                            uint64_t value, unsigned size)
473
 
+{
474
 
+    struct omap_dma_s *s = (struct omap_dma_s *) opaque;
475
 
+    int chnum, irqn = 0;
476
 
+
477
 
+    if (size == 1) {
478
 
+        return omap_badwidth_write16(opaque, addr, value);
479
 
+    }
480
 
+
481
 
+    switch (addr) {
482
 
+    case 0x14: /* DMA4_IRQSTATUS_L3 */
483
 
+        irqn++;
484
 
+        /* fall through */
485
 
+    case 0x10: /* DMA4_IRQSTATUS_L2 */
486
 
+        irqn++;
487
 
+        /* fall through */
488
 
+    case 0x0c: /* DMA4_IRQSTATUS_L1 */
489
 
+        irqn++;
490
 
+        /* fall through */
491
 
+    case 0x08: /* DMA4_IRQSTATUS_L0 */
492
 
+        s->irqstat[irqn] &= ~value;
493
 
+        if (!s->irqstat[irqn]) {
494
 
+            qemu_irq_lower(s->irq[irqn]);
495
 
+        }
496
 
+        break;
497
 
+
498
 
+    case 0x24: /* DMA4_IRQENABLE_L3 */
499
 
+        irqn++;
500
 
+    case 0x20: /* DMA4_IRQENABLE_L2 */
501
 
+        irqn++;
502
 
+    case 0x1c: /* DMA4_IRQENABLE_L1 */
503
 
+        irqn++;
504
 
+    case 0x18: /* DMA4_IRQENABLE_L0 */
505
 
+        s->irqen[irqn] = value;
506
 
+        break;
507
 
+
508
 
+    case 0x2c: /* DMA4_OCP_SYSCONFIG */
509
 
+        if (value & 2) { /* SOFTRESET */
510
 
+            /* N/A on 3630GP?? */
511
 
+            omap_dma_reset(s->dma);
512
 
+        }
513
 
+        s->ocp = value & 0x3321;
514
 
+        if (((s->ocp >> 12) & 3) == 3) { /* MIDLEMODE */
515
 
+            fprintf(stderr, "%s: invalid DMA power mode\n", __func__);
516
 
+        }
517
 
+        break;
518
 
+
519
 
+    case 0x78: /* DMA4_GCR */
520
 
+        s->gcr = value & 0x00ff00ff;
521
 
+        if ((value & 0xff) == 0x00) { /* MAX_CHANNEL_FIFO_DEPTH */
522
 
+            fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __func__);
523
 
+        }
524
 
+        break;
525
 
+
526
 
+    case 0x80 ... 0xfff:
527
 
+        addr -= 0x80;
528
 
+        chnum = addr / 0x60;
529
 
+        addr -= chnum * 0x60;
530
 
+        omap_dma4_write_ch(s, s->ch + chnum, (uint32_t)addr, value);
531
 
+        break;
532
 
+
533
 
+    case 0x00: /* DMA4_REVISION */
534
 
+    case 0x28: /* DMA4_SYSSTATUS */
535
 
+    case 0x64: /* DMA4_CAPS_0 */
536
 
+    case 0x6c: /* DMA4_CAPS_2 */
537
 
+    case 0x70: /* DMA4_CAPS_3 */
538
 
+    case 0x74: /* DMA4_CAPS_4 */
539
 
+        OMAP_RO_REG(addr);
540
 
+        break;
541
 
+
542
 
+    default:
543
 
+        OMAP_BAD_REG(addr);
544
 
+        break;
545
 
     }
546
 
 }
547
 
 
548
 
1.8.1.2
549