1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "xilinx_dpdma.h"
26
27#ifndef DEBUG_DPDMA
28#define DEBUG_DPDMA 0
29#endif
30
31#define DPRINTF(fmt, ...) do { \
32 if (DEBUG_DPDMA) { \
33 qemu_log("xilinx_dpdma: " fmt , ## __VA_ARGS__); \
34 } \
35} while (0);
36
37
38
39
40#define DPDMA_ERR_CTRL (0x00000000)
41#define DPDMA_ISR (0x00000004 >> 2)
42#define DPDMA_IMR (0x00000008 >> 2)
43#define DPDMA_IEN (0x0000000C >> 2)
44#define DPDMA_IDS (0x00000010 >> 2)
45#define DPDMA_EISR (0x00000014 >> 2)
46#define DPDMA_EIMR (0x00000018 >> 2)
47#define DPDMA_EIEN (0x0000001C >> 2)
48#define DPDMA_EIDS (0x00000020 >> 2)
49#define DPDMA_CNTL (0x00000100 >> 2)
50#define DPDMA_GBL (0x00000104 >> 2)
51#define DPDMA_ALC0_CNTL (0x00000108 >> 2)
52#define DPDMA_ALC0_STATUS (0x0000010C >> 2)
53#define DPDMA_ALC0_MAX (0x00000110 >> 2)
54#define DPDMA_ALC0_MIN (0x00000114 >> 2)
55#define DPDMA_ALC0_ACC (0x00000118 >> 2)
56#define DPDMA_ALC0_ACC_TRAN (0x0000011C >> 2)
57#define DPDMA_ALC1_CNTL (0x00000120 >> 2)
58#define DPDMA_ALC1_STATUS (0x00000124 >> 2)
59#define DPDMA_ALC1_MAX (0x00000128 >> 2)
60#define DPDMA_ALC1_MIN (0x0000012C >> 2)
61#define DPDMA_ALC1_ACC (0x00000130 >> 2)
62#define DPDMA_ALC1_ACC_TRAN (0x00000134 >> 2)
63#define DPDMA_CH0_DSCR_STRT_ADDRE (0x00000200 >> 2)
64#define DPDMA_CH0_DSCR_STRT_ADDR (0x00000204 >> 2)
65#define DPDMA_CH0_DSCR_NEXT_ADDRE (0x00000208 >> 2)
66#define DPDMA_CH0_DSCR_NEXT_ADDR (0x0000020C >> 2)
67#define DPDMA_CH0_PYLD_CUR_ADDRE (0x00000210 >> 2)
68#define DPDMA_CH0_PYLD_CUR_ADDR (0x00000214 >> 2)
69#define DPDMA_CH0_CNTL (0x00000218 >> 2)
70#define DPDMA_CH0_STATUS (0x0000021C >> 2)
71#define DPDMA_CH0_VDO (0x00000220 >> 2)
72#define DPDMA_CH0_PYLD_SZ (0x00000224 >> 2)
73#define DPDMA_CH0_DSCR_ID (0x00000228 >> 2)
74#define DPDMA_CH1_DSCR_STRT_ADDRE (0x00000300 >> 2)
75#define DPDMA_CH1_DSCR_STRT_ADDR (0x00000304 >> 2)
76#define DPDMA_CH1_DSCR_NEXT_ADDRE (0x00000308 >> 2)
77#define DPDMA_CH1_DSCR_NEXT_ADDR (0x0000030C >> 2)
78#define DPDMA_CH1_PYLD_CUR_ADDRE (0x00000310 >> 2)
79#define DPDMA_CH1_PYLD_CUR_ADDR (0x00000314 >> 2)
80#define DPDMA_CH1_CNTL (0x00000318 >> 2)
81#define DPDMA_CH1_STATUS (0x0000031C >> 2)
82#define DPDMA_CH1_VDO (0x00000320 >> 2)
83#define DPDMA_CH1_PYLD_SZ (0x00000324 >> 2)
84#define DPDMA_CH1_DSCR_ID (0x00000328 >> 2)
85#define DPDMA_CH2_DSCR_STRT_ADDRE (0x00000400 >> 2)
86#define DPDMA_CH2_DSCR_STRT_ADDR (0x00000404 >> 2)
87#define DPDMA_CH2_DSCR_NEXT_ADDRE (0x00000408 >> 2)
88#define DPDMA_CH2_DSCR_NEXT_ADDR (0x0000040C >> 2)
89#define DPDMA_CH2_PYLD_CUR_ADDRE (0x00000410 >> 2)
90#define DPDMA_CH2_PYLD_CUR_ADDR (0x00000414 >> 2)
91#define DPDMA_CH2_CNTL (0x00000418 >> 2)
92#define DPDMA_CH2_STATUS (0x0000041C >> 2)
93#define DPDMA_CH2_VDO (0x00000420 >> 2)
94#define DPDMA_CH2_PYLD_SZ (0x00000424 >> 2)
95#define DPDMA_CH2_DSCR_ID (0x00000428 >> 2)
96#define DPDMA_CH3_DSCR_STRT_ADDRE (0x00000500 >> 2)
97#define DPDMA_CH3_DSCR_STRT_ADDR (0x00000504 >> 2)
98#define DPDMA_CH3_DSCR_NEXT_ADDRE (0x00000508 >> 2)
99#define DPDMA_CH3_DSCR_NEXT_ADDR (0x0000050C >> 2)
100#define DPDMA_CH3_PYLD_CUR_ADDRE (0x00000510 >> 2)
101#define DPDMA_CH3_PYLD_CUR_ADDR (0x00000514 >> 2)
102#define DPDMA_CH3_CNTL (0x00000518 >> 2)
103#define DPDMA_CH3_STATUS (0x0000051C >> 2)
104#define DPDMA_CH3_VDO (0x00000520 >> 2)
105#define DPDMA_CH3_PYLD_SZ (0x00000524 >> 2)
106#define DPDMA_CH3_DSCR_ID (0x00000528 >> 2)
107#define DPDMA_CH4_DSCR_STRT_ADDRE (0x00000600 >> 2)
108#define DPDMA_CH4_DSCR_STRT_ADDR (0x00000604 >> 2)
109#define DPDMA_CH4_DSCR_NEXT_ADDRE (0x00000608 >> 2)
110#define DPDMA_CH4_DSCR_NEXT_ADDR (0x0000060C >> 2)
111#define DPDMA_CH4_PYLD_CUR_ADDRE (0x00000610 >> 2)
112#define DPDMA_CH4_PYLD_CUR_ADDR (0x00000614 >> 2)
113#define DPDMA_CH4_CNTL (0x00000618 >> 2)
114#define DPDMA_CH4_STATUS (0x0000061C >> 2)
115#define DPDMA_CH4_VDO (0x00000620 >> 2)
116#define DPDMA_CH4_PYLD_SZ (0x00000624 >> 2)
117#define DPDMA_CH4_DSCR_ID (0x00000628 >> 2)
118#define DPDMA_CH5_DSCR_STRT_ADDRE (0x00000700 >> 2)
119#define DPDMA_CH5_DSCR_STRT_ADDR (0x00000704 >> 2)
120#define DPDMA_CH5_DSCR_NEXT_ADDRE (0x00000708 >> 2)
121#define DPDMA_CH5_DSCR_NEXT_ADDR (0x0000070C >> 2)
122#define DPDMA_CH5_PYLD_CUR_ADDRE (0x00000710 >> 2)
123#define DPDMA_CH5_PYLD_CUR_ADDR (0x00000714 >> 2)
124#define DPDMA_CH5_CNTL (0x00000718 >> 2)
125#define DPDMA_CH5_STATUS (0x0000071C >> 2)
126#define DPDMA_CH5_VDO (0x00000720 >> 2)
127#define DPDMA_CH5_PYLD_SZ (0x00000724 >> 2)
128#define DPDMA_CH5_DSCR_ID (0x00000728 >> 2)
129#define DPDMA_ECO (0x00000FFC >> 2)
130
131
132
133
134#define CONTROL_PREAMBLE_VALUE 0xA5
135
136#define CONTROL_PREAMBLE 0xFF
137#define EN_DSCR_DONE_INTR (1 << 8)
138#define EN_DSCR_UPDATE (1 << 9)
139#define IGNORE_DONE (1 << 10)
140#define AXI_BURST_TYPE (1 << 11)
141#define AXCACHE (0x0F << 12)
142#define AXPROT (0x2 << 16)
143#define DESCRIPTOR_MODE (1 << 18)
144#define LAST_DESCRIPTOR (1 << 19)
145#define ENABLE_CRC (1 << 20)
146#define LAST_DESCRIPTOR_OF_FRAME (1 << 21)
147
148typedef enum DPDMABurstType {
149 DPDMA_INCR = 0,
150 DPDMA_FIXED = 1
151} DPDMABurstType;
152
153typedef enum DPDMAMode {
154 DPDMA_CONTIGOUS = 0,
155 DPDMA_FRAGMENTED = 1
156} DPDMAMode;
157
158typedef struct DPDMADescriptor {
159 uint32_t control;
160 uint32_t descriptor_id;
161
162 uint32_t xfer_size;
163 uint32_t line_size_stride;
164 uint32_t timestamp_lsb;
165 uint32_t timestamb_msb;
166
167 uint32_t address_extension;
168 uint32_t next_descriptor;
169 uint32_t source_address;
170 uint32_t address_extension_23;
171 uint32_t address_extension_45;
172 uint32_t source_address2;
173 uint32_t source_address3;
174 uint32_t source_address4;
175 uint32_t source_address5;
176 uint32_t crc;
177} DPDMADescriptor;
178
179static bool xilinx_dpdma_desc_is_last(DPDMADescriptor *desc)
180{
181 return ((desc->control & 0x00080000) != 0);
182}
183
184static bool xilinx_dpdma_desc_is_last_of_frame(DPDMADescriptor *desc)
185{
186 return ((desc->control & 0x00200000) != 0);
187}
188
189static uint64_t xilinx_dpdma_desc_get_next_descriptor_address(DPDMADescriptor
190 *desc)
191{
192 return desc->next_descriptor
193 + ((desc->address_extension & 0x00000FFF) << 8);
194}
195
196static uint64_t xilinx_dpdma_desc_get_source_address(DPDMADescriptor *desc,
197 uint8_t frag)
198{
199 uint64_t addr = 0;
200 assert(frag < 5);
201
202 switch (frag) {
203 case 0:
204 addr = desc->source_address
205 + (extract32(desc->address_extension, 16, 12) << 20);
206 break;
207 case 1:
208 addr = desc->source_address2
209 + (extract32(desc->address_extension_23, 0, 12) << 8);
210 break;
211 case 2:
212 addr = desc->source_address3
213 + (extract32(desc->address_extension_23, 16, 12) << 20);
214 break;
215 case 3:
216 addr = desc->source_address4
217 + (extract32(desc->address_extension_45, 0, 12) << 8);
218 break;
219 case 4:
220 addr = desc->source_address5
221 + (extract32(desc->address_extension_45, 16, 12) << 20);
222 break;
223 default:
224 addr = 0;
225 break;
226 }
227
228 return addr;
229}
230
231static uint32_t xilinx_dpdma_desc_get_transfer_size(DPDMADescriptor *desc)
232{
233 return desc->xfer_size;
234}
235
236static uint32_t xilinx_dpdma_desc_get_line_size(DPDMADescriptor *desc)
237{
238 return desc->line_size_stride & 0x3FFFF;
239}
240
241static uint32_t xilinx_dpdma_desc_get_line_stride(DPDMADescriptor *desc)
242{
243 return (desc->line_size_stride >> 18) * 16;
244}
245
246static inline bool xilinx_dpdma_desc_crc_enabled(DPDMADescriptor *desc)
247{
248 return ((desc->control & (1 << 20)) != 0);
249}
250
251static inline bool xilinx_dpdma_desc_check_crc(DPDMADescriptor *desc)
252{
253 uint32_t *p = (uint32_t *)(desc);
254 uint32_t crc = 0;
255 uint8_t i;
256
257 for (i = 0; i < 15; i++) {
258 crc += p[i];
259 }
260
261 return (crc == desc->crc);
262}
263
264static inline bool xilinx_dpdma_desc_completion_interrupt(DPDMADescriptor *desc)
265{
266 return ((desc->control & (1 << 8)) != 0);
267}
268
269static inline bool xilinx_dpdma_desc_is_valid(DPDMADescriptor *desc)
270{
271 return ((desc->control & 0xFF) == 0xA5);
272}
273
274static inline bool xilinx_dpdma_desc_is_contiguous(DPDMADescriptor *desc)
275{
276 return ((desc->control & 0x00040000) == 0);
277}
278
279struct XilinxDPDMAState {
280 SysBusDevice parent_obj;
281
282 MemoryRegion *dma_mr;
283 AddressSpace *dma_as;
284 MemoryRegion iomem;
285 uint32_t registers[0x1000 >> 2];
286 uint8_t *data[6];
287
288 uint64_t next_desc_addr[6];
289 qemu_irq irq;
290
291 bool temp;
292};
293
294static const VMStateDescription vmstate_xilinx_dpdma = {
295 .name = TYPE_XILINX_DPDMA,
296 .version_id = 1,
297 .fields = (VMStateField[]) {
298
299 VMSTATE_END_OF_LIST()
300 }
301};
302
303static void xilinx_dpdma_update_irq(XilinxDPDMAState *s)
304{
305 bool flags;
306
307 flags = ((s->registers[DPDMA_ISR] & (~s->registers[DPDMA_IMR]))
308 || (s->registers[DPDMA_EISR] & (~s->registers[DPDMA_EIMR])));
309 qemu_set_irq(s->irq, flags);
310}
311
312static uint64_t xilinx_dpdma_descriptor_start_address(XilinxDPDMAState *s,
313 uint8_t channel)
314{
315 switch (channel) {
316 case 0:
317 return (s->registers[DPDMA_CH0_DSCR_STRT_ADDRE] << 16)
318 + s->registers[DPDMA_CH0_DSCR_STRT_ADDR];
319 break;
320 case 1:
321 return (s->registers[DPDMA_CH1_DSCR_STRT_ADDRE] << 16)
322 + s->registers[DPDMA_CH1_DSCR_STRT_ADDR];
323 break;
324 case 2:
325 return (s->registers[DPDMA_CH2_DSCR_STRT_ADDRE] << 16)
326 + s->registers[DPDMA_CH2_DSCR_STRT_ADDR];
327 break;
328 case 3:
329 return (s->registers[DPDMA_CH3_DSCR_STRT_ADDRE] << 16)
330 + s->registers[DPDMA_CH3_DSCR_STRT_ADDR];
331 break;
332 case 4:
333 return (s->registers[DPDMA_CH4_DSCR_STRT_ADDRE] << 16)
334 + s->registers[DPDMA_CH4_DSCR_STRT_ADDR];
335 break;
336 case 5:
337 return (s->registers[DPDMA_CH5_DSCR_STRT_ADDRE] << 16)
338 + s->registers[DPDMA_CH5_DSCR_STRT_ADDR];
339 break;
340 default:
341
342 return 0;
343 break;
344 }
345}
346
347static bool xilinx_dpdma_is_channel_enabled(XilinxDPDMAState *s,
348 uint8_t channel)
349{
350 switch (channel) {
351 case 0:
352 return ((s->registers[DPDMA_CH0_CNTL] & 0x01) != 0);
353 break;
354 case 1:
355 return ((s->registers[DPDMA_CH1_CNTL] & 0x01) != 0);
356 break;
357 case 2:
358 return ((s->registers[DPDMA_CH2_CNTL] & 0x01) != 0);
359 break;
360 case 3:
361 return ((s->registers[DPDMA_CH3_CNTL] & 0x01) != 0);
362 break;
363 case 4:
364 return ((s->registers[DPDMA_CH4_CNTL] & 0x01) != 0);
365 break;
366 case 5:
367 return ((s->registers[DPDMA_CH5_CNTL] & 0x01) != 0);
368 break;
369 default:
370
371 return 0;
372 break;
373 }
374}
375
376static bool xilinx_dpdma_is_channel_paused(XilinxDPDMAState *s,
377 uint8_t channel)
378{
379 switch (channel) {
380 case 0:
381 return ((s->registers[DPDMA_CH0_CNTL] & 0x2) != 0);
382 case 1:
383 return ((s->registers[DPDMA_CH1_CNTL] & 0x2) != 0);
384 case 2:
385 return ((s->registers[DPDMA_CH2_CNTL] & 0x2) != 0);
386 case 3:
387 return ((s->registers[DPDMA_CH3_CNTL] & 0x2) != 0);
388 case 4:
389 return ((s->registers[DPDMA_CH4_CNTL] & 0x2) != 0);
390 case 5:
391 return ((s->registers[DPDMA_CH5_CNTL] & 0x2) != 0);
392 default:
393
394 return false;
395 }
396}
397
398static void xilinx_dpdma_pause_channel(XilinxDPDMAState *s,
399 uint8_t channel)
400{
401 switch (channel) {
402 case 0:
403 s->registers[DPDMA_CH0_CNTL] |= 0x2;
404 case 1:
405 s->registers[DPDMA_CH1_CNTL] |= 0x2;
406 case 2:
407 s->registers[DPDMA_CH2_CNTL] |= 0x2;
408 case 3:
409 s->registers[DPDMA_CH3_CNTL] |= 0x2;
410 case 4:
411 s->registers[DPDMA_CH4_CNTL] |= 0x2;
412 case 5:
413 s->registers[DPDMA_CH5_CNTL] |= 0x2;
414 }
415}
416
417#ifdef DEBUG_DPDMA
418static void xilinx_dpdma_dump_descriptor(DPDMADescriptor *desc)
419{
420 uint8_t *p = ((uint8_t *)(desc));
421 size_t i;
422
423 qemu_log("DUMP DESCRIPTOR:\n");
424 for (i = 0; i < 64; i++) {
425 qemu_log(" 0x%2.2X", *p++);
426 if (((i + 1) % 4) == 0) {
427 qemu_log("\n");
428 }
429 }
430}
431#endif
432
433static uint64_t xilinx_dpdma_read(void *opaque, hwaddr offset,
434 unsigned size)
435{
436 XilinxDPDMAState *s = XILINX_DPDMA(opaque);
437 assert(size == 4);
438 assert((offset % 4) == 0);
439 offset = offset >> 2;
440 DPRINTF("read @%" PRIx64 "\n", offset << 2);
441
442 switch (offset) {
443
444
445
446 case DPDMA_GBL:
447 return 0;
448 break;
449 default:
450 assert(offset <= (0xFFC >> 2));
451 return s->registers[offset];
452 break;
453 }
454 return 0;
455}
456
457static void xilinx_dpdma_write(void *opaque, hwaddr offset,
458 uint64_t value, unsigned size)
459{
460 XilinxDPDMAState *s = XILINX_DPDMA(opaque);
461 assert(size == 4);
462 assert((offset % 4) == 0);
463 offset = offset >> 2;
464 DPRINTF("write @%" PRIx64 " = 0x%8.8lX\n", offset << 2, value);
465
466 switch (offset) {
467 case DPDMA_ISR:
468 value = ~value;
469 s->registers[DPDMA_ISR] &= value;
470 xilinx_dpdma_update_irq(s);
471 break;
472 case DPDMA_IEN:
473 value = ~value;
474 s->registers[DPDMA_IMR] &= value;
475 break;
476 case DPDMA_IDS:
477 s->registers[DPDMA_IMR] |= value;
478 break;
479 case DPDMA_EISR:
480 value = ~value;
481 s->registers[DPDMA_EISR] &= value;
482 xilinx_dpdma_update_irq(s);
483 break;
484 case DPDMA_EIEN:
485 value = ~value;
486 s->registers[DPDMA_EIMR] &= value;
487 break;
488 case DPDMA_EIDS:
489 s->registers[DPDMA_EIMR] |= value;
490 break;
491 case DPDMA_IMR:
492 case DPDMA_EIMR:
493 case DPDMA_CH0_DSCR_NEXT_ADDRE:
494 case DPDMA_CH0_DSCR_NEXT_ADDR:
495 case DPDMA_CH1_DSCR_NEXT_ADDRE:
496 case DPDMA_CH1_DSCR_NEXT_ADDR:
497 case DPDMA_CH2_DSCR_NEXT_ADDRE:
498 case DPDMA_CH2_DSCR_NEXT_ADDR:
499 case DPDMA_CH3_DSCR_NEXT_ADDRE:
500 case DPDMA_CH3_DSCR_NEXT_ADDR:
501 case DPDMA_CH4_DSCR_NEXT_ADDRE:
502 case DPDMA_CH4_DSCR_NEXT_ADDR:
503 case DPDMA_CH5_DSCR_NEXT_ADDRE:
504 case DPDMA_CH5_DSCR_NEXT_ADDR:
505 case DPDMA_CH0_PYLD_CUR_ADDRE:
506 case DPDMA_CH0_PYLD_CUR_ADDR:
507 case DPDMA_CH1_PYLD_CUR_ADDRE:
508 case DPDMA_CH1_PYLD_CUR_ADDR:
509 case DPDMA_CH2_PYLD_CUR_ADDRE:
510 case DPDMA_CH2_PYLD_CUR_ADDR:
511 case DPDMA_CH3_PYLD_CUR_ADDRE:
512 case DPDMA_CH3_PYLD_CUR_ADDR:
513 case DPDMA_CH4_PYLD_CUR_ADDRE:
514 case DPDMA_CH4_PYLD_CUR_ADDR:
515 case DPDMA_CH5_PYLD_CUR_ADDRE:
516 case DPDMA_CH5_PYLD_CUR_ADDR:
517 case DPDMA_CH0_STATUS:
518 case DPDMA_CH1_STATUS:
519 case DPDMA_CH2_STATUS:
520 case DPDMA_CH3_STATUS:
521 case DPDMA_CH4_STATUS:
522 case DPDMA_CH5_STATUS:
523 case DPDMA_CH0_VDO:
524 case DPDMA_CH1_VDO:
525 case DPDMA_CH2_VDO:
526 case DPDMA_CH3_VDO:
527 case DPDMA_CH4_VDO:
528 case DPDMA_CH5_VDO:
529 case DPDMA_CH0_PYLD_SZ:
530 case DPDMA_CH1_PYLD_SZ:
531 case DPDMA_CH2_PYLD_SZ:
532 case DPDMA_CH3_PYLD_SZ:
533 case DPDMA_CH4_PYLD_SZ:
534 case DPDMA_CH5_PYLD_SZ:
535 case DPDMA_CH0_DSCR_ID:
536 case DPDMA_CH1_DSCR_ID:
537 case DPDMA_CH2_DSCR_ID:
538 case DPDMA_CH3_DSCR_ID:
539 case DPDMA_CH4_DSCR_ID:
540 case DPDMA_CH5_DSCR_ID:
541
542
543
544 break;
545 case DPDMA_GBL:
546
547
548
549
550
551
552 s->registers[offset] = value & 0x00000FFF;
553
554
555
556 break;
557 case DPDMA_CH0_DSCR_STRT_ADDRE:
558 case DPDMA_CH1_DSCR_STRT_ADDRE:
559 case DPDMA_CH2_DSCR_STRT_ADDRE:
560 case DPDMA_CH3_DSCR_STRT_ADDRE:
561 case DPDMA_CH4_DSCR_STRT_ADDRE:
562 case DPDMA_CH5_DSCR_STRT_ADDRE:
563 value &= 0x0000FFFF;
564 s->registers[offset] = value;
565 break;
566 case DPDMA_CH0_CNTL:
567 case DPDMA_CH1_CNTL:
568 case DPDMA_CH2_CNTL:
569 case DPDMA_CH3_CNTL:
570 case DPDMA_CH4_CNTL:
571 case DPDMA_CH5_CNTL:
572 value &= 0x3FFFFFFF;
573 s->registers[offset] = value;
574 break;
575 default:
576 assert(offset <= (0xFFC >> 2));
577 s->registers[offset] = value;
578 break;
579 }
580}
581
582static const MemoryRegionOps dma_ops = {
583 .read = xilinx_dpdma_read,
584 .write = xilinx_dpdma_write,
585 .endianness = DEVICE_NATIVE_ENDIAN,
586};
587
588static void xilinx_dpdma_realize(DeviceState *dev, Error **errp)
589{
590 XilinxDPDMAState *s = XILINX_DPDMA(dev);
591
592 s->dma_as = s->dma_mr ? address_space_init_shareable(s->dma_mr, NULL)
593 : &address_space_memory;
594}
595
596static void xilinx_dpdma_init(Object *obj)
597{
598 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
599 XilinxDPDMAState *s = XILINX_DPDMA(obj);
600
601 memory_region_init_io(&s->iomem, obj, &dma_ops, s,
602 TYPE_XILINX_DPDMA, 0x1000);
603 sysbus_init_mmio(sbd, &s->iomem);
604 sysbus_init_irq(sbd, &s->irq);
605
606 object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
607 (Object **)&s->dma_mr,
608 qdev_prop_allow_set_link_before_realize,
609 OBJ_PROP_LINK_UNREF_ON_RELEASE,
610 &error_abort);
611}
612
613static void xilinx_dpdma_reset(DeviceState *dev)
614{
615 XilinxDPDMAState *s = XILINX_DPDMA(dev);
616 memset(s->registers, 0, sizeof(s->registers));
617 s->registers[DPDMA_IMR] = 0x07FFFFFF;
618 s->registers[DPDMA_EIMR] = 0xFFFFFFFF;
619 s->registers[DPDMA_ALC0_MIN] = 0x0000FFFF;
620 s->registers[DPDMA_ALC1_MIN] = 0x0000FFFF;
621}
622
623static void xilinx_dpdma_class_init(ObjectClass *oc, void *data)
624{
625 DeviceClass *dc = DEVICE_CLASS(oc);
626
627 dc->vmsd = &vmstate_xilinx_dpdma;
628 dc->reset = xilinx_dpdma_reset;
629 dc->realize = xilinx_dpdma_realize;
630}
631
632static const TypeInfo xilinx_dpdma_info = {
633 .name = TYPE_XILINX_DPDMA,
634 .parent = TYPE_SYS_BUS_DEVICE,
635 .instance_size = sizeof(XilinxDPDMAState),
636 .instance_init = xilinx_dpdma_init,
637 .class_init = xilinx_dpdma_class_init,
638};
639
640static void xilinx_dpdma_register_types(void)
641{
642 type_register_static(&xilinx_dpdma_info);
643}
644
645bool xilinx_dpdma_start_operation(XilinxDPDMAState *s, uint8_t channel)
646{
647 uint64_t desc_addr;
648 uint64_t source_addr[6];
649 DPDMADescriptor desc;
650 bool done;
651 size_t ptr = 0;
652
653 assert(channel <= 5);
654
655 DPRINTF("dpdma_start_channel() on channel %u\n", channel);
656
657 if (xilinx_dpdma_is_channel_paused(s, channel)) {
658 DPRINTF("Channel is paused..\n");
659 return false;
660 }
661
662 if (!xilinx_dpdma_is_channel_enabled(s, channel)) {
663 DPRINTF("Channel isn't enabled..\n");
664 return false;
665 }
666
667 if ((s->registers[DPDMA_GBL] & (1 << channel)) ||
668 (s->registers[DPDMA_GBL] & ((1 << channel) << 6))) {
669 desc_addr = xilinx_dpdma_descriptor_start_address(s, channel);
670 } else {
671 desc_addr = s->next_desc_addr[channel];
672 }
673
674 s->registers[DPDMA_ISR] |= (1 << 27);
675 xilinx_dpdma_update_irq(s);
676
677
678
679
680
681
682
683 do {
684 if (dma_memory_read(s->dma_as, desc_addr, &desc,
685 sizeof(DPDMADescriptor))) {
686 s->registers[DPDMA_EISR] |= ((1 << 1) << channel);
687 xilinx_dpdma_update_irq(s);
688 DPRINTF("Can't get the descriptor.\n");
689 return false;
690 }
691 #ifdef DEBUG_DPDMA
692 xilinx_dpdma_dump_descriptor(&desc);
693 #endif
694
695 DPRINTF("location of the descriptor: 0x%8.8lx\n", desc_addr);
696 if (!xilinx_dpdma_desc_is_valid(&desc)) {
697 s->registers[DPDMA_EISR] |= ((1 << 7) << channel);
698 xilinx_dpdma_update_irq(s);
699 DPRINTF("Invalid descriptor..\n");
700 break;
701 }
702
703 if (xilinx_dpdma_desc_crc_enabled(&desc)
704 & !xilinx_dpdma_desc_check_crc(&desc)) {
705 s->registers[DPDMA_EISR] |= ((1 << 13) << channel);
706 xilinx_dpdma_update_irq(s);
707 DPRINTF("Bad CRC for descriptor..\n");
708 break;
709 }
710
711 if (s->data[channel]) {
712 int64_t transfer_len =
713 xilinx_dpdma_desc_get_transfer_size(&desc);
714 uint32_t line_size = xilinx_dpdma_desc_get_line_size(&desc);
715 uint32_t line_stride = xilinx_dpdma_desc_get_line_stride(&desc);
716 if (xilinx_dpdma_desc_is_contiguous(&desc)) {
717 source_addr[0] =
718 xilinx_dpdma_desc_get_source_address(&desc, 0);
719 while (transfer_len != 0) {
720 if (dma_memory_read(s->dma_as,
721 source_addr[0],
722 &(s->data[channel][ptr]),
723 line_size)) {
724 s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
725 xilinx_dpdma_update_irq(s);
726 DPRINTF("Can't get data.\n");
727 break;
728 }
729 ptr += line_size;
730 transfer_len -= line_size;
731 source_addr[0] += line_stride;
732 }
733 } else {
734 DPRINTF("Source address:\n");
735 int frag;
736 for (frag = 0; frag < 5; frag++) {
737 source_addr[frag] =
738 xilinx_dpdma_desc_get_source_address(&desc, frag);
739 DPRINTF("Fragment %u: 0x%8.8lX\n", frag + 1,
740 source_addr[frag]);
741 }
742
743 frag = 0;
744 while (transfer_len < 0) {
745 if (frag >= 5) {
746 break;
747 }
748 size_t fragment_len = 4096 - (source_addr[frag] % 4096);
749
750 if (dma_memory_read(s->dma_as,
751 source_addr[frag],
752 &(s->data[channel][ptr]),
753 fragment_len)) {
754 s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
755 xilinx_dpdma_update_irq(s);
756 DPRINTF("Can't get data.\n");
757 break;
758 }
759 ptr += fragment_len;
760 transfer_len -= fragment_len;
761 frag += 1;
762 }
763 }
764 }
765 desc_addr = xilinx_dpdma_desc_get_next_descriptor_address(&desc);
766 DPRINTF("next descriptor address 0x%lx\n", desc_addr);
767
768 if (xilinx_dpdma_desc_completion_interrupt(&desc)) {
769 s->registers[DPDMA_ISR] |= (1 << channel);
770 xilinx_dpdma_update_irq(s);
771 }
772
773 done = xilinx_dpdma_desc_is_last_of_frame(&desc);
774 if (xilinx_dpdma_desc_is_last(&desc)) {
775 done = true;
776 xilinx_dpdma_pause_channel(s, channel);
777 }
778 } while (!done);
779
780 return true;
781}
782
783
784
785
786void xilinx_dpdma_set_host_data_location(XilinxDPDMAState *s, uint8_t channel,
787 void *p)
788{
789 if (!s) {
790 qemu_log_mask(LOG_UNIMP, "DPDMA client not attached to valid DPDMA"
791 " instance\n");
792 return;
793 }
794
795 assert(channel <= 5);
796 s->data[channel] = p;
797}
798
799type_init(xilinx_dpdma_register_types)
800