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

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

 



> -----Original Message-----
> From: kvm-ppc-owner@xxxxxxxxxxxxxxx 
> [mailto:kvm-ppc-owner@xxxxxxxxxxxxxxx] On Behalf Of Hollis Blanchard
> Sent: Friday, January 16, 2009 4:02 AM
> To: Liu Yu-B13201
> Cc: qemu-devel@xxxxxxxxxx; kvm-ppc@xxxxxxxxxxxxxxx
> 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 <yu.liu@xxxxxxxxxxxxx>
> > ---
> >  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,     <yu.liu@xxxxxxxxxxxxx>
> > + *
> > + * 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.

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux