qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] RE: [PATCH 5/9] powerpc/kvm: Add freescale pci controller's


From: Liu Yu
Subject: [Qemu-devel] RE: [PATCH 5/9] powerpc/kvm: Add freescale pci controller's support
Date: Fri, 16 Jan 2009 15:37:42 +0800

> -----Original Message-----
> From: address@hidden 
> [mailto:address@hidden On Behalf Of Hollis Blanchard
> Sent: Friday, January 16, 2009 4:02 AM
> To: Liu Yu-B13201
> Cc: address@hidden; address@hidden
> Subject: Re: [PATCH 5/9] powerpc/kvm: Add freescale pci 
> controller's support
> 
> On Thu, 2009-01-15 at 20:34 +0800, Liu Yu wrote:
> > Signed-off-by: Liu Yu <address@hidden>
> > ---
> >  Makefile.target  |    2 +
> >  hw/ppce500_pci.c |  369 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 371 insertions(+), 0 deletions(-)
> >  create mode 100644 hw/ppce500_pci.c
> > 
> > diff --git a/Makefile.target b/Makefile.target
> > index 58fe88f..2079fcb 100644
> > --- a/Makefile.target
> > +++ b/Makefile.target
> > @@ -649,6 +649,8 @@ OBJS+= unin_pci.o ppc_chrp.o
> >  # PowerPC 4xx boards
> >  OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o 
> ppc405_uc.o ppc405_boards.o
> >  OBJS+= ppc440.o ppc440_bamboo.o
> > +# PowerPC E500 boards
> > +OBJS+= ppce500_pci.o
> >  ifdef FDT_LIBS
> >  OBJS+= device_tree.o
> >  LIBS+= $(FDT_LIBS)
> > diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> > new file mode 100644
> > index 0000000..9077591
> > --- /dev/null
> > +++ b/hw/ppce500_pci.c
> > @@ -0,0 +1,369 @@
> > +/*
> > + * QEMU PowerPC E500 embedded processors pci controller emulation
> > + *
> > + * Copyright (C) 2009 Freescale Semiconductor, Inc. All 
> rights reserved.
> > + *
> > + * Author: Yu Liu,     <address@hidden>
> > + *
> > + * This file is derived from hw/ppc4xx_pci.c,
> > + * the copyright for that material belongs to the original owners.
> > + *
> > + * This 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.
> > + */
> > +
> > +#include "hw.h"
> > +#include "ppc.h"
> > +#include "ppce500.h"
> > +typedef target_phys_addr_t pci_addr_t;
> > +#include "pci.h"
> > +#include "pci_host.h"
> > +#include "bswap.h"
> > +#include "qemu-log.h"
> > +
> > +#ifdef DEBUG_PCI
> > +#define pci_debug(fmt, arg...) fprintf(stderr, fmt, ##arg)
> > +#else
> > +#define pci_debug(fmt, arg...)
> > +#endif
> > +
> > +#define PCIE500_CFGADDR       0x0
> > +#define PCIE500_CFGDATA       0x4
> > +#define PCIE500_REG_BASE      0xC00
> > +#define PCIE500_REG_SIZE      (0x1000 - PCIE500_REG_BASE)
> > +
> > +#define PPCE500_PCI_CONFIG_ADDR            0x0
> > +#define PPCE500_PCI_CONFIG_DATA            0x4
> > +#define PPCE500_PCI_INTACK         0x8
> > +
> > +#define PPCE500_PCI_OW1                    (0xC20 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_OW2                    (0xC40 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_OW3                    (0xC60 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_OW4                    (0xC80 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_IW3                    (0xDA0 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_IW2                    (0xDC0 - 
> PCIE500_REG_BASE)
> > +#define PPCE500_PCI_IW1                    (0xDE0 - 
> PCIE500_REG_BASE)
> > +
> > +#define PPCE500_PCI_GASKET_TIMR            (0xE20 - 
> PCIE500_REG_BASE)
> > +
> > +#define PCI_POTAR          0x0
> > +#define PCI_POTEAR         0x4
> > +#define PCI_POWBAR         0x8
> > +#define PCI_POWAR          0x10
> > +
> > +#define PCI_PITAR          0x0
> > +#define PCI_PIWBAR         0x8
> > +#define PCI_PIWBEAR                0xC
> > +#define PCI_PIWAR          0x10
> > +
> > +#define PPCE500_PCI_NR_POBS 5
> > +#define PPCE500_PCI_NR_PIBS 3
> > +
> > +struct  pci_outbound {
> > +    uint32_t potar;
> > +    uint32_t potear;
> > +    uint32_t powbar;
> > +    uint32_t powar;
> > +};
> > +
> > +struct pci_inbound {
> > +    uint32_t pitar;
> > +    uint32_t piwbar;
> > +    uint32_t piwbear;
> > +    uint32_t piwar;
> > +};
> > +
> > +struct PPCE500PCIState {
> > +    struct pci_outbound pob[PPCE500_PCI_NR_POBS];
> > +    struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
> > +    uint32_t gasket_time;
> 
> Out of curiosity, is "gasket_time" supposed to be an actual timer, or
> just a scratch register? It looks like you've just implemented it as a
> scratch register.

Just a scratch register I think.
I tried today that if I removed it, virtio-pci cannot be found.

> 
> > +    PCIHostState pci_state;
> > +    PCIDevice *pci_dev;
> > +};
> > +
> > +typedef struct PPCE500PCIState PPCE500PCIState;
> > +
> > +static uint32_t pcie500_cfgaddr_readl(void *opaque, 
> target_phys_addr_t addr)
> > +{
> > +    PPCE500PCIState *pci = opaque;
> > +
> > +    pci_debug("%s: (addr:%Lx) -> value:%x\n", __func__, addr,
> > +               pci->pci_state.config_reg);
> > +    return pci->pci_state.config_reg;
> > +}
> > +
> > +static CPUReadMemoryFunc *pcie500_cfgaddr_read[] = {
> > +    &pcie500_cfgaddr_readl,
> > +    &pcie500_cfgaddr_readl,
> > +    &pcie500_cfgaddr_readl,
> > +};
> > +
> > +static void pcie500_cfgaddr_writel(void *opaque, 
> target_phys_addr_t addr,
> > +                                  uint32_t value)
> > +{
> > +    PPCE500PCIState *controller = opaque;
> > +
> > +    pci_debug("%s: value:%x -> (addr%Lx)\n", __func__, 
> value, addr);
> > +    controller->pci_state.config_reg = value & ~0x3;
> > +}
> > +
> > +static CPUWriteMemoryFunc *pcie500_cfgaddr_write[] = {
> > +    pcie500_cfgaddr_writel,
> 
> Missing & here.
Fixed. Thanks.

> 
> > +    &pcie500_cfgaddr_writel,
> > +    &pcie500_cfgaddr_writel,
> > +};
> > +
> > +static CPUReadMemoryFunc *pcie500_cfgdata_read[] = {
> > +    &pci_host_data_readb,
> > +    &pci_host_data_readw,
> > +    &pci_host_data_readl,
> > +};
> > +
> > +static CPUWriteMemoryFunc *pcie500_cfgdata_write[] = {
> > +    &pci_host_data_writeb,
> > +    &pci_host_data_writew,
> > +    &pci_host_data_writel,
> > +};
> > +
> > +static uint32_t pci_reg_read4(void *opaque, 
> target_phys_addr_t addr)
> > +{
> > +    PPCE500PCIState *pci = opaque;
> > +    unsigned long win;
> > +    uint32_t value = 0;
> > +
> > +    win = addr & 0xfe0;
> > +
> > +    switch (win) {
> > +    case PPCE500_PCI_OW1:
> > +    case PPCE500_PCI_OW2:
> > +    case PPCE500_PCI_OW3:
> > +    case PPCE500_PCI_OW4:
> > +   switch (addr & 0xC) {
> > +   case PCI_POTAR: value = pci->pob[(addr >> 5) & 
> 0x7].potar; break;
> > +   case PCI_POTEAR: value = pci->pob[(addr >> 5) & 
> 0x7].potear; break;
> > +   case PCI_POWBAR: value = pci->pob[(addr >> 5) & 
> 0x7].powbar; break;
> > +   case PCI_POWAR: value = pci->pob[(addr >> 5) & 
> 0x7].powar; break;
> > +   default: break;
> > +   }
> > +   break;
> > +
> > +    case PPCE500_PCI_IW3:
> > +    case PPCE500_PCI_IW2:
> > +    case PPCE500_PCI_IW1:
> > +   switch (addr & 0xC) {
> > +   case PCI_PITAR: value = pci->pib[(addr >> 5) & 
> 0x3].pitar; break;
> > +   case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 
> 0x3].piwbar; break;
> > +   case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 
> 0x3].piwbear; break;
> > +   case PCI_PIWAR: value = pci->pib[(addr >> 5) & 
> 0x3].piwar; break;
> > +   default: break;
> > +   };
> > +   break;
> > +
> > +    case PPCE500_PCI_GASKET_TIMR:
> > +   value = pci->gasket_time;
> > +   break;
> > +
> > +    default:
> > +   break;
> > +    }
> > +
> > +    pci_debug("%s: win:%lx(addr:%Lx) -> 
> value:%x\n",__func__,win,addr,value);
> > +    return value;
> > +}
> > +
> > +static CPUReadMemoryFunc *e500_pci_reg_read[] = {
> > +    &pci_reg_read4,
> > +    &pci_reg_read4,
> > +    &pci_reg_read4,
> > +};
> > +
> > +static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
> > +                               uint32_t value)
> > +{
> > +    PPCE500PCIState *pci = opaque;
> > +    unsigned long win;
> > +
> > +    win = addr & 0xfe0;
> > +
> > +    pci_debug("%s: value:%x -> 
> win:%lx(addr:%Lx)\n",__func__,value,win,addr);
> > +
> > +    switch (win) {
> > +    case PPCE500_PCI_OW1:
> > +    case PPCE500_PCI_OW2:
> > +    case PPCE500_PCI_OW3:
> > +    case PPCE500_PCI_OW4:
> > +   switch (addr & 0xC) {
> > +   case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = 
> value; break;
> > +   case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = 
> value; break;
> > +   case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = 
> value; break;
> > +   case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = 
> value; break;
> > +   default: break;
> > +   };
> > +   break;
> > +
> > +    case PPCE500_PCI_IW3:
> > +    case PPCE500_PCI_IW2:
> > +    case PPCE500_PCI_IW1:
> > +   switch (addr & 0xC) {
> > +   case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = 
> value; break;
> > +   case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = 
> value; break;
> > +   case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = 
> value; break;
> > +   case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = 
> value; break;
> > +   default: break;
> > +   };
> > +   break;
> > +
> > +    case PPCE500_PCI_GASKET_TIMR:
> > +   pci->gasket_time = value;
> > +   break;
> > +
> > +    default:
> > +   break;
> > +    };
> > +}
> > +
> > +static CPUWriteMemoryFunc *e500_pci_reg_write[] = {
> > +    &pci_reg_write4,
> > +    &pci_reg_write4,
> > +    &pci_reg_write4,
> > +};
> > +
> > +static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
> > +{
> > +    int devno = pci_dev->devfn >> 3, ret = 0;
> > +
> > +    switch (devno) {
> > +   /* Two PCI slot */
> > +   case 0x11:
> > +   case 0x12:
> > +       ret = (irq_num + devno - 0x10) % 4;
> > +       break;
> > +   default:
> > +       printf("Error:%s:unknow dev number\n", __func__);
> > +    }
> > +
> > +    pci_debug("%s: devfn %x irq %d -> %d  devno:%x\n", __func__,
> > +           pci_dev->devfn, irq_num, ret, devno);
> > +
> > +    return ret;
> > +}
> > +
> > +static void mpc85xx_pci_set_irq(qemu_irq *pic, int 
> irq_num, int level)
> > +{
> > +    pci_debug("%s: PCI irq %d, level:%d\n", __func__, 
> irq_num, level);
> > +
> > +    qemu_set_irq(pic[irq_num], level);
> > +}
> > +
> > +static void ppce500_pci_save(QEMUFile *f, void *opaque)
> > +{
> > +    PPCE500PCIState *controller = opaque;
> > +    int i;
> > +
> > +    pci_device_save(controller->pci_dev, f);
> > +
> > +    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
> > +        qemu_put_be32s(f, &controller->pob[i].potar);
> > +        qemu_put_be32s(f, &controller->pob[i].potear);
> > +        qemu_put_be32s(f, &controller->pob[i].powbar);
> > +        qemu_put_be32s(f, &controller->pob[i].powar);
> > +    }
> > +
> > +    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
> > +        qemu_put_be32s(f, &controller->pib[i].pitar);
> > +        qemu_put_be32s(f, &controller->pib[i].piwbar);
> > +        qemu_put_be32s(f, &controller->pib[i].piwbear);
> > +        qemu_put_be32s(f, &controller->pib[i].piwar);
> > +    }
> > +    qemu_put_be32s(f, &controller->gasket_time);
> > +}
> > +
> > +static int ppce500_pci_load(QEMUFile *f, void *opaque, int 
> version_id)
> > +{
> > +    PPCE500PCIState *controller = opaque;
> > +    int i;
> > +
> > +    if (version_id != 1)
> > +        return -EINVAL;
> > +
> > +    pci_device_load(controller->pci_dev, f);
> > +
> > +    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
> > +        qemu_get_be32s(f, &controller->pob[i].potar);
> > +        qemu_get_be32s(f, &controller->pob[i].potear);
> > +        qemu_get_be32s(f, &controller->pob[i].powbar);
> > +        qemu_get_be32s(f, &controller->pob[i].powar);
> > +    }
> > +
> > +    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
> > +        qemu_get_be32s(f, &controller->pib[i].pitar);
> > +        qemu_get_be32s(f, &controller->pib[i].piwbar);
> > +        qemu_get_be32s(f, &controller->pib[i].piwbear);
> > +        qemu_get_be32s(f, &controller->pib[i].piwar);
> > +    }
> > +    qemu_get_be32s(f, &controller->gasket_time);
> > +
> > +    return 0;
> > +}
> 
> Should have a newline here.
Fixed. Thanks.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]