mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
* sort the PowerPC target object files
* make PowerPC NVRAM accessors generic to be able to use a MacIO NVRAM instead of the M48T59 one * split PowerMac targets code: - move all PowerMac related definitions and prototypes into hw/ppc_mac.h - add hw/mac_dbdma.c, hw/mac_nvram.c and macio.c which implements shared PowerMac devices - define the g3bw machine in a new hw/ppc_oldworld.c file * Fix the g3bw target: - fix the Grackle host PCI device - connect the Heathrow PIC to the PowerPC 6xx bus pins git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3475 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
897b4c6c4e
commit
3cbee15b9a
13 changed files with 914 additions and 518 deletions
|
@ -469,13 +469,20 @@ VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmport.o vmware_vga.o
|
|||
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
|
||||
endif
|
||||
ifeq ($(TARGET_BASE_ARCH), ppc)
|
||||
VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
|
||||
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o pflash_cfi02.o
|
||||
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o
|
||||
VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
|
||||
# PowerPC 4xx boards
|
||||
VL_OBJS+= ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
|
||||
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
|
||||
# shared objects
|
||||
VL_OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o $(AUDIODRV)
|
||||
# PREP target
|
||||
VL_OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
|
||||
VL_OBJS+= prep_pci.o ppc_prep.o
|
||||
# Mac shared devices
|
||||
VL_OBJS+= macio.o cuda.o adb.o mac_nvram.o mac_dbdma.o
|
||||
# OldWorld PowerMac
|
||||
VL_OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
|
||||
# NewWorld PowerMac
|
||||
VL_OBJS+= unin_pci.o ppc_chrp.o
|
||||
# PowerPC 4xx boards
|
||||
VL_OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
|
||||
endif
|
||||
ifeq ($(TARGET_BASE_ARCH), mips)
|
||||
VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
|
||||
|
|
12
hw/cuda.c
12
hw/cuda.c
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* QEMU CUDA support
|
||||
* QEMU PowerMac CUDA device support
|
||||
*
|
||||
* Copyright (c) 2004 Fabrice Bellard
|
||||
* Copyright (c) 2004-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -22,6 +23,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "ppc_mac.h"
|
||||
|
||||
/* XXX: implement all timer modes */
|
||||
|
||||
|
@ -634,10 +636,9 @@ static CPUReadMemoryFunc *cuda_read[] = {
|
|||
&cuda_readl,
|
||||
};
|
||||
|
||||
int cuda_init(qemu_irq irq)
|
||||
void cuda_init (int *cuda_mem_index, qemu_irq irq)
|
||||
{
|
||||
CUDAState *s = &cuda_state;
|
||||
int cuda_mem_index;
|
||||
|
||||
s->irq = irq;
|
||||
|
||||
|
@ -653,6 +654,5 @@ int cuda_init(qemu_irq irq)
|
|||
set_counter(s, &s->timers[1], 0xffff);
|
||||
|
||||
s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
|
||||
cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
|
||||
return cuda_mem_index;
|
||||
*cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* QEMU Grackle (heathrow PPC) PCI host
|
||||
* QEMU Grackle PCI host (heathrow OldWorld PowerMac)
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
* Copyright (c) 2006-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include "vl.h"
|
||||
#include "ppc_mac.h"
|
||||
typedef target_phys_addr_t pci_addr_t;
|
||||
#include "pci_host.h"
|
||||
|
||||
|
@ -82,7 +84,7 @@ static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
|
|||
|
||||
static void pci_grackle_set_irq(qemu_irq *pic, int irq_num, int level)
|
||||
{
|
||||
qemu_set_irq(pic[irq_num + 8], level);
|
||||
qemu_set_irq(pic[irq_num + 0x15], level);
|
||||
}
|
||||
|
||||
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
|
||||
|
@ -93,7 +95,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
|
|||
|
||||
s = qemu_mallocz(sizeof(GrackleState));
|
||||
s->bus = pci_register_bus(pci_grackle_set_irq, pci_grackle_map_irq,
|
||||
pic, 0, 0);
|
||||
pic, 0, 4);
|
||||
|
||||
pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read,
|
||||
pci_grackle_config_write, s);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Heathrow PIC support (standard PowerMac PIC)
|
||||
* Heathrow PIC support (OldWorld PowerMac)
|
||||
*
|
||||
* Copyright (c) 2005 Fabrice Bellard
|
||||
* Copyright (c) 2005-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -22,6 +23,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "ppc_mac.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
|
@ -34,6 +36,7 @@ typedef struct HeathrowPIC {
|
|||
|
||||
typedef struct HeathrowPICS {
|
||||
HeathrowPIC pics[2];
|
||||
qemu_irq *irqs;
|
||||
} HeathrowPICS;
|
||||
|
||||
static inline int check_irq(HeathrowPIC *pic)
|
||||
|
@ -45,9 +48,9 @@ static inline int check_irq(HeathrowPIC *pic)
|
|||
static void heathrow_pic_update(HeathrowPICS *s)
|
||||
{
|
||||
if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) {
|
||||
cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
|
||||
qemu_irq_raise(s->irqs[0]);
|
||||
} else {
|
||||
cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
|
||||
qemu_irq_lower(s->irqs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,12 +60,13 @@ static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
|
|||
HeathrowPIC *pic;
|
||||
unsigned int n;
|
||||
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
value = bswap32(value);
|
||||
#ifdef DEBUG
|
||||
printf("pic_writel: %08x: %08x\n",
|
||||
addr, value);
|
||||
#endif
|
||||
n = ((addr & 0xfff) - 0x10) >> 4;
|
||||
#ifdef DEBUG
|
||||
printf("pic_writel: " PADDRX " %u: %08x\n", addr, n, value);
|
||||
#endif
|
||||
if (n >= 2)
|
||||
return;
|
||||
pic = &s->pics[n];
|
||||
|
@ -110,10 +114,11 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
|
|||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("pic_readl: %08x: %08x\n",
|
||||
addr, value);
|
||||
printf("pic_readl: " PADDRX " %u: %08x\n", addr, n, value);
|
||||
#endif
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
value = bswap32(value);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -156,13 +161,17 @@ static void heathrow_pic_set_irq(void *opaque, int num, int level)
|
|||
heathrow_pic_update(s);
|
||||
}
|
||||
|
||||
qemu_irq *heathrow_pic_init(int *pmem_index)
|
||||
qemu_irq *heathrow_pic_init(int *pmem_index,
|
||||
int nb_cpus, qemu_irq **irqs)
|
||||
{
|
||||
HeathrowPICS *s;
|
||||
|
||||
s = qemu_mallocz(sizeof(HeathrowPICS));
|
||||
s->pics[0].level_triggered = 0;
|
||||
s->pics[1].level_triggered = 0x1ff00000;
|
||||
/* only 1 CPU */
|
||||
s->irqs = irqs[0];
|
||||
*pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s);
|
||||
|
||||
return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
|
||||
}
|
||||
|
|
79
hw/mac_dbdma.c
Normal file
79
hw/mac_dbdma.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* PowerMac descriptor-based DMA emulation
|
||||
*
|
||||
* Copyright (c) 2005-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "ppc_mac.h"
|
||||
|
||||
/* DBDMA: currently no op - should suffice right now */
|
||||
|
||||
static void dbdma_writeb (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
printf("%s: 0x" PADDRX " <= 0x%08x\n", __func__, addr, value);
|
||||
}
|
||||
|
||||
static void dbdma_writew (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
}
|
||||
|
||||
static void dbdma_writel (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
}
|
||||
|
||||
static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
printf("%s: 0x" PADDRX " => 0x00000000\n", __func__, addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CPUWriteMemoryFunc *dbdma_write[] = {
|
||||
&dbdma_writeb,
|
||||
&dbdma_writew,
|
||||
&dbdma_writel,
|
||||
};
|
||||
|
||||
static CPUReadMemoryFunc *dbdma_read[] = {
|
||||
&dbdma_readb,
|
||||
&dbdma_readw,
|
||||
&dbdma_readl,
|
||||
};
|
||||
|
||||
void dbdma_init (int *dbdma_mem_index)
|
||||
{
|
||||
*dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
|
||||
}
|
||||
|
123
hw/mac_nvram.c
Normal file
123
hw/mac_nvram.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* PowerMac NVRAM emulation
|
||||
*
|
||||
* Copyright (c) 2005-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "ppc_mac.h"
|
||||
|
||||
struct MacIONVRAMState {
|
||||
uint8_t data[0x2000];
|
||||
};
|
||||
|
||||
/* Direct access to NVRAM */
|
||||
uint32_t macio_nvram_read (void *opaque, uint32_t addr)
|
||||
{
|
||||
MacIONVRAMState *s = opaque;
|
||||
uint32_t ret;
|
||||
|
||||
// printf("%s: %p addr %04x\n", __func__, s, addr);
|
||||
if (addr < 0x2000)
|
||||
ret = s->data[addr];
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val)
|
||||
{
|
||||
MacIONVRAMState *s = opaque;
|
||||
|
||||
// printf("%s: %p addr %04x val %02x\n", __func__, s, addr, val);
|
||||
if (addr < 0x2000)
|
||||
s->data[addr] = val;
|
||||
}
|
||||
|
||||
/* macio style NVRAM device */
|
||||
static void macio_nvram_writeb (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
MacIONVRAMState *s = opaque;
|
||||
addr = (addr >> 4) & 0x1fff;
|
||||
s->data[addr] = value;
|
||||
// printf("macio_nvram_writeb %04x = %02x\n", addr, value);
|
||||
}
|
||||
|
||||
static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
MacIONVRAMState *s = opaque;
|
||||
uint32_t value;
|
||||
|
||||
addr = (addr >> 4) & 0x1fff;
|
||||
value = s->data[addr];
|
||||
// printf("macio_nvram_readb %04x = %02x\n", addr, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static CPUWriteMemoryFunc *nvram_write[] = {
|
||||
&macio_nvram_writeb,
|
||||
&macio_nvram_writeb,
|
||||
&macio_nvram_writeb,
|
||||
};
|
||||
|
||||
static CPUReadMemoryFunc *nvram_read[] = {
|
||||
&macio_nvram_readb,
|
||||
&macio_nvram_readb,
|
||||
&macio_nvram_readb,
|
||||
};
|
||||
|
||||
MacIONVRAMState *macio_nvram_init (int *mem_index)
|
||||
{
|
||||
MacIONVRAMState *s;
|
||||
s = qemu_mallocz(sizeof(MacIONVRAMState));
|
||||
if (!s)
|
||||
return NULL;
|
||||
*mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint8_t nvram_chksum (const uint8_t *buf, int n)
|
||||
{
|
||||
int sum, i;
|
||||
sum = 0;
|
||||
for(i = 0; i < n; i++)
|
||||
sum += buf[i];
|
||||
return (sum & 0xff) + (sum >> 8);
|
||||
}
|
||||
|
||||
/* set a free Mac OS NVRAM partition */
|
||||
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
|
||||
{
|
||||
uint8_t *buf;
|
||||
char partition_name[12] = "wwwwwwwwwwww";
|
||||
|
||||
buf = nvr->data;
|
||||
buf[0] = 0x7f; /* free partition magic */
|
||||
buf[1] = 0; /* checksum */
|
||||
buf[2] = len >> 8;
|
||||
buf[3] = len;
|
||||
memcpy(buf + 4, partition_name, 12);
|
||||
buf[1] = nvram_chksum(buf, 16);
|
||||
}
|
116
hw/macio.c
Normal file
116
hw/macio.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* PowerMac MacIO device emulation
|
||||
*
|
||||
* Copyright (c) 2005-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "ppc_mac.h"
|
||||
|
||||
typedef struct macio_state_t macio_state_t;
|
||||
struct macio_state_t {
|
||||
int is_oldworld;
|
||||
int pic_mem_index;
|
||||
int dbdma_mem_index;
|
||||
int cuda_mem_index;
|
||||
int nvram_mem_index;
|
||||
int nb_ide;
|
||||
int ide_mem_index[4];
|
||||
};
|
||||
|
||||
static void macio_map (PCIDevice *pci_dev, int region_num,
|
||||
uint32_t addr, uint32_t size, int type)
|
||||
{
|
||||
macio_state_t *macio_state;
|
||||
int i;
|
||||
|
||||
macio_state = (macio_state_t *)(pci_dev + 1);
|
||||
if (macio_state->pic_mem_index >= 0) {
|
||||
if (macio_state->is_oldworld) {
|
||||
/* Heathrow PIC */
|
||||
cpu_register_physical_memory(addr + 0x00000, 0x1000,
|
||||
macio_state->pic_mem_index);
|
||||
} else {
|
||||
/* OpenPIC */
|
||||
cpu_register_physical_memory(addr + 0x40000, 0x40000,
|
||||
macio_state->pic_mem_index);
|
||||
}
|
||||
}
|
||||
if (macio_state->dbdma_mem_index >= 0) {
|
||||
cpu_register_physical_memory(addr + 0x08000, 0x1000,
|
||||
macio_state->dbdma_mem_index);
|
||||
}
|
||||
if (macio_state->cuda_mem_index >= 0) {
|
||||
cpu_register_physical_memory(addr + 0x16000, 0x2000,
|
||||
macio_state->cuda_mem_index);
|
||||
}
|
||||
for (i = 0; i < macio_state->nb_ide; i++) {
|
||||
if (macio_state->ide_mem_index[i] >= 0) {
|
||||
cpu_register_physical_memory(addr + 0x1f000 + (i * 0x1000), 0x1000,
|
||||
macio_state->ide_mem_index[i]);
|
||||
}
|
||||
}
|
||||
if (macio_state->nvram_mem_index >= 0) {
|
||||
cpu_register_physical_memory(addr + 0x60000, 0x20000,
|
||||
macio_state->nvram_mem_index);
|
||||
}
|
||||
}
|
||||
|
||||
void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
|
||||
int dbdma_mem_index, int cuda_mem_index, int nvram_mem_index,
|
||||
int nb_ide, int *ide_mem_index)
|
||||
{
|
||||
PCIDevice *d;
|
||||
macio_state_t *macio_state;
|
||||
int i;
|
||||
|
||||
d = pci_register_device(bus, "macio",
|
||||
sizeof(PCIDevice) + sizeof(macio_state_t),
|
||||
-1, NULL, NULL);
|
||||
macio_state = (macio_state_t *)(d + 1);
|
||||
macio_state->is_oldworld = is_oldworld;
|
||||
macio_state->pic_mem_index = pic_mem_index;
|
||||
macio_state->dbdma_mem_index = dbdma_mem_index;
|
||||
macio_state->cuda_mem_index = cuda_mem_index;
|
||||
macio_state->nvram_mem_index = nvram_mem_index;
|
||||
if (nb_ide > 4)
|
||||
nb_ide = 4;
|
||||
macio_state->nb_ide = nb_ide;
|
||||
for (i = 0; i < nb_ide; i++)
|
||||
macio_state->ide_mem_index[i] = ide_mem_index[i];
|
||||
for (; i < 4; i++)
|
||||
macio_state->ide_mem_index[i] = -1;
|
||||
/* Note: this code is strongly inspirated from the corresponding code
|
||||
in PearPC */
|
||||
d->config[0x00] = 0x6b; // vendor_id
|
||||
d->config[0x01] = 0x10;
|
||||
d->config[0x02] = device_id;
|
||||
d->config[0x03] = device_id >> 8;
|
||||
|
||||
d->config[0x0a] = 0x00; // class_sub = pci2pci
|
||||
d->config[0x0b] = 0xff; // class_base = bridge
|
||||
d->config[0x0e] = 0x00; // header_type
|
||||
|
||||
d->config[0x3d] = 0x01; // interrupt on pin 1
|
||||
|
||||
pci_register_io_region(d, 0, 0x80000,
|
||||
PCI_ADDRESS_SPACE_MEM, macio_map);
|
||||
}
|
67
hw/ppc.c
67
hw/ppc.c
|
@ -22,7 +22,6 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "m48t59.h"
|
||||
|
||||
//#define PPC_DEBUG_IRQ
|
||||
//#define PPC_DEBUG_TB
|
||||
|
@ -1240,63 +1239,75 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
|
|||
|
||||
/*****************************************************************************/
|
||||
/* NVRAM helpers */
|
||||
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
|
||||
static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
|
||||
{
|
||||
m48t59_write(nvram, addr, value);
|
||||
return (*nvram->read_fn)(nvram->opaque, addr);;
|
||||
}
|
||||
|
||||
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
|
||||
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
|
||||
{
|
||||
return m48t59_read(nvram, addr);
|
||||
(*nvram->write_fn)(nvram->opaque, addr, val);
|
||||
}
|
||||
|
||||
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
|
||||
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
|
||||
{
|
||||
m48t59_write(nvram, addr, value >> 8);
|
||||
m48t59_write(nvram, addr + 1, value & 0xFF);
|
||||
nvram_write(nvram, addr, value);
|
||||
}
|
||||
|
||||
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
|
||||
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
|
||||
{
|
||||
return nvram_read(nvram, addr);
|
||||
}
|
||||
|
||||
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
|
||||
{
|
||||
nvram_write(nvram, addr, value >> 8);
|
||||
nvram_write(nvram, addr + 1, value & 0xFF);
|
||||
}
|
||||
|
||||
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
|
||||
{
|
||||
uint16_t tmp;
|
||||
|
||||
tmp = m48t59_read(nvram, addr) << 8;
|
||||
tmp |= m48t59_read(nvram, addr + 1);
|
||||
tmp = nvram_read(nvram, addr) << 8;
|
||||
tmp |= nvram_read(nvram, addr + 1);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
|
||||
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
|
||||
{
|
||||
m48t59_write(nvram, addr, value >> 24);
|
||||
m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
|
||||
m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
|
||||
m48t59_write(nvram, addr + 3, value & 0xFF);
|
||||
nvram_write(nvram, addr, value >> 24);
|
||||
nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
|
||||
nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
|
||||
nvram_write(nvram, addr + 3, value & 0xFF);
|
||||
}
|
||||
|
||||
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
|
||||
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = m48t59_read(nvram, addr) << 24;
|
||||
tmp |= m48t59_read(nvram, addr + 1) << 16;
|
||||
tmp |= m48t59_read(nvram, addr + 2) << 8;
|
||||
tmp |= m48t59_read(nvram, addr + 3);
|
||||
tmp = nvram_read(nvram, addr) << 24;
|
||||
tmp |= nvram_read(nvram, addr + 1) << 16;
|
||||
tmp |= nvram_read(nvram, addr + 2) << 8;
|
||||
tmp |= nvram_read(nvram, addr + 3);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
|
||||
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
|
||||
const unsigned char *str, uint32_t max)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max && str[i] != '\0'; i++) {
|
||||
m48t59_write(nvram, addr + i, str[i]);
|
||||
nvram_write(nvram, addr + i, str[i]);
|
||||
}
|
||||
m48t59_write(nvram, addr + max - 1, '\0');
|
||||
nvram_write(nvram, addr + i, str[i]);
|
||||
nvram_write(nvram, addr + max - 1, '\0');
|
||||
}
|
||||
|
||||
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
|
||||
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1325,7 +1336,7 @@ static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
|
||||
uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
|
||||
{
|
||||
uint32_t i;
|
||||
uint16_t crc = 0xFFFF;
|
||||
|
@ -1345,7 +1356,7 @@ uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
|
|||
|
||||
#define CMDLINE_ADDR 0x017ff000
|
||||
|
||||
int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
|
||||
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
|
||||
const unsigned char *arch,
|
||||
uint32_t RAM_size, int boot_device,
|
||||
uint32_t kernel_image, uint32_t kernel_size,
|
||||
|
@ -1382,7 +1393,7 @@ int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
|
|||
NVRAM_set_word(nvram, 0x56, height);
|
||||
NVRAM_set_word(nvram, 0x58, depth);
|
||||
crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
|
||||
NVRAM_set_word(nvram, 0xFC, crc);
|
||||
NVRAM_set_word(nvram, 0xFC, crc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
552
hw/ppc_chrp.c
552
hw/ppc_chrp.c
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* QEMU PPC CHRP/PMAC hardware System Emulator
|
||||
* QEMU PowerPC CHRP (currently NewWorld PowerMac) hardware System Emulator
|
||||
*
|
||||
* Copyright (c) 2004-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -22,171 +23,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
|
||||
/* SMP is not enabled, for now */
|
||||
#define MAX_CPUS 1
|
||||
|
||||
#define BIOS_FILENAME "ppc_rom.bin"
|
||||
#define VGABIOS_FILENAME "video.x"
|
||||
#define NVRAM_SIZE 0x2000
|
||||
|
||||
#define KERNEL_LOAD_ADDR 0x01000000
|
||||
#define INITRD_LOAD_ADDR 0x01800000
|
||||
|
||||
/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
|
||||
NVRAM */
|
||||
|
||||
static int dbdma_mem_index;
|
||||
static int cuda_mem_index;
|
||||
static int ide0_mem_index = -1;
|
||||
static int ide1_mem_index = -1;
|
||||
static int openpic_mem_index = -1;
|
||||
static int heathrow_pic_mem_index = -1;
|
||||
static int macio_nvram_mem_index = -1;
|
||||
|
||||
/* DBDMA: currently no op - should suffice right now */
|
||||
|
||||
static void dbdma_writeb (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
printf("%s: 0x" PADDRX " <= 0x%08x\n", __func__, addr, value);
|
||||
}
|
||||
|
||||
static void dbdma_writew (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
}
|
||||
|
||||
static void dbdma_writel (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
}
|
||||
|
||||
static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
printf("%s: 0x" PADDRX " => 0x00000000\n", __func__, addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CPUWriteMemoryFunc *dbdma_write[] = {
|
||||
&dbdma_writeb,
|
||||
&dbdma_writew,
|
||||
&dbdma_writel,
|
||||
};
|
||||
|
||||
static CPUReadMemoryFunc *dbdma_read[] = {
|
||||
&dbdma_readb,
|
||||
&dbdma_readw,
|
||||
&dbdma_readl,
|
||||
};
|
||||
|
||||
/* macio style NVRAM device */
|
||||
typedef struct MacIONVRAMState {
|
||||
uint8_t data[0x2000];
|
||||
} MacIONVRAMState;
|
||||
|
||||
static void macio_nvram_writeb (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
MacIONVRAMState *s = opaque;
|
||||
addr = (addr >> 4) & 0x1fff;
|
||||
s->data[addr] = value;
|
||||
// printf("macio_nvram_writeb %04x = %02x\n", addr, value);
|
||||
}
|
||||
|
||||
static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
MacIONVRAMState *s = opaque;
|
||||
uint32_t value;
|
||||
|
||||
addr = (addr >> 4) & 0x1fff;
|
||||
value = s->data[addr];
|
||||
// printf("macio_nvram_readb %04x = %02x\n", addr, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static CPUWriteMemoryFunc *macio_nvram_write[] = {
|
||||
&macio_nvram_writeb,
|
||||
&macio_nvram_writeb,
|
||||
&macio_nvram_writeb,
|
||||
};
|
||||
|
||||
static CPUReadMemoryFunc *macio_nvram_read[] = {
|
||||
&macio_nvram_readb,
|
||||
&macio_nvram_readb,
|
||||
&macio_nvram_readb,
|
||||
};
|
||||
|
||||
static MacIONVRAMState *macio_nvram_init (void)
|
||||
{
|
||||
MacIONVRAMState *s;
|
||||
s = qemu_mallocz(sizeof(MacIONVRAMState));
|
||||
if (!s)
|
||||
return NULL;
|
||||
macio_nvram_mem_index = cpu_register_io_memory(0, macio_nvram_read,
|
||||
macio_nvram_write, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void macio_map (PCIDevice *pci_dev, int region_num,
|
||||
uint32_t addr, uint32_t size, int type)
|
||||
{
|
||||
if (heathrow_pic_mem_index >= 0) {
|
||||
cpu_register_physical_memory(addr + 0x00000, 0x1000,
|
||||
heathrow_pic_mem_index);
|
||||
}
|
||||
cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
|
||||
cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
|
||||
if (ide0_mem_index >= 0)
|
||||
cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index);
|
||||
if (ide1_mem_index >= 0)
|
||||
cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index);
|
||||
if (openpic_mem_index >= 0) {
|
||||
cpu_register_physical_memory(addr + 0x40000, 0x40000,
|
||||
openpic_mem_index);
|
||||
}
|
||||
if (macio_nvram_mem_index >= 0)
|
||||
cpu_register_physical_memory(addr + 0x60000, 0x20000,
|
||||
macio_nvram_mem_index);
|
||||
}
|
||||
|
||||
static void macio_init (PCIBus *bus, int device_id)
|
||||
{
|
||||
PCIDevice *d;
|
||||
|
||||
d = pci_register_device(bus, "macio", sizeof(PCIDevice),
|
||||
-1, NULL, NULL);
|
||||
/* Note: this code is strongly inspirated from the corresponding code
|
||||
in PearPC */
|
||||
d->config[0x00] = 0x6b; // vendor_id
|
||||
d->config[0x01] = 0x10;
|
||||
d->config[0x02] = device_id;
|
||||
d->config[0x03] = device_id >> 8;
|
||||
|
||||
d->config[0x0a] = 0x00; // class_sub = pci2pci
|
||||
d->config[0x0b] = 0xff; // class_base = bridge
|
||||
d->config[0x0e] = 0x00; // header_type
|
||||
|
||||
d->config[0x3d] = 0x01; // interrupt on pin 1
|
||||
|
||||
dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
|
||||
|
||||
pci_register_io_region(d, 0, 0x80000,
|
||||
PCI_ADDRESS_SPACE_MEM, macio_map);
|
||||
}
|
||||
#include "ppc_mac.h"
|
||||
|
||||
/* UniN device */
|
||||
static void unin_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
|
@ -210,118 +47,34 @@ static CPUReadMemoryFunc *unin_read[] = {
|
|||
&unin_readl,
|
||||
};
|
||||
|
||||
/* temporary frame buffer OSI calls for the video.x driver. The right
|
||||
solution is to modify the driver to use VGA PCI I/Os */
|
||||
/* XXX: to be removed. This is no way related to emulation */
|
||||
static int vga_osi_call (CPUState *env)
|
||||
{
|
||||
static int vga_vbl_enabled;
|
||||
int linesize;
|
||||
|
||||
// printf("osi_call R5=%d\n", env->gpr[5]);
|
||||
|
||||
/* same handler as PearPC, coming from the original MOL video
|
||||
driver. */
|
||||
switch(env->gpr[5]) {
|
||||
case 4:
|
||||
break;
|
||||
case 28: /* set_vmode */
|
||||
if (env->gpr[6] != 1 || env->gpr[7] != 0)
|
||||
env->gpr[3] = 1;
|
||||
else
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 29: /* get_vmode_info */
|
||||
if (env->gpr[6] != 0) {
|
||||
if (env->gpr[6] != 1 || env->gpr[7] != 0) {
|
||||
env->gpr[3] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
env->gpr[3] = 0;
|
||||
env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */
|
||||
env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */
|
||||
env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */
|
||||
env->gpr[7] = 85 << 16; /* refresh rate */
|
||||
env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */
|
||||
linesize = ((graphic_depth + 7) >> 3) * graphic_width;
|
||||
linesize = (linesize + 3) & ~3;
|
||||
env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */
|
||||
break;
|
||||
case 31: /* set_video power */
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 39: /* video_ctrl */
|
||||
if (env->gpr[6] == 0 || env->gpr[6] == 1)
|
||||
vga_vbl_enabled = env->gpr[6];
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 47:
|
||||
break;
|
||||
case 59: /* set_color */
|
||||
/* R6 = index, R7 = RGB */
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 64: /* get color */
|
||||
/* R6 = index */
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 116: /* set hwcursor */
|
||||
/* R6 = x, R7 = y, R8 = visible, R9 = data */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unsupported OSI call R5=" REGX "\n", env->gpr[5]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1; /* osi_call handled */
|
||||
}
|
||||
|
||||
static uint8_t nvram_chksum (const uint8_t *buf, int n)
|
||||
{
|
||||
int sum, i;
|
||||
sum = 0;
|
||||
for(i = 0; i < n; i++)
|
||||
sum += buf[i];
|
||||
return (sum & 0xff) + (sum >> 8);
|
||||
}
|
||||
|
||||
/* set a free Mac OS NVRAM partition */
|
||||
void pmac_format_nvram_partition (uint8_t *buf, int len)
|
||||
{
|
||||
char partition_name[12] = "wwwwwwwwwwww";
|
||||
|
||||
buf[0] = 0x7f; /* free partition magic */
|
||||
buf[1] = 0; /* checksum */
|
||||
buf[2] = len >> 8;
|
||||
buf[3] = len;
|
||||
memcpy(buf + 4, partition_name, 12);
|
||||
buf[1] = nvram_chksum(buf, 16);
|
||||
}
|
||||
|
||||
/* PowerPC CHRP hardware initialisation */
|
||||
static 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,
|
||||
const char *cpu_model,
|
||||
int is_heathrow)
|
||||
/* PowerPC Mac99 hardware initialisation */
|
||||
static void ppc_core99_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,
|
||||
const char *cpu_model)
|
||||
{
|
||||
CPUState *env, *envs[MAX_CPUS];
|
||||
char buf[1024];
|
||||
qemu_irq *pic, **openpic_irqs;
|
||||
m48t59_t *nvram;
|
||||
int unin_memory;
|
||||
int linux_boot, i;
|
||||
unsigned long bios_offset, vga_bios_offset;
|
||||
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
|
||||
ppc_def_t *def;
|
||||
PCIBus *pci_bus;
|
||||
const char *arch_name;
|
||||
nvram_t nvram;
|
||||
#if 0
|
||||
MacIONVRAMState *nvr;
|
||||
int nvram_mem_index;
|
||||
#endif
|
||||
m48t59_t *m48t59;
|
||||
int vga_bios_size, bios_size;
|
||||
qemu_irq *dummy_irq;
|
||||
int pic_mem_index, dbdma_mem_index, cuda_mem_index;
|
||||
int ide_mem_index[2];
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
|
@ -338,7 +91,9 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
|
|||
cpu_ppc_reset(env);
|
||||
/* Set time-base frequency to 100 Mhz */
|
||||
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
|
||||
#if 0
|
||||
env->osi_call = vga_osi_call;
|
||||
#endif
|
||||
qemu_register_reset(&cpu_ppc_reset, env);
|
||||
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
|
||||
envs[i] = env;
|
||||
|
@ -413,143 +168,91 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
|
|||
initrd_size = 0;
|
||||
}
|
||||
|
||||
if (is_heathrow) {
|
||||
isa_mem_base = 0x80000000;
|
||||
isa_mem_base = 0x80000000;
|
||||
|
||||
/* Register 2 MB of ISA IO space */
|
||||
isa_mmio_init(0xfe000000, 0x00200000);
|
||||
/* Register 8 MB of ISA IO space */
|
||||
isa_mmio_init(0xf2000000, 0x00800000);
|
||||
|
||||
/* init basic PC hardware */
|
||||
if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
|
||||
cpu_abort(env, "Only 6xx bus is supported on heathrow machine\n");
|
||||
/* UniN init */
|
||||
unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
|
||||
cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
|
||||
|
||||
openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
|
||||
openpic_irqs[0] =
|
||||
qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
/* Mac99 IRQ connection between OpenPIC outputs pins
|
||||
* and PowerPC input pins
|
||||
*/
|
||||
switch (PPC_INPUT(env)) {
|
||||
case PPC_FLAGS_INPUT_6xx:
|
||||
openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_INT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
|
||||
/* Not connected ? */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
|
||||
/* Check this */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
|
||||
break;
|
||||
#if defined(TARGET_PPC64)
|
||||
case PPC_FLAGS_INPUT_970:
|
||||
openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_INT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
|
||||
/* Not connected ? */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
|
||||
/* Check this */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
|
||||
break;
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
default:
|
||||
cpu_abort(env, "Bus model not supported on mac99 machine\n");
|
||||
exit(1);
|
||||
}
|
||||
pic = heathrow_pic_init(&heathrow_pic_mem_index);
|
||||
pci_bus = pci_grackle_init(0xfec00000, pic);
|
||||
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
|
||||
ram_size, vga_ram_size,
|
||||
vga_bios_offset, vga_bios_size);
|
||||
|
||||
/* XXX: suppress that */
|
||||
dummy_irq = i8259_init(NULL);
|
||||
|
||||
/* XXX: use Mac Serial port */
|
||||
serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
|
||||
|
||||
for(i = 0; i < nb_nics; i++) {
|
||||
if (!nd_table[i].model)
|
||||
nd_table[i].model = "ne2k_pci";
|
||||
pci_nic_init(pci_bus, &nd_table[i], -1);
|
||||
}
|
||||
|
||||
pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
|
||||
|
||||
/* cuda also initialize ADB */
|
||||
cuda_mem_index = cuda_init(pic[0x12]);
|
||||
|
||||
adb_kbd_init(&adb_bus);
|
||||
adb_mouse_init(&adb_bus);
|
||||
|
||||
{
|
||||
MacIONVRAMState *nvr;
|
||||
nvr = macio_nvram_init();
|
||||
pmac_format_nvram_partition(nvr->data, 0x2000);
|
||||
}
|
||||
|
||||
macio_init(pci_bus, 0x0017);
|
||||
|
||||
nvram = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
|
||||
|
||||
arch_name = "HEATHROW";
|
||||
} else {
|
||||
isa_mem_base = 0x80000000;
|
||||
|
||||
/* Register 8 MB of ISA IO space */
|
||||
isa_mmio_init(0xf2000000, 0x00800000);
|
||||
|
||||
/* UniN init */
|
||||
unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
|
||||
cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
|
||||
|
||||
openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
|
||||
openpic_irqs[0] =
|
||||
qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
/* Mac99 IRQ connection between OpenPIC outputs pins
|
||||
* and PowerPC input pins
|
||||
*/
|
||||
switch (PPC_INPUT(env)) {
|
||||
case PPC_FLAGS_INPUT_6xx:
|
||||
openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_INT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
|
||||
/* Not connected ? */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
|
||||
/* Check this */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
|
||||
break;
|
||||
#if defined(TARGET_PPC64)
|
||||
case PPC_FLAGS_INPUT_970:
|
||||
openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_INT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
|
||||
/* Not connected ? */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
|
||||
/* Check this */
|
||||
openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
|
||||
break;
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
default:
|
||||
cpu_abort(env, "Bus model not supported on mac99 machine\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
pic = openpic_init(NULL, &openpic_mem_index, smp_cpus,
|
||||
openpic_irqs, NULL);
|
||||
pci_bus = pci_pmac_init(pic);
|
||||
/* init basic PC hardware */
|
||||
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
|
||||
ram_size, vga_ram_size,
|
||||
vga_bios_offset, vga_bios_size);
|
||||
|
||||
/* XXX: suppress that */
|
||||
dummy_irq = i8259_init(NULL);
|
||||
|
||||
/* XXX: use Mac Serial port */
|
||||
serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
|
||||
for(i = 0; i < nb_nics; i++) {
|
||||
if (!nd_table[i].model)
|
||||
nd_table[i].model = "ne2k_pci";
|
||||
pci_nic_init(pci_bus, &nd_table[i], -1);
|
||||
}
|
||||
#if 1
|
||||
ide0_mem_index = pmac_ide_init(&bs_table[0], pic[0x13]);
|
||||
ide1_mem_index = pmac_ide_init(&bs_table[2], pic[0x14]);
|
||||
#else
|
||||
pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
|
||||
#endif
|
||||
/* cuda also initialize ADB */
|
||||
cuda_mem_index = cuda_init(pic[0x19]);
|
||||
|
||||
adb_kbd_init(&adb_bus);
|
||||
adb_mouse_init(&adb_bus);
|
||||
|
||||
macio_init(pci_bus, 0x0022);
|
||||
|
||||
nvram = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
|
||||
|
||||
arch_name = "MAC99";
|
||||
}
|
||||
pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
|
||||
pci_bus = pci_pmac_init(pic);
|
||||
/* init basic PC hardware */
|
||||
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
|
||||
ram_size, vga_ram_size,
|
||||
vga_bios_offset, vga_bios_size);
|
||||
|
||||
/* XXX: suppress that */
|
||||
dummy_irq = i8259_init(NULL);
|
||||
|
||||
/* XXX: use Mac Serial port */
|
||||
serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
|
||||
for(i = 0; i < nb_nics; i++) {
|
||||
if (!nd_table[i].model)
|
||||
nd_table[i].model = "ne2k_pci";
|
||||
pci_nic_init(pci_bus, &nd_table[i], -1);
|
||||
}
|
||||
#if 1
|
||||
ide_mem_index[0] = pmac_ide_init(&bs_table[0], pic[0x13]);
|
||||
ide_mem_index[1] = pmac_ide_init(&bs_table[2], pic[0x14]);
|
||||
#else
|
||||
pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
|
||||
#endif
|
||||
/* cuda also initialize ADB */
|
||||
cuda_init(&cuda_mem_index, pic[0x19]);
|
||||
|
||||
adb_kbd_init(&adb_bus);
|
||||
adb_mouse_init(&adb_bus);
|
||||
|
||||
dbdma_init(&dbdma_mem_index);
|
||||
|
||||
macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
|
||||
cuda_mem_index, -1, 2, ide_mem_index);
|
||||
|
||||
if (usb_enabled) {
|
||||
usb_ohci_init_pci(pci_bus, 3, -1);
|
||||
|
@ -557,8 +260,21 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
|
|||
|
||||
if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
|
||||
graphic_depth = 15;
|
||||
|
||||
PPC_NVRAM_set_params(nvram, NVRAM_SIZE, arch_name, ram_size, boot_device,
|
||||
#if 0 /* XXX: this is ugly but needed for now, or OHW won't boot */
|
||||
/* The NewWorld NVRAM is not located in the MacIO device */
|
||||
nvr = macio_nvram_init(&nvram_mem_index);
|
||||
pmac_format_nvram_partition(nvr, 0x2000);
|
||||
cpu_register_physical_memory(0xFFF04000, 0x20000, nvram_mem_index);
|
||||
nvram.opaque = nvr;
|
||||
nvram.read_fn = &macio_nvram_read;
|
||||
nvram.write_fn = &macio_nvram_write;
|
||||
#else
|
||||
m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
|
||||
nvram.opaque = m48t59;
|
||||
nvram.read_fn = &m48t59_read;
|
||||
nvram.write_fn = &m48t59_write;
|
||||
#endif
|
||||
PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "MAC99", ram_size, boot_device,
|
||||
kernel_base, kernel_size,
|
||||
kernel_cmdline,
|
||||
initrd_base, initrd_size,
|
||||
|
@ -569,44 +285,10 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
|
|||
|
||||
/* Special port to get debug messages from Open-Firmware */
|
||||
register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
|
||||
}
|
||||
|
||||
static void ppc_core99_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,
|
||||
const char *cpu_model)
|
||||
{
|
||||
ppc_chrp_init(ram_size, vga_ram_size, boot_device,
|
||||
ds, fd_filename, snapshot,
|
||||
kernel_filename, kernel_cmdline,
|
||||
initrd_filename, cpu_model, 0);
|
||||
}
|
||||
|
||||
static void ppc_heathrow_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,
|
||||
const char *cpu_model)
|
||||
{
|
||||
ppc_chrp_init(ram_size, vga_ram_size, boot_device,
|
||||
ds, fd_filename, snapshot,
|
||||
kernel_filename, kernel_cmdline,
|
||||
initrd_filename, cpu_model, 1);
|
||||
}
|
||||
}
|
||||
|
||||
QEMUMachine core99_machine = {
|
||||
"mac99",
|
||||
"Mac99 based PowerMAC",
|
||||
ppc_core99_init,
|
||||
};
|
||||
|
||||
QEMUMachine heathrow_machine = {
|
||||
"g3bw",
|
||||
"Heathrow based PowerMAC",
|
||||
ppc_heathrow_init,
|
||||
};
|
||||
|
|
70
hw/ppc_mac.h
Normal file
70
hw/ppc_mac.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* QEMU PowerMac emulation shared definitions and prototypes
|
||||
*
|
||||
* Copyright (c) 2004-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#if !defined(__PPC_MAC_H__)
|
||||
#define __PPC_MAC_H__
|
||||
|
||||
/* SMP is not enabled, for now */
|
||||
#define MAX_CPUS 1
|
||||
|
||||
#define BIOS_FILENAME "ppc_rom.bin"
|
||||
#define VGABIOS_FILENAME "video.x"
|
||||
#define NVRAM_SIZE 0x2000
|
||||
|
||||
#define KERNEL_LOAD_ADDR 0x01000000
|
||||
#define INITRD_LOAD_ADDR 0x01800000
|
||||
|
||||
/* DBDMA */
|
||||
void dbdma_init (int *dbdma_mem_index);
|
||||
|
||||
/* Cuda */
|
||||
void cuda_init (int *cuda_mem_index, qemu_irq irq);
|
||||
|
||||
/* MacIO */
|
||||
void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
|
||||
int dbdma_mem_index, int cuda_mem_index, int nvram_mem_index,
|
||||
int nb_ide, int *ide_mem_index);
|
||||
|
||||
/* NewWorld PowerMac IDE */
|
||||
int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq);
|
||||
|
||||
/* Heathrow PIC */
|
||||
qemu_irq *heathrow_pic_init(int *pmem_index,
|
||||
int nb_cpus, qemu_irq **irqs);
|
||||
|
||||
/* Grackle PCI */
|
||||
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
|
||||
|
||||
/* UniNorth PCI */
|
||||
PCIBus *pci_pmac_init(qemu_irq *pic);
|
||||
|
||||
/* Mac NVRAM */
|
||||
typedef struct MacIONVRAMState MacIONVRAMState;
|
||||
|
||||
MacIONVRAMState *macio_nvram_init (int *mem_index);
|
||||
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
|
||||
uint32_t macio_nvram_read (void *opaque, uint32_t addr);
|
||||
void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val);
|
||||
|
||||
#endif /* !defined(__PPC_MAC_H__) */
|
298
hw/ppc_oldworld.c
Normal file
298
hw/ppc_oldworld.c
Normal file
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* QEMU OldWorld PowerMac (currently ~G3 B&W) hardware System Emulator
|
||||
*
|
||||
* Copyright (c) 2004-2007 Fabrice Bellard
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include "ppc_mac.h"
|
||||
|
||||
/* temporary frame buffer OSI calls for the video.x driver. The right
|
||||
solution is to modify the driver to use VGA PCI I/Os */
|
||||
/* XXX: to be removed. This is no way related to emulation */
|
||||
static int vga_osi_call (CPUState *env)
|
||||
{
|
||||
static int vga_vbl_enabled;
|
||||
int linesize;
|
||||
|
||||
// printf("osi_call R5=%d\n", env->gpr[5]);
|
||||
|
||||
/* same handler as PearPC, coming from the original MOL video
|
||||
driver. */
|
||||
switch(env->gpr[5]) {
|
||||
case 4:
|
||||
break;
|
||||
case 28: /* set_vmode */
|
||||
if (env->gpr[6] != 1 || env->gpr[7] != 0)
|
||||
env->gpr[3] = 1;
|
||||
else
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 29: /* get_vmode_info */
|
||||
if (env->gpr[6] != 0) {
|
||||
if (env->gpr[6] != 1 || env->gpr[7] != 0) {
|
||||
env->gpr[3] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
env->gpr[3] = 0;
|
||||
env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */
|
||||
env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */
|
||||
env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */
|
||||
env->gpr[7] = 85 << 16; /* refresh rate */
|
||||
env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */
|
||||
linesize = ((graphic_depth + 7) >> 3) * graphic_width;
|
||||
linesize = (linesize + 3) & ~3;
|
||||
env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */
|
||||
break;
|
||||
case 31: /* set_video power */
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 39: /* video_ctrl */
|
||||
if (env->gpr[6] == 0 || env->gpr[6] == 1)
|
||||
vga_vbl_enabled = env->gpr[6];
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 47:
|
||||
break;
|
||||
case 59: /* set_color */
|
||||
/* R6 = index, R7 = RGB */
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 64: /* get color */
|
||||
/* R6 = index */
|
||||
env->gpr[3] = 0;
|
||||
break;
|
||||
case 116: /* set hwcursor */
|
||||
/* R6 = x, R7 = y, R8 = visible, R9 = data */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unsupported OSI call R5=" REGX "\n", env->gpr[5]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1; /* osi_call handled */
|
||||
}
|
||||
|
||||
static void ppc_heathrow_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,
|
||||
const char *cpu_model)
|
||||
{
|
||||
CPUState *env, *envs[MAX_CPUS];
|
||||
char buf[1024];
|
||||
qemu_irq *pic, **heathrow_irqs;
|
||||
nvram_t nvram;
|
||||
m48t59_t *m48t59;
|
||||
int linux_boot, i;
|
||||
unsigned long bios_offset, vga_bios_offset;
|
||||
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
|
||||
ppc_def_t *def;
|
||||
PCIBus *pci_bus;
|
||||
MacIONVRAMState *nvr;
|
||||
int vga_bios_size, bios_size;
|
||||
qemu_irq *dummy_irq;
|
||||
int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
/* init CPUs */
|
||||
env = cpu_init();
|
||||
if (cpu_model == NULL)
|
||||
cpu_model = "default";
|
||||
ppc_find_by_name(cpu_model, &def);
|
||||
if (def == NULL) {
|
||||
cpu_abort(env, "Unable to find PowerPC CPU definition\n");
|
||||
}
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
cpu_ppc_register(env, def);
|
||||
cpu_ppc_reset(env);
|
||||
/* Set time-base frequency to 100 Mhz */
|
||||
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
|
||||
env->osi_call = vga_osi_call;
|
||||
qemu_register_reset(&cpu_ppc_reset, env);
|
||||
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
|
||||
envs[i] = env;
|
||||
}
|
||||
|
||||
/* allocate RAM */
|
||||
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
|
||||
|
||||
/* allocate and load BIOS */
|
||||
bios_offset = ram_size + vga_ram_size;
|
||||
if (bios_name == NULL)
|
||||
bios_name = BIOS_FILENAME;
|
||||
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
|
||||
bios_size = load_image(buf, phys_ram_base + bios_offset);
|
||||
if (bios_size < 0 || bios_size > BIOS_SIZE) {
|
||||
cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
bios_size = (bios_size + 0xfff) & ~0xfff;
|
||||
cpu_register_physical_memory((uint32_t)(-bios_size),
|
||||
bios_size, bios_offset | IO_MEM_ROM);
|
||||
|
||||
/* allocate and load VGA BIOS */
|
||||
vga_bios_offset = bios_offset + bios_size;
|
||||
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
|
||||
vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
|
||||
if (vga_bios_size < 0) {
|
||||
/* if no bios is present, we can still work */
|
||||
fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
|
||||
vga_bios_size = 0;
|
||||
} else {
|
||||
/* set a specific header (XXX: find real Apple format for NDRV
|
||||
drivers) */
|
||||
phys_ram_base[vga_bios_offset] = 'N';
|
||||
phys_ram_base[vga_bios_offset + 1] = 'D';
|
||||
phys_ram_base[vga_bios_offset + 2] = 'R';
|
||||
phys_ram_base[vga_bios_offset + 3] = 'V';
|
||||
cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
|
||||
vga_bios_size);
|
||||
vga_bios_size += 8;
|
||||
}
|
||||
vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;
|
||||
|
||||
if (linux_boot) {
|
||||
kernel_base = KERNEL_LOAD_ADDR;
|
||||
/* now we can load the kernel */
|
||||
kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
|
||||
if (kernel_size < 0) {
|
||||
cpu_abort(env, "qemu: could not load kernel '%s'\n",
|
||||
kernel_filename);
|
||||
exit(1);
|
||||
}
|
||||
/* load initrd */
|
||||
if (initrd_filename) {
|
||||
initrd_base = INITRD_LOAD_ADDR;
|
||||
initrd_size = load_image(initrd_filename,
|
||||
phys_ram_base + initrd_base);
|
||||
if (initrd_size < 0) {
|
||||
cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
|
||||
initrd_filename);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
initrd_base = 0;
|
||||
initrd_size = 0;
|
||||
}
|
||||
boot_device = 'm';
|
||||
} else {
|
||||
kernel_base = 0;
|
||||
kernel_size = 0;
|
||||
initrd_base = 0;
|
||||
initrd_size = 0;
|
||||
}
|
||||
|
||||
isa_mem_base = 0x80000000;
|
||||
|
||||
/* Register 2 MB of ISA IO space */
|
||||
isa_mmio_init(0xfe000000, 0x00200000);
|
||||
|
||||
/* XXX: we register only 1 output pin for heathrow PIC */
|
||||
heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
|
||||
heathrow_irqs[0] =
|
||||
qemu_mallocz(smp_cpus * sizeof(qemu_irq) * 1);
|
||||
/* Connect the heathrow PIC outputs to the 6xx bus */
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
switch (PPC_INPUT(env)) {
|
||||
case PPC_FLAGS_INPUT_6xx:
|
||||
heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);
|
||||
heathrow_irqs[i][0] =
|
||||
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
|
||||
break;
|
||||
default:
|
||||
cpu_abort(env, "Bus model not supported on OldWorld Mac machine\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* init basic PC hardware */
|
||||
if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
|
||||
cpu_abort(env, "Only 6xx bus is supported on heathrow machine\n");
|
||||
exit(1);
|
||||
}
|
||||
pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
|
||||
pci_bus = pci_grackle_init(0xfec00000, pic);
|
||||
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
|
||||
ram_size, vga_ram_size,
|
||||
vga_bios_offset, vga_bios_size);
|
||||
|
||||
/* XXX: suppress that */
|
||||
dummy_irq = i8259_init(NULL);
|
||||
|
||||
/* XXX: use Mac Serial port */
|
||||
serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
|
||||
|
||||
for(i = 0; i < nb_nics; i++) {
|
||||
if (!nd_table[i].model)
|
||||
nd_table[i].model = "ne2k_pci";
|
||||
pci_nic_init(pci_bus, &nd_table[i], -1);
|
||||
}
|
||||
|
||||
pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
|
||||
|
||||
/* cuda also initialize ADB */
|
||||
cuda_init(&cuda_mem_index, pic[0x12]);
|
||||
|
||||
adb_kbd_init(&adb_bus);
|
||||
adb_mouse_init(&adb_bus);
|
||||
|
||||
nvr = macio_nvram_init(&nvram_mem_index);
|
||||
pmac_format_nvram_partition(nvr, 0x2000);
|
||||
|
||||
dbdma_init(&dbdma_mem_index);
|
||||
|
||||
macio_init(pci_bus, 0x0017, 1, pic_mem_index, dbdma_mem_index,
|
||||
cuda_mem_index, nvram_mem_index, 0, NULL);
|
||||
|
||||
if (usb_enabled) {
|
||||
usb_ohci_init_pci(pci_bus, 3, -1);
|
||||
}
|
||||
|
||||
if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
|
||||
graphic_depth = 15;
|
||||
|
||||
m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
|
||||
nvram.opaque = m48t59;
|
||||
nvram.read_fn = &m48t59_read;
|
||||
nvram.write_fn = &m48t59_write;
|
||||
PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "HEATHROW", ram_size, boot_device,
|
||||
kernel_base, kernel_size,
|
||||
kernel_cmdline,
|
||||
initrd_base, initrd_size,
|
||||
/* XXX: need an option to load a NVRAM image */
|
||||
0,
|
||||
graphic_width, graphic_height, graphic_depth);
|
||||
/* No PCI init: the BIOS will do it */
|
||||
|
||||
/* Special port to get debug messages from Open-Firmware */
|
||||
register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
|
||||
}
|
||||
|
||||
QEMUMachine heathrow_machine = {
|
||||
"g3bw",
|
||||
"Heathrow based PowerMAC",
|
||||
ppc_heathrow_init,
|
||||
};
|
|
@ -527,7 +527,8 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
|
|||
{
|
||||
CPUState *env, *envs[MAX_CPUS];
|
||||
char buf[1024];
|
||||
m48t59_t *nvram;
|
||||
nvram_t nvram;
|
||||
m48t59_t *m48t59;
|
||||
int PPC_io_memory;
|
||||
int linux_boot, i, nb_nics1, bios_size;
|
||||
unsigned long bios_offset;
|
||||
|
@ -678,13 +679,16 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
|
|||
usb_ohci_init_pci(pci_bus, 3, -1);
|
||||
}
|
||||
|
||||
nvram = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
|
||||
if (nvram == NULL)
|
||||
m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
|
||||
if (m48t59 == NULL)
|
||||
return;
|
||||
sysctrl->nvram = nvram;
|
||||
sysctrl->nvram = m48t59;
|
||||
|
||||
/* Initialise NVRAM */
|
||||
PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
|
||||
nvram.opaque = m48t59;
|
||||
nvram.read_fn = &m48t59_read;
|
||||
nvram.write_fn = &m48t59_write;
|
||||
PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
|
||||
kernel_base, kernel_size,
|
||||
kernel_cmdline,
|
||||
initrd_base, initrd_size,
|
||||
|
|
43
vl.h
43
vl.h
|
@ -859,12 +859,6 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
|
|||
/* prep_pci.c */
|
||||
PCIBus *pci_prep_init(qemu_irq *pic);
|
||||
|
||||
/* grackle_pci.c */
|
||||
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
|
||||
|
||||
/* unin_pci.c */
|
||||
PCIBus *pci_pmac_init(qemu_irq *pic);
|
||||
|
||||
/* apb_pci.c */
|
||||
PCIBus *pci_apb_init(target_phys_addr_t special_base, target_phys_addr_t mem_base,
|
||||
qemu_irq *pic);
|
||||
|
@ -892,9 +886,6 @@ enum {
|
|||
qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
|
||||
qemu_irq **irqs, qemu_irq irq_out);
|
||||
|
||||
/* heathrow_pic.c */
|
||||
qemu_irq *heathrow_pic_init(int *pmem_index);
|
||||
|
||||
/* gt64xxx.c */
|
||||
PCIBus *pci_gt64120_init(qemu_irq *pic);
|
||||
|
||||
|
@ -1004,7 +995,6 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
|
|||
qemu_irq *pic);
|
||||
void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
|
||||
qemu_irq *pic);
|
||||
int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq);
|
||||
|
||||
/* cdrom.c */
|
||||
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
|
||||
|
@ -1242,12 +1232,12 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq);
|
|||
void ppc40x_core_reset (CPUState *env);
|
||||
void ppc40x_chip_reset (CPUState *env);
|
||||
void ppc40x_system_reset (CPUState *env);
|
||||
#endif
|
||||
void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);
|
||||
|
||||
extern CPUWriteMemoryFunc *PPC_io_write[];
|
||||
extern CPUReadMemoryFunc *PPC_io_read[];
|
||||
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
|
||||
#endif
|
||||
|
||||
/* sun4m.c */
|
||||
extern QEMUMachine ss5_machine, ss10_machine;
|
||||
|
@ -1327,20 +1317,28 @@ void cs_init(target_phys_addr_t base, int irq, void *intctl);
|
|||
extern QEMUMachine sun4u_machine;
|
||||
|
||||
/* NVRAM helpers */
|
||||
typedef uint32_t (*nvram_read_t)(void *private, uint32_t addr);
|
||||
typedef void (*nvram_write_t)(void *private, uint32_t addr, uint32_t val);
|
||||
typedef struct nvram_t {
|
||||
void *opaque;
|
||||
nvram_read_t read_fn;
|
||||
nvram_write_t write_fn;
|
||||
} nvram_t;
|
||||
|
||||
#include "hw/m48t59.h"
|
||||
|
||||
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value);
|
||||
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr);
|
||||
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value);
|
||||
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr);
|
||||
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value);
|
||||
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr);
|
||||
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
|
||||
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value);
|
||||
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr);
|
||||
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value);
|
||||
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr);
|
||||
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value);
|
||||
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr);
|
||||
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
|
||||
const unsigned char *str, uint32_t max);
|
||||
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max);
|
||||
void NVRAM_set_crc (m48t59_t *nvram, uint32_t addr,
|
||||
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max);
|
||||
void NVRAM_set_crc (nvram_t *nvram, uint32_t addr,
|
||||
uint32_t start, uint32_t count);
|
||||
int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
|
||||
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
|
||||
const unsigned char *arch,
|
||||
uint32_t RAM_size, int boot_device,
|
||||
uint32_t kernel_image, uint32_t kernel_size,
|
||||
|
@ -1388,10 +1386,7 @@ ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
|
|||
void adb_kbd_init(ADBBusState *bus);
|
||||
void adb_mouse_init(ADBBusState *bus);
|
||||
|
||||
/* cuda.c */
|
||||
|
||||
extern ADBBusState adb_bus;
|
||||
int cuda_init(qemu_irq irq);
|
||||
|
||||
#include "hw/usb.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue