cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

xlnx_dpdma.c (26459B)


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