qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

xilinx_axidma.c (18873B)


      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_IOC_IRQ  = 1 << 12,
     75     DMASR_DLY_IRQ  = 1 << 13,
     76 
     77     DMASR_IRQ_MASK = 7 << 12
     78 };
     79 
     80 struct SDesc {
     81     uint64_t nxtdesc;
     82     uint64_t buffer_address;
     83     uint64_t reserved;
     84     uint32_t control;
     85     uint32_t status;
     86     uint8_t app[CONTROL_PAYLOAD_SIZE];
     87 };
     88 
     89 enum {
     90     SDESC_CTRL_EOF = (1 << 26),
     91     SDESC_CTRL_SOF = (1 << 27),
     92 
     93     SDESC_CTRL_LEN_MASK = (1 << 23) - 1
     94 };
     95 
     96 enum {
     97     SDESC_STATUS_EOF = (1 << 26),
     98     SDESC_STATUS_SOF_BIT = 27,
     99     SDESC_STATUS_SOF = (1 << SDESC_STATUS_SOF_BIT),
    100     SDESC_STATUS_COMPLETE = (1 << 31)
    101 };
    102 
    103 struct Stream {
    104     struct XilinxAXIDMA *dma;
    105     ptimer_state *ptimer;
    106     qemu_irq irq;
    107 
    108     int nr;
    109 
    110     bool sof;
    111     struct SDesc desc;
    112     unsigned int complete_cnt;
    113     uint32_t regs[R_MAX];
    114     uint8_t app[20];
    115     unsigned char txbuf[16 * 1024];
    116 };
    117 
    118 struct XilinxAXIDMAStreamSink {
    119     Object parent;
    120 
    121     struct XilinxAXIDMA *dma;
    122 };
    123 
    124 struct XilinxAXIDMA {
    125     SysBusDevice busdev;
    126     MemoryRegion iomem;
    127     MemoryRegion *dma_mr;
    128     AddressSpace as;
    129 
    130     uint32_t freqhz;
    131     StreamSink *tx_data_dev;
    132     StreamSink *tx_control_dev;
    133     XilinxAXIDMAStreamSink rx_data_dev;
    134     XilinxAXIDMAStreamSink rx_control_dev;
    135 
    136     struct Stream streams[2];
    137 
    138     StreamCanPushNotifyFn notify;
    139     void *notify_opaque;
    140 };
    141 
    142 /*
    143  * Helper calls to extract info from descriptors and other trivial
    144  * state from regs.
    145  */
    146 static inline int stream_desc_sof(struct SDesc *d)
    147 {
    148     return d->control & SDESC_CTRL_SOF;
    149 }
    150 
    151 static inline int stream_desc_eof(struct SDesc *d)
    152 {
    153     return d->control & SDESC_CTRL_EOF;
    154 }
    155 
    156 static inline int stream_resetting(struct Stream *s)
    157 {
    158     return !!(s->regs[R_DMACR] & DMACR_RESET);
    159 }
    160 
    161 static inline int stream_running(struct Stream *s)
    162 {
    163     return s->regs[R_DMACR] & DMACR_RUNSTOP;
    164 }
    165 
    166 static inline int stream_idle(struct Stream *s)
    167 {
    168     return !!(s->regs[R_DMASR] & DMASR_IDLE);
    169 }
    170 
    171 static void stream_reset(struct Stream *s)
    172 {
    173     s->regs[R_DMASR] = DMASR_HALTED;  /* starts up halted.  */
    174     s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold.  */
    175     s->sof = true;
    176 }
    177 
    178 /* Map an offset addr into a channel index.  */
    179 static inline int streamid_from_addr(hwaddr addr)
    180 {
    181     int sid;
    182 
    183     sid = addr / (0x30);
    184     sid &= 1;
    185     return sid;
    186 }
    187 
    188 static void stream_desc_load(struct Stream *s, hwaddr addr)
    189 {
    190     struct SDesc *d = &s->desc;
    191 
    192     address_space_read(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
    193 
    194     /* Convert from LE into host endianness.  */
    195     d->buffer_address = le64_to_cpu(d->buffer_address);
    196     d->nxtdesc = le64_to_cpu(d->nxtdesc);
    197     d->control = le32_to_cpu(d->control);
    198     d->status = le32_to_cpu(d->status);
    199 }
    200 
    201 static void stream_desc_store(struct Stream *s, hwaddr addr)
    202 {
    203     struct SDesc *d = &s->desc;
    204 
    205     /* Convert from host endianness into LE.  */
    206     d->buffer_address = cpu_to_le64(d->buffer_address);
    207     d->nxtdesc = cpu_to_le64(d->nxtdesc);
    208     d->control = cpu_to_le32(d->control);
    209     d->status = cpu_to_le32(d->status);
    210     address_space_write(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED,
    211                         d, sizeof *d);
    212 }
    213 
    214 static void stream_update_irq(struct Stream *s)
    215 {
    216     unsigned int pending, mask, irq;
    217 
    218     pending = s->regs[R_DMASR] & DMASR_IRQ_MASK;
    219     mask = s->regs[R_DMACR] & DMASR_IRQ_MASK;
    220 
    221     irq = pending & mask;
    222 
    223     qemu_set_irq(s->irq, !!irq);
    224 }
    225 
    226 static void stream_reload_complete_cnt(struct Stream *s)
    227 {
    228     unsigned int comp_th;
    229     comp_th = (s->regs[R_DMACR] >> 16) & 0xff;
    230     s->complete_cnt = comp_th;
    231 }
    232 
    233 static void timer_hit(void *opaque)
    234 {
    235     struct Stream *s = opaque;
    236 
    237     stream_reload_complete_cnt(s);
    238     s->regs[R_DMASR] |= DMASR_DLY_IRQ;
    239     stream_update_irq(s);
    240 }
    241 
    242 static void stream_complete(struct Stream *s)
    243 {
    244     unsigned int comp_delay;
    245 
    246     /* Start the delayed timer.  */
    247     ptimer_transaction_begin(s->ptimer);
    248     comp_delay = s->regs[R_DMACR] >> 24;
    249     if (comp_delay) {
    250         ptimer_stop(s->ptimer);
    251         ptimer_set_count(s->ptimer, comp_delay);
    252         ptimer_run(s->ptimer, 1);
    253     }
    254 
    255     s->complete_cnt--;
    256     if (s->complete_cnt == 0) {
    257         /* Raise the IOC irq.  */
    258         s->regs[R_DMASR] |= DMASR_IOC_IRQ;
    259         stream_reload_complete_cnt(s);
    260     }
    261     ptimer_transaction_commit(s->ptimer);
    262 }
    263 
    264 static void stream_process_mem2s(struct Stream *s, StreamSink *tx_data_dev,
    265                                  StreamSink *tx_control_dev)
    266 {
    267     uint32_t prev_d;
    268     uint32_t txlen;
    269     uint64_t addr;
    270     bool eop;
    271 
    272     if (!stream_running(s) || stream_idle(s)) {
    273         return;
    274     }
    275 
    276     while (1) {
    277         stream_desc_load(s, s->regs[R_CURDESC]);
    278 
    279         if (s->desc.status & SDESC_STATUS_COMPLETE) {
    280             s->regs[R_DMASR] |= DMASR_HALTED;
    281             break;
    282         }
    283 
    284         if (stream_desc_sof(&s->desc)) {
    285             stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true);
    286         }
    287 
    288         txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
    289 
    290         eop = stream_desc_eof(&s->desc);
    291         addr = s->desc.buffer_address;
    292         while (txlen) {
    293             unsigned int len;
    294 
    295             len = txlen > sizeof s->txbuf ? sizeof s->txbuf : txlen;
    296             address_space_read(&s->dma->as, addr,
    297                                MEMTXATTRS_UNSPECIFIED,
    298                                s->txbuf, len);
    299             stream_push(tx_data_dev, s->txbuf, len, eop && len == txlen);
    300             txlen -= len;
    301             addr += len;
    302         }
    303 
    304         if (eop) {
    305             stream_complete(s);
    306         }
    307 
    308         /* Update the descriptor.  */
    309         s->desc.status = txlen | SDESC_STATUS_COMPLETE;
    310         stream_desc_store(s, s->regs[R_CURDESC]);
    311 
    312         /* Advance.  */
    313         prev_d = s->regs[R_CURDESC];
    314         s->regs[R_CURDESC] = s->desc.nxtdesc;
    315         if (prev_d == s->regs[R_TAILDESC]) {
    316             s->regs[R_DMASR] |= DMASR_IDLE;
    317             break;
    318         }
    319     }
    320 }
    321 
    322 static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
    323                                    size_t len, bool eop)
    324 {
    325     uint32_t prev_d;
    326     unsigned int rxlen;
    327     size_t pos = 0;
    328 
    329     if (!stream_running(s) || stream_idle(s)) {
    330         return 0;
    331     }
    332 
    333     while (len) {
    334         stream_desc_load(s, s->regs[R_CURDESC]);
    335 
    336         if (s->desc.status & SDESC_STATUS_COMPLETE) {
    337             s->regs[R_DMASR] |= DMASR_HALTED;
    338             break;
    339         }
    340 
    341         rxlen = s->desc.control & SDESC_CTRL_LEN_MASK;
    342         if (rxlen > len) {
    343             /* It fits.  */
    344             rxlen = len;
    345         }
    346 
    347         address_space_write(&s->dma->as, s->desc.buffer_address,
    348                             MEMTXATTRS_UNSPECIFIED, buf + pos, rxlen);
    349         len -= rxlen;
    350         pos += rxlen;
    351 
    352         /* Update the descriptor.  */
    353         if (eop) {
    354             stream_complete(s);
    355             memcpy(s->desc.app, s->app, sizeof(s->desc.app));
    356             s->desc.status |= SDESC_STATUS_EOF;
    357         }
    358 
    359         s->desc.status |= s->sof << SDESC_STATUS_SOF_BIT;
    360         s->desc.status |= SDESC_STATUS_COMPLETE;
    361         stream_desc_store(s, s->regs[R_CURDESC]);
    362         s->sof = eop;
    363 
    364         /* Advance.  */
    365         prev_d = s->regs[R_CURDESC];
    366         s->regs[R_CURDESC] = s->desc.nxtdesc;
    367         if (prev_d == s->regs[R_TAILDESC]) {
    368             s->regs[R_DMASR] |= DMASR_IDLE;
    369             break;
    370         }
    371     }
    372 
    373     return pos;
    374 }
    375 
    376 static void xilinx_axidma_reset(DeviceState *dev)
    377 {
    378     int i;
    379     XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
    380 
    381     for (i = 0; i < 2; i++) {
    382         stream_reset(&s->streams[i]);
    383     }
    384 }
    385 
    386 static size_t
    387 xilinx_axidma_control_stream_push(StreamSink *obj, unsigned char *buf,
    388                                   size_t len, bool eop)
    389 {
    390     XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
    391     struct Stream *s = &cs->dma->streams[1];
    392 
    393     if (len != CONTROL_PAYLOAD_SIZE) {
    394         hw_error("AXI DMA requires %d byte control stream payload\n",
    395                  (int)CONTROL_PAYLOAD_SIZE);
    396     }
    397 
    398     memcpy(s->app, buf, len);
    399     return len;
    400 }
    401 
    402 static bool
    403 xilinx_axidma_data_stream_can_push(StreamSink *obj,
    404                                    StreamCanPushNotifyFn notify,
    405                                    void *notify_opaque)
    406 {
    407     XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
    408     struct Stream *s = &ds->dma->streams[1];
    409 
    410     if (!stream_running(s) || stream_idle(s)) {
    411         ds->dma->notify = notify;
    412         ds->dma->notify_opaque = notify_opaque;
    413         return false;
    414     }
    415 
    416     return true;
    417 }
    418 
    419 static size_t
    420 xilinx_axidma_data_stream_push(StreamSink *obj, unsigned char *buf, size_t len,
    421                                bool eop)
    422 {
    423     XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
    424     struct Stream *s = &ds->dma->streams[1];
    425     size_t ret;
    426 
    427     ret = stream_process_s2mem(s, buf, len, eop);
    428     stream_update_irq(s);
    429     return ret;
    430 }
    431 
    432 static uint64_t axidma_read(void *opaque, hwaddr addr,
    433                             unsigned size)
    434 {
    435     XilinxAXIDMA *d = opaque;
    436     struct Stream *s;
    437     uint32_t r = 0;
    438     int sid;
    439 
    440     sid = streamid_from_addr(addr);
    441     s = &d->streams[sid];
    442 
    443     addr = addr % 0x30;
    444     addr >>= 2;
    445     switch (addr) {
    446         case R_DMACR:
    447             /* Simulate one cycles reset delay.  */
    448             s->regs[addr] &= ~DMACR_RESET;
    449             r = s->regs[addr];
    450             break;
    451         case R_DMASR:
    452             s->regs[addr] &= 0xffff;
    453             s->regs[addr] |= (s->complete_cnt & 0xff) << 16;
    454             s->regs[addr] |= (ptimer_get_count(s->ptimer) & 0xff) << 24;
    455             r = s->regs[addr];
    456             break;
    457         default:
    458             r = s->regs[addr];
    459             D(qemu_log("%s ch=%d addr=" TARGET_FMT_plx " v=%x\n",
    460                            __func__, sid, addr * 4, r));
    461             break;
    462     }
    463     return r;
    464 
    465 }
    466 
    467 static void axidma_write(void *opaque, hwaddr addr,
    468                          uint64_t value, unsigned size)
    469 {
    470     XilinxAXIDMA *d = opaque;
    471     struct Stream *s;
    472     int sid;
    473 
    474     sid = streamid_from_addr(addr);
    475     s = &d->streams[sid];
    476 
    477     addr = addr % 0x30;
    478     addr >>= 2;
    479     switch (addr) {
    480         case R_DMACR:
    481             /* Tailptr mode is always on.  */
    482             value |= DMACR_TAILPTR_MODE;
    483             /* Remember our previous reset state.  */
    484             value |= (s->regs[addr] & DMACR_RESET);
    485             s->regs[addr] = value;
    486 
    487             if (value & DMACR_RESET) {
    488                 stream_reset(s);
    489             }
    490 
    491             if ((value & 1) && !stream_resetting(s)) {
    492                 /* Start processing.  */
    493                 s->regs[R_DMASR] &= ~(DMASR_HALTED | DMASR_IDLE);
    494             }
    495             stream_reload_complete_cnt(s);
    496             break;
    497 
    498         case R_DMASR:
    499             /* Mask away write to clear irq lines.  */
    500             value &= ~(value & DMASR_IRQ_MASK);
    501             s->regs[addr] = value;
    502             break;
    503 
    504         case R_TAILDESC:
    505             s->regs[addr] = value;
    506             s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle.  */
    507             if (!sid) {
    508                 stream_process_mem2s(s, d->tx_data_dev, d->tx_control_dev);
    509             }
    510             break;
    511         default:
    512             D(qemu_log("%s: ch=%d addr=" TARGET_FMT_plx " v=%x\n",
    513                   __func__, sid, addr * 4, (unsigned)value));
    514             s->regs[addr] = value;
    515             break;
    516     }
    517     if (sid == 1 && d->notify) {
    518         StreamCanPushNotifyFn notifytmp = d->notify;
    519         d->notify = NULL;
    520         notifytmp(d->notify_opaque);
    521     }
    522     stream_update_irq(s);
    523 }
    524 
    525 static const MemoryRegionOps axidma_ops = {
    526     .read = axidma_read,
    527     .write = axidma_write,
    528     .endianness = DEVICE_NATIVE_ENDIAN,
    529 };
    530 
    531 static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
    532 {
    533     XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
    534     XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev);
    535     XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM(
    536                                                             &s->rx_control_dev);
    537     int i;
    538 
    539     object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
    540                              (Object **)&ds->dma,
    541                              object_property_allow_set_link,
    542                              OBJ_PROP_LINK_STRONG);
    543     object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
    544                              (Object **)&cs->dma,
    545                              object_property_allow_set_link,
    546                              OBJ_PROP_LINK_STRONG);
    547     object_property_set_link(OBJECT(ds), "dma", OBJECT(s), &error_abort);
    548     object_property_set_link(OBJECT(cs), "dma", OBJECT(s), &error_abort);
    549 
    550     for (i = 0; i < 2; i++) {
    551         struct Stream *st = &s->streams[i];
    552 
    553         st->dma = s;
    554         st->nr = i;
    555         st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_LEGACY);
    556         ptimer_transaction_begin(st->ptimer);
    557         ptimer_set_freq(st->ptimer, s->freqhz);
    558         ptimer_transaction_commit(st->ptimer);
    559     }
    560 
    561     address_space_init(&s->as,
    562                        s->dma_mr ? s->dma_mr : get_system_memory(), "dma");
    563 }
    564 
    565 static void xilinx_axidma_init(Object *obj)
    566 {
    567     XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
    568     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    569 
    570     object_initialize_child(OBJECT(s), "axistream-connected-target",
    571                             &s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM);
    572     object_initialize_child(OBJECT(s), "axistream-control-connected-target",
    573                             &s->rx_control_dev,
    574                             TYPE_XILINX_AXI_DMA_CONTROL_STREAM);
    575     object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
    576                              (Object **)&s->dma_mr,
    577                              qdev_prop_allow_set_link_before_realize,
    578                              OBJ_PROP_LINK_STRONG);
    579 
    580     sysbus_init_irq(sbd, &s->streams[0].irq);
    581     sysbus_init_irq(sbd, &s->streams[1].irq);
    582 
    583     memory_region_init_io(&s->iomem, obj, &axidma_ops, s,
    584                           "xlnx.axi-dma", R_MAX * 4 * 2);
    585     sysbus_init_mmio(sbd, &s->iomem);
    586 }
    587 
    588 static Property axidma_properties[] = {
    589     DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000),
    590     DEFINE_PROP_LINK("axistream-connected", XilinxAXIDMA,
    591                      tx_data_dev, TYPE_STREAM_SINK, StreamSink *),
    592     DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIDMA,
    593                      tx_control_dev, TYPE_STREAM_SINK, StreamSink *),
    594     DEFINE_PROP_END_OF_LIST(),
    595 };
    596 
    597 static void axidma_class_init(ObjectClass *klass, void *data)
    598 {
    599     DeviceClass *dc = DEVICE_CLASS(klass);
    600 
    601     dc->realize = xilinx_axidma_realize,
    602     dc->reset = xilinx_axidma_reset;
    603     device_class_set_props(dc, axidma_properties);
    604 }
    605 
    606 static StreamSinkClass xilinx_axidma_data_stream_class = {
    607     .push = xilinx_axidma_data_stream_push,
    608     .can_push = xilinx_axidma_data_stream_can_push,
    609 };
    610 
    611 static StreamSinkClass xilinx_axidma_control_stream_class = {
    612     .push = xilinx_axidma_control_stream_push,
    613 };
    614 
    615 static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data)
    616 {
    617     StreamSinkClass *ssc = STREAM_SINK_CLASS(klass);
    618 
    619     ssc->push = ((StreamSinkClass *)data)->push;
    620     ssc->can_push = ((StreamSinkClass *)data)->can_push;
    621 }
    622 
    623 static const TypeInfo axidma_info = {
    624     .name          = TYPE_XILINX_AXI_DMA,
    625     .parent        = TYPE_SYS_BUS_DEVICE,
    626     .instance_size = sizeof(XilinxAXIDMA),
    627     .class_init    = axidma_class_init,
    628     .instance_init = xilinx_axidma_init,
    629 };
    630 
    631 static const TypeInfo xilinx_axidma_data_stream_info = {
    632     .name          = TYPE_XILINX_AXI_DMA_DATA_STREAM,
    633     .parent        = TYPE_OBJECT,
    634     .instance_size = sizeof(XilinxAXIDMAStreamSink),
    635     .class_init    = xilinx_axidma_stream_class_init,
    636     .class_data    = &xilinx_axidma_data_stream_class,
    637     .interfaces = (InterfaceInfo[]) {
    638         { TYPE_STREAM_SINK },
    639         { }
    640     }
    641 };
    642 
    643 static const TypeInfo xilinx_axidma_control_stream_info = {
    644     .name          = TYPE_XILINX_AXI_DMA_CONTROL_STREAM,
    645     .parent        = TYPE_OBJECT,
    646     .instance_size = sizeof(XilinxAXIDMAStreamSink),
    647     .class_init    = xilinx_axidma_stream_class_init,
    648     .class_data    = &xilinx_axidma_control_stream_class,
    649     .interfaces = (InterfaceInfo[]) {
    650         { TYPE_STREAM_SINK },
    651         { }
    652     }
    653 };
    654 
    655 static void xilinx_axidma_register_types(void)
    656 {
    657     type_register_static(&axidma_info);
    658     type_register_static(&xilinx_axidma_data_stream_info);
    659     type_register_static(&xilinx_axidma_control_stream_info);
    660 }
    661 
    662 type_init(xilinx_axidma_register_types)