PowerPC prep/chrp/pmac support

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@863 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2004-05-26 22:13:53 +00:00
parent a2a444d6e0
commit 77d4bc349a
3 changed files with 341 additions and 1 deletions

300
hw/pci.c
View File

@ -470,6 +470,259 @@ void piix3_init(void)
piix3_reset(d);
}
/* PREP pci init */
static inline void set_config(PCIBridge *s, target_phys_addr_t addr)
{
int devfn, i;
for(i = 0; i < 11; i++) {
if ((addr & (1 << (11 + i))) != 0)
break;
}
devfn = ((addr >> 8) & 7) | (i << 3);
s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8);
}
static void PPC_PCIIO_writeb (target_phys_addr_t addr, uint32_t val)
{
PCIBridge *s = &pci_bridge;
set_config(s, addr);
pci_data_write(s, addr, val, 1);
}
static void PPC_PCIIO_writew (target_phys_addr_t addr, uint32_t val)
{
PCIBridge *s = &pci_bridge;
set_config(s, addr);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
pci_data_write(s, addr, val, 2);
}
static void PPC_PCIIO_writel (target_phys_addr_t addr, uint32_t val)
{
PCIBridge *s = &pci_bridge;
set_config(s, addr);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
pci_data_write(s, addr, val, 4);
}
static uint32_t PPC_PCIIO_readb (target_phys_addr_t addr)
{
PCIBridge *s = &pci_bridge;
uint32_t val;
set_config(s, addr);
val = pci_data_read(s, addr, 1);
return val;
}
static uint32_t PPC_PCIIO_readw (target_phys_addr_t addr)
{
PCIBridge *s = &pci_bridge;
uint32_t val;
set_config(s, addr);
val = pci_data_read(s, addr, 2);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
return val;
}
static uint32_t PPC_PCIIO_readl (target_phys_addr_t addr)
{
PCIBridge *s = &pci_bridge;
uint32_t val;
set_config(s, addr);
val = pci_data_read(s, addr, 4);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *PPC_PCIIO_write[] = {
&PPC_PCIIO_writeb,
&PPC_PCIIO_writew,
&PPC_PCIIO_writel,
};
static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
&PPC_PCIIO_readb,
&PPC_PCIIO_readw,
&PPC_PCIIO_readl,
};
void pci_prep_init(void)
{
PCIDevice *d;
int PPC_io_memory;
PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, PPC_PCIIO_write);
cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
d = pci_register_device("PREP PCI Bridge", sizeof(PCIDevice), 0, 0,
NULL, NULL);
/* XXX: put correct IDs */
d->config[0x00] = 0x11; // vendor_id
d->config[0x01] = 0x10;
d->config[0x02] = 0x26; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x02; // revision
d->config[0x0a] = 0x04; // class_sub = pci2pci
d->config[0x0b] = 0x06; // class_base = PCI_bridge
d->config[0x0e] = 0x01; // header_type
}
/* pmac pci init */
static void pci_pmac_config_writel (target_phys_addr_t addr, uint32_t val)
{
PCIBridge *s = &pci_bridge;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
s->config_reg = val;
}
static uint32_t pci_pmac_config_readl (target_phys_addr_t addr)
{
PCIBridge *s = &pci_bridge;
uint32_t val;
val = s->config_reg;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *pci_pmac_config_write[] = {
&pci_pmac_config_writel,
&pci_pmac_config_writel,
&pci_pmac_config_writel,
};
static CPUReadMemoryFunc *pci_pmac_config_read[] = {
&pci_pmac_config_readl,
&pci_pmac_config_readl,
&pci_pmac_config_readl,
};
static void pci_pmac_writeb (target_phys_addr_t addr, uint32_t val)
{
PCIBridge *s = &pci_bridge;
pci_data_write(s, addr, val, 1);
}
static void pci_pmac_writew (target_phys_addr_t addr, uint32_t val)
{
PCIBridge *s = &pci_bridge;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
pci_data_write(s, addr, val, 2);
}
static void pci_pmac_writel (target_phys_addr_t addr, uint32_t val)
{
PCIBridge *s = &pci_bridge;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
pci_data_write(s, addr, val, 4);
}
static uint32_t pci_pmac_readb (target_phys_addr_t addr)
{
PCIBridge *s = &pci_bridge;
uint32_t val;
val = pci_data_read(s, addr, 1);
return val;
}
static uint32_t pci_pmac_readw (target_phys_addr_t addr)
{
PCIBridge *s = &pci_bridge;
uint32_t val;
val = pci_data_read(s, addr, 2);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
return val;
}
static uint32_t pci_pmac_readl (target_phys_addr_t addr)
{
PCIBridge *s = &pci_bridge;
uint32_t val;
val = pci_data_read(s, addr, 4);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *pci_pmac_write[] = {
&pci_pmac_writeb,
&pci_pmac_writew,
&pci_pmac_writel,
};
static CPUReadMemoryFunc *pci_pmac_read[] = {
&pci_pmac_readb,
&pci_pmac_readw,
&pci_pmac_readl,
};
void pci_pmac_init(void)
{
PCIDevice *d;
int pci_mem_config, pci_mem_data;
pci_mem_config = cpu_register_io_memory(0, pci_pmac_config_read,
pci_pmac_config_write);
pci_mem_data = cpu_register_io_memory(0, pci_pmac_read, pci_pmac_write);
cpu_register_physical_memory(0xfec00000, 0x1000, pci_mem_config);
cpu_register_physical_memory(0xfee00000, 0x1000, pci_mem_data);
d = pci_register_device("MPC106", sizeof(PCIDevice), 0, 0,
NULL, NULL);
/* same values as PearPC - check this */
d->config[0x00] = 0x11; // vendor_id
d->config[0x01] = 0x10;
d->config[0x02] = 0x26; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x02; // revision
d->config[0x0a] = 0x04; // class_sub = pci2pci
d->config[0x0b] = 0x06; // class_base = PCI_bridge
d->config[0x0e] = 0x01; // header_type
d->config[0x18] = 0x0; // primary_bus
d->config[0x19] = 0x1; // secondary_bus
d->config[0x1a] = 0x1; // subordinate_bus
d->config[0x1c] = 0x10; // io_base
d->config[0x1d] = 0x20; // io_limit
d->config[0x20] = 0x80; // memory_base
d->config[0x21] = 0x80;
d->config[0x22] = 0x90; // memory_limit
d->config[0x23] = 0x80;
d->config[0x24] = 0x00; // prefetchable_memory_base
d->config[0x25] = 0x84;
d->config[0x26] = 0x00; // prefetchable_memory_limit
d->config[0x27] = 0x85;
}
/***********************************************************/
/* generic PCI irq support */
@ -484,6 +737,11 @@ static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
}
/* 0 <= irq_num <= 3. level must be 0 or 1 */
#ifdef TARGET_PPC
void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
{
}
#else
void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
{
int irq_index, shift, pic_irq, pic_level;
@ -519,6 +777,7 @@ void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
pic_set_irq(pic_irq, pic_level);
}
}
#endif
/***********************************************************/
/* monitor info on PCI */
@ -780,3 +1039,44 @@ void pci_bios_init(void)
}
}
}
/*
* This function initializes the PCI devices as a normal PCI BIOS
* would do. It is provided just in case the BIOS has no support for
* PCI.
*/
void pci_ppc_bios_init(void)
{
PCIBridge *s = &pci_bridge;
PCIDevice **bus;
int bus_num, devfn, i, irq;
uint8_t elcr[2];
pci_bios_io_addr = 0xc000;
pci_bios_mem_addr = 0xc0000000;
#if 0
/* activate IRQ mappings */
elcr[0] = 0x00;
elcr[1] = 0x00;
for(i = 0; i < 4; i++) {
irq = pci_irqs[i];
/* set to trigger level */
elcr[irq >> 3] |= (1 << (irq & 7));
/* activate irq remapping in PIIX */
pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq);
}
isa_outb(elcr[0], 0x4d0);
isa_outb(elcr[1], 0x4d1);
#endif
for(bus_num = 0; bus_num < 256; bus_num++) {
bus = s->pci_bus[bus_num];
if (bus) {
for(devfn = 0; devfn < 256; devfn++) {
if (bus[devfn])
pci_bios_init_device(bus[devfn]);
}
}
}
}

20
vl.c
View File

@ -93,8 +93,11 @@ extern void __sigaction();
#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
#endif
#ifdef TARGET_PPC
#define DEFAULT_RAM_SIZE 144
#else
#define DEFAULT_RAM_SIZE 32
#endif
/* in ms */
#define GUI_REFRESH_INTERVAL 30
@ -125,6 +128,7 @@ QEMUTimer *gui_timer;
int vm_running;
int audio_enabled = 0;
int pci_enabled = 0;
int prep_enabled = 0;
/***********************************************************/
/* x86 ISA bus support */
@ -876,12 +880,17 @@ int serial_open_device(void)
/* use console for serial port */
return 0;
} else {
#if 0
/* Not satisfying */
if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
fprintf(stderr, "warning: could not create pseudo terminal for serial port\n");
return -1;
}
fprintf(stderr, "Serial port redirected to %s\n", slave_name);
return master_fd;
#else
return -1;
#endif
}
}
@ -2005,6 +2014,7 @@ enum {
QEMU_OPTION_L,
QEMU_OPTION_no_code_copy,
QEMU_OPTION_pci,
QEMU_OPTION_prep,
};
typedef struct QEMUOption {
@ -2049,7 +2059,12 @@ const QEMUOption qemu_options[] = {
{ "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
{ "L", HAS_ARG, QEMU_OPTION_L },
{ "no-code-copy", 0, QEMU_OPTION_no_code_copy },
/* temporary options */
{ "pci", 0, QEMU_OPTION_pci },
#ifdef TARGET_PPC
{ "prep", 0, QEMU_OPTION_prep },
#endif
{ NULL },
};
@ -2323,6 +2338,9 @@ int main(int argc, char **argv)
case QEMU_OPTION_pci:
pci_enabled = 1;
break;
case QEMU_OPTION_prep:
prep_enabled = 1;
break;
}
}
}

22
vl.h
View File

@ -429,6 +429,11 @@ void piix3_init(void);
void pci_bios_init(void);
void pci_info(void);
/* temporary: will be moved in platform specific file */
void pci_prep_init(void);
void pci_pmac_init(void);
void pci_ppc_bios_init(void);
/* vga.c */
#define VGA_RAM_SIZE (4096 * 1024)
@ -580,6 +585,23 @@ void ppc_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename);
void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename);
void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename);
ppc_tb_t *cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
struct sysctrl_t;
int prep_NVRAM_init (struct sysctrl_t *sysctrl, uint32_t RAM_size,
uint32_t BIOS_size, int boot_device,
uint32_t kernel_image);
extern CPUWriteMemoryFunc *PPC_io_write[];
extern CPUReadMemoryFunc *PPC_io_read[];
extern int prep_enabled;
/* monitor.c */
void monitor_init(void);