qemu/hw/dma/xilinx_dpdma.c
<<
>>
Prefs
   1/*
   2 * xilinx_dpdma.c
   3 *
   4 *  Copyright (C) 2015 : GreenSocs Ltd
   5 *      http://www.greensocs.com/ , email: info@greensocs.com
   6 *
   7 *  Developed by :
   8 *  Frederic Konrad   <fred.konrad@greensocs.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation, either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License along
  21 * with this program; if not, see <http://www.gnu.org/licenses/>.
  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 * Registers offset for DPDMA.
  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 * Descriptor control field.
 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    /* transfer size in byte. */
 162    uint32_t xfer_size;
 163    uint32_t line_size_stride;
 164    uint32_t timestamp_lsb;
 165    uint32_t timestamb_msb;
 166    /* contains extension for both descriptor and source. */
 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        /* Should not happen. */
 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        /* Should not happen. */
 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            /* Should not happen. */
 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     * Trying to read a write only register.
 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         * Trying to write to a read only register..
 543         */
 544        break;
 545    case DPDMA_GBL:
 546        /*
 547         * This is a write only register so it's read as zero in the read
 548         * callback.
 549         * We store the value anyway so we can know if the channel is
 550         * enabled.
 551         */
 552        s->registers[offset] = value & 0x00000FFF;
 553        /*
 554         * TODO: enable the channels, change next fetch to start address.
 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     * XXX: Maybe we can improve that:
 679     *      - load descriptors.
 680     *      - fetch all data in one call if they are contiguous for example.
 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 * Set the host location to be filled with the data.
 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