mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 18:23:57 -06:00
Merge remote branch 'mst/for_anthony' into staging
This commit is contained in:
commit
9edf5051f3
20 changed files with 523 additions and 251 deletions
|
@ -402,7 +402,9 @@ static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
|
|||
ch->io.dma_end = dbdma_end;
|
||||
ch->io.is_dma_out = 1;
|
||||
ch->processing = 1;
|
||||
ch->rw(&ch->io);
|
||||
if (ch->rw) {
|
||||
ch->rw(&ch->io);
|
||||
}
|
||||
}
|
||||
|
||||
static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
|
||||
|
@ -425,7 +427,9 @@ static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
|
|||
ch->io.dma_end = dbdma_end;
|
||||
ch->io.is_dma_out = 0;
|
||||
ch->processing = 1;
|
||||
ch->rw(&ch->io);
|
||||
if (ch->rw) {
|
||||
ch->rw(&ch->io);
|
||||
}
|
||||
}
|
||||
|
||||
static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
|
||||
|
@ -688,7 +692,7 @@ dbdma_control_write(DBDMA_channel *ch)
|
|||
|
||||
if (status & ACTIVE)
|
||||
qemu_bh_schedule(dbdma_bh);
|
||||
if (status & FLUSH)
|
||||
if ((status & FLUSH) && ch->flush)
|
||||
ch->flush(&ch->io);
|
||||
}
|
||||
|
||||
|
|
1
hw/pci.h
1
hw/pci.h
|
@ -70,7 +70,6 @@
|
|||
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
|
||||
#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003
|
||||
|
||||
typedef uint64_t pcibus_t;
|
||||
#define FMT_PCIBUS PRIx64
|
||||
|
||||
typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
|
||||
|
|
196
hw/pci_host.c
196
hw/pci_host.c
|
@ -79,152 +79,120 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
|
|||
return val;
|
||||
}
|
||||
|
||||
static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t val)
|
||||
static void pci_host_config_write(ReadWriteHandler *handler,
|
||||
pcibus_t addr, uint32_t val, int len)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
|
||||
|
||||
PCI_DPRINTF("%s addr %" FMT_PCIBUS " %d val %"PRIx32"\n",
|
||||
__func__, addr, len, val);
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = bswap32(val);
|
||||
val = qemu_bswap_len(val, len);
|
||||
#endif
|
||||
PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
|
||||
__func__, addr, val);
|
||||
s->config_reg = val;
|
||||
}
|
||||
|
||||
static uint32_t pci_host_config_readl(void *opaque, target_phys_addr_t addr)
|
||||
static uint32_t pci_host_config_read(ReadWriteHandler *handler,
|
||||
pcibus_t addr, int len)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
|
||||
uint32_t val = s->config_reg;
|
||||
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = bswap32(val);
|
||||
val = qemu_bswap_len(val, len);
|
||||
#endif
|
||||
PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
|
||||
__func__, addr, val);
|
||||
PCI_DPRINTF("%s addr %" FMT_PCIBUS " len %d val %"PRIx32"\n",
|
||||
__func__, addr, len, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static CPUWriteMemoryFunc * const pci_host_config_write[] = {
|
||||
&pci_host_config_writel,
|
||||
&pci_host_config_writel,
|
||||
&pci_host_config_writel,
|
||||
};
|
||||
static void pci_host_config_write_noswap(ReadWriteHandler *handler,
|
||||
pcibus_t addr, uint32_t val, int len)
|
||||
{
|
||||
PCIHostState *s = container_of(handler, PCIHostState, conf_noswap_handler);
|
||||
|
||||
static CPUReadMemoryFunc * const pci_host_config_read[] = {
|
||||
&pci_host_config_readl,
|
||||
&pci_host_config_readl,
|
||||
&pci_host_config_readl,
|
||||
};
|
||||
PCI_DPRINTF("%s addr %" FMT_PCIBUS " %d val %"PRIx32"\n",
|
||||
__func__, addr, len, val);
|
||||
s->config_reg = val;
|
||||
}
|
||||
|
||||
static uint32_t pci_host_config_read_noswap(ReadWriteHandler *handler,
|
||||
pcibus_t addr, int len)
|
||||
{
|
||||
PCIHostState *s = container_of(handler, PCIHostState, conf_noswap_handler);
|
||||
uint32_t val = s->config_reg;
|
||||
|
||||
PCI_DPRINTF("%s addr %" FMT_PCIBUS " len %d val %"PRIx32"\n",
|
||||
__func__, addr, len, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pci_host_data_write(ReadWriteHandler *handler,
|
||||
pcibus_t addr, uint32_t val, int len)
|
||||
{
|
||||
PCIHostState *s = container_of(handler, PCIHostState, data_handler);
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = qemu_bswap_len(val, len);
|
||||
#endif
|
||||
PCI_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n",
|
||||
addr, len, val);
|
||||
if (s->config_reg & (1u << 31))
|
||||
pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
|
||||
}
|
||||
|
||||
static uint32_t pci_host_data_read(ReadWriteHandler *handler,
|
||||
pcibus_t addr, int len)
|
||||
{
|
||||
PCIHostState *s = container_of(handler, PCIHostState, data_handler);
|
||||
uint32_t val;
|
||||
if (!(s->config_reg & (1 << 31)))
|
||||
return 0xffffffff;
|
||||
val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
|
||||
PCI_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 void pci_host_init(PCIHostState *s)
|
||||
{
|
||||
s->conf_handler.write = pci_host_config_write;
|
||||
s->conf_handler.read = pci_host_config_read;
|
||||
s->conf_noswap_handler.write = pci_host_config_write_noswap;
|
||||
s->conf_noswap_handler.read = pci_host_config_read_noswap;
|
||||
s->data_handler.write = pci_host_data_write;
|
||||
s->data_handler.read = pci_host_data_read;
|
||||
}
|
||||
|
||||
int pci_host_conf_register_mmio(PCIHostState *s)
|
||||
{
|
||||
return cpu_register_io_memory(pci_host_config_read,
|
||||
pci_host_config_write, s);
|
||||
pci_host_init(s);
|
||||
return cpu_register_io_memory_simple(&s->conf_handler);
|
||||
}
|
||||
|
||||
static void pci_host_config_writel_noswap(void *opaque,
|
||||
target_phys_addr_t addr,
|
||||
uint32_t val)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
|
||||
PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
|
||||
__func__, addr, val);
|
||||
s->config_reg = val;
|
||||
}
|
||||
|
||||
static uint32_t pci_host_config_readl_noswap(void *opaque,
|
||||
target_phys_addr_t addr)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
uint32_t val = s->config_reg;
|
||||
|
||||
PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
|
||||
__func__, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static CPUWriteMemoryFunc * const pci_host_config_write_noswap[] = {
|
||||
&pci_host_config_writel_noswap,
|
||||
&pci_host_config_writel_noswap,
|
||||
&pci_host_config_writel_noswap,
|
||||
};
|
||||
|
||||
static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
|
||||
&pci_host_config_readl_noswap,
|
||||
&pci_host_config_readl_noswap,
|
||||
&pci_host_config_readl_noswap,
|
||||
};
|
||||
|
||||
int pci_host_conf_register_mmio_noswap(PCIHostState *s)
|
||||
{
|
||||
return cpu_register_io_memory(pci_host_config_read_noswap,
|
||||
pci_host_config_write_noswap, s);
|
||||
}
|
||||
|
||||
static void pci_host_config_writel_ioport(void *opaque,
|
||||
uint32_t addr, uint32_t val)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
|
||||
PCI_DPRINTF("%s addr %"PRIx32 " val %"PRIx32"\n", __func__, addr, val);
|
||||
s->config_reg = val;
|
||||
}
|
||||
|
||||
static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
uint32_t val = s->config_reg;
|
||||
|
||||
PCI_DPRINTF("%s addr %"PRIx32" val %"PRIx32"\n", __func__, addr, val);
|
||||
return val;
|
||||
pci_host_init(s);
|
||||
return cpu_register_io_memory_simple(&s->conf_noswap_handler);
|
||||
}
|
||||
|
||||
void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s)
|
||||
{
|
||||
register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s);
|
||||
register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s);
|
||||
pci_host_init(s);
|
||||
register_ioport_simple(&s->conf_noswap_handler, ioport, 4, 4);
|
||||
}
|
||||
|
||||
#define PCI_ADDR_T target_phys_addr_t
|
||||
#define PCI_HOST_SUFFIX _mmio
|
||||
|
||||
#include "pci_host_template.h"
|
||||
|
||||
static CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
|
||||
pci_host_data_writeb_mmio,
|
||||
pci_host_data_writew_mmio,
|
||||
pci_host_data_writel_mmio,
|
||||
};
|
||||
|
||||
static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
|
||||
pci_host_data_readb_mmio,
|
||||
pci_host_data_readw_mmio,
|
||||
pci_host_data_readl_mmio,
|
||||
};
|
||||
|
||||
int pci_host_data_register_mmio(PCIHostState *s)
|
||||
{
|
||||
return cpu_register_io_memory(pci_host_data_read_mmio,
|
||||
pci_host_data_write_mmio,
|
||||
s);
|
||||
pci_host_init(s);
|
||||
return cpu_register_io_memory_simple(&s->data_handler);
|
||||
}
|
||||
|
||||
#undef PCI_ADDR_T
|
||||
#undef PCI_HOST_SUFFIX
|
||||
|
||||
#define PCI_ADDR_T uint32_t
|
||||
#define PCI_HOST_SUFFIX _ioport
|
||||
|
||||
#include "pci_host_template.h"
|
||||
|
||||
void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
|
||||
{
|
||||
register_ioport_write(ioport, 4, 1, pci_host_data_writeb_ioport, s);
|
||||
register_ioport_write(ioport, 4, 2, pci_host_data_writew_ioport, s);
|
||||
register_ioport_write(ioport, 4, 4, pci_host_data_writel_ioport, s);
|
||||
register_ioport_read(ioport, 4, 1, pci_host_data_readb_ioport, s);
|
||||
register_ioport_read(ioport, 4, 2, pci_host_data_readw_ioport, s);
|
||||
register_ioport_read(ioport, 4, 4, pci_host_data_readl_ioport, s);
|
||||
pci_host_init(s);
|
||||
register_ioport_simple(&s->data_handler, ioport, 4, 1);
|
||||
register_ioport_simple(&s->data_handler, ioport, 4, 2);
|
||||
register_ioport_simple(&s->data_handler, ioport, 4, 4);
|
||||
}
|
||||
|
|
|
@ -29,9 +29,13 @@
|
|||
#define PCI_HOST_H
|
||||
|
||||
#include "sysbus.h"
|
||||
#include "rwhandler.h"
|
||||
|
||||
struct PCIHostState {
|
||||
SysBusDevice busdev;
|
||||
ReadWriteHandler conf_noswap_handler;
|
||||
ReadWriteHandler conf_handler;
|
||||
ReadWriteHandler data_handler;
|
||||
uint32_t config_reg;
|
||||
PCIBus *bus;
|
||||
};
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* QEMU Common PCI Host bridge configuration data space access routines.
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Worker routines for a PCI host controller that uses an {address,data}
|
||||
register pair to access PCI configuration space. */
|
||||
|
||||
static void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
|
||||
void* opaque, PCI_ADDR_T addr, uint32_t val)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
|
||||
PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
|
||||
(target_phys_addr_t)addr, val);
|
||||
if (s->config_reg & (1u << 31))
|
||||
pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
|
||||
}
|
||||
|
||||
static void glue(pci_host_data_writew, PCI_HOST_SUFFIX)(
|
||||
void* opaque, PCI_ADDR_T addr, uint32_t val)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = bswap16(val);
|
||||
#endif
|
||||
PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
|
||||
(target_phys_addr_t)addr, val);
|
||||
if (s->config_reg & (1u << 31))
|
||||
pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
|
||||
}
|
||||
|
||||
static void glue(pci_host_data_writel, PCI_HOST_SUFFIX)(
|
||||
void* opaque, PCI_ADDR_T addr, uint32_t val)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = bswap32(val);
|
||||
#endif
|
||||
PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
|
||||
(target_phys_addr_t)addr, val);
|
||||
if (s->config_reg & (1u << 31))
|
||||
pci_data_write(s->bus, s->config_reg, val, 4);
|
||||
}
|
||||
|
||||
static uint32_t glue(pci_host_data_readb, PCI_HOST_SUFFIX)(
|
||||
void* opaque, PCI_ADDR_T addr)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
uint32_t val;
|
||||
|
||||
if (!(s->config_reg & (1 << 31)))
|
||||
return 0xff;
|
||||
val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
|
||||
PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
|
||||
(target_phys_addr_t)addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint32_t glue(pci_host_data_readw, PCI_HOST_SUFFIX)(
|
||||
void* opaque, PCI_ADDR_T addr)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
uint32_t val;
|
||||
if (!(s->config_reg & (1 << 31)))
|
||||
return 0xffff;
|
||||
val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
|
||||
PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
|
||||
(target_phys_addr_t)addr, val);
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = bswap16(val);
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
|
||||
void* opaque, PCI_ADDR_T addr)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
uint32_t val;
|
||||
if (!(s->config_reg & (1 << 31)))
|
||||
return 0xffffffff;
|
||||
val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
|
||||
PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
|
||||
(target_phys_addr_t)addr, val);
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = bswap32(val);
|
||||
#endif
|
||||
return val;
|
||||
}
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#define PCI_VENDOR_ID_APPLE 0x106b
|
||||
#define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020
|
||||
#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b
|
||||
|
||||
#define PCI_VENDOR_ID_SUN 0x108e
|
||||
#define PCI_DEVICE_ID_SUN_EBUS 0x1000
|
||||
|
|
2
hw/ppc.h
2
hw/ppc.h
|
@ -40,10 +40,12 @@ enum {
|
|||
ARCH_PREP = 0,
|
||||
ARCH_MAC99,
|
||||
ARCH_HEATHROW,
|
||||
ARCH_MAC99_U3,
|
||||
};
|
||||
|
||||
#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
|
||||
#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
|
||||
#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
|
||||
#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03)
|
||||
|
||||
#define PPC_SERIAL_MM_BAUDBASE 399193
|
||||
|
|
|
@ -58,6 +58,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
|
|||
|
||||
/* UniNorth PCI */
|
||||
PCIBus *pci_pmac_init(qemu_irq *pic);
|
||||
PCIBus *pci_pmac_u3_init(qemu_irq *pic);
|
||||
|
||||
/* Mac NVRAM */
|
||||
typedef struct MacIONVRAMState MacIONVRAMState;
|
||||
|
|
|
@ -21,6 +21,30 @@
|
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* PCI bus layout on a real G5 (U3 based):
|
||||
*
|
||||
* 0000:f0:0b.0 Host bridge [0600]: Apple Computer Inc. U3 AGP [106b:004b]
|
||||
* 0000:f0:10.0 VGA compatible controller [0300]: ATI Technologies Inc RV350 AP [Radeon 9600] [1002:4150]
|
||||
* 0001:00:00.0 Host bridge [0600]: Apple Computer Inc. CPC945 HT Bridge [106b:004a]
|
||||
* 0001:00:01.0 PCI bridge [0604]: Advanced Micro Devices [AMD] AMD-8131 PCI-X Bridge [1022:7450] (rev 12)
|
||||
* 0001:00:02.0 PCI bridge [0604]: Advanced Micro Devices [AMD] AMD-8131 PCI-X Bridge [1022:7450] (rev 12)
|
||||
* 0001:00:03.0 PCI bridge [0604]: Apple Computer Inc. K2 HT-PCI Bridge [106b:0045]
|
||||
* 0001:00:04.0 PCI bridge [0604]: Apple Computer Inc. K2 HT-PCI Bridge [106b:0046]
|
||||
* 0001:00:05.0 PCI bridge [0604]: Apple Computer Inc. K2 HT-PCI Bridge [106b:0047]
|
||||
* 0001:00:06.0 PCI bridge [0604]: Apple Computer Inc. K2 HT-PCI Bridge [106b:0048]
|
||||
* 0001:00:07.0 PCI bridge [0604]: Apple Computer Inc. K2 HT-PCI Bridge [106b:0049]
|
||||
* 0001:01:07.0 Class [ff00]: Apple Computer Inc. K2 KeyLargo Mac/IO [106b:0041] (rev 20)
|
||||
* 0001:01:08.0 USB Controller [0c03]: Apple Computer Inc. K2 KeyLargo USB [106b:0040]
|
||||
* 0001:01:09.0 USB Controller [0c03]: Apple Computer Inc. K2 KeyLargo USB [106b:0040]
|
||||
* 0001:02:0b.0 USB Controller [0c03]: NEC Corporation USB [1033:0035] (rev 43)
|
||||
* 0001:02:0b.1 USB Controller [0c03]: NEC Corporation USB [1033:0035] (rev 43)
|
||||
* 0001:02:0b.2 USB Controller [0c03]: NEC Corporation USB 2.0 [1033:00e0] (rev 04)
|
||||
* 0001:03:0d.0 Class [ff00]: Apple Computer Inc. K2 ATA/100 [106b:0043]
|
||||
* 0001:03:0e.0 FireWire (IEEE 1394) [0c00]: Apple Computer Inc. K2 FireWire [106b:0042]
|
||||
* 0001:04:0f.0 Ethernet controller [0200]: Apple Computer Inc. K2 GMAC (Sun GEM) [106b:004c]
|
||||
* 0001:05:0c.0 IDE interface [0101]: Broadcom K2 SATA [1166:0240]
|
||||
*
|
||||
*/
|
||||
#include "hw.h"
|
||||
#include "ppc.h"
|
||||
|
@ -40,6 +64,8 @@
|
|||
#include "loader.h"
|
||||
#include "elf.h"
|
||||
#include "kvm.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "hw/usb.h"
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
#define VGA_BIOS_SIZE 65536
|
||||
|
@ -109,11 +135,13 @@ static void ppc_core99_init (ram_addr_t ram_size,
|
|||
int nvram_mem_index;
|
||||
int vga_bios_size, bios_size;
|
||||
int pic_mem_index, dbdma_mem_index, cuda_mem_index, escc_mem_index;
|
||||
int ide_mem_index[3];
|
||||
int ppc_boot_device;
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
void *fw_cfg;
|
||||
void *dbdma;
|
||||
uint8_t *vga_bios_ptr;
|
||||
int machine_arch;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
|
@ -317,7 +345,14 @@ static void ppc_core99_init (ram_addr_t ram_size,
|
|||
}
|
||||
}
|
||||
pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
|
||||
pci_bus = pci_pmac_init(pic);
|
||||
if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
|
||||
/* 970 gets a U3 bus */
|
||||
pci_bus = pci_pmac_u3_init(pic);
|
||||
machine_arch = ARCH_MAC99_U3;
|
||||
} else {
|
||||
pci_bus = pci_pmac_init(pic);
|
||||
machine_arch = ARCH_MAC99;
|
||||
}
|
||||
/* init basic PC hardware */
|
||||
pci_vga_init(pci_bus, vga_bios_offset, vga_bios_size);
|
||||
|
||||
|
@ -331,27 +366,41 @@ static void ppc_core99_init (ram_addr_t ram_size,
|
|||
fprintf(stderr, "qemu: too many IDE bus\n");
|
||||
exit(1);
|
||||
}
|
||||
for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
|
||||
hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
|
||||
}
|
||||
dbdma = DBDMA_init(&dbdma_mem_index);
|
||||
pci_cmd646_ide_init(pci_bus, hd, 0);
|
||||
|
||||
/* We only emulate 2 out of 3 IDE controllers for now */
|
||||
ide_mem_index[0] = -1;
|
||||
hd[0] = drive_get(IF_IDE, 0, 0);
|
||||
hd[1] = drive_get(IF_IDE, 0, 1);
|
||||
ide_mem_index[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]);
|
||||
hd[0] = drive_get(IF_IDE, 1, 0);
|
||||
hd[1] = drive_get(IF_IDE, 1, 1);
|
||||
ide_mem_index[2] = pmac_ide_init(hd, pic[0x0e], dbdma, 0x1a, pic[0x02]);
|
||||
|
||||
/* cuda also initialize ADB */
|
||||
if (machine_arch == ARCH_MAC99_U3) {
|
||||
usb_enabled = 1;
|
||||
}
|
||||
cuda_init(&cuda_mem_index, pic[0x19]);
|
||||
|
||||
adb_kbd_init(&adb_bus);
|
||||
adb_mouse_init(&adb_bus);
|
||||
|
||||
|
||||
macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem_index,
|
||||
dbdma_mem_index, cuda_mem_index, NULL, 0, NULL,
|
||||
dbdma_mem_index, cuda_mem_index, NULL, 3, ide_mem_index,
|
||||
escc_mem_index);
|
||||
|
||||
if (usb_enabled) {
|
||||
usb_ohci_init_pci(pci_bus, -1);
|
||||
}
|
||||
|
||||
/* U3 needs to use USB for input because Linux doesn't support via-cuda
|
||||
on PPC64 */
|
||||
if (machine_arch == ARCH_MAC99_U3) {
|
||||
usbdevice_create("keyboard");
|
||||
usbdevice_create("mouse");
|
||||
}
|
||||
|
||||
if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
|
||||
graphic_depth = 15;
|
||||
|
||||
|
@ -364,7 +413,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
|
|||
fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_MAC99);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
|
||||
if (kernel_cmdline) {
|
||||
|
@ -381,6 +430,14 @@ static void ppc_core99_init (ram_addr_t ram_size,
|
|||
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
|
||||
|
||||
if (kvm_enabled()) {
|
||||
#ifdef CONFIG_KVM
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
|
||||
#endif
|
||||
} else {
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
|
||||
}
|
||||
|
||||
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "loader.h"
|
||||
#include "elf.h"
|
||||
#include "kvm.h"
|
||||
#include "kvm_ppc.h"
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
#define VGA_BIOS_SIZE 65536
|
||||
|
@ -401,6 +402,14 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
|
|||
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
|
||||
|
||||
if (kvm_enabled()) {
|
||||
#ifdef CONFIG_KVM
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
|
||||
#endif
|
||||
} else {
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
|
||||
}
|
||||
|
||||
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
|
||||
}
|
||||
|
||||
|
|
151
hw/unin_pci.c
151
hw/unin_pci.c
|
@ -36,22 +36,31 @@
|
|||
#define UNIN_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
|
||||
|
||||
typedef struct UNINState {
|
||||
SysBusDevice busdev;
|
||||
PCIHostState host_state;
|
||||
ReadWriteHandler data_handler;
|
||||
} UNINState;
|
||||
|
||||
/* Don't know if this matches real hardware, but it agrees with OHW. */
|
||||
static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
|
||||
{
|
||||
return (irq_num + (pci_dev->devfn >> 3)) & 3;
|
||||
int retval;
|
||||
int devfn = pci_dev->devfn & 0x00FFFFFF;
|
||||
|
||||
retval = (((devfn >> 11) & 0x1F) + irq_num) & 3;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pci_unin_set_irq(void *opaque, int irq_num, int level)
|
||||
{
|
||||
qemu_irq *pic = opaque;
|
||||
|
||||
qemu_set_irq(pic[irq_num + 8], level);
|
||||
UNIN_DPRINTF("%s: setting INT %d = %d\n", __func__,
|
||||
unin_irq_line[irq_num], level);
|
||||
qemu_set_irq(pic[unin_irq_line[irq_num]], level);
|
||||
}
|
||||
|
||||
static void pci_unin_save(QEMUFile* f, void *opaque)
|
||||
|
@ -75,6 +84,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)
|
||||
{
|
||||
UNINState *s;
|
||||
|
@ -85,7 +156,9 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
|
|||
s = FROM_SYSBUS(UNINState, dev);
|
||||
|
||||
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_data);
|
||||
|
||||
|
@ -94,6 +167,27 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pci_u3_agp_init_device(SysBusDevice *dev)
|
||||
{
|
||||
UNINState *s;
|
||||
int pci_mem_config, pci_mem_data;
|
||||
|
||||
/* Uninorth U3 AGP bus */
|
||||
s = FROM_SYSBUS(UNINState, dev);
|
||||
|
||||
pci_mem_config = pci_host_conf_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_data);
|
||||
|
||||
register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
|
||||
qemu_register_reset(pci_unin_reset, &s->host_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_unin_agp_init_device(SysBusDevice *dev)
|
||||
{
|
||||
UNINState *s;
|
||||
|
@ -175,6 +269,31 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
|
|||
return d->host_state.bus;
|
||||
}
|
||||
|
||||
PCIBus *pci_pmac_u3_init(qemu_irq *pic)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
UNINState *d;
|
||||
|
||||
/* Uninorth AGP bus */
|
||||
|
||||
dev = qdev_create(NULL, "u3-agp");
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
d = FROM_SYSBUS(UNINState, s);
|
||||
|
||||
d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
|
||||
pci_unin_set_irq, pci_unin_map_irq,
|
||||
pic, 11 << 3, 4);
|
||||
|
||||
sysbus_mmio_map(s, 0, 0xf0800000);
|
||||
sysbus_mmio_map(s, 1, 0xf0c00000);
|
||||
|
||||
pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp");
|
||||
|
||||
return d->host_state.bus;
|
||||
}
|
||||
|
||||
static int unin_main_pci_host_init(PCIDevice *d)
|
||||
{
|
||||
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
|
||||
|
@ -201,6 +320,21 @@ static int unin_agp_pci_host_init(PCIDevice *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int u3_agp_pci_host_init(PCIDevice *d)
|
||||
{
|
||||
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
|
||||
pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_U3_AGP);
|
||||
/* revision */
|
||||
d->config[0x08] = 0x00;
|
||||
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
|
||||
/* cache line size */
|
||||
d->config[0x0C] = 0x08;
|
||||
/* latency timer */
|
||||
d->config[0x0D] = 0x10;
|
||||
d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unin_internal_pci_host_init(PCIDevice *d)
|
||||
{
|
||||
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
|
||||
|
@ -220,6 +354,12 @@ static PCIDeviceInfo unin_main_pci_host_info = {
|
|||
.init = unin_main_pci_host_init,
|
||||
};
|
||||
|
||||
static PCIDeviceInfo u3_agp_pci_host_info = {
|
||||
.qdev.name = "u3-agp",
|
||||
.qdev.size = sizeof(PCIDevice),
|
||||
.init = u3_agp_pci_host_init,
|
||||
};
|
||||
|
||||
static PCIDeviceInfo unin_agp_pci_host_info = {
|
||||
.qdev.name = "uni-north-agp",
|
||||
.qdev.size = sizeof(PCIDevice),
|
||||
|
@ -237,6 +377,9 @@ static void unin_register_devices(void)
|
|||
sysbus_register_dev("uni-north", sizeof(UNINState),
|
||||
pci_unin_main_init_device);
|
||||
pci_qdev_register(&unin_main_pci_host_info);
|
||||
sysbus_register_dev("u3-agp", sizeof(UNINState),
|
||||
pci_u3_agp_init_device);
|
||||
pci_qdev_register(&u3_agp_pci_host_info);
|
||||
sysbus_register_dev("uni-north-agp", sizeof(UNINState),
|
||||
pci_unin_agp_init_device);
|
||||
pci_qdev_register(&unin_agp_pci_host_info);
|
||||
|
|
|
@ -147,14 +147,10 @@ static int versatile_pci_host_init(PCIDevice *d)
|
|||
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_XILINX);
|
||||
/* Both boards have the same device ID. Oh well. */
|
||||
pci_config_set_device_id(d->config, PCI_DEVICE_ID_XILINX_XC2VP30);
|
||||
d->config[0x04] = 0x00;
|
||||
d->config[0x05] = 0x00;
|
||||
d->config[0x06] = 0x20;
|
||||
d->config[0x07] = 0x02;
|
||||
d->config[0x08] = 0x00; // revision
|
||||
d->config[0x09] = 0x00; // programming i/f
|
||||
pci_set_word(d->config + PCI_STATUS,
|
||||
PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
|
||||
pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_CO);
|
||||
d->config[0x0D] = 0x10; // latency_timer
|
||||
pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue