diff options
author | Peter Crosthwaite <peter.crosthwaite@xilinx.com> | 2013-04-16 10:28:35 +1000 |
---|---|---|
committer | Edgar E. Iglesias <edgar.iglesias@gmail.com> | 2013-04-16 10:04:23 +0200 |
commit | 42bb9c9178ae7ac4c439172b1ae99cc29188a5c6 (patch) | |
tree | faf02d3b510f34a449701c82744a1c701e19569d /hw/dma/xilinx_axidma.c | |
parent | 3630ae952a17c2107db25f397233536ef874558e (diff) |
stream: Remove app argument hack
The uint32_t *app argument doesn't exist in real hardware. It was a hack in
xilinx_axidma/enet to fake the (secondary) control stream connection. Removed
the argument and added the second stream to axienet/dma.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Diffstat (limited to 'hw/dma/xilinx_axidma.c')
-rw-r--r-- | hw/dma/xilinx_axidma.c | 99 |
1 files changed, 70 insertions, 29 deletions
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index a5bf10241b..1c23762210 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -35,6 +35,7 @@ #define TYPE_XILINX_AXI_DMA "xlnx.axi-dma" #define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream" +#define TYPE_XILINX_AXI_DMA_CONTROL_STREAM "xilinx-axi-dma-control-stream" #define XILINX_AXI_DMA(obj) \ OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA) @@ -43,12 +44,19 @@ OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\ TYPE_XILINX_AXI_DMA_DATA_STREAM) +#define XILINX_AXI_DMA_CONTROL_STREAM(obj) \ + OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\ + TYPE_XILINX_AXI_DMA_CONTROL_STREAM) + #define R_DMACR (0x00 / 4) #define R_DMASR (0x04 / 4) #define R_CURDESC (0x08 / 4) #define R_TAILDESC (0x10 / 4) #define R_MAX (0x30 / 4) +#define CONTROL_PAYLOAD_WORDS 5 +#define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t))) + typedef struct XilinxAXIDMA XilinxAXIDMA; typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave; @@ -73,7 +81,7 @@ struct SDesc { uint64_t reserved; uint32_t control; uint32_t status; - uint32_t app[6]; + uint8_t app[CONTROL_PAYLOAD_SIZE]; }; enum { @@ -101,6 +109,7 @@ struct Stream { int pos; unsigned int complete_cnt; uint32_t regs[R_MAX]; + uint8_t app[20]; }; struct XilinxAXIDMAStreamSlave { @@ -113,8 +122,10 @@ struct XilinxAXIDMA { SysBusDevice busdev; MemoryRegion iomem; uint32_t freqhz; - StreamSlave *tx_dev; + StreamSlave *tx_data_dev; + StreamSlave *tx_control_dev; XilinxAXIDMAStreamSlave rx_data_dev; + XilinxAXIDMAStreamSlave rx_control_dev; struct Stream streams[2]; @@ -185,7 +196,6 @@ static void stream_desc_show(struct SDesc *d) static void stream_desc_load(struct Stream *s, hwaddr addr) { struct SDesc *d = &s->desc; - int i; cpu_physical_memory_read(addr, (void *) d, sizeof *d); @@ -194,24 +204,17 @@ static void stream_desc_load(struct Stream *s, hwaddr addr) d->nxtdesc = le64_to_cpu(d->nxtdesc); d->control = le32_to_cpu(d->control); d->status = le32_to_cpu(d->status); - for (i = 0; i < ARRAY_SIZE(d->app); i++) { - d->app[i] = le32_to_cpu(d->app[i]); - } } static void stream_desc_store(struct Stream *s, hwaddr addr) { struct SDesc *d = &s->desc; - int i; /* Convert from host endianness into LE. */ d->buffer_address = cpu_to_le64(d->buffer_address); d->nxtdesc = cpu_to_le64(d->nxtdesc); d->control = cpu_to_le32(d->control); d->status = cpu_to_le32(d->status); - for (i = 0; i < ARRAY_SIZE(d->app); i++) { - d->app[i] = cpu_to_le32(d->app[i]); - } cpu_physical_memory_write(addr, (void *) d, sizeof *d); } @@ -263,13 +266,12 @@ static void stream_complete(struct Stream *s) } } -static void stream_process_mem2s(struct Stream *s, - StreamSlave *tx_dev) +static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, + StreamSlave *tx_control_dev) { uint32_t prev_d; unsigned char txbuf[16 * 1024]; unsigned int txlen; - uint32_t app[6]; if (!stream_running(s) || stream_idle(s)) { return; @@ -285,7 +287,7 @@ static void stream_process_mem2s(struct Stream *s, if (stream_desc_sof(&s->desc)) { s->pos = 0; - memcpy(app, s->desc.app, sizeof app); + stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app)); } txlen = s->desc.control & SDESC_CTRL_LEN_MASK; @@ -299,7 +301,7 @@ static void stream_process_mem2s(struct Stream *s, s->pos += txlen; if (stream_desc_eof(&s->desc)) { - stream_push(tx_dev, txbuf, s->pos, app); + stream_push(tx_data_dev, txbuf, s->pos); s->pos = 0; stream_complete(s); } @@ -319,7 +321,7 @@ static void stream_process_mem2s(struct Stream *s, } static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf, - size_t len, uint32_t *app) + size_t len) { uint32_t prev_d; unsigned int rxlen; @@ -350,12 +352,8 @@ static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf, /* Update the descriptor. */ if (!len) { - int i; - stream_complete(s); - for (i = 0; i < 5; i++) { - s->desc.app[i] = app[i]; - } + memcpy(s->desc.app, s->app, sizeof(s->desc.app)); s->desc.status |= SDESC_STATUS_EOF; } @@ -386,6 +384,22 @@ static void xilinx_axidma_reset(DeviceState *dev) } } +static size_t +xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf, + size_t len) +{ + XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); + struct Stream *s = &cs->dma->streams[1]; + + if (len != CONTROL_PAYLOAD_SIZE) { + hw_error("AXI DMA requires %d byte control stream payload\n", + (int)CONTROL_PAYLOAD_SIZE); + } + + memcpy(s->app, buf, len); + return len; +} + static bool xilinx_axidma_data_stream_can_push(StreamSlave *obj, StreamCanPushNotifyFn notify, @@ -404,17 +418,13 @@ xilinx_axidma_data_stream_can_push(StreamSlave *obj, } static size_t -xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len, - uint32_t *app) +xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len) { XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); struct Stream *s = &ds->dma->streams[1]; size_t ret; - if (!app) { - hw_error("No stream app data!\n"); - } - ret = stream_process_s2mem(s, buf, len, app); + ret = stream_process_s2mem(s, buf, len); stream_update_irq(s); return ret; } @@ -495,7 +505,7 @@ static void axidma_write(void *opaque, hwaddr addr, s->regs[addr] = value; s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle. */ if (!sid) { - stream_process_mem2s(s, d->tx_dev); + stream_process_mem2s(s, d->tx_data_dev, d->tx_control_dev); } break; default: @@ -521,14 +531,19 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) { XilinxAXIDMA *s = XILINX_AXI_DMA(dev); XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); + XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM( + &s->rx_control_dev); Error *local_errp = NULL; object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA, (Object **)&ds->dma, &local_errp); + object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA, + (Object **)&cs->dma, &local_errp); if (local_errp) { goto xilinx_axidma_realize_fail; } object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_errp); + object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_errp); if (local_errp) { goto xilinx_axidma_realize_fail; } @@ -556,12 +571,21 @@ static void xilinx_axidma_init(Object *obj) Error *errp = NULL; object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE, - (Object **) &s->tx_dev, NULL); + (Object **) &s->tx_data_dev, &errp); + assert_no_error(errp); + object_property_add_link(obj, "axistream-control-connected", + TYPE_STREAM_SLAVE, + (Object **) &s->tx_control_dev, &errp); + assert_no_error(errp); object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM); + object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_DMA_CONTROL_STREAM); object_property_add_child(OBJECT(s), "axistream-connected-target", (Object *)&s->rx_data_dev, &errp); assert_no_error(errp); + object_property_add_child(OBJECT(s), "axistream-control-connected-target", + (Object *)&s->rx_control_dev, &errp); + assert_no_error(errp); sysbus_init_irq(sbd, &s->streams[0].irq); sysbus_init_irq(sbd, &s->streams[1].irq); @@ -590,6 +614,10 @@ static StreamSlaveClass xilinx_axidma_data_stream_class = { .can_push = xilinx_axidma_data_stream_can_push, }; +static StreamSlaveClass xilinx_axidma_control_stream_class = { + .push = xilinx_axidma_control_stream_push, +}; + static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data) { StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); @@ -618,10 +646,23 @@ static const TypeInfo xilinx_axidma_data_stream_info = { } }; +static const TypeInfo xilinx_axidma_control_stream_info = { + .name = TYPE_XILINX_AXI_DMA_CONTROL_STREAM, + .parent = TYPE_OBJECT, + .instance_size = sizeof(struct XilinxAXIDMAStreamSlave), + .class_init = xilinx_axidma_stream_class_init, + .class_data = &xilinx_axidma_control_stream_class, + .interfaces = (InterfaceInfo[]) { + { TYPE_STREAM_SLAVE }, + { } + } +}; + static void xilinx_axidma_register_types(void) { type_register_static(&axidma_info); type_register_static(&xilinx_axidma_data_stream_info); + type_register_static(&xilinx_axidma_control_stream_info); } type_init(xilinx_axidma_register_types) |