qemu/hw/dma/xlnx_dpdma.c
<<
>>
Prefs
   1/*
   2 * xlnx_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 "qemu/osdep.h"
  26#include "qapi/error.h"
  27#include "qemu/log.h"
  28#include "hw/dma/xlnx_dpdma.h"
  29
  30#ifndef DEBUG_DPDMA
  31#define DEBUG_DPDMA 0
  32#endif
  33
  34#define DPRINTF(fmt, ...) do {                                                 \
  35    if (DEBUG_DPDMA) {                                                         \
  36        qemu_log("xlnx_dpdma: " fmt , ## __VA_ARGS__);                         \
  37    }                                                                          \
  38} while (0);
  39
  40/*
  41 * Registers offset for DPDMA.
  42 */
  43#define DPDMA_ERR_CTRL                        (0x0000)
  44#define DPDMA_ISR                             (0x0004 >> 2)
  45#define DPDMA_IMR                             (0x0008 >> 2)
  46#define DPDMA_IEN                             (0x000C >> 2)
  47#define DPDMA_IDS                             (0x0010 >> 2)
  48#define DPDMA_EISR                            (0x0014 >> 2)
  49#define DPDMA_EIMR                            (0x0018 >> 2)
  50#define DPDMA_EIEN                            (0x001C >> 2)
  51#define DPDMA_EIDS                            (0x0020 >> 2)
  52#define DPDMA_CNTL                            (0x0100 >> 2)
  53
  54#define DPDMA_GBL                             (0x0104 >> 2)
  55#define DPDMA_GBL_TRG_CH(n)                   (1 << n)
  56#define DPDMA_GBL_RTRG_CH(n)                  (1 << 6 << n)
  57
  58#define DPDMA_ALC0_CNTL                       (0x0108 >> 2)
  59#define DPDMA_ALC0_STATUS                     (0x010C >> 2)
  60#define DPDMA_ALC0_MAX                        (0x0110 >> 2)
  61#define DPDMA_ALC0_MIN                        (0x0114 >> 2)
  62#define DPDMA_ALC0_ACC                        (0x0118 >> 2)
  63#define DPDMA_ALC0_ACC_TRAN                   (0x011C >> 2)
  64#define DPDMA_ALC1_CNTL                       (0x0120 >> 2)
  65#define DPDMA_ALC1_STATUS                     (0x0124 >> 2)
  66#define DPDMA_ALC1_MAX                        (0x0128 >> 2)
  67#define DPDMA_ALC1_MIN                        (0x012C >> 2)
  68#define DPDMA_ALC1_ACC                        (0x0130 >> 2)
  69#define DPDMA_ALC1_ACC_TRAN                   (0x0134 >> 2)
  70
  71#define DPDMA_DSCR_STRT_ADDRE_CH(n)           ((0x0200 + n * 0x100) >> 2)
  72#define DPDMA_DSCR_STRT_ADDR_CH(n)            ((0x0204 + n * 0x100) >> 2)
  73#define DPDMA_DSCR_NEXT_ADDRE_CH(n)           ((0x0208 + n * 0x100) >> 2)
  74#define DPDMA_DSCR_NEXT_ADDR_CH(n)            ((0x020C + n * 0x100) >> 2)
  75#define DPDMA_PYLD_CUR_ADDRE_CH(n)            ((0x0210 + n * 0x100) >> 2)
  76#define DPDMA_PYLD_CUR_ADDR_CH(n)             ((0x0214 + n * 0x100) >> 2)
  77
  78#define DPDMA_CNTL_CH(n)                      ((0x0218 + n * 0x100) >> 2)
  79#define DPDMA_CNTL_CH_EN                      (1)
  80#define DPDMA_CNTL_CH_PAUSED                  (1 << 1)
  81
  82#define DPDMA_STATUS_CH(n)                    ((0x021C + n * 0x100) >> 2)
  83#define DPDMA_STATUS_BURST_TYPE               (1 << 4)
  84#define DPDMA_STATUS_MODE                     (1 << 5)
  85#define DPDMA_STATUS_EN_CRC                   (1 << 6)
  86#define DPDMA_STATUS_LAST_DSCR                (1 << 7)
  87#define DPDMA_STATUS_LDSCR_FRAME              (1 << 8)
  88#define DPDMA_STATUS_IGNR_DONE                (1 << 9)
  89#define DPDMA_STATUS_DSCR_DONE                (1 << 10)
  90#define DPDMA_STATUS_EN_DSCR_UP               (1 << 11)
  91#define DPDMA_STATUS_EN_DSCR_INTR             (1 << 12)
  92#define DPDMA_STATUS_PREAMBLE_OFF             (13)
  93
  94#define DPDMA_VDO_CH(n)                       ((0x0220 + n * 0x100) >> 2)
  95#define DPDMA_PYLD_SZ_CH(n)                   ((0x0224 + n * 0x100) >> 2)
  96#define DPDMA_DSCR_ID_CH(n)                   ((0x0228 + n * 0x100) >> 2)
  97
  98/*
  99 * Descriptor control field.
 100 */
 101#define CONTROL_PREAMBLE_VALUE                0xA5
 102
 103#define DSCR_CTRL_PREAMBLE                    0xFF
 104#define DSCR_CTRL_EN_DSCR_DONE_INTR           (1 << 8)
 105#define DSCR_CTRL_EN_DSCR_UPDATE              (1 << 9)
 106#define DSCR_CTRL_IGNORE_DONE                 (1 << 10)
 107#define DSCR_CTRL_AXI_BURST_TYPE              (1 << 11)
 108#define DSCR_CTRL_AXCACHE                     (0x0F << 12)
 109#define DSCR_CTRL_AXPROT                      (0x2 << 16)
 110#define DSCR_CTRL_DESCRIPTOR_MODE             (1 << 18)
 111#define DSCR_CTRL_LAST_DESCRIPTOR             (1 << 19)
 112#define DSCR_CTRL_ENABLE_CRC                  (1 << 20)
 113#define DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME    (1 << 21)
 114
 115/*
 116 * Descriptor timestamp field.
 117 */
 118#define STATUS_DONE                           (1 << 31)
 119
 120#define DPDMA_FRAG_MAX_SZ                     (4096)
 121
 122enum DPDMABurstType {
 123    DPDMA_INCR = 0,
 124    DPDMA_FIXED = 1
 125};
 126
 127enum DPDMAMode {
 128    DPDMA_CONTIGOUS = 0,
 129    DPDMA_FRAGMENTED = 1
 130};
 131
 132struct DPDMADescriptor {
 133    uint32_t control;
 134    uint32_t descriptor_id;
 135    /* transfer size in byte. */
 136    uint32_t xfer_size;
 137    uint32_t line_size_stride;
 138    uint32_t timestamp_lsb;
 139    uint32_t timestamp_msb;
 140    /* contains extension for both descriptor and source. */
 141    uint32_t address_extension;
 142    uint32_t next_descriptor;
 143    uint32_t source_address;
 144    uint32_t address_extension_23;
 145    uint32_t address_extension_45;
 146    uint32_t source_address2;
 147    uint32_t source_address3;
 148    uint32_t source_address4;
 149    uint32_t source_address5;
 150    uint32_t crc;
 151};
 152
 153typedef enum DPDMABurstType DPDMABurstType;
 154typedef enum DPDMAMode DPDMAMode;
 155typedef struct DPDMADescriptor DPDMADescriptor;
 156
 157static bool xlnx_dpdma_desc_is_last(DPDMADescriptor *desc)
 158{
 159    return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0);
 160}
 161
 162static bool xlnx_dpdma_desc_is_last_of_frame(DPDMADescriptor *desc)
 163{
 164    return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0);
 165}
 166
 167static uint64_t xlnx_dpdma_desc_get_source_address(DPDMADescriptor *desc,
 168                                                     uint8_t frag)
 169{
 170    uint64_t addr = 0;
 171    assert(frag < 5);
 172
 173    switch (frag) {
 174    case 0:
 175        addr = desc->source_address
 176            + (extract32(desc->address_extension, 16, 12) << 20);
 177        break;
 178    case 1:
 179        addr = desc->source_address2
 180            + (extract32(desc->address_extension_23, 0, 12) << 8);
 181        break;
 182    case 2:
 183        addr = desc->source_address3
 184            + (extract32(desc->address_extension_23, 16, 12) << 20);
 185        break;
 186    case 3:
 187        addr = desc->source_address4
 188            + (extract32(desc->address_extension_45, 0, 12) << 8);
 189        break;
 190    case 4:
 191        addr = desc->source_address5
 192            + (extract32(desc->address_extension_45, 16, 12) << 20);
 193        break;
 194    default:
 195        addr = 0;
 196        break;
 197    }
 198
 199    return addr;
 200}
 201
 202static uint32_t xlnx_dpdma_desc_get_transfer_size(DPDMADescriptor *desc)
 203{
 204    return desc->xfer_size;
 205}
 206
 207static uint32_t xlnx_dpdma_desc_get_line_size(DPDMADescriptor *desc)
 208{
 209    return extract32(desc->line_size_stride, 0, 18);
 210}
 211
 212static uint32_t xlnx_dpdma_desc_get_line_stride(DPDMADescriptor *desc)
 213{
 214    return extract32(desc->line_size_stride, 18, 14) * 16;
 215}
 216
 217static inline bool xlnx_dpdma_desc_crc_enabled(DPDMADescriptor *desc)
 218{
 219    return (desc->control & DSCR_CTRL_ENABLE_CRC) != 0;
 220}
 221
 222static inline bool xlnx_dpdma_desc_check_crc(DPDMADescriptor *desc)
 223{
 224    uint32_t *p = (uint32_t *)desc;
 225    uint32_t crc = 0;
 226    uint8_t i;
 227
 228    /*
 229     * CRC is calculated on the whole descriptor except the last 32bits word
 230     * using 32bits addition.
 231     */
 232    for (i = 0; i < 15; i++) {
 233        crc += p[i];
 234    }
 235
 236    return crc == desc->crc;
 237}
 238
 239static inline bool xlnx_dpdma_desc_completion_interrupt(DPDMADescriptor *desc)
 240{
 241    return (desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0;
 242}
 243
 244static inline bool xlnx_dpdma_desc_is_valid(DPDMADescriptor *desc)
 245{
 246    return (desc->control & DSCR_CTRL_PREAMBLE) == CONTROL_PREAMBLE_VALUE;
 247}
 248
 249static inline bool xlnx_dpdma_desc_is_contiguous(DPDMADescriptor *desc)
 250{
 251    return (desc->control & DSCR_CTRL_DESCRIPTOR_MODE) == 0;
 252}
 253
 254static inline bool xlnx_dpdma_desc_update_enabled(DPDMADescriptor *desc)
 255{
 256    return (desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0;
 257}
 258
 259static inline void xlnx_dpdma_desc_set_done(DPDMADescriptor *desc)
 260{
 261    desc->timestamp_msb |= STATUS_DONE;
 262}
 263
 264static inline bool xlnx_dpdma_desc_is_already_done(DPDMADescriptor *desc)
 265{
 266    return (desc->timestamp_msb & STATUS_DONE) != 0;
 267}
 268
 269static inline bool xlnx_dpdma_desc_ignore_done_bit(DPDMADescriptor *desc)
 270{
 271    return (desc->control & DSCR_CTRL_IGNORE_DONE) != 0;
 272}
 273
 274static const VMStateDescription vmstate_xlnx_dpdma = {
 275    .name = TYPE_XLNX_DPDMA,
 276    .version_id = 1,
 277    .fields = (VMStateField[]) {
 278        VMSTATE_UINT32_ARRAY(registers, XlnxDPDMAState,
 279                             XLNX_DPDMA_REG_ARRAY_SIZE),
 280        VMSTATE_BOOL_ARRAY(operation_finished, XlnxDPDMAState, 6),
 281        VMSTATE_END_OF_LIST()
 282    }
 283};
 284
 285static void xlnx_dpdma_update_irq(XlnxDPDMAState *s)
 286{
 287    bool flags;
 288
 289    flags = ((s->registers[DPDMA_ISR] & (~s->registers[DPDMA_IMR]))
 290          || (s->registers[DPDMA_EISR] & (~s->registers[DPDMA_EIMR])));
 291    qemu_set_irq(s->irq, flags);
 292}
 293
 294static uint64_t xlnx_dpdma_descriptor_start_address(XlnxDPDMAState *s,
 295                                                      uint8_t channel)
 296{
 297    return (s->registers[DPDMA_DSCR_STRT_ADDRE_CH(channel)] << 16)
 298          + s->registers[DPDMA_DSCR_STRT_ADDR_CH(channel)];
 299}
 300
 301static uint64_t xlnx_dpdma_descriptor_next_address(XlnxDPDMAState *s,
 302                                                     uint8_t channel)
 303{
 304    return ((uint64_t)s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] << 32)
 305           + s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)];
 306}
 307
 308static inline void xlnx_dpdma_set_desc_next_address(XlnxDPDMAState *s,
 309                                                      uint8_t channel,
 310                                                      uint64_t addr)
 311{
 312    s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] = extract64(addr, 32, 32);
 313    s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)] = extract64(addr, 0, 32);
 314}
 315
 316static bool xlnx_dpdma_is_channel_enabled(XlnxDPDMAState *s,
 317                                            uint8_t channel)
 318{
 319    return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_EN) != 0;
 320}
 321
 322static bool xlnx_dpdma_is_channel_paused(XlnxDPDMAState *s,
 323                                           uint8_t channel)
 324{
 325    return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_PAUSED) != 0;
 326}
 327
 328static inline bool xlnx_dpdma_is_channel_retriggered(XlnxDPDMAState *s,
 329                                                       uint8_t channel)
 330{
 331    /* Clear the retriggered bit after reading it. */
 332    bool channel_is_retriggered = s->registers[DPDMA_GBL]
 333                                & DPDMA_GBL_RTRG_CH(channel);
 334    s->registers[DPDMA_GBL] &= ~DPDMA_GBL_RTRG_CH(channel);
 335    return channel_is_retriggered;
 336}
 337
 338static inline bool xlnx_dpdma_is_channel_triggered(XlnxDPDMAState *s,
 339                                                     uint8_t channel)
 340{
 341    return s->registers[DPDMA_GBL] & DPDMA_GBL_TRG_CH(channel);
 342}
 343
 344static void xlnx_dpdma_update_desc_info(XlnxDPDMAState *s, uint8_t channel,
 345                                          DPDMADescriptor *desc)
 346{
 347    s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] =
 348                                extract32(desc->address_extension, 0, 16);
 349    s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)] = desc->next_descriptor;
 350    s->registers[DPDMA_PYLD_CUR_ADDRE_CH(channel)] =
 351                                extract32(desc->address_extension, 16, 16);
 352    s->registers[DPDMA_PYLD_CUR_ADDR_CH(channel)] = desc->source_address;
 353    s->registers[DPDMA_VDO_CH(channel)] =
 354                                extract32(desc->line_size_stride, 18, 14)
 355                                + (extract32(desc->line_size_stride, 0, 18)
 356                                  << 14);
 357    s->registers[DPDMA_PYLD_SZ_CH(channel)] = desc->xfer_size;
 358    s->registers[DPDMA_DSCR_ID_CH(channel)] = desc->descriptor_id;
 359
 360    /* Compute the status register with the descriptor information. */
 361    s->registers[DPDMA_STATUS_CH(channel)] =
 362                                extract32(desc->control, 0, 8) << 13;
 363    if ((desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0) {
 364        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_INTR;
 365    }
 366    if ((desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0) {
 367        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_UP;
 368    }
 369    if ((desc->timestamp_msb & STATUS_DONE) != 0) {
 370        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_DSCR_DONE;
 371    }
 372    if ((desc->control & DSCR_CTRL_IGNORE_DONE) != 0) {
 373        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_IGNR_DONE;
 374    }
 375    if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0) {
 376        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LDSCR_FRAME;
 377    }
 378    if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0) {
 379        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LAST_DSCR;
 380    }
 381    if ((desc->control & DSCR_CTRL_ENABLE_CRC) != 0) {
 382        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_CRC;
 383    }
 384    if ((desc->control & DSCR_CTRL_DESCRIPTOR_MODE) != 0) {
 385        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_MODE;
 386    }
 387    if ((desc->control & DSCR_CTRL_AXI_BURST_TYPE) != 0) {
 388        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_BURST_TYPE;
 389    }
 390}
 391
 392static void xlnx_dpdma_dump_descriptor(DPDMADescriptor *desc)
 393{
 394    if (DEBUG_DPDMA) {
 395        qemu_log("DUMP DESCRIPTOR:\n");
 396        qemu_hexdump((char *)desc, stdout, "", sizeof(DPDMADescriptor));
 397    }
 398}
 399
 400static uint64_t xlnx_dpdma_read(void *opaque, hwaddr offset,
 401                                unsigned size)
 402{
 403    XlnxDPDMAState *s = XLNX_DPDMA(opaque);
 404
 405    DPRINTF("read @%" HWADDR_PRIx "\n", offset);
 406    offset = offset >> 2;
 407
 408    switch (offset) {
 409    /*
 410     * Trying to read a write only register.
 411     */
 412    case DPDMA_GBL:
 413        return 0;
 414    default:
 415        assert(offset <= (0xFFC >> 2));
 416        return s->registers[offset];
 417    }
 418    return 0;
 419}
 420
 421static void xlnx_dpdma_write(void *opaque, hwaddr offset,
 422                               uint64_t value, unsigned size)
 423{
 424    XlnxDPDMAState *s = XLNX_DPDMA(opaque);
 425
 426    DPRINTF("write @%" HWADDR_PRIx " = %" PRIx64 "\n", offset, value);
 427    offset = offset >> 2;
 428
 429    switch (offset) {
 430    case DPDMA_ISR:
 431        s->registers[DPDMA_ISR] &= ~value;
 432        xlnx_dpdma_update_irq(s);
 433        break;
 434    case DPDMA_IEN:
 435        s->registers[DPDMA_IMR] &= ~value;
 436        break;
 437    case DPDMA_IDS:
 438        s->registers[DPDMA_IMR] |= value;
 439        break;
 440    case DPDMA_EISR:
 441        s->registers[DPDMA_EISR] &= ~value;
 442        xlnx_dpdma_update_irq(s);
 443        break;
 444    case DPDMA_EIEN:
 445        s->registers[DPDMA_EIMR] &= ~value;
 446        break;
 447    case DPDMA_EIDS:
 448        s->registers[DPDMA_EIMR] |= value;
 449        break;
 450    case DPDMA_IMR:
 451    case DPDMA_EIMR:
 452    case DPDMA_DSCR_NEXT_ADDRE_CH(0):
 453    case DPDMA_DSCR_NEXT_ADDRE_CH(1):
 454    case DPDMA_DSCR_NEXT_ADDRE_CH(2):
 455    case DPDMA_DSCR_NEXT_ADDRE_CH(3):
 456    case DPDMA_DSCR_NEXT_ADDRE_CH(4):
 457    case DPDMA_DSCR_NEXT_ADDRE_CH(5):
 458    case DPDMA_DSCR_NEXT_ADDR_CH(0):
 459    case DPDMA_DSCR_NEXT_ADDR_CH(1):
 460    case DPDMA_DSCR_NEXT_ADDR_CH(2):
 461    case DPDMA_DSCR_NEXT_ADDR_CH(3):
 462    case DPDMA_DSCR_NEXT_ADDR_CH(4):
 463    case DPDMA_DSCR_NEXT_ADDR_CH(5):
 464    case DPDMA_PYLD_CUR_ADDRE_CH(0):
 465    case DPDMA_PYLD_CUR_ADDRE_CH(1):
 466    case DPDMA_PYLD_CUR_ADDRE_CH(2):
 467    case DPDMA_PYLD_CUR_ADDRE_CH(3):
 468    case DPDMA_PYLD_CUR_ADDRE_CH(4):
 469    case DPDMA_PYLD_CUR_ADDRE_CH(5):
 470    case DPDMA_PYLD_CUR_ADDR_CH(0):
 471    case DPDMA_PYLD_CUR_ADDR_CH(1):
 472    case DPDMA_PYLD_CUR_ADDR_CH(2):
 473    case DPDMA_PYLD_CUR_ADDR_CH(3):
 474    case DPDMA_PYLD_CUR_ADDR_CH(4):
 475    case DPDMA_PYLD_CUR_ADDR_CH(5):
 476    case DPDMA_STATUS_CH(0):
 477    case DPDMA_STATUS_CH(1):
 478    case DPDMA_STATUS_CH(2):
 479    case DPDMA_STATUS_CH(3):
 480    case DPDMA_STATUS_CH(4):
 481    case DPDMA_STATUS_CH(5):
 482    case DPDMA_VDO_CH(0):
 483    case DPDMA_VDO_CH(1):
 484    case DPDMA_VDO_CH(2):
 485    case DPDMA_VDO_CH(3):
 486    case DPDMA_VDO_CH(4):
 487    case DPDMA_VDO_CH(5):
 488    case DPDMA_PYLD_SZ_CH(0):
 489    case DPDMA_PYLD_SZ_CH(1):
 490    case DPDMA_PYLD_SZ_CH(2):
 491    case DPDMA_PYLD_SZ_CH(3):
 492    case DPDMA_PYLD_SZ_CH(4):
 493    case DPDMA_PYLD_SZ_CH(5):
 494    case DPDMA_DSCR_ID_CH(0):
 495    case DPDMA_DSCR_ID_CH(1):
 496    case DPDMA_DSCR_ID_CH(2):
 497    case DPDMA_DSCR_ID_CH(3):
 498    case DPDMA_DSCR_ID_CH(4):
 499    case DPDMA_DSCR_ID_CH(5):
 500        /*
 501         * Trying to write to a read only register..
 502         */
 503        break;
 504    case DPDMA_GBL:
 505        /*
 506         * This is a write only register so it's read as zero in the read
 507         * callback.
 508         * We store the value anyway so we can know if the channel is
 509         * enabled.
 510         */
 511        s->registers[offset] |= value & 0x00000FFF;
 512        break;
 513    case DPDMA_DSCR_STRT_ADDRE_CH(0):
 514    case DPDMA_DSCR_STRT_ADDRE_CH(1):
 515    case DPDMA_DSCR_STRT_ADDRE_CH(2):
 516    case DPDMA_DSCR_STRT_ADDRE_CH(3):
 517    case DPDMA_DSCR_STRT_ADDRE_CH(4):
 518    case DPDMA_DSCR_STRT_ADDRE_CH(5):
 519        value &= 0x0000FFFF;
 520        s->registers[offset] = value;
 521        break;
 522    case DPDMA_CNTL_CH(0):
 523        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(0);
 524        value &= 0x3FFFFFFF;
 525        s->registers[offset] = value;
 526        break;
 527    case DPDMA_CNTL_CH(1):
 528        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(1);
 529        value &= 0x3FFFFFFF;
 530        s->registers[offset] = value;
 531        break;
 532    case DPDMA_CNTL_CH(2):
 533        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(2);
 534        value &= 0x3FFFFFFF;
 535        s->registers[offset] = value;
 536        break;
 537    case DPDMA_CNTL_CH(3):
 538        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(3);
 539        value &= 0x3FFFFFFF;
 540        s->registers[offset] = value;
 541        break;
 542    case DPDMA_CNTL_CH(4):
 543        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(4);
 544        value &= 0x3FFFFFFF;
 545        s->registers[offset] = value;
 546        break;
 547    case DPDMA_CNTL_CH(5):
 548        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(5);
 549        value &= 0x3FFFFFFF;
 550        s->registers[offset] = value;
 551        break;
 552    default:
 553        assert(offset <= (0xFFC >> 2));
 554        s->registers[offset] = value;
 555        break;
 556    }
 557}
 558
 559static const MemoryRegionOps dma_ops = {
 560    .read = xlnx_dpdma_read,
 561    .write = xlnx_dpdma_write,
 562    .endianness = DEVICE_NATIVE_ENDIAN,
 563    .valid = {
 564        .min_access_size = 4,
 565        .max_access_size = 4,
 566    },
 567    .impl = {
 568        .min_access_size = 4,
 569        .max_access_size = 4,
 570    },
 571};
 572
 573static void xlnx_dpdma_realize(DeviceState *dev, Error **errp)
 574{
 575    XlnxDPDMAState *s = XLNX_DPDMA(dev);
 576
 577    s->dma_as = s->dma_mr ? address_space_init_shareable(s->dma_mr, NULL)
 578                          : &address_space_memory;
 579}
 580
 581static void xlnx_dpdma_init(Object *obj)
 582{
 583    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 584    XlnxDPDMAState *s = XLNX_DPDMA(obj);
 585
 586    memory_region_init_io(&s->iomem, obj, &dma_ops, s,
 587                          TYPE_XLNX_DPDMA, 0x1000);
 588    sysbus_init_mmio(sbd, &s->iomem);
 589    sysbus_init_irq(sbd, &s->irq);
 590    object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
 591                             (Object **)&s->dma_mr,
 592                             qdev_prop_allow_set_link_before_realize,
 593                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
 594                             &error_abort);
 595}
 596
 597static void xlnx_dpdma_reset(DeviceState *dev)
 598{
 599    XlnxDPDMAState *s = XLNX_DPDMA(dev);
 600    size_t i;
 601
 602    memset(s->registers, 0, sizeof(s->registers));
 603    s->registers[DPDMA_IMR] =  0x07FFFFFF;
 604    s->registers[DPDMA_EIMR] = 0xFFFFFFFF;
 605    s->registers[DPDMA_ALC0_MIN] = 0x0000FFFF;
 606    s->registers[DPDMA_ALC1_MIN] = 0x0000FFFF;
 607
 608    for (i = 0; i < 6; i++) {
 609        s->data[i] = NULL;
 610        s->operation_finished[i] = true;
 611    }
 612}
 613
 614static void xlnx_dpdma_class_init(ObjectClass *oc, void *data)
 615{
 616    DeviceClass *dc = DEVICE_CLASS(oc);
 617
 618    dc->vmsd = &vmstate_xlnx_dpdma;
 619    dc->reset = xlnx_dpdma_reset;
 620    dc->realize = xlnx_dpdma_realize;
 621}
 622
 623static const TypeInfo xlnx_dpdma_info = {
 624    .name          = TYPE_XLNX_DPDMA,
 625    .parent        = TYPE_SYS_BUS_DEVICE,
 626    .instance_size = sizeof(XlnxDPDMAState),
 627    .instance_init = xlnx_dpdma_init,
 628    .class_init    = xlnx_dpdma_class_init,
 629};
 630
 631static void xlnx_dpdma_register_types(void)
 632{
 633    type_register_static(&xlnx_dpdma_info);
 634}
 635
 636size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel,
 637                                    bool one_desc)
 638{
 639    uint64_t desc_addr;
 640    uint64_t source_addr[6];
 641    DPDMADescriptor desc;
 642    bool done = false;
 643    size_t ptr = 0;
 644
 645    assert(channel <= 5);
 646
 647    DPRINTF("start dpdma channel 0x%" PRIX8 "\n", channel);
 648
 649    if (!xlnx_dpdma_is_channel_triggered(s, channel)) {
 650        DPRINTF("Channel isn't triggered..\n");
 651        return 0;
 652    }
 653
 654    if (!xlnx_dpdma_is_channel_enabled(s, channel)) {
 655        DPRINTF("Channel isn't enabled..\n");
 656        return 0;
 657    }
 658
 659    if (xlnx_dpdma_is_channel_paused(s, channel)) {
 660        DPRINTF("Channel is paused..\n");
 661        return 0;
 662    }
 663
 664    do {
 665        if ((s->operation_finished[channel])
 666          || xlnx_dpdma_is_channel_retriggered(s, channel)) {
 667            desc_addr = xlnx_dpdma_descriptor_start_address(s, channel);
 668            s->operation_finished[channel] = false;
 669        } else {
 670            desc_addr = xlnx_dpdma_descriptor_next_address(s, channel);
 671        }
 672
 673        if (dma_memory_read(s->dma_as, desc_addr, &desc,
 674                            sizeof(DPDMADescriptor))) {
 675            s->registers[DPDMA_EISR] |= ((1 << 1) << channel);
 676            xlnx_dpdma_update_irq(s);
 677            s->operation_finished[channel] = true;
 678            DPRINTF("Can't get the descriptor.\n");
 679            break;
 680        }
 681
 682        xlnx_dpdma_update_desc_info(s, channel, &desc);
 683
 684#ifdef DEBUG_DPDMA
 685        xlnx_dpdma_dump_descriptor(&desc);
 686#endif
 687
 688        DPRINTF("location of the descriptor: %" PRIx64 "\n", desc_addr);
 689        if (!xlnx_dpdma_desc_is_valid(&desc)) {
 690            s->registers[DPDMA_EISR] |= ((1 << 7) << channel);
 691            xlnx_dpdma_update_irq(s);
 692            s->operation_finished[channel] = true;
 693            DPRINTF("Invalid descriptor..\n");
 694            break;
 695        }
 696
 697        if (xlnx_dpdma_desc_crc_enabled(&desc)
 698            && !xlnx_dpdma_desc_check_crc(&desc)) {
 699            s->registers[DPDMA_EISR] |= ((1 << 13) << channel);
 700            xlnx_dpdma_update_irq(s);
 701            s->operation_finished[channel] = true;
 702            DPRINTF("Bad CRC for descriptor..\n");
 703            break;
 704        }
 705
 706        if (xlnx_dpdma_desc_is_already_done(&desc)
 707            && !xlnx_dpdma_desc_ignore_done_bit(&desc)) {
 708            /* We are trying to process an already processed descriptor. */
 709            s->registers[DPDMA_EISR] |= ((1 << 25) << channel);
 710            xlnx_dpdma_update_irq(s);
 711            s->operation_finished[channel] = true;
 712            DPRINTF("Already processed descriptor..\n");
 713            break;
 714        }
 715
 716        done = xlnx_dpdma_desc_is_last(&desc)
 717             || xlnx_dpdma_desc_is_last_of_frame(&desc);
 718
 719        s->operation_finished[channel] = done;
 720        if (s->data[channel]) {
 721            int64_t transfer_len = xlnx_dpdma_desc_get_transfer_size(&desc);
 722            uint32_t line_size = xlnx_dpdma_desc_get_line_size(&desc);
 723            uint32_t line_stride = xlnx_dpdma_desc_get_line_stride(&desc);
 724            if (xlnx_dpdma_desc_is_contiguous(&desc)) {
 725                source_addr[0] = xlnx_dpdma_desc_get_source_address(&desc, 0);
 726                while (transfer_len != 0) {
 727                    if (dma_memory_read(s->dma_as,
 728                                        source_addr[0],
 729                                        &s->data[channel][ptr],
 730                                        line_size)) {
 731                        s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
 732                        xlnx_dpdma_update_irq(s);
 733                        DPRINTF("Can't get data.\n");
 734                        break;
 735                    }
 736                    ptr += line_size;
 737                    transfer_len -= line_size;
 738                    source_addr[0] += line_stride;
 739                }
 740            } else {
 741                DPRINTF("Source address:\n");
 742                int frag;
 743                for (frag = 0; frag < 5; frag++) {
 744                    source_addr[frag] =
 745                          xlnx_dpdma_desc_get_source_address(&desc, frag);
 746                    DPRINTF("Fragment %u: %" PRIx64 "\n", frag + 1,
 747                            source_addr[frag]);
 748                }
 749
 750                frag = 0;
 751                while ((transfer_len < 0) && (frag < 5)) {
 752                    size_t fragment_len = DPDMA_FRAG_MAX_SZ
 753                                    - (source_addr[frag] % DPDMA_FRAG_MAX_SZ);
 754
 755                    if (dma_memory_read(s->dma_as,
 756                                        source_addr[frag],
 757                                        &(s->data[channel][ptr]),
 758                                        fragment_len)) {
 759                        s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
 760                        xlnx_dpdma_update_irq(s);
 761                        DPRINTF("Can't get data.\n");
 762                        break;
 763                    }
 764                    ptr += fragment_len;
 765                    transfer_len -= fragment_len;
 766                    frag += 1;
 767                }
 768            }
 769        }
 770
 771        if (xlnx_dpdma_desc_update_enabled(&desc)) {
 772            /* The descriptor need to be updated when it's completed. */
 773            DPRINTF("update the descriptor with the done flag set.\n");
 774            xlnx_dpdma_desc_set_done(&desc);
 775            dma_memory_write(s->dma_as, desc_addr, &desc,
 776                             sizeof(DPDMADescriptor));
 777        }
 778
 779        if (xlnx_dpdma_desc_completion_interrupt(&desc)) {
 780            DPRINTF("completion interrupt enabled!\n");
 781            s->registers[DPDMA_ISR] |= (1 << channel);
 782            xlnx_dpdma_update_irq(s);
 783        }
 784
 785    } while (!done && !one_desc);
 786
 787    return ptr;
 788}
 789
 790void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t channel,
 791                                         void *p)
 792{
 793    if (!s) {
 794        qemu_log_mask(LOG_UNIMP, "DPDMA client not attached to valid DPDMA"
 795                      " instance\n");
 796        return;
 797    }
 798
 799    assert(channel <= 5);
 800    s->data[channel] = p;
 801}
 802
 803void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s)
 804{
 805    s->registers[DPDMA_ISR] |= (1 << 27);
 806    xlnx_dpdma_update_irq(s);
 807}
 808
 809type_init(xlnx_dpdma_register_types)
 810