PPC: Uninorth config space accessor
The Uninorth PCI bridge requires different layouts in its PCI config space accessors. This patch introduces a conversion function that makes it compatible with the way Linux accesses it. I also kept an OpenBIOS compatibility hack in. I think it'd be better to take small steps here and do the config space access rework in OpenBIOS later on. When that's done we can remove that hack. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
9f6f0423cf
commit
d86f0e32c6
@ -39,6 +39,7 @@
|
|||||||
typedef struct UNINState {
|
typedef struct UNINState {
|
||||||
SysBusDevice busdev;
|
SysBusDevice busdev;
|
||||||
PCIHostState host_state;
|
PCIHostState host_state;
|
||||||
|
ReadWriteHandler data_handler;
|
||||||
} UNINState;
|
} UNINState;
|
||||||
|
|
||||||
/* Don't know if this matches real hardware, but it agrees with OHW. */
|
/* Don't know if this matches real hardware, but it agrees with OHW. */
|
||||||
@ -75,6 +76,68 @@ static void pci_unin_reset(void *opaque)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
|
||||||
|
{
|
||||||
|
uint32_t retval;
|
||||||
|
|
||||||
|
if (reg & (1u << 31)) {
|
||||||
|
/* XXX OpenBIOS compatibility hack */
|
||||||
|
retval = reg | (addr & 3);
|
||||||
|
} else if (reg & 1) {
|
||||||
|
/* CFA1 style */
|
||||||
|
retval = (reg & ~7u) | (addr & 7);
|
||||||
|
} else {
|
||||||
|
uint32_t slot, func;
|
||||||
|
|
||||||
|
/* Grab CFA0 style values */
|
||||||
|
slot = ffs(reg & 0xfffff800) - 1;
|
||||||
|
func = (reg >> 8) & 7;
|
||||||
|
|
||||||
|
/* ... and then convert them to x86 format */
|
||||||
|
/* config pointer */
|
||||||
|
retval = (reg & (0xff - 7)) | (addr & 7);
|
||||||
|
/* slot */
|
||||||
|
retval |= slot << 11;
|
||||||
|
/* fn */
|
||||||
|
retval |= func << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n",
|
||||||
|
reg, addr, retval);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unin_data_write(ReadWriteHandler *handler,
|
||||||
|
pcibus_t addr, uint32_t val, int len)
|
||||||
|
{
|
||||||
|
UNINState *s = container_of(handler, UNINState, data_handler);
|
||||||
|
#ifdef TARGET_WORDS_BIGENDIAN
|
||||||
|
val = qemu_bswap_len(val, len);
|
||||||
|
#endif
|
||||||
|
UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
|
||||||
|
pci_data_write(s->host_state.bus,
|
||||||
|
unin_get_config_reg(s->host_state.config_reg, addr),
|
||||||
|
val, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t unin_data_read(ReadWriteHandler *handler,
|
||||||
|
pcibus_t addr, int len)
|
||||||
|
{
|
||||||
|
UNINState *s = container_of(handler, UNINState, data_handler);
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
val = pci_data_read(s->host_state.bus,
|
||||||
|
unin_get_config_reg(s->host_state.config_reg, addr),
|
||||||
|
len);
|
||||||
|
UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
|
||||||
|
#ifdef TARGET_WORDS_BIGENDIAN
|
||||||
|
val = qemu_bswap_len(val, len);
|
||||||
|
#endif
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
static int pci_unin_main_init_device(SysBusDevice *dev)
|
static int pci_unin_main_init_device(SysBusDevice *dev)
|
||||||
{
|
{
|
||||||
UNINState *s;
|
UNINState *s;
|
||||||
@ -85,7 +148,9 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
|
|||||||
s = FROM_SYSBUS(UNINState, dev);
|
s = FROM_SYSBUS(UNINState, dev);
|
||||||
|
|
||||||
pci_mem_config = pci_host_conf_register_mmio(&s->host_state);
|
pci_mem_config = pci_host_conf_register_mmio(&s->host_state);
|
||||||
pci_mem_data = pci_host_data_register_mmio(&s->host_state);
|
s->data_handler.read = unin_data_read;
|
||||||
|
s->data_handler.write = unin_data_write;
|
||||||
|
pci_mem_data = cpu_register_io_memory_simple(&s->data_handler);
|
||||||
sysbus_init_mmio(dev, 0x1000, pci_mem_config);
|
sysbus_init_mmio(dev, 0x1000, pci_mem_config);
|
||||||
sysbus_init_mmio(dev, 0x1000, pci_mem_data);
|
sysbus_init_mmio(dev, 0x1000, pci_mem_data);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user