[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH V4 6/8] Introduce xilinx dpdma.
From: |
Alistair Francis |
Subject: |
Re: [Qemu-devel] [PATCH V4 6/8] Introduce xilinx dpdma. |
Date: |
Fri, 4 Sep 2015 11:21:14 -0700 |
On Fri, Sep 4, 2015 at 2:01 AM, Frederic Konrad
<address@hidden> wrote:
> On 04/09/2015 01:34, Alistair Francis wrote:
>>
>> On Thu, Sep 3, 2015 at 12:28 AM, Frederic Konrad
>> <address@hidden> wrote:
>>>
>>> On 02/09/2015 23:39, Alistair Francis wrote:
>>>>
>>>> On Tue, Jul 21, 2015 at 10:17 AM, <address@hidden> wrote:
>>>>>
>>>>> From: KONRAD Frederic <address@hidden>
>>>>>
>>>>> This is the implementation of the DPDMA.
>>>>>
>>>>> Signed-off-by: KONRAD Frederic <address@hidden>
>>>>> ---
>>>>> hw/dma/Makefile.objs | 1 +
>>>>> hw/dma/xlnx_dpdma.c | 790
>>>>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>>> hw/dma/xlnx_dpdma.h | 85 ++++++
>>>>> 3 files changed, 876 insertions(+)
>>>>> create mode 100644 hw/dma/xlnx_dpdma.c
>>>>> create mode 100644 hw/dma/xlnx_dpdma.h
>>>>
>>>> What are the rules with the placement of the header files? Should the
>>>> header be in the include directory instead of being here?
>>>
>>> Probably moving headers to include/hw makes sense here..
>>> I will change it.
>>
>> Hey Fred,
>>
>> Great, thanks
>>
>>> [...]
>>>>>
>>>>> +
>>>>> + if (xlnx_dpdma_desc_is_already_done(&desc)
>>>>> + && !xlnx_dpdma_desc_ignore_done_bit(&desc)) {
>>>>
>>>> The second line of the if should be indented across.
>>>>
>>>> Also, I generally think the operator should go on the first line, but
>>>> that doesn't seem worth changing throughout.
>>>
>>> Ok I can do that.
>>>
>>>>> + /* We are trying to process an already processed
>>>>> descriptor.
>>>>> */
>>>>> + s->registers[DPDMA_EISR] |= ((1 << 25) << channel);
>>>>> + xlnx_dpdma_update_irq(s);
>>>>> + s->operation_finished[channel] = true;
>>>>> + DPRINTF("Already processed descriptor..\n");
>>>>> + break;
>>>>> + }
>>>>> +
>>>>> + done = xlnx_dpdma_desc_is_last(&desc)
>>>>> + || xlnx_dpdma_desc_is_last_of_frame(&desc);
>>>>> +
>>>>> + s->operation_finished[channel] = done;
>>>>> + if (s->data[channel]) {
>>>>> + int64_t transfer_len =
>>>>> +
>>>>> xlnx_dpdma_desc_get_transfer_size(&desc);
>>>>
>>>> Why is this over two lines?
>>>
>>>
>>> Probably because of the 79~80 columns limitation.
>>
>> It looks like it is less then 80 columns though.
>
> Oh yes missed that when I replaced xilinx by xlnx in functions..
> I fixed that.
Great! Thanks
Alistair
>
> Thanks,
> Fred
>
>>
>> Thanks,
>>
>> Alistair
>>
>>> Thanks,
>>> Fred
>>>
>>>> Functioanlly it looks fine.
>>>>
>>>> Besides the header file location, which someone else will need to
>>>> comment
>>>> on:
>>>>
>>>> Reviewed-by: Alistair Francis <address@hidden>
>>>> Tested-By: Hyun Kwon <address@hidden>
>>>>
>>>> Thanks,
>>>>
>>>> Alistair
>>>>
>>>>> + uint32_t line_size = xlnx_dpdma_desc_get_line_size(&desc);
>>>>> + uint32_t line_stride =
>>>>> xlnx_dpdma_desc_get_line_stride(&desc);
>>>>> + if (xlnx_dpdma_desc_is_contiguous(&desc)) {
>>>>> + source_addr[0] =
>>>>> + xlnx_dpdma_desc_get_source_address(&desc,
>>>>> 0);
>>>>> + while (transfer_len != 0) {
>>>>> + if (dma_memory_read(&address_space_memory,
>>>>> + source_addr[0],
>>>>> + &s->data[channel][ptr],
>>>>> + line_size)) {
>>>>> + s->registers[DPDMA_ISR] |= ((1 << 12) <<
>>>>> channel);
>>>>> + xlnx_dpdma_update_irq(s);
>>>>> + DPRINTF("Can't get data.\n");
>>>>> + break;
>>>>> + }
>>>>> + ptr += line_size;
>>>>> + transfer_len -= line_size;
>>>>> + source_addr[0] += line_stride;
>>>>> + }
>>>>> + } else {
>>>>> + DPRINTF("Source address:\n");
>>>>> + int frag;
>>>>> + for (frag = 0; frag < 5; frag++) {
>>>>> + source_addr[frag] =
>>>>> + xlnx_dpdma_desc_get_source_address(&desc,
>>>>> frag);
>>>>> + DPRINTF("Fragment %u: %" PRIx64 "\n", frag + 1,
>>>>> + source_addr[frag]);
>>>>> + }
>>>>> +
>>>>> + frag = 0;
>>>>> + while ((transfer_len < 0) && (frag < 5)) {
>>>>> + size_t fragment_len = DPDMA_FRAG_MAX_SZ
>>>>> + - (source_addr[frag] %
>>>>> DPDMA_FRAG_MAX_SZ);
>>>>> +
>>>>> + if (dma_memory_read(&address_space_memory,
>>>>> + source_addr[frag],
>>>>> + &(s->data[channel][ptr]),
>>>>> + fragment_len)) {
>>>>> + s->registers[DPDMA_ISR] |= ((1 << 12) <<
>>>>> channel);
>>>>> + xlnx_dpdma_update_irq(s);
>>>>> + DPRINTF("Can't get data.\n");
>>>>> + break;
>>>>> + }
>>>>> + ptr += fragment_len;
>>>>> + transfer_len -= fragment_len;
>>>>> + frag += 1;
>>>>> + }
>>>>> + }
>>>>> + }
>>>>> +
>>>>> + if (xlnx_dpdma_desc_update_enabled(&desc)) {
>>>>> + /* The descriptor need to be updated when it's completed.
>>>>> */
>>>>> + DPRINTF("update the descriptor with the done flag
>>>>> set.\n");
>>>>> + xlnx_dpdma_desc_set_done(&desc);
>>>>> + dma_memory_write(&address_space_memory, desc_addr, &desc,
>>>>> + sizeof(DPDMADescriptor));
>>>>> + }
>>>>> +
>>>>> + if (xlnx_dpdma_desc_completion_interrupt(&desc)) {
>>>>> + DPRINTF("completion interrupt enabled!\n");
>>>>> + s->registers[DPDMA_ISR] |= (1 << channel);
>>>>> + xlnx_dpdma_update_irq(s);
>>>>> + }
>>>>> +
>>>>> + } while (!done && !one_desc);
>>>>> +
>>>>> + return ptr;
>>>>> +}
>>>>> +
>>>>> +void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t
>>>>> channel,
>>>>> + void *p)
>>>>> +{
>>>>> + if (!s) {
>>>>> + qemu_log_mask(LOG_UNIMP, "DPDMA client not attached to valid
>>>>> DPDMA"
>>>>> + " instance\n");
>>>>> + return;
>>>>> + }
>>>>> +
>>>>> + assert(channel <= 5);
>>>>> + s->data[channel] = p;
>>>>> +}
>>>>> +
>>>>> +void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s)
>>>>> +{
>>>>> + s->registers[DPDMA_ISR] |= (1 << 27);
>>>>> + xlnx_dpdma_update_irq(s);
>>>>> +}
>>>>> +
>>>>> +type_init(xlnx_dpdma_register_types)
>>>>> diff --git a/hw/dma/xlnx_dpdma.h b/hw/dma/xlnx_dpdma.h
>>>>> new file mode 100644
>>>>> index 0000000..ae571a0
>>>>> --- /dev/null
>>>>> +++ b/hw/dma/xlnx_dpdma.h
>>>>> @@ -0,0 +1,85 @@
>>>>> +/*
>>>>> + * xlnx_dpdma.h
>>>>> + *
>>>>> + * Copyright (C) 2015 : GreenSocs Ltd
>>>>> + * http://www.greensocs.com/ , email: address@hidden
>>>>> + *
>>>>> + * Developed by :
>>>>> + * Frederic Konrad <address@hidden>
>>>>> + *
>>>>> + * This program is free software; you can redistribute it and/or
>>>>> modify
>>>>> + * it under the terms of the GNU General Public License as published
>>>>> by
>>>>> + * the Free Software Foundation, either version 2 of the License, or
>>>>> + * (at your option) any later version.
>>>>> + *
>>>>> + * This program is distributed in the hope that it will be useful,
>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>>> + * GNU General Public License for more details.
>>>>> + *
>>>>> + * You should have received a copy of the GNU General Public License
>>>>> along
>>>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>>>> + *
>>>>> + */
>>>>> +
>>>>> +#ifndef XLNX_DPDMA_H
>>>>> +#define XLNX_DPDMA_H
>>>>> +
>>>>> +#include "hw/sysbus.h"
>>>>> +#include "ui/console.h"
>>>>> +#include "sysemu/dma.h"
>>>>> +
>>>>> +#define XLNX_DPDMA_REG_ARRAY_SIZE (0x1000 >> 2)
>>>>> +
>>>>> +struct XlnxDPDMAState {
>>>>> + /*< private >*/
>>>>> + SysBusDevice parent_obj;
>>>>> + /*< public >*/
>>>>> + MemoryRegion iomem;
>>>>> + uint32_t registers[XLNX_DPDMA_REG_ARRAY_SIZE];
>>>>> + uint8_t *data[6];
>>>>> + bool operation_finished[6];
>>>>> + qemu_irq irq;
>>>>> +};
>>>>> +
>>>>> +typedef struct XlnxDPDMAState XlnxDPDMAState;
>>>>> +
>>>>> +#define TYPE_XLNX_DPDMA "xlnx.dpdma"
>>>>> +#define XLNX_DPDMA(obj) OBJECT_CHECK(XlnxDPDMAState, (obj),
>>>>> TYPE_XLNX_DPDMA)
>>>>> +
>>>>> +/*
>>>>> + * xlnx_dpdma_start_operation: Start the operation on the specified
>>>>> channel. The
>>>>> + * DPDMA gets the current descriptor and
>>>>> retrieves
>>>>> + * data to the buffer specified by
>>>>> + * dpdma_set_host_data_location().
>>>>> + *
>>>>> + * Returns The number of bytes transfered by the DPDMA or 0 if an
>>>>> error
>>>>> occured.
>>>>> + *
>>>>> + * @s The DPDMA state.
>>>>> + * @channel The channel to start.
>>>>> + */
>>>>> +size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel,
>>>>> + bool one_desc);
>>>>> +
>>>>> +/*
>>>>> + * xlnx_dpdma_set_host_data_location: Set the location in the host
>>>>> memory where
>>>>> + * to store the data out from the
>>>>> dma
>>>>> + * channel.
>>>>> + *
>>>>> + * @s The DPDMA state.
>>>>> + * @channel The channel associated to the pointer.
>>>>> + * @p The buffer where to store the data.
>>>>> + */
>>>>> +/* XXX: add a maximum size arg and send an interrupt in case of
>>>>> overflow. */
>>>>> +void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t
>>>>> channel,
>>>>> + void *p);
>>>>> +
>>>>> +/*
>>>>> + * xlnx_dpdma_trigger_vsync_irq: Trigger a VSYNC IRQ when the display
>>>>> is
>>>>> + * updated.
>>>>> + *
>>>>> + * @s The DPDMA state.
>>>>> + */
>>>>> +void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s);
>>>>> +
>>>>> +#endif /* !XLNX_DPDMA_H */
>>>>> --
>>>>> 1.9.0
>>>>>
>>>>>
>