mirror of https://github.com/xemu-project/xemu.git
Fix basic Xbox machine init
This commit is contained in:
parent
68ff73b5b5
commit
8e24af7bda
604
hw/xbox/xbox.c
604
hw/xbox/xbox.c
|
@ -2,8 +2,9 @@
|
|||
* QEMU Xbox System Emulator
|
||||
*
|
||||
* Copyright (c) 2012 espes
|
||||
* Copyright (c) 2018 Matt Borgerson
|
||||
*
|
||||
* Based on pc.c
|
||||
* Based on pc.c and pc_piix.c
|
||||
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -20,64 +21,112 @@
|
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/smbios/smbios.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_ids.h"
|
||||
#include "hw/usb.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/ide.h"
|
||||
#include "hw/timer/mc146818rtc.h"
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "hw/audio/pcspk.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "hw/kvm/clock.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "hw/i2c/smbus.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/xen/xen.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "cpu.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#ifdef CONFIG_XEN
|
||||
#include <xen/hvm/hvm_info_table.h>
|
||||
#include "hw/xen/xen_pt.h"
|
||||
#endif
|
||||
#include "migration/global_state.h"
|
||||
#include "migration/misc.h"
|
||||
#include "kvm_i386.h"
|
||||
#include "sysemu/numa.h"
|
||||
|
||||
#include "hw/xbox/xbox_pci.h"
|
||||
#include "hw/xbox/nv2a.h"
|
||||
#include "hw/timer/mc146818rtc.h"
|
||||
#include "xbox_pci.h"
|
||||
#include "smbus.h"
|
||||
|
||||
#include "hw/xbox/xbox.h"
|
||||
#include "qemu/option.h"
|
||||
#include "xbox.h"
|
||||
|
||||
#include "net/net.h"
|
||||
#define MAX_IDE_BUS 2
|
||||
|
||||
/* mostly from pc_memory_init */
|
||||
static void xbox_memory_init(MemoryRegion *system_memory,
|
||||
ram_addr_t mem_size,
|
||||
MemoryRegion *rom_memory,
|
||||
MemoryRegion **ram_memory)
|
||||
static char *machine_get_bootrom(Object *obj, Error **errp);
|
||||
static void machine_set_bootrom(Object *obj, const char *value,
|
||||
Error **errp);
|
||||
static void machine_set_short_animation(Object *obj, bool value,
|
||||
Error **errp);
|
||||
static bool machine_get_short_animation(Object *obj, Error **errp);
|
||||
|
||||
// XBOX_TODO: Should be passed in through configuration
|
||||
/* bunnie's eeprom */
|
||||
const uint8_t default_eeprom[] = {
|
||||
0xe3, 0x1c, 0x5c, 0x23, 0x6a, 0x58, 0x68, 0x37,
|
||||
0xb7, 0x12, 0x26, 0x6c, 0x99, 0x11, 0x30, 0xd1,
|
||||
0xe2, 0x3e, 0x4d, 0x56, 0xf7, 0x73, 0x2b, 0x73,
|
||||
0x85, 0xfe, 0x7f, 0x0a, 0x08, 0xef, 0x15, 0x3c,
|
||||
0x77, 0xee, 0x6d, 0x4e, 0x93, 0x2f, 0x28, 0xee,
|
||||
0xf8, 0x61, 0xf7, 0x94, 0x17, 0x1f, 0xfc, 0x11,
|
||||
0x0b, 0x84, 0x44, 0xed, 0x31, 0x30, 0x35, 0x35,
|
||||
0x38, 0x31, 0x31, 0x31, 0x34, 0x30, 0x30, 0x33,
|
||||
0x00, 0x50, 0xf2, 0x4f, 0x65, 0x52, 0x00, 0x00,
|
||||
0x0a, 0x1e, 0x35, 0x33, 0x71, 0x85, 0x31, 0x4d,
|
||||
0x59, 0x12, 0x38, 0x48, 0x1c, 0x91, 0x53, 0x60,
|
||||
0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x75, 0x61, 0x57, 0xfb, 0x2c, 0x01, 0x00, 0x00,
|
||||
0x45, 0x53, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x05, 0x00, 0x02, 0x04, 0x01, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff, 0xff,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static void xbox_flash_init(MemoryRegion *rom_memory)
|
||||
{
|
||||
MemoryRegion *ram;
|
||||
|
||||
int ret;
|
||||
char *filename;
|
||||
int bios_size;
|
||||
int bootrom_size;
|
||||
|
||||
MemoryRegion *bios;
|
||||
|
||||
MemoryRegion *map_bios;
|
||||
|
||||
uint32_t map_loc;
|
||||
int rc, fd = -1;
|
||||
|
||||
/* Allocate RAM. We allocate it as a single memory region and use
|
||||
* aliases to address portions of it, mostly for backwards compatibility
|
||||
* with older qemus that used qemu_ram_alloc().
|
||||
*/
|
||||
ram = g_malloc(sizeof(*ram));
|
||||
memory_region_init_ram(ram, NULL, "xbox.ram", mem_size);
|
||||
vmstate_register_ram_global(ram);
|
||||
*ram_memory = ram;
|
||||
memory_region_add_subregion(system_memory, 0, ram);
|
||||
char *bios_data;
|
||||
|
||||
|
||||
/* Load the bios. (mostly from pc_sysfw)
|
||||
* Can't use it verbatim, since we need the bios repeated
|
||||
* over top 1MB of memory.
|
||||
*/
|
||||
/* Locate BIOS ROM image */
|
||||
if (bios_name == NULL) {
|
||||
bios_name = "bios.bin";
|
||||
}
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
if (filename) {
|
||||
bios_size = get_image_size(filename);
|
||||
|
@ -88,122 +137,266 @@ static void xbox_memory_init(MemoryRegion *system_memory,
|
|||
(bios_size % 65536) != 0) {
|
||||
goto bios_error;
|
||||
}
|
||||
bios = g_malloc(sizeof(*bios));
|
||||
memory_region_init_ram(bios, NULL, "xbox.bios", bios_size);
|
||||
vmstate_register_ram_global(bios);
|
||||
memory_region_set_readonly(bios, true);
|
||||
ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
|
||||
if (ret != 0) {
|
||||
bios_error:
|
||||
fprintf(stderr, "qemu: could not load xbox BIOS '%s'\n", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
if (filename) {
|
||||
|
||||
/* Read BIOS ROM into memory */
|
||||
bios_data = g_malloc(bios_size);
|
||||
assert(bios_data != NULL);
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
assert(fd >= 0);
|
||||
rc = read(fd, bios_data, bios_size);
|
||||
assert(rc == bios_size);
|
||||
close(fd);
|
||||
g_free(filename);
|
||||
|
||||
/* XBOX_FIXME: What follows is a big hack to overlay the MCPX ROM on the
|
||||
* top 512 bytes of the ROM region. This differs from original XQEMU
|
||||
* sources which copied it in at lpc init; new QEMU seems to be different
|
||||
* now in that the BIOS images supplied to rom_add_file_fixed will be
|
||||
* loaded *after* lpc init is called, so the MCPX ROM would get
|
||||
* overwritten. Instead, let's just map it in right here while we map in
|
||||
* BIOS.
|
||||
*
|
||||
* Anyway it behaves the same as before--that is, wrongly. Really, we
|
||||
* should let the CPU execute from MMIO emulating the TSOP access with
|
||||
* bootrom overlay being controlled by the magic bit..but this is "good
|
||||
* enough" for now ;).
|
||||
*/
|
||||
|
||||
/* Locate and overlay MCPX ROM image into new copy of BIOS if provided */
|
||||
const char *bootrom_file = object_property_get_str(qdev_get_machine(),
|
||||
"bootrom", NULL);
|
||||
|
||||
if ((bootrom_file != NULL) && *bootrom_file) {
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bootrom_file);
|
||||
assert(filename);
|
||||
|
||||
bootrom_size = get_image_size(filename);
|
||||
if (bootrom_size != 512) {
|
||||
fprintf(stderr, "MCPX bootrom should be 512 bytes, got %d\n",
|
||||
bootrom_size);
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read in MCPX ROM over last 512 bytes of BIOS data */
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
assert(fd >= 0);
|
||||
rc = read(fd, &bios_data[bios_size - bootrom_size], bootrom_size);
|
||||
assert(rc == bootrom_size);
|
||||
close(fd);
|
||||
g_free(filename);
|
||||
}
|
||||
|
||||
/* Create BIOS region */
|
||||
bios = g_malloc(sizeof(*bios));
|
||||
assert(bios != NULL);
|
||||
memory_region_init_ram(bios, NULL, "xbox.bios", bios_size, &error_fatal);
|
||||
memory_region_set_readonly(bios, true);
|
||||
rom_add_blob_fixed("xbox.bios", bios_data, bios_size,
|
||||
(uint32_t)(-2 * bios_size));
|
||||
|
||||
/* map the bios repeated at the top of memory */
|
||||
for (map_loc=(uint32_t)(-bios_size); map_loc >= 0xff000000; map_loc-=bios_size) {
|
||||
/* Assuming bios_data will be needed for duration of execution
|
||||
* so no free(bios) here.
|
||||
*/
|
||||
|
||||
/* Mirror ROM from 0xff000000 - 0xffffffff */
|
||||
for (map_loc = (uint32_t)(-bios_size);
|
||||
map_loc >= 0xff000000;
|
||||
map_loc -= bios_size) {
|
||||
map_bios = g_malloc(sizeof(*map_bios));
|
||||
memory_region_init_alias(map_bios, NULL, NULL, bios, 0, bios_size);
|
||||
|
||||
memory_region_init_alias(map_bios, NULL, "pci-bios", bios, 0, bios_size);
|
||||
memory_region_add_subregion(rom_memory, map_loc, map_bios);
|
||||
memory_region_set_readonly(map_bios, true);
|
||||
}
|
||||
|
||||
/*memory_region_add_subregion(rom_memory,
|
||||
(uint32_t)(-bios_size),
|
||||
bios);
|
||||
*/
|
||||
return;
|
||||
|
||||
bios_error:
|
||||
fprintf(stderr, "qemu: could not load xbox BIOS '%s'\n", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* mostly from pc_init1 */
|
||||
void xbox_init_common(QEMUMachineInitArgs *args,
|
||||
const uint8_t *default_eeprom,
|
||||
ISABus **out_isa_bus)
|
||||
static void xbox_memory_init(PCMachineState *pcms,
|
||||
MemoryRegion *system_memory,
|
||||
MemoryRegion *rom_memory,
|
||||
MemoryRegion **ram_memory)
|
||||
{
|
||||
int i;
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
// int linux_boot, i;
|
||||
MemoryRegion *ram;//, *option_rom_mr;
|
||||
// FWCfgState *fw_cfg;
|
||||
MachineState *machine = MACHINE(pcms);
|
||||
// PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
||||
|
||||
PCIBus *host_bus;
|
||||
// linux_boot = (machine->kernel_filename != NULL);
|
||||
|
||||
/* Allocate RAM. We allocate it as a single memory region and use
|
||||
* aliases to address portions of it, mostly for backwards compatibility
|
||||
* with older qemus that used qemu_ram_alloc().
|
||||
*/
|
||||
ram = g_malloc(sizeof(*ram));
|
||||
memory_region_init_ram(ram, NULL, "xbox.ram",
|
||||
machine->ram_size, &error_fatal);
|
||||
|
||||
*ram_memory = ram;
|
||||
memory_region_add_subregion(system_memory, 0, ram);
|
||||
|
||||
xbox_flash_init(rom_memory);
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Move to header file */
|
||||
void nv2a_init(PCIBus *bus, int devfn, MemoryRegion *ram);
|
||||
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "hw/audio/pcspk.h"
|
||||
|
||||
/* PC hardware initialisation */
|
||||
static void xbox_init(MachineState *machine)
|
||||
{
|
||||
xbox_init_common(machine, default_eeprom, NULL, NULL);
|
||||
}
|
||||
|
||||
void xbox_init_common(MachineState *machine,
|
||||
const uint8_t *eeprom,
|
||||
PCIBus **pci_bus_out,
|
||||
ISABus **isa_bus_out)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(machine);
|
||||
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
||||
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
// MemoryRegion *system_io = get_system_io();
|
||||
|
||||
int i;
|
||||
|
||||
PCIBus *pci_bus;
|
||||
ISABus *isa_bus;
|
||||
|
||||
qemu_irq *i8259;
|
||||
// qemu_irq smi_irq; // XBOX_TODO: SMM support?
|
||||
|
||||
GSIState *gsi_state;
|
||||
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
BusState *idebus[MAX_IDE_BUS];
|
||||
ISADevice *rtc_state;
|
||||
// ISADevice *pit;
|
||||
|
||||
MemoryRegion *ram_memory;
|
||||
MemoryRegion *pci_memory;
|
||||
MemoryRegion *rom_memory;
|
||||
|
||||
qemu_irq *cpu_irq;
|
||||
qemu_irq *gsi;
|
||||
qemu_irq *i8259;
|
||||
GSIState *gsi_state;
|
||||
|
||||
PCIDevice *ide_dev;
|
||||
BusState *idebus[MAX_IDE_BUS];
|
||||
|
||||
ISADevice *rtc_state;
|
||||
ISADevice *pit;
|
||||
i2c_bus *smbus;
|
||||
I2CBus *smbus;
|
||||
PCIBus *agp_bus;
|
||||
|
||||
pc_cpus_init(pcms);
|
||||
|
||||
DeviceState *icc_bridge;
|
||||
icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
|
||||
object_property_add_child(qdev_get_machine(), "icc-bridge",
|
||||
OBJECT(icc_bridge), NULL);
|
||||
|
||||
pc_cpus_init(cpu_model, icc_bridge);
|
||||
if (kvm_enabled() && pcmc->kvmclock_enabled) {
|
||||
kvmclock_create();
|
||||
}
|
||||
|
||||
pci_memory = g_new(MemoryRegion, 1);
|
||||
memory_region_init(pci_memory, NULL, "pci", INT64_MAX);
|
||||
memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
|
||||
rom_memory = pci_memory;
|
||||
|
||||
pc_guest_info_init(pcms);
|
||||
|
||||
/* allocate ram and load rom/bios */
|
||||
xbox_memory_init(get_system_memory(), ram_size,
|
||||
pci_memory, &ram_memory);
|
||||
|
||||
xbox_memory_init(pcms, system_memory, rom_memory, &ram_memory);
|
||||
|
||||
gsi_state = g_malloc0(sizeof(*gsi_state));
|
||||
gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
|
||||
pcms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
|
||||
|
||||
|
||||
/* init buses */
|
||||
xbox_pci_init(gsi,
|
||||
xbox_pci_init(pcms->gsi,
|
||||
get_system_memory(), get_system_io(),
|
||||
pci_memory, ram_memory,
|
||||
&host_bus,
|
||||
&pci_bus,
|
||||
&isa_bus,
|
||||
&smbus,
|
||||
&agp_bus);
|
||||
|
||||
pcms->bus = pci_bus;
|
||||
|
||||
/* irq shit */
|
||||
isa_bus_irqs(isa_bus, gsi);
|
||||
cpu_irq = pc_allocate_cpu_irq();
|
||||
i8259 = i8259_init(isa_bus, cpu_irq[0]);
|
||||
isa_bus_irqs(isa_bus, pcms->gsi);
|
||||
|
||||
// if (kvm_pic_in_kernel()) {
|
||||
// i8259 = kvm_i8259_init(isa_bus);
|
||||
// } else if (xen_enabled()) {
|
||||
// i8259 = xen_interrupt_controller_init();
|
||||
// } else {
|
||||
i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq());
|
||||
// }
|
||||
|
||||
for (i = 0; i < ISA_NUM_IRQS; i++) {
|
||||
gsi_state->i8259_irq[i] = i8259[i];
|
||||
}
|
||||
g_free(i8259);
|
||||
|
||||
// if (pcmc->pci_enabled) {
|
||||
// ioapic_init_gsi(gsi_state, "i440fx");
|
||||
// }
|
||||
|
||||
/* basic device init */
|
||||
rtc_state = rtc_init(isa_bus, 2000, NULL);
|
||||
pit = pit_init(isa_bus, 0x40, 0, NULL);
|
||||
pc_register_ferr_irq(pcms->gsi[13]);
|
||||
|
||||
/* does apparently have a pc speaker, though not used? */
|
||||
// pc_vga_init(isa_bus, pcmc->pci_enabled ? pci_bus : NULL);
|
||||
|
||||
assert(pcms->vmport != ON_OFF_AUTO__MAX);
|
||||
if (pcms->vmport == ON_OFF_AUTO_AUTO) {
|
||||
pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
|
||||
}
|
||||
|
||||
/* init basic PC hardware */
|
||||
pcms->pit = 1; // XBOX_FIXME: What's the right way to do this?
|
||||
// pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, true,
|
||||
// (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit, 0x4);
|
||||
rtc_state = mc146818_rtc_init(isa_bus, 2000, NULL);
|
||||
|
||||
// qemu_register_boot_set(pc_boot_set, rtc_state);
|
||||
ISADevice *pit = NULL;
|
||||
|
||||
if (kvm_pit_in_kernel()) {
|
||||
pit = kvm_pit_init(isa_bus, 0x40);
|
||||
} else {
|
||||
pit = i8254_pit_init(isa_bus, 0x40, 0, NULL);
|
||||
}
|
||||
// if (hpet) {
|
||||
// /* connect PIT to output control line of the HPET */
|
||||
// qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(DEVICE(pit), 0));
|
||||
// }
|
||||
pcspk_init(isa_bus, pit);
|
||||
|
||||
/* IDE shit
|
||||
* piix3's ide be right for now, maybe
|
||||
*/
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_dev = pci_piix3_ide_init(host_bus, hd, PCI_DEVFN(9, 0));
|
||||
// i8257_dma_init(isa_bus, 0);
|
||||
|
||||
// pc_nic_init(pcmc, isa_bus, pci_bus);
|
||||
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
// if (pcmc->pci_enabled) {
|
||||
PCIDevice *dev;
|
||||
// if (xen_enabled()) {
|
||||
// dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
|
||||
// } else {
|
||||
dev = pci_piix3_ide_init(pci_bus, hd, PCI_DEVFN(9, 0));
|
||||
// }
|
||||
idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
|
||||
idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
|
||||
// } else {
|
||||
// for(i = 0; i < MAX_IDE_BUS; i++) {
|
||||
// ISADevice *dev;
|
||||
// char busname[] = "ide.0";
|
||||
// dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
|
||||
// ide_irq[i],
|
||||
// hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
|
||||
// /*
|
||||
// * The ide bus name is ide.0 for the first bus and ide.1 for the
|
||||
// * second one.
|
||||
// */
|
||||
// busname[4] = '0' + i;
|
||||
// idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
|
||||
// }
|
||||
// }
|
||||
|
||||
pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
|
||||
|
||||
idebus[0] = qdev_get_child_bus(&ide_dev->qdev, "ide.0");
|
||||
idebus[1] = qdev_get_child_bus(&ide_dev->qdev, "ide.1");
|
||||
|
||||
// xbox bios wants this bit pattern set to mark the data as valid
|
||||
uint8_t bits = 0x55;
|
||||
for (i = 0x10; i < 0x70; i++) {
|
||||
|
@ -218,25 +411,24 @@ void xbox_init_common(QEMUMachineInitArgs *args,
|
|||
|
||||
/* smbus devices */
|
||||
uint8_t *eeprom_buf = g_malloc0(256);
|
||||
memcpy(eeprom_buf, default_eeprom, 256);
|
||||
memcpy(eeprom_buf, eeprom, 256);
|
||||
smbus_eeprom_init_single(smbus, 0x54, eeprom_buf);
|
||||
|
||||
|
||||
smbus_xbox_smc_init(smbus, 0x10);
|
||||
smbus_cx25871_init(smbus, 0x45);
|
||||
smbus_adm1032_init(smbus, 0x4c);
|
||||
|
||||
|
||||
/* USB */
|
||||
PCIDevice *usb1 = pci_create(host_bus, PCI_DEVFN(3, 0), "pci-ohci");
|
||||
PCIDevice *usb1 = pci_create(pci_bus, PCI_DEVFN(3, 0), "pci-ohci");
|
||||
qdev_prop_set_uint32(&usb1->qdev, "num-ports", 4);
|
||||
qdev_init_nofail(&usb1->qdev);
|
||||
|
||||
PCIDevice *usb0 = pci_create(host_bus, PCI_DEVFN(2, 0), "pci-ohci");
|
||||
PCIDevice *usb0 = pci_create(pci_bus, PCI_DEVFN(2, 0), "pci-ohci");
|
||||
qdev_prop_set_uint32(&usb0->qdev, "num-ports", 4);
|
||||
qdev_init_nofail(&usb0->qdev);
|
||||
|
||||
/* Ethernet! */
|
||||
PCIDevice *nvnet = pci_create(host_bus, PCI_DEVFN(4, 0), "nvnet");
|
||||
PCIDevice *nvnet = pci_create(pci_bus, PCI_DEVFN(4, 0), "nvnet");
|
||||
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
NICInfo *nd = &nd_table[i];
|
||||
|
@ -246,113 +438,115 @@ void xbox_init_common(QEMUMachineInitArgs *args,
|
|||
}
|
||||
|
||||
/* APU! */
|
||||
PCIDevice *apu = pci_create_simple(host_bus, PCI_DEVFN(5, 0), "mcpx-apu");
|
||||
pci_create_simple(pci_bus, PCI_DEVFN(5, 0), "mcpx-apu");
|
||||
|
||||
/* ACI! */
|
||||
PCIDevice *aci = pci_create_simple(host_bus, PCI_DEVFN(6, 0), "mcpx-aci");
|
||||
pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "mcpx-aci");
|
||||
|
||||
/* GPU! */
|
||||
nv2a_init(agp_bus, PCI_DEVFN(0, 0), ram_memory);
|
||||
|
||||
*out_isa_bus = isa_bus;
|
||||
if (pci_bus_out) {
|
||||
*pci_bus_out = pci_bus;
|
||||
}
|
||||
if (isa_bus_out) {
|
||||
*isa_bus_out = isa_bus;
|
||||
}
|
||||
}
|
||||
|
||||
static void xbox_init(QEMUMachineInitArgs *args)
|
||||
static void xbox_machine_options(MachineClass *m)
|
||||
{
|
||||
#if 0
|
||||
/* Placeholder blank eeprom for xbox 1.0:
|
||||
* Serial number 000000000000
|
||||
* Mac address 00:00:00:00:00:00
|
||||
* ...etc.
|
||||
*/
|
||||
const uint8_t eeprom[] = {
|
||||
0x25, 0x42, 0x88, 0x24, 0xA3, 0x1A, 0x7D, 0xF4,
|
||||
0xEE, 0x53, 0x3F, 0x39, 0x5D, 0x27, 0x98, 0x0E,
|
||||
0x58, 0xB3, 0x26, 0xC3, 0x70, 0x82, 0xE5, 0xC6,
|
||||
0xF7, 0xC5, 0x54, 0x38, 0xA0, 0x58, 0xB9, 0x5D,
|
||||
0xB7, 0x27, 0xC7, 0xB1, 0x67, 0xCF, 0x99, 0x3E,
|
||||
0xC8, 0x6E, 0xC8, 0x53, 0xEF, 0x7C, 0x01, 0x37,
|
||||
0x6F, 0x6E, 0x2F, 0x6F, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
#endif
|
||||
/* bunnie's eeprom */
|
||||
const uint8_t eeprom[] = {
|
||||
0xe3, 0x1c, 0x5c, 0x23, 0x6a, 0x58, 0x68, 0x37,
|
||||
0xb7, 0x12, 0x26, 0x6c, 0x99, 0x11, 0x30, 0xd1,
|
||||
0xe2, 0x3e, 0x4d, 0x56, 0xf7, 0x73, 0x2b, 0x73,
|
||||
0x85, 0xfe, 0x7f, 0x0a, 0x08, 0xef, 0x15, 0x3c,
|
||||
0x77, 0xee, 0x6d, 0x4e, 0x93, 0x2f, 0x28, 0xee,
|
||||
0xf8, 0x61, 0xf7, 0x94, 0x17, 0x1f, 0xfc, 0x11,
|
||||
0x0b, 0x84, 0x44, 0xed, 0x31, 0x30, 0x35, 0x35,
|
||||
0x38, 0x31, 0x31, 0x31, 0x34, 0x30, 0x30, 0x33,
|
||||
0x00, 0x50, 0xf2, 0x4f, 0x65, 0x52, 0x00, 0x00,
|
||||
0x0a, 0x1e, 0x35, 0x33, 0x71, 0x85, 0x31, 0x4d,
|
||||
0x59, 0x12, 0x38, 0x48, 0x1c, 0x91, 0x53, 0x60,
|
||||
0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x75, 0x61, 0x57, 0xfb, 0x2c, 0x01, 0x00, 0x00,
|
||||
0x45, 0x53, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x05, 0x00, 0x02, 0x04, 0x01, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff, 0xff,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
m->desc = "Microsoft Xbox";
|
||||
m->max_cpus = 1;
|
||||
m->option_rom_has_mr = true;
|
||||
m->rom_file_has_mr = false;
|
||||
m->no_floppy = 1,
|
||||
m->no_cdrom = 1,
|
||||
m->no_sdcard = 1,
|
||||
m->default_cpu_type = X86_CPU_TYPE_NAME("486");
|
||||
|
||||
ISABus *isa_bus;
|
||||
xbox_init_common(args, eeprom, &isa_bus);
|
||||
pcmc->pci_enabled = true;
|
||||
pcmc->has_acpi_build = false;
|
||||
pcmc->smbios_defaults = false;
|
||||
pcmc->gigabyte_align = false;
|
||||
pcmc->smbios_legacy_mode = true;
|
||||
pcmc->has_reserved_memory = false;
|
||||
pcmc->default_nic_model = "nvnet";
|
||||
}
|
||||
|
||||
static QEMUMachine xbox_machine = {
|
||||
.name = "xbox",
|
||||
.desc = "Microsoft Xbox",
|
||||
.init = xbox_init,
|
||||
.max_cpus = 1,
|
||||
.no_floppy = 1,
|
||||
.no_cdrom = 1,
|
||||
.no_sdcard = 1,
|
||||
PC_DEFAULT_MACHINE_OPTIONS
|
||||
static char *machine_get_bootrom(Object *obj, Error **errp)
|
||||
{
|
||||
XboxMachineState *ms = XBOX_MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->bootrom);
|
||||
}
|
||||
|
||||
static void machine_set_bootrom(Object *obj, const char *value,
|
||||
Error **errp)
|
||||
{
|
||||
XboxMachineState *ms = XBOX_MACHINE(obj);
|
||||
|
||||
g_free(ms->bootrom);
|
||||
ms->bootrom = g_strdup(value);
|
||||
}
|
||||
|
||||
static void machine_set_short_animation(Object *obj, bool value,
|
||||
Error **errp)
|
||||
{
|
||||
XboxMachineState *ms = XBOX_MACHINE(obj);
|
||||
|
||||
ms->short_animation = value;
|
||||
}
|
||||
|
||||
static bool machine_get_short_animation(Object *obj, Error **errp)
|
||||
{
|
||||
XboxMachineState *ms = XBOX_MACHINE(obj);
|
||||
return ms->short_animation;
|
||||
}
|
||||
|
||||
static inline void xbox_machine_initfn(Object *obj)
|
||||
{
|
||||
object_property_add_str(obj, "bootrom", machine_get_bootrom,
|
||||
machine_set_bootrom, NULL);
|
||||
object_property_set_description(obj, "bootrom",
|
||||
"Xbox bootrom file", NULL);
|
||||
|
||||
object_property_add_bool(obj, "short-animation",
|
||||
machine_get_short_animation,
|
||||
machine_set_short_animation, NULL);
|
||||
object_property_set_description(obj, "short-animation",
|
||||
"Skip Xbox boot animation",
|
||||
NULL);
|
||||
object_property_set_bool(obj, false, "short-animation", NULL);
|
||||
|
||||
}
|
||||
|
||||
static void xbox_machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
xbox_machine_options(mc);
|
||||
mc->init = xbox_init;
|
||||
}
|
||||
|
||||
static const TypeInfo pc_machine_type_xbox = {
|
||||
.name = TYPE_XBOX_MACHINE,
|
||||
.parent = TYPE_PC_MACHINE,
|
||||
.abstract = false,
|
||||
.instance_size = sizeof(XboxMachineState),
|
||||
.instance_init = xbox_machine_initfn,
|
||||
.class_size = sizeof(XboxMachineClass),
|
||||
.class_init = xbox_machine_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
// { TYPE_HOTPLUG_HANDLER },
|
||||
// { TYPE_NMI },
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static void xbox_machine_init(void) {
|
||||
qemu_register_machine(&xbox_machine);
|
||||
static void pc_machine_init_xbox(void)
|
||||
{
|
||||
type_register(&pc_machine_type_xbox);
|
||||
}
|
||||
|
||||
machine_init(xbox_machine_init);
|
||||
type_init(pc_machine_init_xbox)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* QEMU Xbox System Emulator
|
||||
*
|
||||
* Copyright (c) 2013 espes
|
||||
* Copyright (c) 2018 Matt Borgerson
|
||||
*
|
||||
* Based on pc.c
|
||||
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||
|
@ -23,10 +24,37 @@
|
|||
#ifndef HW_XBOX_H
|
||||
#define HW_XBOX_H
|
||||
|
||||
#include "hw/boards.h"
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
|
||||
void xbox_init_common(QEMUMachineInitArgs *args,
|
||||
const uint8_t *default_eeprom,
|
||||
ISABus **out_isa_bus);
|
||||
void xbox_init_common(MachineState *machine,
|
||||
const uint8_t *eeprom,
|
||||
PCIBus **pci_bus_out,
|
||||
ISABus **isa_bus_out);
|
||||
|
||||
#endif
|
||||
#define TYPE_XBOX_MACHINE MACHINE_TYPE_NAME("xbox")
|
||||
|
||||
#define XBOX_MACHINE(obj) \
|
||||
OBJECT_CHECK(XboxMachineState, (obj), TYPE_XBOX_MACHINE)
|
||||
|
||||
#define XBOX_MACHINE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(XboxMachineClass, (klass), TYPE_XBOX_MACHINE)
|
||||
|
||||
typedef struct XboxMachineState {
|
||||
/*< private >*/
|
||||
PCMachineState parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
char *bootrom;
|
||||
bool short_animation;
|
||||
} XboxMachineState;
|
||||
|
||||
typedef struct XboxMachineClass {
|
||||
/*< private >*/
|
||||
PCMachineClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
} XboxMachineClass;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* QEMU Xbox PCI buses implementation
|
||||
*
|
||||
* Copyright (c) 2012 espes
|
||||
* Copyright (c) 2018 Matt Borgerson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
|
@ -16,28 +17,36 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/range.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/loader.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/range.h"
|
||||
#include "hw/xen/xen.h"
|
||||
#include "hw/pci-host/pam.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/loader.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
#include "qemu/option.h"
|
||||
#include "hw/xbox/acpi_xbox.h"
|
||||
#include "hw/xbox/amd_smbus.h"
|
||||
|
||||
#include "hw/xbox/xbox_pci.h"
|
||||
|
||||
|
||||
/*
|
||||
* xbox chipset based on nForce 420, which was based on AMD-760
|
||||
*
|
||||
*
|
||||
* http://support.amd.com/us/ChipsetMotherboard_TechDocs/24494.pdf
|
||||
* http://support.amd.com/us/ChipsetMotherboard_TechDocs/24416.pdf
|
||||
* http://support.amd.com/us/ChipsetMotherboard_TechDocs/24467.pdf
|
||||
|
@ -57,8 +66,6 @@
|
|||
# define XBOXPCI_DPRINTF(format, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define XBOX_NUM_INT_IRQS 8
|
||||
#define XBOX_NUM_PIRQS 4
|
||||
|
||||
|
@ -80,7 +87,7 @@ static void xbox_lpc_set_irq(void *opaque, int pirq, int level)
|
|||
if (pirq < XBOX_NUM_INT_IRQS) {
|
||||
/* devices on the internal bus */
|
||||
uint32_t routing = pci_get_long(lpc->dev.config + XBOX_LPC_INT_IRQ_ROUT);
|
||||
pic_irq = (routing >> (pirq*4)) & 0xF;
|
||||
pic_irq = (routing >> (pirq * 4)) & 0xF;
|
||||
|
||||
if (pic_irq == 0) {
|
||||
return;
|
||||
|
@ -124,7 +131,7 @@ static void xbox_lpc_set_acpi_irq(void *opaque, int irq_num, int level)
|
|||
assert(irq_num == 0 || irq_num == 1);
|
||||
|
||||
uint32_t routing = pci_get_long(lpc->dev.config + XBOX_LPC_ACPI_IRQ_ROUT);
|
||||
int irq = (routing >> (irq_num*8)) & 0xff;
|
||||
int irq = (routing >> (irq_num * 8)) & 0xff;
|
||||
|
||||
if (irq == 0 || irq >= XBOX_NUM_PIC_IRQS) {
|
||||
return;
|
||||
|
@ -132,8 +139,6 @@ static void xbox_lpc_set_acpi_irq(void *opaque, int irq_num, int level)
|
|||
qemu_set_irq(lpc->pic[irq], level);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void xbox_pci_init(qemu_irq *pic,
|
||||
MemoryRegion *address_space_mem,
|
||||
MemoryRegion *address_space_io,
|
||||
|
@ -141,7 +146,7 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
MemoryRegion *ram_memory,
|
||||
PCIBus **out_host_bus,
|
||||
ISABus **out_isa_bus,
|
||||
i2c_bus **out_smbus,
|
||||
I2CBus **out_smbus,
|
||||
PCIBus **out_agp_bus)
|
||||
{
|
||||
DeviceState *host;
|
||||
|
@ -154,7 +159,7 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
host = qdev_create(NULL, "xbox-pcihost");
|
||||
host_state = PCI_HOST_BRIDGE(host);
|
||||
|
||||
host_bus = pci_bus_new(host, NULL,
|
||||
host_bus = pci_root_bus_new(host, NULL,
|
||||
pci_memory, address_space_io, 0, TYPE_PCI_BUS);
|
||||
host_state->bus = host_bus;
|
||||
qdev_init_nofail(host);
|
||||
|
@ -172,7 +177,7 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
"pci-hole",
|
||||
bridge_state->pci_address_space,
|
||||
ram_size,
|
||||
0x100000000ULL - ram_size);
|
||||
0x100000000ULL - ram_size);
|
||||
memory_region_add_subregion(bridge_state->system_memory, ram_size,
|
||||
&bridge_state->pci_hole);
|
||||
|
||||
|
@ -191,9 +196,9 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
xbox_pm_init(lpc, &lpc_state->pm, acpi_irq[0]);
|
||||
//xbox_lpc_reset(&s->dev.qdev);
|
||||
|
||||
|
||||
/* smbus */
|
||||
PCIDevice *smbus = pci_create_simple_multifunction(host_bus, PCI_DEVFN(1, 1),
|
||||
PCIDevice *smbus = pci_create_simple_multifunction(host_bus,
|
||||
PCI_DEVFN(1, 1),
|
||||
true, "xbox-smbus");
|
||||
|
||||
XBOX_SMBState *smbus_state = XBOX_SMBUS_DEVICE(smbus);
|
||||
|
@ -206,15 +211,12 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
//qdev_init_nofail(qdev);
|
||||
PCIBus *agp_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(agp));
|
||||
|
||||
|
||||
|
||||
*out_host_bus = host_bus;
|
||||
*out_isa_bus = lpc_state->isa_bus;
|
||||
*out_smbus = smbus_state->smb.smbus;
|
||||
*out_agp_bus = agp_bus;
|
||||
}
|
||||
|
||||
|
||||
#define XBOX_SMBUS_BASE_BAR 1
|
||||
|
||||
static void xbox_smb_ioport_writeb(void *opaque, hwaddr addr,
|
||||
|
@ -245,7 +247,7 @@ static const MemoryRegionOps xbox_smbus_ops = {
|
|||
},
|
||||
};
|
||||
|
||||
static int xbox_smbus_initfn(PCIDevice *dev)
|
||||
static void xbox_smbus_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
XBOX_SMBState *s = XBOX_SMBUS_DEVICE(dev);
|
||||
|
||||
|
@ -253,24 +255,21 @@ static int xbox_smbus_initfn(PCIDevice *dev)
|
|||
s, "xbox-smbus-bar", 32);
|
||||
pci_register_bar(dev, XBOX_SMBUS_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
|
||||
&s->smb_bar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void xbox_smbus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = xbox_smbus_initfn;
|
||||
k->realize = xbox_smbus_realize;
|
||||
k->vendor_id = PCI_VENDOR_ID_NVIDIA;
|
||||
k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS;
|
||||
k->revision = 161;
|
||||
k->class_id = PCI_CLASS_SERIAL_SMBUS;
|
||||
|
||||
dc->desc = "nForce PCI System Management";
|
||||
dc->no_user = 1;
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo xbox_smbus_info = {
|
||||
|
@ -278,84 +277,31 @@ static const TypeInfo xbox_smbus_info = {
|
|||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(XBOX_SMBState),
|
||||
.class_init = xbox_smbus_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int xbox_lpc_initfn(PCIDevice *d)
|
||||
static void xbox_lpc_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
XBOX_LPCState *s = XBOX_LPC_DEVICE(d);
|
||||
XBOX_LPCState *d = XBOX_LPC_DEVICE(dev);
|
||||
ISABus *isa_bus;
|
||||
|
||||
isa_bus = isa_bus_new(&d->qdev, get_system_io());
|
||||
s->isa_bus = isa_bus;
|
||||
|
||||
|
||||
/* southbridge chip contains and controls bootrom image.
|
||||
* can't load it through loader.c because it overlaps with the bios...
|
||||
* We really should just commandeer the entire top 16Mb.
|
||||
*/
|
||||
QemuOpts *machine_opts = qemu_opts_find(qemu_find_opts("machine"), NULL);
|
||||
if (machine_opts) {
|
||||
const char *bootrom_file = qemu_opt_get(machine_opts, "bootrom");
|
||||
|
||||
int rc, fd = -1;
|
||||
if (bootrom_file) {
|
||||
char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bootrom_file);
|
||||
assert(filename);
|
||||
|
||||
s->bootrom_size = get_image_size(filename);
|
||||
if (s->bootrom_size != 512) {
|
||||
fprintf(stderr, "MCPX bootrom should be 512 bytes, got %d\n",
|
||||
s->bootrom_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
assert(fd >= 0);
|
||||
rc = read(fd, s->bootrom_data, s->bootrom_size);
|
||||
assert(rc == s->bootrom_size);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
isa_bus = isa_bus_new(DEVICE(d), get_system_memory(),
|
||||
pci_address_space_io(dev), errp);
|
||||
if (isa_bus == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
d->isa_bus = isa_bus;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void xbox_lpc_reset(DeviceState *dev)
|
||||
{
|
||||
PCIDevice *d = PCI_DEVICE(dev);
|
||||
XBOX_LPCState *s = XBOX_LPC_DEVICE(d);
|
||||
|
||||
|
||||
if (s->bootrom_size) {
|
||||
/* qemu's memory region shit is actually kinda broken -
|
||||
* Trying to execute off a non-page-aligned memory region
|
||||
* is fucked, so we can't just map in the bootrom.
|
||||
*
|
||||
* We need to be able to disable it at runtime, and
|
||||
* it shouldn't be visible ontop of the bios mirrors. It'll have to
|
||||
* be a hack.
|
||||
*
|
||||
* Be lazy for now and just write it ontop of the bios.
|
||||
*
|
||||
* (We do this here since loader.c loads roms into memory in a reset
|
||||
* handler, and here we /should/ be handled after it.)
|
||||
*/
|
||||
|
||||
hwaddr bootrom_addr = (uint32_t)(-s->bootrom_size);
|
||||
cpu_physical_memory_write_rom(bootrom_addr,
|
||||
s->bootrom_data,
|
||||
s->bootrom_size);
|
||||
}
|
||||
|
||||
// PCIDevice *d = PCI_DEVICE(dev);
|
||||
// XBOX_LPCState *s = XBOX_LPC_DEVICE(d);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Xbox 1.1 uses a config register instead of a bar to set the pm base address */
|
||||
#define XBOX_LPC_PMBASE 0x84
|
||||
|
@ -409,8 +355,8 @@ static void xbox_lpc_class_init(ObjectClass *klass, void *data)
|
|||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->no_hotplug = 1;
|
||||
k->init = xbox_lpc_initfn;
|
||||
dc->hotpluggable = false;
|
||||
k->realize = xbox_lpc_realize;
|
||||
//k->config_write = xbox_lpc_config_write;
|
||||
k->vendor_id = PCI_VENDOR_ID_NVIDIA;
|
||||
k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_LPC;
|
||||
|
@ -418,7 +364,7 @@ static void xbox_lpc_class_init(ObjectClass *klass, void *data)
|
|||
k->class_id = PCI_CLASS_BRIDGE_ISA;
|
||||
|
||||
dc->desc = "nForce LPC Bridge";
|
||||
dc->no_user = 1;
|
||||
dc->user_creatable = false;
|
||||
dc->reset = xbox_lpc_reset;
|
||||
//dc->vmsd = &vmstate_xbox_lpc;
|
||||
}
|
||||
|
@ -428,16 +374,17 @@ static const TypeInfo xbox_lpc_info = {
|
|||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(XBOX_LPCState),
|
||||
.class_init = xbox_lpc_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static int xbox_agp_initfn(PCIDevice *d)
|
||||
static void xbox_agp_realize(PCIDevice *d, Error **errp)
|
||||
{
|
||||
pci_set_word(d->config + PCI_PREF_MEMORY_BASE, PCI_PREF_RANGE_TYPE_32);
|
||||
pci_set_word(d->config + PCI_PREF_MEMORY_LIMIT, PCI_PREF_RANGE_TYPE_32);
|
||||
return pci_bridge_initfn(d, TYPE_PCI_BUS);
|
||||
pci_bridge_initfn(d, TYPE_PCI_BUS);
|
||||
}
|
||||
|
||||
static void xbox_agp_class_init(ObjectClass *klass, void *data)
|
||||
|
@ -445,7 +392,7 @@ static void xbox_agp_class_init(ObjectClass *klass, void *data)
|
|||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = xbox_agp_initfn;
|
||||
k->realize = xbox_agp_realize;
|
||||
k->exit = pci_bridge_exitfn;
|
||||
k->config_write = pci_bridge_write_config;
|
||||
k->is_bridge = 1;
|
||||
|
@ -462,18 +409,15 @@ static const TypeInfo xbox_agp_info = {
|
|||
.parent = TYPE_PCI_BRIDGE,
|
||||
.instance_size = sizeof(PCIBridge),
|
||||
.class_init = xbox_agp_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int xbox_pci_initfn(PCIDevice *d)
|
||||
static void xbox_pci_realize(PCIDevice *d, Error **errp)
|
||||
{
|
||||
//XBOX_PCIState *s = DO_UPCAST(XBOX_PCIState, dev, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xbox_pci_class_init(ObjectClass *klass, void *data)
|
||||
|
@ -481,8 +425,8 @@ static void xbox_pci_class_init(ObjectClass *klass, void *data)
|
|||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->no_hotplug = 1;
|
||||
k->init = xbox_pci_initfn;
|
||||
dc->hotpluggable = false;
|
||||
k->realize = xbox_pci_realize;
|
||||
//k->config_write = xbox_pci_write_config;
|
||||
k->vendor_id = PCI_VENDOR_ID_NVIDIA;
|
||||
k->device_id = PCI_DEVICE_ID_NVIDIA_XBOX_PCHB;
|
||||
|
@ -490,7 +434,7 @@ static void xbox_pci_class_init(ObjectClass *klass, void *data)
|
|||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
|
||||
dc->desc = "Xbox PCI Host";
|
||||
dc->no_user = 1;
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo xbox_pci_info = {
|
||||
|
@ -498,10 +442,12 @@ static const TypeInfo xbox_pci_info = {
|
|||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(XBOX_PCIState),
|
||||
.class_init = xbox_pci_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define CONFIG_ADDR 0xcf8
|
||||
#define CONFIG_DATA 0xcfc
|
||||
|
||||
|
@ -524,14 +470,13 @@ static int xbox_pcihost_initfn(SysBusDevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void xbox_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = xbox_pcihost_initfn;
|
||||
dc->no_user = 1;
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo xbox_pcihost_info = {
|
||||
|
@ -541,7 +486,6 @@ static const TypeInfo xbox_pcihost_info = {
|
|||
.class_init = xbox_pcihost_class_init,
|
||||
};
|
||||
|
||||
|
||||
static void xboxpci_register_types(void)
|
||||
{
|
||||
type_register(&xbox_pcihost_info);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/xbox/acpi_xbox.h"
|
||||
|
||||
|
||||
typedef struct XBOX_PCIState {
|
||||
PCIDevice dev;
|
||||
|
||||
|
@ -68,8 +67,6 @@ typedef struct XBOX_LPCState {
|
|||
#define XBOX_LPC_DEVICE(obj) \
|
||||
OBJECT_CHECK(XBOX_LPCState, (obj), "xbox-lpc")
|
||||
|
||||
|
||||
|
||||
void xbox_pci_init(qemu_irq *pic,
|
||||
MemoryRegion *address_space_mem,
|
||||
MemoryRegion *address_space_io,
|
||||
|
@ -77,7 +74,7 @@ void xbox_pci_init(qemu_irq *pic,
|
|||
MemoryRegion *ram_memory,
|
||||
PCIBus **out_host_bus,
|
||||
ISABus **out_isa_bus,
|
||||
i2c_bus **out_smbus,
|
||||
I2CBus **out_smbus,
|
||||
PCIBus **out_agp_bus);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue