qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: BALATON Zoltan <balaton@eik.bme.hu>
Cc: qemu-devel@nongnu.org, qemu-ppc@nongnu.org,
	Alexander Graf <agraf@suse.de>, Cedric Le Goater <clg@kaod.org>
Subject: Re: [Qemu-devel] [PATCH v6 4/5] ppc440_uc: Basic emulation of PPC440 DMA controller
Date: Fri, 29 Jun 2018 14:59:31 +1000	[thread overview]
Message-ID: <20180629045931.GJ3422@umbus.fritz.box> (raw)
In-Reply-To: <20180629044840.GH3422@umbus.fritz.box>

[-- Attachment #1: Type: text/plain, Size: 11687 bytes --]

On Fri, Jun 29, 2018 at 02:48:40PM +1000, David Gibson wrote:
> On Fri, Jun 29, 2018 at 12:38:33AM +0200, BALATON Zoltan wrote:
> > PPC440 SoCs such as the AMCC 460EX have a DMA controller which is used
> > by AmigaOS on the sam460ex. Implement the parts used by AmigaOS so it
> > can get further booting on the sam460ex machine.
> > 
> > Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> > ---
> > v6:
> > - CamelCase type names
> > - Check return value of cpu_physical_memory_map
> 
> I don't really have the knowledge to review this, but since it's a new
> device that no-one else is using, I've applied it.

I take that back.  This breaks compile for me with:

  CC      ppc-softmmu/hw/ppc/ppc440_uc.o
/home/dwg/src/qemu/hw/ppc/ppc440_uc.c: In function ‘dcr_write_dma’:
/home/dwg/src/qemu/hw/ppc/ppc440_uc.c:907:35: error: ‘sidx’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
                     int width, i, sidx, didx;
                                   ^~~~
/home/dwg/src/qemu/hw/ppc/ppc440_uc.c:935:25: error: ‘didx’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
                         cpu_physical_memory_unmap(wptr, wlen, 1, didx);
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

gcc 8.1.1 on Fedora 28.


> 
> > 
> >  hw/ppc/ppc440.h    |   1 +
> >  hw/ppc/ppc440_uc.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  hw/ppc/sam460ex.c  |   3 +
> >  3 files changed, 225 insertions(+)
> > 
> > diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
> > index ad27db1..7cef936 100644
> > --- a/hw/ppc/ppc440.h
> > +++ b/hw/ppc/ppc440.h
> > @@ -21,6 +21,7 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
> >                         hwaddr *ram_bases, hwaddr *ram_sizes,
> >                         int do_init);
> >  void ppc4xx_ahb_init(CPUPPCState *env);
> > +void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
> >  void ppc460ex_pcie_init(CPUPPCState *env);
> >  
> >  #endif /* PPC440_H */
> > diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
> > index 123f4ac..97808ce 100644
> > --- a/hw/ppc/ppc440_uc.c
> > +++ b/hw/ppc/ppc440_uc.c
> > @@ -13,6 +13,7 @@
> >  #include "qemu/cutils.h"
> >  #include "qemu/error-report.h"
> >  #include "qapi/error.h"
> > +#include "qemu/log.h"
> >  #include "cpu.h"
> >  #include "hw/hw.h"
> >  #include "exec/address-spaces.h"
> > @@ -803,6 +804,226 @@ void ppc4xx_ahb_init(CPUPPCState *env)
> >  }
> >  
> >  /*****************************************************************************/
> > +/* DMA controller */
> > +
> > +#define DMA0_CR_CE  (1 << 31)
> > +#define DMA0_CR_PW  (1 << 26 | 1 << 25)
> > +#define DMA0_CR_DAI (1 << 24)
> > +#define DMA0_CR_SAI (1 << 23)
> > +#define DMA0_CR_DEC (1 << 2)
> > +
> > +enum {
> > +    DMA0_CR  = 0x00,
> > +    DMA0_CT,
> > +    DMA0_SAH,
> > +    DMA0_SAL,
> > +    DMA0_DAH,
> > +    DMA0_DAL,
> > +    DMA0_SGH,
> > +    DMA0_SGL,
> > +
> > +    DMA0_SR  = 0x20,
> > +    DMA0_SGC = 0x23,
> > +    DMA0_SLP = 0x25,
> > +    DMA0_POL = 0x26,
> > +};
> > +
> > +typedef struct {
> > +    uint32_t cr;
> > +    uint32_t ct;
> > +    uint64_t sa;
> > +    uint64_t da;
> > +    uint64_t sg;
> > +} PPC4xxDmaChnl;
> > +
> > +typedef struct {
> > +    int base;
> > +    PPC4xxDmaChnl ch[4];
> > +    uint32_t sr;
> > +} PPC4xxDmaState;
> > +
> > +static uint32_t dcr_read_dma(void *opaque, int dcrn)
> > +{
> > +    PPC4xxDmaState *dma = opaque;
> > +    uint32_t val = 0;
> > +    int addr = dcrn - dma->base;
> > +    int chnl = addr / 8;
> > +
> > +    switch (addr) {
> > +    case 0x00 ... 0x1f:
> > +        switch (addr % 8) {
> > +        case DMA0_CR:
> > +            val = dma->ch[chnl].cr;
> > +            break;
> > +        case DMA0_CT:
> > +            val = dma->ch[chnl].ct;
> > +            break;
> > +        case DMA0_SAH:
> > +            val = dma->ch[chnl].sa >> 32;
> > +            break;
> > +        case DMA0_SAL:
> > +            val = dma->ch[chnl].sa;
> > +            break;
> > +        case DMA0_DAH:
> > +            val = dma->ch[chnl].da >> 32;
> > +            break;
> > +        case DMA0_DAL:
> > +            val = dma->ch[chnl].da;
> > +            break;
> > +        case DMA0_SGH:
> > +            val = dma->ch[chnl].sg >> 32;
> > +            break;
> > +        case DMA0_SGL:
> > +            val = dma->ch[chnl].sg;
> > +            break;
> > +        }
> > +        break;
> > +    case DMA0_SR:
> > +        val = dma->sr;
> > +        break;
> > +    default:
> > +        qemu_log_mask(LOG_UNIMP, "%s: unimplemented register %x (%d, %x)\n",
> > +                      __func__, dcrn, chnl, addr);
> > +    }
> > +
> > +    return val;
> > +}
> > +
> > +static void dcr_write_dma(void *opaque, int dcrn, uint32_t val)
> > +{
> > +    PPC4xxDmaState *dma = opaque;
> > +    int addr = dcrn - dma->base;
> > +    int chnl = addr / 8;
> > +
> > +    switch (addr) {
> > +    case 0x00 ... 0x1f:
> > +        switch (addr % 8) {
> > +        case DMA0_CR:
> > +            dma->ch[chnl].cr = val;
> > +            if (val & DMA0_CR_CE) {
> > +                int count = dma->ch[chnl].ct & 0xffff;
> > +
> > +                if (count) {
> > +                    int width, i, sidx, didx;
> > +                    uint8_t *rptr, *wptr;
> > +                    hwaddr rlen, wlen;
> > +
> > +                    width = 1 << ((val & DMA0_CR_PW) >> 25);
> > +                    rptr = cpu_physical_memory_map(dma->ch[chnl].sa, &rlen, 0);
> > +                    wptr = cpu_physical_memory_map(dma->ch[chnl].da, &wlen, 1);
> > +                    if (rptr && wptr) {
> > +                        if (!(val & DMA0_CR_DEC) &&
> > +                            val & DMA0_CR_SAI && val & DMA0_CR_DAI) {
> > +                            /* optimise common case */
> > +                            memmove(wptr, rptr, count * width);
> > +                            sidx = didx = count * width;
> > +                        } else {
> > +                            /* do it the slow way */
> > +                            for (sidx = didx = i = 0; i < count; i++) {
> > +                                uint64_t v = ldn_le_p(rptr + sidx, width);
> > +                                stn_le_p(wptr + didx, width, v);
> > +                                if (val & DMA0_CR_SAI) {
> > +                                    sidx += width;
> > +                                }
> > +                                if (val & DMA0_CR_DAI) {
> > +                                    didx += width;
> > +                                }
> > +                            }
> > +                        }
> > +                    }
> > +                    if (wptr) {
> > +                        cpu_physical_memory_unmap(wptr, wlen, 1, didx);
> > +                    }
> > +                    if (wptr) {
> > +                        cpu_physical_memory_unmap(rptr, rlen, 0, sidx);
> > +                    }
> > +                }
> > +            }
> > +            break;
> > +        case DMA0_CT:
> > +            dma->ch[chnl].ct = val;
> > +            break;
> > +        case DMA0_SAH:
> > +            dma->ch[chnl].sa &= 0xffffffffULL;
> > +            dma->ch[chnl].sa |= (uint64_t)val << 32;
> > +            break;
> > +        case DMA0_SAL:
> > +            dma->ch[chnl].sa &= 0xffffffff00000000ULL;
> > +            dma->ch[chnl].sa |= val;
> > +            break;
> > +        case DMA0_DAH:
> > +            dma->ch[chnl].da &= 0xffffffffULL;
> > +            dma->ch[chnl].da |= (uint64_t)val << 32;
> > +            break;
> > +        case DMA0_DAL:
> > +            dma->ch[chnl].da &= 0xffffffff00000000ULL;
> > +            dma->ch[chnl].da |= val;
> > +            break;
> > +        case DMA0_SGH:
> > +            dma->ch[chnl].sg &= 0xffffffffULL;
> > +            dma->ch[chnl].sg |= (uint64_t)val << 32;
> > +            break;
> > +        case DMA0_SGL:
> > +            dma->ch[chnl].sg &= 0xffffffff00000000ULL;
> > +            dma->ch[chnl].sg |= val;
> > +            break;
> > +        }
> > +        break;
> > +    case DMA0_SR:
> > +        dma->sr &= ~val;
> > +        break;
> > +    default:
> > +        qemu_log_mask(LOG_UNIMP, "%s: unimplemented register %x (%d, %x)\n",
> > +                      __func__, dcrn, chnl, addr);
> > +    }
> > +}
> > +
> > +static void ppc4xx_dma_reset(void *opaque)
> > +{
> > +    PPC4xxDmaState *dma = opaque;
> > +    int dma_base = dma->base;
> > +
> > +    memset(dma, 0, sizeof(*dma));
> > +    dma->base = dma_base;
> > +}
> > +
> > +void ppc4xx_dma_init(CPUPPCState *env, int dcr_base)
> > +{
> > +    PPC4xxDmaState *dma;
> > +    int i;
> > +
> > +    dma = g_malloc0(sizeof(*dma));
> > +    dma->base = dcr_base;
> > +    qemu_register_reset(&ppc4xx_dma_reset, dma);
> > +    for (i = 0; i < 4; i++) {
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_CR,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_CT,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SAH,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SAL,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_DAH,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_DAL,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SGH,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +        ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SGL,
> > +                         dma, &dcr_read_dma, &dcr_write_dma);
> > +    }
> > +    ppc_dcr_register(env, dcr_base + DMA0_SR,
> > +                     dma, &dcr_read_dma, &dcr_write_dma);
> > +    ppc_dcr_register(env, dcr_base + DMA0_SGC,
> > +                     dma, &dcr_read_dma, &dcr_write_dma);
> > +    ppc_dcr_register(env, dcr_base + DMA0_SLP,
> > +                     dma, &dcr_read_dma, &dcr_write_dma);
> > +    ppc_dcr_register(env, dcr_base + DMA0_POL,
> > +                     dma, &dcr_read_dma, &dcr_write_dma);
> > +}
> > +
> > +/*****************************************************************************/
> >  /* PCI Express controller */
> >  /* FIXME: This is not complete and does not work, only implemented partially
> >   * to allow firmware and guests to find an empty bus. Cards should use PCI.
> > diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
> > index dc730cc..4f9248e 100644
> > --- a/hw/ppc/sam460ex.c
> > +++ b/hw/ppc/sam460ex.c
> > @@ -477,6 +477,9 @@ static void sam460ex_init(MachineState *machine)
> >      /* MAL */
> >      ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
> >  
> > +    /* DMA */
> > +    ppc4xx_dma_init(env, 0x200);
> > +
> >      /* 256K of L2 cache as memory */
> >      ppc4xx_l2sram_init(env);
> >      /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
> 



-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2018-06-29  4:59 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-28 22:38 [Qemu-devel] [PATCH v6 0/5] Misc sam460ex improvements BALATON Zoltan
2018-06-28 22:38 ` [Qemu-devel] [PATCH v6 2/5] hw/timer: Add basic M41T80 emulation BALATON Zoltan
2018-06-28 22:38 ` [Qemu-devel] [PATCH v6 5/5] target/ppc: Relax reserved bitmask of indexed store instructions BALATON Zoltan
2018-07-03  1:13   ` [Qemu-devel] [Qemu-ppc] " David Gibson
2018-06-28 22:38 ` [Qemu-devel] [PATCH v6 1/5] ppc4xx_i2c: Rewrite to model hardware more closely BALATON Zoltan
2018-06-28 22:38 ` [Qemu-devel] [PATCH v6 4/5] ppc440_uc: Basic emulation of PPC440 DMA controller BALATON Zoltan
2018-06-29  4:48   ` David Gibson
2018-06-29  4:59     ` David Gibson [this message]
2018-06-29 12:14       ` [Qemu-devel] [Qemu-ppc] " BALATON Zoltan
2018-07-02  0:03         ` David Gibson
2018-06-28 22:38 ` [Qemu-devel] [PATCH v6 3/5] sam460ex: Add RTC device BALATON Zoltan
2018-06-29  4:47   ` David Gibson
2018-07-02  4:04     ` David Gibson
2018-07-01 23:52 ` [Qemu-devel] [PATCH v6 0/5] Misc sam460ex improvements no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180629045931.GJ3422@umbus.fritz.box \
    --to=david@gibson.dropbear.id.au \
    --cc=agraf@suse.de \
    --cc=balaton@eik.bme.hu \
    --cc=clg@kaod.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).