1 /* 2 * QEMU model of Xilinx AXI-DMA block. 3 * 4 * Copyright (c) 2011 Edgar E. Iglesias. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "hw/sysbus.h" 27 #include "qapi/error.h" 28 #include "qemu/timer.h" 29 #include "hw/hw.h" 30 #include "hw/irq.h" 31 #include "hw/ptimer.h" 32 #include "hw/qdev-properties.h" 33 #include "qemu/log.h" 34 #include "qemu/module.h" 35 36 #include "sysemu/dma.h" 37 #include "hw/stream.h" 38 #include "qom/object.h" 39 40 #define D(x) 41 42 #define TYPE_XILINX_AXI_DMA "xlnx.axi-dma" 43 #define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream" 44 #define TYPE_XILINX_AXI_DMA_CONTROL_STREAM "xilinx-axi-dma-control-stream" 45 46 OBJECT_DECLARE_SIMPLE_TYPE(XilinxAXIDMA, XILINX_AXI_DMA) 47 48 typedef struct XilinxAXIDMAStreamSink XilinxAXIDMAStreamSink; 49 DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSink, XILINX_AXI_DMA_DATA_STREAM, 50 TYPE_XILINX_AXI_DMA_DATA_STREAM) 51 52 DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSink, XILINX_AXI_DMA_CONTROL_STREAM, 53 TYPE_XILINX_AXI_DMA_CONTROL_STREAM) 54 55 #define R_DMACR (0x00 / 4) 56 #define R_DMASR (0x04 / 4) 57 #define R_CURDESC (0x08 / 4) 58 #define R_TAILDESC (0x10 / 4) 59 #define R_MAX (0x30 / 4) 60 61 #define CONTROL_PAYLOAD_WORDS 5 62 #define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t))) 63 64 65 enum { 66 DMACR_RUNSTOP = 1, 67 DMACR_TAILPTR_MODE = 2, 68 DMACR_RESET = 4 69 }; 70 71 enum { 72 DMASR_HALTED = 1, 73 DMASR_IDLE = 2, 74 DMASR_SLVERR = 1 << 5, 75 DMASR_DECERR = 1 << 6, 76 DMASR_IOC_IRQ = 1 << 12, 77 DMASR_DLY_IRQ = 1 << 13, 78 DMASR_ERR_IRQ = 1 << 14, 79 80 DMASR_IRQ_MASK = 7 << 12 81 }; 82 83 struct SDesc { 84 uint64_t nxtdesc; 85 uint64_t buffer_address; 86 uint64_t reserved; 87 uint32_t control; 88 uint32_t status; 89 uint8_t app[CONTROL_PAYLOAD_SIZE]; 90 }; 91 92 enum { 93 SDESC_CTRL_EOF = (1 << 26), 94 SDESC_CTRL_SOF = (1 << 27), 95 96 SDESC_CTRL_LEN_MASK = (1 << 23) - 1 97 }; 98 99 enum { 100 SDESC_STATUS_EOF = (1 << 26), 101 SDESC_STATUS_SOF_BIT = 27, 102 SDESC_STATUS_SOF = (1 << SDESC_STATUS_SOF_BIT), 103 SDESC_STATUS_COMPLETE = (1 << 31) 104 }; 105 106 struct Stream { 107 struct XilinxAXIDMA *dma; 108 ptimer_state *ptimer; 109 qemu_irq irq; 110 111 int nr; 112 113 bool sof; 114 struct SDesc desc; 115 unsigned int complete_cnt; 116 uint32_t regs[R_MAX]; 117 uint8_t app[20]; 118 unsigned char txbuf[16 * 1024]; 119 }; 120 121 struct XilinxAXIDMAStreamSink { 122 Object parent; 123 124 struct XilinxAXIDMA *dma; 125 }; 126 127 struct XilinxAXIDMA { 128 SysBusDevice busdev; 129 MemoryRegion iomem; 130 MemoryRegion *dma_mr; 131 AddressSpace as; 132 133 uint32_t freqhz; 134 StreamSink *tx_data_dev; 135 StreamSink *tx_control_dev; 136 XilinxAXIDMAStreamSink rx_data_dev; 137 XilinxAXIDMAStreamSink rx_control_dev; 138 139 struct Stream streams[2]; 140 141 StreamCanPushNotifyFn notify; 142 void *notify_opaque; 143 }; 144 145 /* 146 * Helper calls to extract info from descriptors and other trivial 147 * state from regs. 148 */ 149 static inline int stream_desc_sof(struct SDesc *d) 150 { 151 return d->control & SDESC_CTRL_SOF; 152 } 153 154 static inline int stream_desc_eof(struct SDesc *d) 155 { 156 return d->control & SDESC_CTRL_EOF; 157 } 158 159 static inline int stream_resetting(struct Stream *s) 160 { 161 return !!(s->regs[R_DMACR] & DMACR_RESET); 162 } 163 164 static inline int stream_running(struct Stream *s) 165 { 166 return s->regs[R_DMACR] & DMACR_RUNSTOP; 167 } 168 169 static inline int stream_idle(struct Stream *s) 170 { 171 return !!(s->regs[R_DMASR] & DMASR_IDLE); 172 } 173 174 static inline int stream_halted(struct Stream *s) 175 { 176 return !!(s->regs[R_DMASR] & DMASR_HALTED); 177 } 178 179 static void stream_reset(struct Stream *s) 180 { 181 s->regs[R_DMASR] = DMASR_HALTED; /* starts up halted. */ 182 s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold. */ 183 s->sof = true; 184 } 185 186 /* Map an offset addr into a channel index. */ 187 static inline int streamid_from_addr(hwaddr addr) 188 { 189 int sid; 190 191 sid = addr / (0x30); 192 sid &= 1; 193 return sid; 194 } 195 196 static MemTxResult stream_desc_load(struct Stream *s, hwaddr addr) 197 { 198 struct SDesc *d = &s->desc; 199 200 MemTxResult result = address_space_read(&s->dma->as, 201 addr, MEMTXATTRS_UNSPECIFIED, 202 d, sizeof *d); 203 if (result != MEMTX_OK) { 204 if (result == MEMTX_DECODE_ERROR) { 205 s->regs[R_DMASR] |= DMASR_DECERR; 206 } else { 207 s->regs[R_DMASR] |= DMASR_SLVERR; 208 } 209 210 s->regs[R_DMACR] &= ~DMACR_RUNSTOP; 211 s->regs[R_DMASR] |= DMASR_HALTED; 212 s->regs[R_DMASR] |= DMASR_ERR_IRQ; 213 return result; 214 } 215 216 /* Convert from LE into host endianness. */ 217 d->buffer_address = le64_to_cpu(d->buffer_address); 218 d->nxtdesc = le64_to_cpu(d->nxtdesc); 219 d->control = le32_to_cpu(d->control); 220 d->status = le32_to_cpu(d->status); 221 return result; 222 } 223 224 static void stream_desc_store(struct Stream *s, hwaddr addr) 225 { 226 struct SDesc *d = &s->desc; 227 228 /* Convert from host endianness into LE. */ 229 d->buffer_address = cpu_to_le64(d->buffer_address); 230 d->nxtdesc = cpu_to_le64(d->nxtdesc); 231 d->control = cpu_to_le32(d->control); 232 d->status = cpu_to_le32(d->status); 233 address_space_write(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED, 234 d, sizeof *d); 235 } 236 237 static void stream_update_irq(struct Stream *s) 238 { 239 unsigned int pending, mask, irq; 240 241 pending = s->regs[R_DMASR] & DMASR_IRQ_MASK; 242 mask = s->regs[R_DMACR] & DMASR_IRQ_MASK; 243 244 irq = pending & mask; 245 246 qemu_set_irq(s->irq, !!irq); 247 } 248 249 static void stream_reload_complete_cnt(struct Stream *s) 250 { 251 unsigned int comp_th; 252 comp_th = (s->regs[R_DMACR] >> 16) & 0xff; 253 s->complete_cnt = comp_th; 254 } 255 256 static void timer_hit(void *opaque) 257 { 258 struct Stream *s = opaque; 259 260 stream_reload_complete_cnt(s); 261 s->regs[R_DMASR] |= DMASR_DLY_IRQ; 262 stream_update_irq(s); 263 } 264 265 static void stream_complete(struct Stream *s) 266 { 267 unsigned int comp_delay; 268 269 /* Start the delayed timer. */ 270 ptimer_transaction_begin(s->ptimer); 271 comp_delay = s->regs[R_DMACR] >> 24; 272 if (comp_delay) { 273 ptimer_stop(s->ptimer); 274 ptimer_set_count(s->ptimer, comp_delay); 275 ptimer_run(s->ptimer, 1); 276 } 277 278 s->complete_cnt--; 279 if (s->complete_cnt == 0) { 280 /* Raise the IOC irq. */ 281 s->regs[R_DMASR] |= DMASR_IOC_IRQ; 282 stream_reload_complete_cnt(s); 283 } 284 ptimer_transaction_commit(s->ptimer); 285 } 286 287 static void stream_process_mem2s(struct Stream *s, StreamSink *tx_data_dev, 288 StreamSink *tx_control_dev) 289 { 290 uint32_t prev_d; 291 uint32_t txlen; 292 uint64_t addr; 293 bool eop; 294 295 if (!stream_running(s) || stream_idle(s) || stream_halted(s)) { 296 return; 297 } 298 299 while (1) { 300 if (MEMTX_OK != stream_desc_load(s, s->regs[R_CURDESC])) { 301 break; 302 } 303 304 if (s->desc.status & SDESC_STATUS_COMPLETE) { 305 s->regs[R_DMASR] |= DMASR_HALTED; 306 break; 307 } 308 309 if (stream_desc_sof(&s->desc)) { 310 stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true); 311 } 312 313 txlen = s->desc.control & SDESC_CTRL_LEN_MASK; 314 315 eop = stream_desc_eof(&s->desc); 316 addr = s->desc.buffer_address; 317 while (txlen) { 318 unsigned int len; 319 320 len = txlen > sizeof s->txbuf ? sizeof s->txbuf : txlen; 321 address_space_read(&s->dma->as, addr, 322 MEMTXATTRS_UNSPECIFIED, 323 s->txbuf, len); 324 stream_push(tx_data_dev, s->txbuf, len, eop && len == txlen); 325 txlen -= len; 326 addr += len; 327 } 328 329 if (eop) { 330 stream_complete(s); 331 } 332 333 /* Update the descriptor. */ 334 s->desc.status = txlen | SDESC_STATUS_COMPLETE; 335 stream_desc_store(s, s->regs[R_CURDESC]); 336 337 /* Advance. */ 338 prev_d = s->regs[R_CURDESC]; 339 s->regs[R_CURDESC] = s->desc.nxtdesc; 340 if (prev_d == s->regs[R_TAILDESC]) { 341 s->regs[R_DMASR] |= DMASR_IDLE; 342 break; 343 } 344 } 345 } 346 347 static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf, 348 size_t len, bool eop) 349 { 350 uint32_t prev_d; 351 unsigned int rxlen; 352 size_t pos = 0; 353 354 if (!stream_running(s) || stream_idle(s) || stream_halted(s)) { 355 return 0; 356 } 357 358 while (len) { 359 if (MEMTX_OK != stream_desc_load(s, s->regs[R_CURDESC])) { 360 break; 361 } 362 363 if (s->desc.status & SDESC_STATUS_COMPLETE) { 364 s->regs[R_DMASR] |= DMASR_HALTED; 365 break; 366 } 367 368 rxlen = s->desc.control & SDESC_CTRL_LEN_MASK; 369 if (rxlen > len) { 370 /* It fits. */ 371 rxlen = len; 372 } 373 374 address_space_write(&s->dma->as, s->desc.buffer_address, 375 MEMTXATTRS_UNSPECIFIED, buf + pos, rxlen); 376 len -= rxlen; 377 pos += rxlen; 378 379 /* Update the descriptor. */ 380 if (eop) { 381 stream_complete(s); 382 memcpy(s->desc.app, s->app, sizeof(s->desc.app)); 383 s->desc.status |= SDESC_STATUS_EOF; 384 } 385 386 s->desc.status |= s->sof << SDESC_STATUS_SOF_BIT; 387 s->desc.status |= SDESC_STATUS_COMPLETE; 388 stream_desc_store(s, s->regs[R_CURDESC]); 389 s->sof = eop; 390 391 /* Advance. */ 392 prev_d = s->regs[R_CURDESC]; 393 s->regs[R_CURDESC] = s->desc.nxtdesc; 394 if (prev_d == s->regs[R_TAILDESC]) { 395 s->regs[R_DMASR] |= DMASR_IDLE; 396 break; 397 } 398 } 399 400 return pos; 401 } 402 403 static void xilinx_axidma_reset(DeviceState *dev) 404 { 405 int i; 406 XilinxAXIDMA *s = XILINX_AXI_DMA(dev); 407 408 for (i = 0; i < 2; i++) { 409 stream_reset(&s->streams[i]); 410 } 411 } 412 413 static size_t 414 xilinx_axidma_control_stream_push(StreamSink *obj, unsigned char *buf, 415 size_t len, bool eop) 416 { 417 XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); 418 struct Stream *s = &cs->dma->streams[1]; 419 420 if (len != CONTROL_PAYLOAD_SIZE) { 421 hw_error("AXI DMA requires %d byte control stream payload\n", 422 (int)CONTROL_PAYLOAD_SIZE); 423 } 424 425 memcpy(s->app, buf, len); 426 return len; 427 } 428 429 static bool 430 xilinx_axidma_data_stream_can_push(StreamSink *obj, 431 StreamCanPushNotifyFn notify, 432 void *notify_opaque) 433 { 434 XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj); 435 struct Stream *s = &ds->dma->streams[1]; 436 437 if (!stream_running(s) || stream_idle(s) || stream_halted(s)) { 438 ds->dma->notify = notify; 439 ds->dma->notify_opaque = notify_opaque; 440 return false; 441 } 442 443 return true; 444 } 445 446 static size_t 447 xilinx_axidma_data_stream_push(StreamSink *obj, unsigned char *buf, size_t len, 448 bool eop) 449 { 450 XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj); 451 struct Stream *s = &ds->dma->streams[1]; 452 size_t ret; 453 454 ret = stream_process_s2mem(s, buf, len, eop); 455 stream_update_irq(s); 456 return ret; 457 } 458 459 static uint64_t axidma_read(void *opaque, hwaddr addr, 460 unsigned size) 461 { 462 XilinxAXIDMA *d = opaque; 463 struct Stream *s; 464 uint32_t r = 0; 465 int sid; 466 467 sid = streamid_from_addr(addr); 468 s = &d->streams[sid]; 469 470 addr = addr % 0x30; 471 addr >>= 2; 472 switch (addr) { 473 case R_DMACR: 474 /* Simulate one cycles reset delay. */ 475 s->regs[addr] &= ~DMACR_RESET; 476 r = s->regs[addr]; 477 break; 478 case R_DMASR: 479 s->regs[addr] &= 0xffff; 480 s->regs[addr] |= (s->complete_cnt & 0xff) << 16; 481 s->regs[addr] |= (ptimer_get_count(s->ptimer) & 0xff) << 24; 482 r = s->regs[addr]; 483 break; 484 default: 485 r = s->regs[addr]; 486 D(qemu_log("%s ch=%d addr=" HWADDR_FMT_plx " v=%x\n", 487 __func__, sid, addr * 4, r)); 488 break; 489 } 490 return r; 491 492 } 493 494 static void axidma_write(void *opaque, hwaddr addr, 495 uint64_t value, unsigned size) 496 { 497 XilinxAXIDMA *d = opaque; 498 struct Stream *s; 499 int sid; 500 501 sid = streamid_from_addr(addr); 502 s = &d->streams[sid]; 503 504 addr = addr % 0x30; 505 addr >>= 2; 506 switch (addr) { 507 case R_DMACR: 508 /* Tailptr mode is always on. */ 509 value |= DMACR_TAILPTR_MODE; 510 /* Remember our previous reset state. */ 511 value |= (s->regs[addr] & DMACR_RESET); 512 s->regs[addr] = value; 513 514 if (value & DMACR_RESET) { 515 stream_reset(s); 516 } 517 518 if ((value & 1) && !stream_resetting(s)) { 519 /* Start processing. */ 520 s->regs[R_DMASR] &= ~(DMASR_HALTED | DMASR_IDLE); 521 } 522 stream_reload_complete_cnt(s); 523 break; 524 525 case R_DMASR: 526 /* Mask away write to clear irq lines. */ 527 value &= ~(value & DMASR_IRQ_MASK); 528 s->regs[addr] = value; 529 break; 530 531 case R_TAILDESC: 532 s->regs[addr] = value; 533 s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle. */ 534 if (!sid) { 535 stream_process_mem2s(s, d->tx_data_dev, d->tx_control_dev); 536 } 537 break; 538 default: 539 D(qemu_log("%s: ch=%d addr=" HWADDR_FMT_plx " v=%x\n", 540 __func__, sid, addr * 4, (unsigned)value)); 541 s->regs[addr] = value; 542 break; 543 } 544 if (sid == 1 && d->notify) { 545 StreamCanPushNotifyFn notifytmp = d->notify; 546 d->notify = NULL; 547 notifytmp(d->notify_opaque); 548 } 549 stream_update_irq(s); 550 } 551 552 static const MemoryRegionOps axidma_ops = { 553 .read = axidma_read, 554 .write = axidma_write, 555 .endianness = DEVICE_NATIVE_ENDIAN, 556 }; 557 558 static void xilinx_axidma_realize(DeviceState *dev, Error **errp) 559 { 560 XilinxAXIDMA *s = XILINX_AXI_DMA(dev); 561 XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); 562 XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM( 563 &s->rx_control_dev); 564 int i; 565 566 object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA, 567 (Object **)&ds->dma, 568 object_property_allow_set_link, 569 OBJ_PROP_LINK_STRONG); 570 object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA, 571 (Object **)&cs->dma, 572 object_property_allow_set_link, 573 OBJ_PROP_LINK_STRONG); 574 object_property_set_link(OBJECT(ds), "dma", OBJECT(s), &error_abort); 575 object_property_set_link(OBJECT(cs), "dma", OBJECT(s), &error_abort); 576 577 for (i = 0; i < 2; i++) { 578 struct Stream *st = &s->streams[i]; 579 580 st->dma = s; 581 st->nr = i; 582 st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_LEGACY); 583 ptimer_transaction_begin(st->ptimer); 584 ptimer_set_freq(st->ptimer, s->freqhz); 585 ptimer_transaction_commit(st->ptimer); 586 } 587 588 address_space_init(&s->as, 589 s->dma_mr ? s->dma_mr : get_system_memory(), "dma"); 590 } 591 592 static void xilinx_axidma_init(Object *obj) 593 { 594 XilinxAXIDMA *s = XILINX_AXI_DMA(obj); 595 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 596 597 object_initialize_child(OBJECT(s), "axistream-connected-target", 598 &s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM); 599 object_initialize_child(OBJECT(s), "axistream-control-connected-target", 600 &s->rx_control_dev, 601 TYPE_XILINX_AXI_DMA_CONTROL_STREAM); 602 603 sysbus_init_irq(sbd, &s->streams[0].irq); 604 sysbus_init_irq(sbd, &s->streams[1].irq); 605 606 memory_region_init_io(&s->iomem, obj, &axidma_ops, s, 607 "xlnx.axi-dma", R_MAX * 4 * 2); 608 sysbus_init_mmio(sbd, &s->iomem); 609 } 610 611 static Property axidma_properties[] = { 612 DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000), 613 DEFINE_PROP_LINK("axistream-connected", XilinxAXIDMA, 614 tx_data_dev, TYPE_STREAM_SINK, StreamSink *), 615 DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIDMA, 616 tx_control_dev, TYPE_STREAM_SINK, StreamSink *), 617 DEFINE_PROP_LINK("dma", XilinxAXIDMA, dma_mr, 618 TYPE_MEMORY_REGION, MemoryRegion *), 619 DEFINE_PROP_END_OF_LIST(), 620 }; 621 622 static void axidma_class_init(ObjectClass *klass, void *data) 623 { 624 DeviceClass *dc = DEVICE_CLASS(klass); 625 626 dc->realize = xilinx_axidma_realize, 627 dc->reset = xilinx_axidma_reset; 628 device_class_set_props(dc, axidma_properties); 629 } 630 631 static StreamSinkClass xilinx_axidma_data_stream_class = { 632 .push = xilinx_axidma_data_stream_push, 633 .can_push = xilinx_axidma_data_stream_can_push, 634 }; 635 636 static StreamSinkClass xilinx_axidma_control_stream_class = { 637 .push = xilinx_axidma_control_stream_push, 638 }; 639 640 static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data) 641 { 642 StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); 643 644 ssc->push = ((StreamSinkClass *)data)->push; 645 ssc->can_push = ((StreamSinkClass *)data)->can_push; 646 } 647 648 static const TypeInfo axidma_info = { 649 .name = TYPE_XILINX_AXI_DMA, 650 .parent = TYPE_SYS_BUS_DEVICE, 651 .instance_size = sizeof(XilinxAXIDMA), 652 .class_init = axidma_class_init, 653 .instance_init = xilinx_axidma_init, 654 }; 655 656 static const TypeInfo xilinx_axidma_data_stream_info = { 657 .name = TYPE_XILINX_AXI_DMA_DATA_STREAM, 658 .parent = TYPE_OBJECT, 659 .instance_size = sizeof(XilinxAXIDMAStreamSink), 660 .class_init = xilinx_axidma_stream_class_init, 661 .class_data = &xilinx_axidma_data_stream_class, 662 .interfaces = (InterfaceInfo[]) { 663 { TYPE_STREAM_SINK }, 664 { } 665 } 666 }; 667 668 static const TypeInfo xilinx_axidma_control_stream_info = { 669 .name = TYPE_XILINX_AXI_DMA_CONTROL_STREAM, 670 .parent = TYPE_OBJECT, 671 .instance_size = sizeof(XilinxAXIDMAStreamSink), 672 .class_init = xilinx_axidma_stream_class_init, 673 .class_data = &xilinx_axidma_control_stream_class, 674 .interfaces = (InterfaceInfo[]) { 675 { TYPE_STREAM_SINK }, 676 { } 677 } 678 }; 679 680 static void xilinx_axidma_register_types(void) 681 { 682 type_register_static(&axidma_info); 683 type_register_static(&xilinx_axidma_data_stream_info); 684 type_register_static(&xilinx_axidma_control_stream_info); 685 } 686 687 type_init(xilinx_axidma_register_types) 688