qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

xlnx-zdma: Add a model of the Xilinx ZynqMP generic DMA

Add a model of the generic DMA found on Xilinx ZynqMP.

Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20180503214201.29082-2-frasse.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Francisco Iglesias and committed by
Peter Maydell
22cd0945 200bf5b7

+917
+1
hw/dma/Makefile.objs
··· 10 10 common-obj-$(CONFIG_STP2000) += sparc32_dma.o 11 11 obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dpdma.o 12 12 obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx_dpdma.o 13 + common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zdma.o 13 14 14 15 obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o 15 16 obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
+832
hw/dma/xlnx-zdma.c
··· 1 + /* 2 + * QEMU model of the ZynqMP generic DMA 3 + * 4 + * Copyright (c) 2014 Xilinx Inc. 5 + * Copyright (c) 2018 FEIMTECH AB 6 + * 7 + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>, 8 + * Francisco Iglesias <francisco.iglesias@feimtech.se> 9 + * 10 + * Permission is hereby granted, free of charge, to any person obtaining a copy 11 + * of this software and associated documentation files (the "Software"), to deal 12 + * in the Software without restriction, including without limitation the rights 13 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 + * copies of the Software, and to permit persons to whom the Software is 15 + * furnished to do so, subject to the following conditions: 16 + * 17 + * The above copyright notice and this permission notice shall be included in 18 + * all copies or substantial portions of the Software. 19 + * 20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 + * THE SOFTWARE. 27 + */ 28 + 29 + #include "qemu/osdep.h" 30 + #include "hw/dma/xlnx-zdma.h" 31 + #include "qemu/bitops.h" 32 + #include "qemu/log.h" 33 + #include "qapi/error.h" 34 + 35 + #ifndef XLNX_ZDMA_ERR_DEBUG 36 + #define XLNX_ZDMA_ERR_DEBUG 0 37 + #endif 38 + 39 + REG32(ZDMA_ERR_CTRL, 0x0) 40 + FIELD(ZDMA_ERR_CTRL, APB_ERR_RES, 0, 1) 41 + REG32(ZDMA_CH_ISR, 0x100) 42 + FIELD(ZDMA_CH_ISR, DMA_PAUSE, 11, 1) 43 + FIELD(ZDMA_CH_ISR, DMA_DONE, 10, 1) 44 + FIELD(ZDMA_CH_ISR, AXI_WR_DATA, 9, 1) 45 + FIELD(ZDMA_CH_ISR, AXI_RD_DATA, 8, 1) 46 + FIELD(ZDMA_CH_ISR, AXI_RD_DST_DSCR, 7, 1) 47 + FIELD(ZDMA_CH_ISR, AXI_RD_SRC_DSCR, 6, 1) 48 + FIELD(ZDMA_CH_ISR, IRQ_DST_ACCT_ERR, 5, 1) 49 + FIELD(ZDMA_CH_ISR, IRQ_SRC_ACCT_ERR, 4, 1) 50 + FIELD(ZDMA_CH_ISR, BYTE_CNT_OVRFL, 3, 1) 51 + FIELD(ZDMA_CH_ISR, DST_DSCR_DONE, 2, 1) 52 + FIELD(ZDMA_CH_ISR, SRC_DSCR_DONE, 1, 1) 53 + FIELD(ZDMA_CH_ISR, INV_APB, 0, 1) 54 + REG32(ZDMA_CH_IMR, 0x104) 55 + FIELD(ZDMA_CH_IMR, DMA_PAUSE, 11, 1) 56 + FIELD(ZDMA_CH_IMR, DMA_DONE, 10, 1) 57 + FIELD(ZDMA_CH_IMR, AXI_WR_DATA, 9, 1) 58 + FIELD(ZDMA_CH_IMR, AXI_RD_DATA, 8, 1) 59 + FIELD(ZDMA_CH_IMR, AXI_RD_DST_DSCR, 7, 1) 60 + FIELD(ZDMA_CH_IMR, AXI_RD_SRC_DSCR, 6, 1) 61 + FIELD(ZDMA_CH_IMR, IRQ_DST_ACCT_ERR, 5, 1) 62 + FIELD(ZDMA_CH_IMR, IRQ_SRC_ACCT_ERR, 4, 1) 63 + FIELD(ZDMA_CH_IMR, BYTE_CNT_OVRFL, 3, 1) 64 + FIELD(ZDMA_CH_IMR, DST_DSCR_DONE, 2, 1) 65 + FIELD(ZDMA_CH_IMR, SRC_DSCR_DONE, 1, 1) 66 + FIELD(ZDMA_CH_IMR, INV_APB, 0, 1) 67 + REG32(ZDMA_CH_IEN, 0x108) 68 + FIELD(ZDMA_CH_IEN, DMA_PAUSE, 11, 1) 69 + FIELD(ZDMA_CH_IEN, DMA_DONE, 10, 1) 70 + FIELD(ZDMA_CH_IEN, AXI_WR_DATA, 9, 1) 71 + FIELD(ZDMA_CH_IEN, AXI_RD_DATA, 8, 1) 72 + FIELD(ZDMA_CH_IEN, AXI_RD_DST_DSCR, 7, 1) 73 + FIELD(ZDMA_CH_IEN, AXI_RD_SRC_DSCR, 6, 1) 74 + FIELD(ZDMA_CH_IEN, IRQ_DST_ACCT_ERR, 5, 1) 75 + FIELD(ZDMA_CH_IEN, IRQ_SRC_ACCT_ERR, 4, 1) 76 + FIELD(ZDMA_CH_IEN, BYTE_CNT_OVRFL, 3, 1) 77 + FIELD(ZDMA_CH_IEN, DST_DSCR_DONE, 2, 1) 78 + FIELD(ZDMA_CH_IEN, SRC_DSCR_DONE, 1, 1) 79 + FIELD(ZDMA_CH_IEN, INV_APB, 0, 1) 80 + REG32(ZDMA_CH_IDS, 0x10c) 81 + FIELD(ZDMA_CH_IDS, DMA_PAUSE, 11, 1) 82 + FIELD(ZDMA_CH_IDS, DMA_DONE, 10, 1) 83 + FIELD(ZDMA_CH_IDS, AXI_WR_DATA, 9, 1) 84 + FIELD(ZDMA_CH_IDS, AXI_RD_DATA, 8, 1) 85 + FIELD(ZDMA_CH_IDS, AXI_RD_DST_DSCR, 7, 1) 86 + FIELD(ZDMA_CH_IDS, AXI_RD_SRC_DSCR, 6, 1) 87 + FIELD(ZDMA_CH_IDS, IRQ_DST_ACCT_ERR, 5, 1) 88 + FIELD(ZDMA_CH_IDS, IRQ_SRC_ACCT_ERR, 4, 1) 89 + FIELD(ZDMA_CH_IDS, BYTE_CNT_OVRFL, 3, 1) 90 + FIELD(ZDMA_CH_IDS, DST_DSCR_DONE, 2, 1) 91 + FIELD(ZDMA_CH_IDS, SRC_DSCR_DONE, 1, 1) 92 + FIELD(ZDMA_CH_IDS, INV_APB, 0, 1) 93 + REG32(ZDMA_CH_CTRL0, 0x110) 94 + FIELD(ZDMA_CH_CTRL0, OVR_FETCH, 7, 1) 95 + FIELD(ZDMA_CH_CTRL0, POINT_TYPE, 6, 1) 96 + FIELD(ZDMA_CH_CTRL0, MODE, 4, 2) 97 + FIELD(ZDMA_CH_CTRL0, RATE_CTRL, 3, 1) 98 + FIELD(ZDMA_CH_CTRL0, CONT_ADDR, 2, 1) 99 + FIELD(ZDMA_CH_CTRL0, CONT, 1, 1) 100 + REG32(ZDMA_CH_CTRL1, 0x114) 101 + FIELD(ZDMA_CH_CTRL1, DST_ISSUE, 5, 5) 102 + FIELD(ZDMA_CH_CTRL1, SRC_ISSUE, 0, 5) 103 + REG32(ZDMA_CH_FCI, 0x118) 104 + FIELD(ZDMA_CH_FCI, PROG_CELL_CNT, 2, 2) 105 + FIELD(ZDMA_CH_FCI, SIDE, 1, 1) 106 + FIELD(ZDMA_CH_FCI, EN, 0, 1) 107 + REG32(ZDMA_CH_STATUS, 0x11c) 108 + FIELD(ZDMA_CH_STATUS, STATE, 0, 2) 109 + REG32(ZDMA_CH_DATA_ATTR, 0x120) 110 + FIELD(ZDMA_CH_DATA_ATTR, ARBURST, 26, 2) 111 + FIELD(ZDMA_CH_DATA_ATTR, ARCACHE, 22, 4) 112 + FIELD(ZDMA_CH_DATA_ATTR, ARQOS, 18, 4) 113 + FIELD(ZDMA_CH_DATA_ATTR, ARLEN, 14, 4) 114 + FIELD(ZDMA_CH_DATA_ATTR, AWBURST, 12, 2) 115 + FIELD(ZDMA_CH_DATA_ATTR, AWCACHE, 8, 4) 116 + FIELD(ZDMA_CH_DATA_ATTR, AWQOS, 4, 4) 117 + FIELD(ZDMA_CH_DATA_ATTR, AWLEN, 0, 4) 118 + REG32(ZDMA_CH_DSCR_ATTR, 0x124) 119 + FIELD(ZDMA_CH_DSCR_ATTR, AXCOHRNT, 8, 1) 120 + FIELD(ZDMA_CH_DSCR_ATTR, AXCACHE, 4, 4) 121 + FIELD(ZDMA_CH_DSCR_ATTR, AXQOS, 0, 4) 122 + REG32(ZDMA_CH_SRC_DSCR_WORD0, 0x128) 123 + REG32(ZDMA_CH_SRC_DSCR_WORD1, 0x12c) 124 + FIELD(ZDMA_CH_SRC_DSCR_WORD1, MSB, 0, 17) 125 + REG32(ZDMA_CH_SRC_DSCR_WORD2, 0x130) 126 + FIELD(ZDMA_CH_SRC_DSCR_WORD2, SIZE, 0, 30) 127 + REG32(ZDMA_CH_SRC_DSCR_WORD3, 0x134) 128 + FIELD(ZDMA_CH_SRC_DSCR_WORD3, CMD, 3, 2) 129 + FIELD(ZDMA_CH_SRC_DSCR_WORD3, INTR, 2, 1) 130 + FIELD(ZDMA_CH_SRC_DSCR_WORD3, TYPE, 1, 1) 131 + FIELD(ZDMA_CH_SRC_DSCR_WORD3, COHRNT, 0, 1) 132 + REG32(ZDMA_CH_DST_DSCR_WORD0, 0x138) 133 + REG32(ZDMA_CH_DST_DSCR_WORD1, 0x13c) 134 + FIELD(ZDMA_CH_DST_DSCR_WORD1, MSB, 0, 17) 135 + REG32(ZDMA_CH_DST_DSCR_WORD2, 0x140) 136 + FIELD(ZDMA_CH_DST_DSCR_WORD2, SIZE, 0, 30) 137 + REG32(ZDMA_CH_DST_DSCR_WORD3, 0x144) 138 + FIELD(ZDMA_CH_DST_DSCR_WORD3, INTR, 2, 1) 139 + FIELD(ZDMA_CH_DST_DSCR_WORD3, TYPE, 1, 1) 140 + FIELD(ZDMA_CH_DST_DSCR_WORD3, COHRNT, 0, 1) 141 + REG32(ZDMA_CH_WR_ONLY_WORD0, 0x148) 142 + REG32(ZDMA_CH_WR_ONLY_WORD1, 0x14c) 143 + REG32(ZDMA_CH_WR_ONLY_WORD2, 0x150) 144 + REG32(ZDMA_CH_WR_ONLY_WORD3, 0x154) 145 + REG32(ZDMA_CH_SRC_START_LSB, 0x158) 146 + REG32(ZDMA_CH_SRC_START_MSB, 0x15c) 147 + FIELD(ZDMA_CH_SRC_START_MSB, ADDR, 0, 17) 148 + REG32(ZDMA_CH_DST_START_LSB, 0x160) 149 + REG32(ZDMA_CH_DST_START_MSB, 0x164) 150 + FIELD(ZDMA_CH_DST_START_MSB, ADDR, 0, 17) 151 + REG32(ZDMA_CH_RATE_CTRL, 0x18c) 152 + FIELD(ZDMA_CH_RATE_CTRL, CNT, 0, 12) 153 + REG32(ZDMA_CH_SRC_CUR_PYLD_LSB, 0x168) 154 + REG32(ZDMA_CH_SRC_CUR_PYLD_MSB, 0x16c) 155 + FIELD(ZDMA_CH_SRC_CUR_PYLD_MSB, ADDR, 0, 17) 156 + REG32(ZDMA_CH_DST_CUR_PYLD_LSB, 0x170) 157 + REG32(ZDMA_CH_DST_CUR_PYLD_MSB, 0x174) 158 + FIELD(ZDMA_CH_DST_CUR_PYLD_MSB, ADDR, 0, 17) 159 + REG32(ZDMA_CH_SRC_CUR_DSCR_LSB, 0x178) 160 + REG32(ZDMA_CH_SRC_CUR_DSCR_MSB, 0x17c) 161 + FIELD(ZDMA_CH_SRC_CUR_DSCR_MSB, ADDR, 0, 17) 162 + REG32(ZDMA_CH_DST_CUR_DSCR_LSB, 0x180) 163 + REG32(ZDMA_CH_DST_CUR_DSCR_MSB, 0x184) 164 + FIELD(ZDMA_CH_DST_CUR_DSCR_MSB, ADDR, 0, 17) 165 + REG32(ZDMA_CH_TOTAL_BYTE, 0x188) 166 + REG32(ZDMA_CH_RATE_CNTL, 0x18c) 167 + FIELD(ZDMA_CH_RATE_CNTL, CNT, 0, 12) 168 + REG32(ZDMA_CH_IRQ_SRC_ACCT, 0x190) 169 + FIELD(ZDMA_CH_IRQ_SRC_ACCT, CNT, 0, 8) 170 + REG32(ZDMA_CH_IRQ_DST_ACCT, 0x194) 171 + FIELD(ZDMA_CH_IRQ_DST_ACCT, CNT, 0, 8) 172 + REG32(ZDMA_CH_DBG0, 0x198) 173 + FIELD(ZDMA_CH_DBG0, CMN_BUF_FREE, 0, 9) 174 + REG32(ZDMA_CH_DBG1, 0x19c) 175 + FIELD(ZDMA_CH_DBG1, CMN_BUF_OCC, 0, 9) 176 + REG32(ZDMA_CH_CTRL2, 0x200) 177 + FIELD(ZDMA_CH_CTRL2, EN, 0, 1) 178 + 179 + enum { 180 + PT_REG = 0, 181 + PT_MEM = 1, 182 + }; 183 + 184 + enum { 185 + CMD_HALT = 1, 186 + CMD_STOP = 2, 187 + }; 188 + 189 + enum { 190 + RW_MODE_RW = 0, 191 + RW_MODE_WO = 1, 192 + RW_MODE_RO = 2, 193 + }; 194 + 195 + enum { 196 + DTYPE_LINEAR = 0, 197 + DTYPE_LINKED = 1, 198 + }; 199 + 200 + enum { 201 + AXI_BURST_FIXED = 0, 202 + AXI_BURST_INCR = 1, 203 + }; 204 + 205 + static void zdma_ch_imr_update_irq(XlnxZDMA *s) 206 + { 207 + bool pending; 208 + 209 + pending = s->regs[R_ZDMA_CH_ISR] & ~s->regs[R_ZDMA_CH_IMR]; 210 + 211 + qemu_set_irq(s->irq_zdma_ch_imr, pending); 212 + } 213 + 214 + static void zdma_ch_isr_postw(RegisterInfo *reg, uint64_t val64) 215 + { 216 + XlnxZDMA *s = XLNX_ZDMA(reg->opaque); 217 + zdma_ch_imr_update_irq(s); 218 + } 219 + 220 + static uint64_t zdma_ch_ien_prew(RegisterInfo *reg, uint64_t val64) 221 + { 222 + XlnxZDMA *s = XLNX_ZDMA(reg->opaque); 223 + uint32_t val = val64; 224 + 225 + s->regs[R_ZDMA_CH_IMR] &= ~val; 226 + zdma_ch_imr_update_irq(s); 227 + return 0; 228 + } 229 + 230 + static uint64_t zdma_ch_ids_prew(RegisterInfo *reg, uint64_t val64) 231 + { 232 + XlnxZDMA *s = XLNX_ZDMA(reg->opaque); 233 + uint32_t val = val64; 234 + 235 + s->regs[R_ZDMA_CH_IMR] |= val; 236 + zdma_ch_imr_update_irq(s); 237 + return 0; 238 + } 239 + 240 + static void zdma_set_state(XlnxZDMA *s, XlnxZDMAState state) 241 + { 242 + s->state = state; 243 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_STATUS, STATE, state); 244 + 245 + /* Signal error if we have an error condition. */ 246 + if (s->error) { 247 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_STATUS, STATE, 3); 248 + } 249 + } 250 + 251 + static void zdma_src_done(XlnxZDMA *s) 252 + { 253 + unsigned int cnt; 254 + cnt = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_SRC_ACCT, CNT); 255 + cnt++; 256 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_IRQ_SRC_ACCT, CNT, cnt); 257 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, SRC_DSCR_DONE, true); 258 + 259 + /* Did we overflow? */ 260 + if (cnt != ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_SRC_ACCT, CNT)) { 261 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, IRQ_SRC_ACCT_ERR, true); 262 + } 263 + zdma_ch_imr_update_irq(s); 264 + } 265 + 266 + static void zdma_dst_done(XlnxZDMA *s) 267 + { 268 + unsigned int cnt; 269 + cnt = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_DST_ACCT, CNT); 270 + cnt++; 271 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_IRQ_DST_ACCT, CNT, cnt); 272 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, DST_DSCR_DONE, true); 273 + 274 + /* Did we overflow? */ 275 + if (cnt != ARRAY_FIELD_EX32(s->regs, ZDMA_CH_IRQ_DST_ACCT, CNT)) { 276 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, IRQ_DST_ACCT_ERR, true); 277 + } 278 + zdma_ch_imr_update_irq(s); 279 + } 280 + 281 + static uint64_t zdma_get_regaddr64(XlnxZDMA *s, unsigned int basereg) 282 + { 283 + uint64_t addr; 284 + 285 + addr = s->regs[basereg + 1]; 286 + addr <<= 32; 287 + addr |= s->regs[basereg]; 288 + 289 + return addr; 290 + } 291 + 292 + static void zdma_put_regaddr64(XlnxZDMA *s, unsigned int basereg, uint64_t addr) 293 + { 294 + s->regs[basereg] = addr; 295 + s->regs[basereg + 1] = addr >> 32; 296 + } 297 + 298 + static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr, void *buf) 299 + { 300 + /* ZDMA descriptors must be aligned to their own size. */ 301 + if (addr % sizeof(XlnxZDMADescr)) { 302 + qemu_log_mask(LOG_GUEST_ERROR, 303 + "zdma: unaligned descriptor at %" PRIx64, 304 + addr); 305 + memset(buf, 0xdeadbeef, sizeof(XlnxZDMADescr)); 306 + s->error = true; 307 + return false; 308 + } 309 + 310 + address_space_rw(s->dma_as, addr, s->attr, 311 + buf, sizeof(XlnxZDMADescr), false); 312 + return true; 313 + } 314 + 315 + static void zdma_load_src_descriptor(XlnxZDMA *s) 316 + { 317 + uint64_t src_addr; 318 + unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE); 319 + 320 + if (ptype == PT_REG) { 321 + memcpy(&s->dsc_src, &s->regs[R_ZDMA_CH_SRC_DSCR_WORD0], 322 + sizeof(s->dsc_src)); 323 + return; 324 + } 325 + 326 + src_addr = zdma_get_regaddr64(s, R_ZDMA_CH_SRC_CUR_DSCR_LSB); 327 + 328 + if (!zdma_load_descriptor(s, src_addr, &s->dsc_src)) { 329 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, AXI_RD_SRC_DSCR, true); 330 + } 331 + } 332 + 333 + static void zdma_load_dst_descriptor(XlnxZDMA *s) 334 + { 335 + uint64_t dst_addr; 336 + unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE); 337 + 338 + if (ptype == PT_REG) { 339 + memcpy(&s->dsc_dst, &s->regs[R_ZDMA_CH_DST_DSCR_WORD0], 340 + sizeof(s->dsc_dst)); 341 + return; 342 + } 343 + 344 + dst_addr = zdma_get_regaddr64(s, R_ZDMA_CH_DST_CUR_DSCR_LSB); 345 + 346 + if (!zdma_load_descriptor(s, dst_addr, &s->dsc_dst)) { 347 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, AXI_RD_DST_DSCR, true); 348 + } 349 + } 350 + 351 + static uint64_t zdma_update_descr_addr(XlnxZDMA *s, bool type, 352 + unsigned int basereg) 353 + { 354 + uint64_t addr, next; 355 + 356 + if (type == DTYPE_LINEAR) { 357 + next = zdma_get_regaddr64(s, basereg); 358 + next += sizeof(s->dsc_dst); 359 + zdma_put_regaddr64(s, basereg, next); 360 + } else { 361 + addr = zdma_get_regaddr64(s, basereg); 362 + addr += sizeof(s->dsc_dst); 363 + address_space_rw(s->dma_as, addr, s->attr, (void *) &next, 8, false); 364 + zdma_put_regaddr64(s, basereg, next); 365 + } 366 + return next; 367 + } 368 + 369 + static void zdma_write_dst(XlnxZDMA *s, uint8_t *buf, uint32_t len) 370 + { 371 + uint32_t dst_size, dlen; 372 + bool dst_intr, dst_type; 373 + unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE); 374 + unsigned int rw_mode = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, MODE); 375 + unsigned int burst_type = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_DATA_ATTR, 376 + AWBURST); 377 + 378 + /* FIXED burst types are only supported in simple dma mode. */ 379 + if (ptype != PT_REG) { 380 + burst_type = AXI_BURST_INCR; 381 + } 382 + 383 + while (len) { 384 + dst_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2, 385 + SIZE); 386 + dst_type = FIELD_EX32(s->dsc_dst.words[3], ZDMA_CH_DST_DSCR_WORD3, 387 + TYPE); 388 + if (dst_size == 0 && ptype == PT_MEM) { 389 + uint64_t next; 390 + next = zdma_update_descr_addr(s, dst_type, 391 + R_ZDMA_CH_DST_CUR_DSCR_LSB); 392 + zdma_load_descriptor(s, next, &s->dsc_dst); 393 + dst_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2, 394 + SIZE); 395 + dst_type = FIELD_EX32(s->dsc_dst.words[3], ZDMA_CH_DST_DSCR_WORD3, 396 + TYPE); 397 + } 398 + 399 + /* Match what hardware does by ignoring the dst_size and only using 400 + * the src size for Simple register mode. */ 401 + if (ptype == PT_REG && rw_mode != RW_MODE_WO) { 402 + dst_size = len; 403 + } 404 + 405 + dst_intr = FIELD_EX32(s->dsc_dst.words[3], ZDMA_CH_DST_DSCR_WORD3, 406 + INTR); 407 + 408 + dlen = len > dst_size ? dst_size : len; 409 + if (burst_type == AXI_BURST_FIXED) { 410 + if (dlen > (s->cfg.bus_width / 8)) { 411 + dlen = s->cfg.bus_width / 8; 412 + } 413 + } 414 + 415 + address_space_rw(s->dma_as, s->dsc_dst.addr, s->attr, buf, dlen, 416 + true); 417 + if (burst_type == AXI_BURST_INCR) { 418 + s->dsc_dst.addr += dlen; 419 + } 420 + dst_size -= dlen; 421 + buf += dlen; 422 + len -= dlen; 423 + 424 + if (dst_size == 0 && dst_intr) { 425 + zdma_dst_done(s); 426 + } 427 + 428 + /* Write back to buffered descriptor. */ 429 + s->dsc_dst.words[2] = FIELD_DP32(s->dsc_dst.words[2], 430 + ZDMA_CH_DST_DSCR_WORD2, 431 + SIZE, 432 + dst_size); 433 + } 434 + } 435 + 436 + static void zdma_process_descr(XlnxZDMA *s) 437 + { 438 + uint64_t src_addr; 439 + uint32_t src_size, len; 440 + unsigned int src_cmd; 441 + bool src_intr, src_type; 442 + unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE); 443 + unsigned int rw_mode = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, MODE); 444 + unsigned int burst_type = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_DATA_ATTR, 445 + ARBURST); 446 + 447 + src_addr = s->dsc_src.addr; 448 + src_size = FIELD_EX32(s->dsc_src.words[2], ZDMA_CH_SRC_DSCR_WORD2, SIZE); 449 + src_cmd = FIELD_EX32(s->dsc_src.words[3], ZDMA_CH_SRC_DSCR_WORD3, CMD); 450 + src_type = FIELD_EX32(s->dsc_src.words[3], ZDMA_CH_SRC_DSCR_WORD3, TYPE); 451 + src_intr = FIELD_EX32(s->dsc_src.words[3], ZDMA_CH_SRC_DSCR_WORD3, INTR); 452 + 453 + /* FIXED burst types and non-rw modes are only supported in 454 + * simple dma mode. 455 + */ 456 + if (ptype != PT_REG) { 457 + if (rw_mode != RW_MODE_RW) { 458 + qemu_log_mask(LOG_GUEST_ERROR, 459 + "zDMA: rw-mode=%d but not simple DMA mode.\n", 460 + rw_mode); 461 + } 462 + if (burst_type != AXI_BURST_INCR) { 463 + qemu_log_mask(LOG_GUEST_ERROR, 464 + "zDMA: burst_type=%d but not simple DMA mode.\n", 465 + burst_type); 466 + } 467 + burst_type = AXI_BURST_INCR; 468 + rw_mode = RW_MODE_RW; 469 + } 470 + 471 + if (rw_mode == RW_MODE_WO) { 472 + /* In Simple DMA Write-Only, we need to push DST size bytes 473 + * regardless of what SRC size is set to. */ 474 + src_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2, 475 + SIZE); 476 + memcpy(s->buf, &s->regs[R_ZDMA_CH_WR_ONLY_WORD0], s->cfg.bus_width / 8); 477 + } 478 + 479 + while (src_size) { 480 + len = src_size > ARRAY_SIZE(s->buf) ? ARRAY_SIZE(s->buf) : src_size; 481 + if (burst_type == AXI_BURST_FIXED) { 482 + if (len > (s->cfg.bus_width / 8)) { 483 + len = s->cfg.bus_width / 8; 484 + } 485 + } 486 + 487 + if (rw_mode == RW_MODE_WO) { 488 + if (len > s->cfg.bus_width / 8) { 489 + len = s->cfg.bus_width / 8; 490 + } 491 + } else { 492 + address_space_rw(s->dma_as, src_addr, s->attr, s->buf, len, 493 + false); 494 + if (burst_type == AXI_BURST_INCR) { 495 + src_addr += len; 496 + } 497 + } 498 + 499 + if (rw_mode != RW_MODE_RO) { 500 + zdma_write_dst(s, s->buf, len); 501 + } 502 + 503 + s->regs[R_ZDMA_CH_TOTAL_BYTE] += len; 504 + src_size -= len; 505 + } 506 + 507 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, DMA_DONE, true); 508 + 509 + if (src_intr) { 510 + zdma_src_done(s); 511 + } 512 + 513 + /* Load next descriptor. */ 514 + if (ptype == PT_REG || src_cmd == CMD_STOP) { 515 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_CTRL2, EN, 0); 516 + zdma_set_state(s, DISABLED); 517 + return; 518 + } 519 + 520 + if (src_cmd == CMD_HALT) { 521 + zdma_set_state(s, PAUSED); 522 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, DMA_PAUSE, 1); 523 + zdma_ch_imr_update_irq(s); 524 + return; 525 + } 526 + 527 + zdma_update_descr_addr(s, src_type, R_ZDMA_CH_SRC_CUR_DSCR_LSB); 528 + } 529 + 530 + static void zdma_run(XlnxZDMA *s) 531 + { 532 + while (s->state == ENABLED && !s->error) { 533 + zdma_load_src_descriptor(s); 534 + 535 + if (s->error) { 536 + zdma_set_state(s, DISABLED); 537 + } else { 538 + zdma_process_descr(s); 539 + } 540 + } 541 + 542 + zdma_ch_imr_update_irq(s); 543 + } 544 + 545 + static void zdma_update_descr_addr_from_start(XlnxZDMA *s) 546 + { 547 + uint64_t src_addr, dst_addr; 548 + 549 + src_addr = zdma_get_regaddr64(s, R_ZDMA_CH_SRC_START_LSB); 550 + zdma_put_regaddr64(s, R_ZDMA_CH_SRC_CUR_DSCR_LSB, src_addr); 551 + dst_addr = zdma_get_regaddr64(s, R_ZDMA_CH_DST_START_LSB); 552 + zdma_put_regaddr64(s, R_ZDMA_CH_DST_CUR_DSCR_LSB, dst_addr); 553 + zdma_load_dst_descriptor(s); 554 + } 555 + 556 + static void zdma_ch_ctrlx_postw(RegisterInfo *reg, uint64_t val64) 557 + { 558 + XlnxZDMA *s = XLNX_ZDMA(reg->opaque); 559 + 560 + if (ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL2, EN)) { 561 + s->error = false; 562 + 563 + if (s->state == PAUSED && 564 + ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, CONT)) { 565 + if (ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, CONT_ADDR) == 1) { 566 + zdma_update_descr_addr_from_start(s); 567 + } else { 568 + bool src_type = FIELD_EX32(s->dsc_src.words[3], 569 + ZDMA_CH_SRC_DSCR_WORD3, TYPE); 570 + zdma_update_descr_addr(s, src_type, 571 + R_ZDMA_CH_SRC_CUR_DSCR_LSB); 572 + } 573 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_CTRL0, CONT, false); 574 + zdma_set_state(s, ENABLED); 575 + } else if (s->state == DISABLED) { 576 + zdma_update_descr_addr_from_start(s); 577 + zdma_set_state(s, ENABLED); 578 + } 579 + } else { 580 + /* Leave Paused state? */ 581 + if (s->state == PAUSED && 582 + ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, CONT)) { 583 + zdma_set_state(s, DISABLED); 584 + } 585 + } 586 + 587 + zdma_run(s); 588 + } 589 + 590 + static RegisterAccessInfo zdma_regs_info[] = { 591 + { .name = "ZDMA_ERR_CTRL", .addr = A_ZDMA_ERR_CTRL, 592 + .rsvd = 0xfffffffe, 593 + },{ .name = "ZDMA_CH_ISR", .addr = A_ZDMA_CH_ISR, 594 + .rsvd = 0xfffff000, 595 + .w1c = 0xfff, 596 + .post_write = zdma_ch_isr_postw, 597 + },{ .name = "ZDMA_CH_IMR", .addr = A_ZDMA_CH_IMR, 598 + .reset = 0xfff, 599 + .rsvd = 0xfffff000, 600 + .ro = 0xfff, 601 + },{ .name = "ZDMA_CH_IEN", .addr = A_ZDMA_CH_IEN, 602 + .rsvd = 0xfffff000, 603 + .pre_write = zdma_ch_ien_prew, 604 + },{ .name = "ZDMA_CH_IDS", .addr = A_ZDMA_CH_IDS, 605 + .rsvd = 0xfffff000, 606 + .pre_write = zdma_ch_ids_prew, 607 + },{ .name = "ZDMA_CH_CTRL0", .addr = A_ZDMA_CH_CTRL0, 608 + .reset = 0x80, 609 + .rsvd = 0xffffff01, 610 + .post_write = zdma_ch_ctrlx_postw, 611 + },{ .name = "ZDMA_CH_CTRL1", .addr = A_ZDMA_CH_CTRL1, 612 + .reset = 0x3ff, 613 + .rsvd = 0xfffffc00, 614 + },{ .name = "ZDMA_CH_FCI", .addr = A_ZDMA_CH_FCI, 615 + .rsvd = 0xffffffc0, 616 + },{ .name = "ZDMA_CH_STATUS", .addr = A_ZDMA_CH_STATUS, 617 + .rsvd = 0xfffffffc, 618 + .ro = 0x3, 619 + },{ .name = "ZDMA_CH_DATA_ATTR", .addr = A_ZDMA_CH_DATA_ATTR, 620 + .reset = 0x483d20f, 621 + .rsvd = 0xf0000000, 622 + },{ .name = "ZDMA_CH_DSCR_ATTR", .addr = A_ZDMA_CH_DSCR_ATTR, 623 + .rsvd = 0xfffffe00, 624 + },{ .name = "ZDMA_CH_SRC_DSCR_WORD0", .addr = A_ZDMA_CH_SRC_DSCR_WORD0, 625 + },{ .name = "ZDMA_CH_SRC_DSCR_WORD1", .addr = A_ZDMA_CH_SRC_DSCR_WORD1, 626 + .rsvd = 0xfffe0000, 627 + },{ .name = "ZDMA_CH_SRC_DSCR_WORD2", .addr = A_ZDMA_CH_SRC_DSCR_WORD2, 628 + .rsvd = 0xc0000000, 629 + },{ .name = "ZDMA_CH_SRC_DSCR_WORD3", .addr = A_ZDMA_CH_SRC_DSCR_WORD3, 630 + .rsvd = 0xffffffe0, 631 + },{ .name = "ZDMA_CH_DST_DSCR_WORD0", .addr = A_ZDMA_CH_DST_DSCR_WORD0, 632 + },{ .name = "ZDMA_CH_DST_DSCR_WORD1", .addr = A_ZDMA_CH_DST_DSCR_WORD1, 633 + .rsvd = 0xfffe0000, 634 + },{ .name = "ZDMA_CH_DST_DSCR_WORD2", .addr = A_ZDMA_CH_DST_DSCR_WORD2, 635 + .rsvd = 0xc0000000, 636 + },{ .name = "ZDMA_CH_DST_DSCR_WORD3", .addr = A_ZDMA_CH_DST_DSCR_WORD3, 637 + .rsvd = 0xfffffffa, 638 + },{ .name = "ZDMA_CH_WR_ONLY_WORD0", .addr = A_ZDMA_CH_WR_ONLY_WORD0, 639 + },{ .name = "ZDMA_CH_WR_ONLY_WORD1", .addr = A_ZDMA_CH_WR_ONLY_WORD1, 640 + },{ .name = "ZDMA_CH_WR_ONLY_WORD2", .addr = A_ZDMA_CH_WR_ONLY_WORD2, 641 + },{ .name = "ZDMA_CH_WR_ONLY_WORD3", .addr = A_ZDMA_CH_WR_ONLY_WORD3, 642 + },{ .name = "ZDMA_CH_SRC_START_LSB", .addr = A_ZDMA_CH_SRC_START_LSB, 643 + },{ .name = "ZDMA_CH_SRC_START_MSB", .addr = A_ZDMA_CH_SRC_START_MSB, 644 + .rsvd = 0xfffe0000, 645 + },{ .name = "ZDMA_CH_DST_START_LSB", .addr = A_ZDMA_CH_DST_START_LSB, 646 + },{ .name = "ZDMA_CH_DST_START_MSB", .addr = A_ZDMA_CH_DST_START_MSB, 647 + .rsvd = 0xfffe0000, 648 + },{ .name = "ZDMA_CH_SRC_CUR_PYLD_LSB", .addr = A_ZDMA_CH_SRC_CUR_PYLD_LSB, 649 + .ro = 0xffffffff, 650 + },{ .name = "ZDMA_CH_SRC_CUR_PYLD_MSB", .addr = A_ZDMA_CH_SRC_CUR_PYLD_MSB, 651 + .rsvd = 0xfffe0000, 652 + .ro = 0x1ffff, 653 + },{ .name = "ZDMA_CH_DST_CUR_PYLD_LSB", .addr = A_ZDMA_CH_DST_CUR_PYLD_LSB, 654 + .ro = 0xffffffff, 655 + },{ .name = "ZDMA_CH_DST_CUR_PYLD_MSB", .addr = A_ZDMA_CH_DST_CUR_PYLD_MSB, 656 + .rsvd = 0xfffe0000, 657 + .ro = 0x1ffff, 658 + },{ .name = "ZDMA_CH_SRC_CUR_DSCR_LSB", .addr = A_ZDMA_CH_SRC_CUR_DSCR_LSB, 659 + .ro = 0xffffffff, 660 + },{ .name = "ZDMA_CH_SRC_CUR_DSCR_MSB", .addr = A_ZDMA_CH_SRC_CUR_DSCR_MSB, 661 + .rsvd = 0xfffe0000, 662 + .ro = 0x1ffff, 663 + },{ .name = "ZDMA_CH_DST_CUR_DSCR_LSB", .addr = A_ZDMA_CH_DST_CUR_DSCR_LSB, 664 + .ro = 0xffffffff, 665 + },{ .name = "ZDMA_CH_DST_CUR_DSCR_MSB", .addr = A_ZDMA_CH_DST_CUR_DSCR_MSB, 666 + .rsvd = 0xfffe0000, 667 + .ro = 0x1ffff, 668 + },{ .name = "ZDMA_CH_TOTAL_BYTE", .addr = A_ZDMA_CH_TOTAL_BYTE, 669 + .w1c = 0xffffffff, 670 + },{ .name = "ZDMA_CH_RATE_CNTL", .addr = A_ZDMA_CH_RATE_CNTL, 671 + .rsvd = 0xfffff000, 672 + },{ .name = "ZDMA_CH_IRQ_SRC_ACCT", .addr = A_ZDMA_CH_IRQ_SRC_ACCT, 673 + .rsvd = 0xffffff00, 674 + .ro = 0xff, 675 + .cor = 0xff, 676 + },{ .name = "ZDMA_CH_IRQ_DST_ACCT", .addr = A_ZDMA_CH_IRQ_DST_ACCT, 677 + .rsvd = 0xffffff00, 678 + .ro = 0xff, 679 + .cor = 0xff, 680 + },{ .name = "ZDMA_CH_DBG0", .addr = A_ZDMA_CH_DBG0, 681 + .rsvd = 0xfffffe00, 682 + .ro = 0x1ff, 683 + },{ .name = "ZDMA_CH_DBG1", .addr = A_ZDMA_CH_DBG1, 684 + .rsvd = 0xfffffe00, 685 + .ro = 0x1ff, 686 + },{ .name = "ZDMA_CH_CTRL2", .addr = A_ZDMA_CH_CTRL2, 687 + .rsvd = 0xfffffffe, 688 + .post_write = zdma_ch_ctrlx_postw, 689 + } 690 + }; 691 + 692 + static void zdma_reset(DeviceState *dev) 693 + { 694 + XlnxZDMA *s = XLNX_ZDMA(dev); 695 + unsigned int i; 696 + 697 + for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { 698 + register_reset(&s->regs_info[i]); 699 + } 700 + 701 + zdma_ch_imr_update_irq(s); 702 + } 703 + 704 + static uint64_t zdma_read(void *opaque, hwaddr addr, unsigned size) 705 + { 706 + XlnxZDMA *s = XLNX_ZDMA(opaque); 707 + RegisterInfo *r = &s->regs_info[addr / 4]; 708 + 709 + if (!r->data) { 710 + qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n", 711 + object_get_canonical_path(OBJECT(s)), 712 + addr); 713 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, INV_APB, true); 714 + zdma_ch_imr_update_irq(s); 715 + return 0; 716 + } 717 + return register_read(r, ~0, NULL, false); 718 + } 719 + 720 + static void zdma_write(void *opaque, hwaddr addr, uint64_t value, 721 + unsigned size) 722 + { 723 + XlnxZDMA *s = XLNX_ZDMA(opaque); 724 + RegisterInfo *r = &s->regs_info[addr / 4]; 725 + 726 + if (!r->data) { 727 + qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n", 728 + object_get_canonical_path(OBJECT(s)), 729 + addr, value); 730 + ARRAY_FIELD_DP32(s->regs, ZDMA_CH_ISR, INV_APB, true); 731 + zdma_ch_imr_update_irq(s); 732 + return; 733 + } 734 + register_write(r, value, ~0, NULL, false); 735 + } 736 + 737 + static const MemoryRegionOps zdma_ops = { 738 + .read = zdma_read, 739 + .write = zdma_write, 740 + .endianness = DEVICE_LITTLE_ENDIAN, 741 + .valid = { 742 + .min_access_size = 4, 743 + .max_access_size = 4, 744 + }, 745 + }; 746 + 747 + static void zdma_realize(DeviceState *dev, Error **errp) 748 + { 749 + XlnxZDMA *s = XLNX_ZDMA(dev); 750 + unsigned int i; 751 + 752 + for (i = 0; i < ARRAY_SIZE(zdma_regs_info); ++i) { 753 + RegisterInfo *r = &s->regs_info[zdma_regs_info[i].addr / 4]; 754 + 755 + *r = (RegisterInfo) { 756 + .data = (uint8_t *)&s->regs[ 757 + zdma_regs_info[i].addr / 4], 758 + .data_size = sizeof(uint32_t), 759 + .access = &zdma_regs_info[i], 760 + .opaque = s, 761 + }; 762 + } 763 + 764 + if (s->dma_mr) { 765 + s->dma_as = g_malloc0(sizeof(AddressSpace)); 766 + address_space_init(s->dma_as, s->dma_mr, NULL); 767 + } else { 768 + s->dma_as = &address_space_memory; 769 + } 770 + s->attr = MEMTXATTRS_UNSPECIFIED; 771 + } 772 + 773 + static void zdma_init(Object *obj) 774 + { 775 + XlnxZDMA *s = XLNX_ZDMA(obj); 776 + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 777 + 778 + memory_region_init_io(&s->iomem, obj, &zdma_ops, s, 779 + TYPE_XLNX_ZDMA, ZDMA_R_MAX * 4); 780 + sysbus_init_mmio(sbd, &s->iomem); 781 + sysbus_init_irq(sbd, &s->irq_zdma_ch_imr); 782 + 783 + object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, 784 + (Object **)&s->dma_mr, 785 + qdev_prop_allow_set_link_before_realize, 786 + OBJ_PROP_LINK_UNREF_ON_RELEASE, 787 + &error_abort); 788 + } 789 + 790 + static const VMStateDescription vmstate_zdma = { 791 + .name = TYPE_XLNX_ZDMA, 792 + .version_id = 1, 793 + .minimum_version_id = 1, 794 + .minimum_version_id_old = 1, 795 + .fields = (VMStateField[]) { 796 + VMSTATE_UINT32_ARRAY(regs, XlnxZDMA, ZDMA_R_MAX), 797 + VMSTATE_UINT32(state, XlnxZDMA), 798 + VMSTATE_UINT32_ARRAY(dsc_src.words, XlnxZDMA, 4), 799 + VMSTATE_UINT32_ARRAY(dsc_dst.words, XlnxZDMA, 4), 800 + VMSTATE_END_OF_LIST(), 801 + } 802 + }; 803 + 804 + static Property zdma_props[] = { 805 + DEFINE_PROP_UINT32("bus-width", XlnxZDMA, cfg.bus_width, 64), 806 + DEFINE_PROP_END_OF_LIST(), 807 + }; 808 + 809 + static void zdma_class_init(ObjectClass *klass, void *data) 810 + { 811 + DeviceClass *dc = DEVICE_CLASS(klass); 812 + 813 + dc->reset = zdma_reset; 814 + dc->realize = zdma_realize; 815 + dc->props = zdma_props; 816 + dc->vmsd = &vmstate_zdma; 817 + } 818 + 819 + static const TypeInfo zdma_info = { 820 + .name = TYPE_XLNX_ZDMA, 821 + .parent = TYPE_SYS_BUS_DEVICE, 822 + .instance_size = sizeof(XlnxZDMA), 823 + .class_init = zdma_class_init, 824 + .instance_init = zdma_init, 825 + }; 826 + 827 + static void zdma_register_types(void) 828 + { 829 + type_register_static(&zdma_info); 830 + } 831 + 832 + type_init(zdma_register_types)
+84
include/hw/dma/xlnx-zdma.h
··· 1 + /* 2 + * QEMU model of the ZynqMP generic DMA 3 + * 4 + * Copyright (c) 2014 Xilinx Inc. 5 + * Copyright (c) 2018 FEIMTECH AB 6 + * 7 + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>, 8 + * Francisco Iglesias <francisco.iglesias@feimtech.se> 9 + * 10 + * Permission is hereby granted, free of charge, to any person obtaining a copy 11 + * of this software and associated documentation files (the "Software"), to deal 12 + * in the Software without restriction, including without limitation the rights 13 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 + * copies of the Software, and to permit persons to whom the Software is 15 + * furnished to do so, subject to the following conditions: 16 + * 17 + * The above copyright notice and this permission notice shall be included in 18 + * all copies or substantial portions of the Software. 19 + * 20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 + * THE SOFTWARE. 27 + */ 28 + 29 + #ifndef XLNX_ZDMA_H 30 + #define XLNX_ZDMA_H 31 + 32 + #include "hw/sysbus.h" 33 + #include "hw/register.h" 34 + #include "sysemu/dma.h" 35 + 36 + #define ZDMA_R_MAX (0x204 / 4) 37 + 38 + typedef enum { 39 + DISABLED = 0, 40 + ENABLED = 1, 41 + PAUSED = 2, 42 + } XlnxZDMAState; 43 + 44 + typedef union { 45 + struct { 46 + uint64_t addr; 47 + uint32_t size; 48 + uint32_t attr; 49 + }; 50 + uint32_t words[4]; 51 + } XlnxZDMADescr; 52 + 53 + typedef struct XlnxZDMA { 54 + SysBusDevice parent_obj; 55 + MemoryRegion iomem; 56 + MemTxAttrs attr; 57 + MemoryRegion *dma_mr; 58 + AddressSpace *dma_as; 59 + qemu_irq irq_zdma_ch_imr; 60 + 61 + struct { 62 + uint32_t bus_width; 63 + } cfg; 64 + 65 + XlnxZDMAState state; 66 + bool error; 67 + 68 + XlnxZDMADescr dsc_src; 69 + XlnxZDMADescr dsc_dst; 70 + 71 + uint32_t regs[ZDMA_R_MAX]; 72 + RegisterInfo regs_info[ZDMA_R_MAX]; 73 + 74 + /* We don't model the common bufs. Must be at least 16 bytes 75 + to model write only mode. */ 76 + uint8_t buf[2048]; 77 + } XlnxZDMA; 78 + 79 + #define TYPE_XLNX_ZDMA "xlnx.zdma" 80 + 81 + #define XLNX_ZDMA(obj) \ 82 + OBJECT_CHECK(XlnxZDMA, (obj), TYPE_XLNX_ZDMA) 83 + 84 + #endif /* XLNX_ZDMA_H */