> -----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