2018-03-24 08:04:15 +00:00
|
|
|
/*
|
|
|
|
* QEMU Xbox System Emulator
|
|
|
|
*
|
|
|
|
* Copyright (c) 2012 espes
|
2021-03-03 10:24:24 +00:00
|
|
|
* Copyright (c) 2018-2021 Matt Borgerson
|
2018-03-24 08:04:15 +00:00
|
|
|
*
|
2018-10-10 03:38:16 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
2018-03-24 08:04:15 +00:00
|
|
|
*
|
2018-10-10 03:38:16 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2018-03-24 08:04:15 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2018-10-10 03:38:16 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2018-03-24 08:04:15 +00:00
|
|
|
*
|
2018-10-10 03:38:16 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
2018-03-24 08:04:15 +00:00
|
|
|
*/
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
#include "qemu/osdep.h"
|
2018-09-26 09:03:42 +00:00
|
|
|
#include "qemu/option.h"
|
2018-03-24 08:04:15 +00:00
|
|
|
#include "hw/hw.h"
|
2018-06-26 21:45:02 +00:00
|
|
|
#include "hw/loader.h"
|
2018-03-24 08:04:15 +00:00
|
|
|
#include "hw/i386/pc.h"
|
|
|
|
#include "hw/pci/pci.h"
|
2018-06-26 21:45:02 +00:00
|
|
|
#include "hw/pci/pci_ids.h"
|
|
|
|
#include "hw/usb.h"
|
|
|
|
#include "net/net.h"
|
2018-03-24 08:04:15 +00:00
|
|
|
#include "hw/boards.h"
|
2020-05-01 09:47:01 +00:00
|
|
|
#include "hw/ide/pci.h"
|
2018-03-24 08:04:15 +00:00
|
|
|
#include "sysemu/sysemu.h"
|
2020-02-18 06:51:45 +00:00
|
|
|
#include "sysemu/kvm.h"
|
|
|
|
#include "kvm_i386.h"
|
|
|
|
#include "hw/kvm/clock.h"
|
|
|
|
#include "hw/dma/i8257.h"
|
|
|
|
|
2018-03-24 08:04:15 +00:00
|
|
|
#include "hw/sysbus.h"
|
2018-06-26 21:45:02 +00:00
|
|
|
#include "sysemu/arch_init.h"
|
|
|
|
#include "exec/memory.h"
|
2018-03-24 08:04:15 +00:00
|
|
|
#include "exec/address-spaces.h"
|
2018-06-26 21:45:02 +00:00
|
|
|
#include "cpu.h"
|
2018-09-26 09:03:42 +00:00
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "qemu/error-report.h"
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2018-09-26 09:03:42 +00:00
|
|
|
#include "hw/timer/i8254.h"
|
|
|
|
#include "hw/audio/pcspk.h"
|
2020-02-18 06:51:45 +00:00
|
|
|
#include "hw/rtc/mc146818rtc.h"
|
2018-06-26 21:45:02 +00:00
|
|
|
|
2018-09-26 09:03:42 +00:00
|
|
|
#include "hw/xbox/xbox_pci.h"
|
2019-07-04 06:00:39 +00:00
|
|
|
#include "hw/i2c/i2c.h"
|
|
|
|
#include "hw/i2c/smbus_eeprom.h"
|
2018-09-26 09:42:41 +00:00
|
|
|
#include "hw/xbox/nv2a/nv2a.h"
|
2020-12-18 08:25:28 +00:00
|
|
|
#include "hw/xbox/mcpx/apu.h"
|
2021-03-03 10:24:24 +00:00
|
|
|
|
2018-09-26 09:03:42 +00:00
|
|
|
#include "hw/xbox/xbox.h"
|
2019-07-04 07:03:17 +00:00
|
|
|
#include "smbus.h"
|
2018-09-26 09:03:42 +00:00
|
|
|
|
|
|
|
#define MAX_IDE_BUS 2
|
2018-06-26 21:45:02 +00:00
|
|
|
|
2020-03-26 07:04:51 +00:00
|
|
|
/* FIXME: Clean this up and propagate errors to UI */
|
2018-06-26 21:45:02 +00:00
|
|
|
static void xbox_flash_init(MemoryRegion *rom_memory)
|
2018-03-24 08:04:15 +00:00
|
|
|
{
|
2018-06-26 21:45:02 +00:00
|
|
|
/* Locate BIOS ROM image */
|
2018-03-24 08:04:15 +00:00
|
|
|
if (bios_name == NULL) {
|
|
|
|
bios_name = "bios.bin";
|
|
|
|
}
|
2018-06-26 21:45:02 +00:00
|
|
|
|
2020-03-26 07:04:51 +00:00
|
|
|
int failed_to_load_bios = 1;
|
|
|
|
char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
|
|
|
int bios_size = 256*1024;
|
|
|
|
|
|
|
|
if (filename != NULL) {
|
|
|
|
int bios_file_size = get_image_size(filename);
|
|
|
|
if ((bios_file_size > 0) && ((bios_file_size % 65536) == 0)) {
|
|
|
|
failed_to_load_bios = 0;
|
|
|
|
bios_size = bios_file_size;
|
|
|
|
}
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
2018-06-26 21:45:02 +00:00
|
|
|
|
2020-03-26 07:04:51 +00:00
|
|
|
char *bios_data = g_malloc(bios_size);
|
2018-06-26 21:45:02 +00:00
|
|
|
assert(bios_data != NULL);
|
2020-03-26 07:04:51 +00:00
|
|
|
|
|
|
|
if (!failed_to_load_bios && (filename != NULL)) {
|
|
|
|
/* Read BIOS ROM into memory */
|
|
|
|
failed_to_load_bios = 1;
|
|
|
|
int fd = open(filename, O_RDONLY | O_BINARY);
|
|
|
|
if (fd >= 0) {
|
|
|
|
int rc = read(fd, bios_data, bios_size);
|
|
|
|
if (rc == bios_size) {
|
|
|
|
failed_to_load_bios = 0;
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (failed_to_load_bios) {
|
|
|
|
fprintf(stderr, "Failed to load BIOS '%s'\n", filename);
|
|
|
|
memset(bios_data, 0xff, bios_size);
|
|
|
|
}
|
|
|
|
if (filename != NULL) {
|
|
|
|
g_free(filename);
|
|
|
|
}
|
2018-06-26 21:45:02 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2020-03-26 07:04:51 +00:00
|
|
|
int bootrom_size = get_image_size(filename);
|
2018-06-26 21:45:02 +00:00
|
|
|
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 */
|
2020-03-26 07:04:51 +00:00
|
|
|
int fd = open(filename, O_RDONLY | O_BINARY);
|
2018-06-26 21:45:02 +00:00
|
|
|
assert(fd >= 0);
|
2020-03-26 07:04:51 +00:00
|
|
|
int rc = read(fd, &bios_data[bios_size - bootrom_size], bootrom_size);
|
2018-06-26 21:45:02 +00:00
|
|
|
assert(rc == bootrom_size);
|
|
|
|
close(fd);
|
2018-03-24 08:04:15 +00:00
|
|
|
g_free(filename);
|
|
|
|
}
|
|
|
|
|
2020-11-12 06:11:30 +00:00
|
|
|
/* XBOX_FIXME: The "memory_region_set_readonly" calls below have been
|
|
|
|
* temporarily commented out due to MCPX 1.1-based kernels hanging
|
|
|
|
* in the first bootloader stage when doing RSA signature verification.
|
2021-03-03 10:24:24 +00:00
|
|
|
*
|
2020-11-12 06:11:30 +00:00
|
|
|
* This is caused by code incorrectly using the flash memory range to
|
|
|
|
* store the following computation; luckily real hardware's writeback
|
|
|
|
* cache policy (verified against MTRR config) appears to allow this
|
|
|
|
* to succeed, but qemu's emulation of such isn't capable of this yet
|
|
|
|
* so the value is never updated in ROM unless readonly is unspecified.
|
2021-03-03 10:24:24 +00:00
|
|
|
*
|
2020-11-12 06:11:30 +00:00
|
|
|
* sub ds:0FFFFD52Ch, eax
|
|
|
|
* mov eax, ds:0FFFFD52Ch
|
|
|
|
*/
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
/* Create BIOS region */
|
2020-03-26 07:04:51 +00:00
|
|
|
MemoryRegion *bios;
|
2018-06-26 21:45:02 +00:00
|
|
|
bios = g_malloc(sizeof(*bios));
|
|
|
|
assert(bios != NULL);
|
|
|
|
memory_region_init_ram(bios, NULL, "xbox.bios", bios_size, &error_fatal);
|
2020-11-12 06:11:30 +00:00
|
|
|
//memory_region_set_readonly(bios, true);
|
2018-06-26 21:45:02 +00:00
|
|
|
rom_add_blob_fixed("xbox.bios", bios_data, bios_size,
|
|
|
|
(uint32_t)(-2 * bios_size));
|
|
|
|
|
|
|
|
/* Assuming bios_data will be needed for duration of execution
|
|
|
|
* so no free(bios) here.
|
|
|
|
*/
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
/* Mirror ROM from 0xff000000 - 0xffffffff */
|
2020-03-26 07:04:51 +00:00
|
|
|
uint32_t map_loc;
|
2018-06-26 21:45:02 +00:00
|
|
|
for (map_loc = (uint32_t)(-bios_size);
|
|
|
|
map_loc >= 0xff000000;
|
|
|
|
map_loc -= bios_size) {
|
2020-03-26 07:04:51 +00:00
|
|
|
MemoryRegion *map_bios = g_malloc(sizeof(*map_bios));
|
2018-06-26 21:45:02 +00:00
|
|
|
memory_region_init_alias(map_bios, NULL, "pci-bios", bios, 0, bios_size);
|
2018-03-24 08:04:15 +00:00
|
|
|
memory_region_add_subregion(rom_memory, map_loc, map_bios);
|
2020-11-12 06:11:30 +00:00
|
|
|
//memory_region_set_readonly(map_bios, true);
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
2018-06-26 21:45:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void xbox_memory_init(PCMachineState *pcms,
|
|
|
|
MemoryRegion *system_memory,
|
|
|
|
MemoryRegion *rom_memory,
|
|
|
|
MemoryRegion **ram_memory)
|
|
|
|
{
|
|
|
|
// int linux_boot, i;
|
|
|
|
MemoryRegion *ram;//, *option_rom_mr;
|
|
|
|
// FWCfgState *fw_cfg;
|
|
|
|
MachineState *machine = MACHINE(pcms);
|
|
|
|
// PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
|
|
|
|
|
|
|
// 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);
|
2020-08-25 21:35:47 +00:00
|
|
|
pc_system_flash_cleanup_unused(pcms);
|
2018-06-26 21:45:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* PC hardware initialisation */
|
|
|
|
static void xbox_init(MachineState *machine)
|
|
|
|
{
|
2020-10-29 20:59:51 +00:00
|
|
|
xbox_init_common(machine, NULL, NULL);
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
void xbox_init_common(MachineState *machine,
|
|
|
|
PCIBus **pci_bus_out,
|
|
|
|
ISABus **isa_bus_out)
|
2018-03-24 08:04:15 +00:00
|
|
|
{
|
2018-06-26 21:45:02 +00:00
|
|
|
PCMachineState *pcms = PC_MACHINE(machine);
|
2020-02-18 06:51:45 +00:00
|
|
|
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
|
|
|
X86MachineState *x86ms = X86_MACHINE(machine);
|
2018-06-26 21:45:02 +00:00
|
|
|
MemoryRegion *system_memory = get_system_memory();
|
|
|
|
// MemoryRegion *system_io = get_system_io();
|
|
|
|
|
2018-03-24 08:04:15 +00:00
|
|
|
int i;
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
PCIBus *pci_bus;
|
2018-03-24 08:04:15 +00:00
|
|
|
ISABus *isa_bus;
|
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
// qemu_irq *i8259;
|
2018-06-26 21:45:02 +00:00
|
|
|
// qemu_irq smi_irq; // XBOX_TODO: SMM support?
|
|
|
|
|
2018-03-24 08:04:15 +00:00
|
|
|
GSIState *gsi_state;
|
|
|
|
|
2020-05-01 09:47:01 +00:00
|
|
|
// DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
2020-02-18 06:51:45 +00:00
|
|
|
// BusState *idebus[MAX_IDE_BUS];
|
2018-03-24 08:04:15 +00:00
|
|
|
ISADevice *rtc_state;
|
2020-02-18 06:51:45 +00:00
|
|
|
ISADevice *pit = NULL;
|
|
|
|
int pit_isa_irq = 0;
|
|
|
|
qemu_irq pit_alt_irq = NULL;
|
2018-06-26 21:45:02 +00:00
|
|
|
// ISADevice *pit;
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
MemoryRegion *ram_memory;
|
|
|
|
MemoryRegion *pci_memory;
|
|
|
|
MemoryRegion *rom_memory;
|
|
|
|
|
|
|
|
I2CBus *smbus;
|
|
|
|
PCIBus *agp_bus;
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
x86_cpus_init(x86ms, pcmc->default_cpu_version);
|
|
|
|
|
|
|
|
if (kvm_enabled() && pcmc->kvmclock_enabled) {
|
|
|
|
kvmclock_create();
|
|
|
|
}
|
2018-03-24 08:04:15 +00:00
|
|
|
|
|
|
|
pci_memory = g_new(MemoryRegion, 1);
|
2018-06-26 21:45:02 +00:00
|
|
|
memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
|
|
|
|
rom_memory = pci_memory;
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2018-09-26 09:03:42 +00:00
|
|
|
// pc_guest_info_init(pcms);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
/* allocate ram and load rom/bios */
|
|
|
|
xbox_memory_init(pcms, system_memory, rom_memory, &ram_memory);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
gsi_state = pc_gsi_create(&x86ms->gsi, pcmc->pci_enabled);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
xbox_pci_init(x86ms->gsi,
|
2018-03-24 08:04:15 +00:00
|
|
|
get_system_memory(), get_system_io(),
|
|
|
|
pci_memory, ram_memory,
|
2018-06-26 21:45:02 +00:00
|
|
|
&pci_bus,
|
2018-03-24 08:04:15 +00:00
|
|
|
&isa_bus,
|
|
|
|
&smbus,
|
|
|
|
&agp_bus);
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
pcms->bus = pci_bus;
|
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
isa_bus_irqs(isa_bus, x86ms->gsi);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
pc_i8259_create(isa_bus, gsi_state->i8259_irq);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
if (tcg_enabled()) {
|
|
|
|
x86_register_ferr_irq(x86ms->gsi[13]);
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
/* init basic PC hardware */
|
2019-07-04 06:00:39 +00:00
|
|
|
pcms->pit_enabled = 1; // XBOX_FIXME: What's the right way to do this?
|
2018-06-26 21:45:02 +00:00
|
|
|
rtc_state = mc146818_rtc_init(isa_bus, 2000, NULL);
|
|
|
|
|
2020-02-18 06:51:45 +00:00
|
|
|
if (kvm_pit_in_kernel()) {
|
|
|
|
pit = kvm_pit_init(isa_bus, 0x40);
|
|
|
|
} else {
|
|
|
|
pit = i8254_pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
|
|
|
|
}
|
|
|
|
|
|
|
|
i8257_dma_init(isa_bus, 0);
|
2018-06-26 21:45:02 +00:00
|
|
|
|
2020-08-25 21:38:41 +00:00
|
|
|
pcspk_init(pcms->pcspk, isa_bus, pit);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2020-05-01 09:47:01 +00:00
|
|
|
PCIDevice *dev = pci_create_simple(pci_bus, PCI_DEVFN(9, 0), "piix3-ide");
|
|
|
|
pci_ide_create_devs(dev);
|
|
|
|
// idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
|
|
|
|
// idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
|
2018-03-24 08:04:15 +00:00
|
|
|
|
|
|
|
// xbox bios wants this bit pattern set to mark the data as valid
|
|
|
|
uint8_t bits = 0x55;
|
|
|
|
for (i = 0x10; i < 0x70; i++) {
|
|
|
|
rtc_set_memory(rtc_state, i, bits);
|
|
|
|
bits = ~bits;
|
|
|
|
}
|
|
|
|
bits = 0x55;
|
|
|
|
for (i = 0x80; i < 0x100; i++) {
|
|
|
|
rtc_set_memory(rtc_state, i, bits);
|
|
|
|
bits = ~bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* smbus devices */
|
|
|
|
smbus_xbox_smc_init(smbus, 0x10);
|
|
|
|
smbus_cx25871_init(smbus, 0x45);
|
|
|
|
smbus_adm1032_init(smbus, 0x4c);
|
|
|
|
|
|
|
|
/* USB */
|
2020-08-25 21:41:16 +00:00
|
|
|
PCIDevice *usb1 = pci_new(PCI_DEVFN(3, 0), "pci-ohci");
|
2018-03-24 08:04:15 +00:00
|
|
|
qdev_prop_set_uint32(&usb1->qdev, "num-ports", 4);
|
2020-08-25 21:41:16 +00:00
|
|
|
pci_realize_and_unref(usb1, pci_bus, &error_fatal);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2020-08-25 21:41:16 +00:00
|
|
|
PCIDevice *usb0 = pci_new(PCI_DEVFN(2, 0), "pci-ohci");
|
2018-03-24 08:04:15 +00:00
|
|
|
qdev_prop_set_uint32(&usb0->qdev, "num-ports", 4);
|
2020-08-25 21:41:16 +00:00
|
|
|
pci_realize_and_unref(usb0, pci_bus, &error_fatal);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
|
|
|
/* Ethernet! */
|
2020-08-25 21:41:16 +00:00
|
|
|
PCIDevice *nvnet = pci_new(PCI_DEVFN(4, 0), "nvnet");
|
2018-03-24 08:04:15 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nb_nics; i++) {
|
|
|
|
NICInfo *nd = &nd_table[i];
|
|
|
|
qemu_check_nic_model(nd, "nvnet");
|
|
|
|
qdev_set_nic_properties(&nvnet->qdev, nd);
|
2020-08-25 21:41:16 +00:00
|
|
|
pci_realize_and_unref(nvnet, pci_bus, &error_fatal);
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* APU! */
|
2018-12-26 21:23:25 +00:00
|
|
|
mcpx_apu_init(pci_bus, PCI_DEVFN(5, 0), ram_memory);
|
2018-03-24 08:04:15 +00:00
|
|
|
|
|
|
|
/* ACI! */
|
2018-06-26 21:45:02 +00:00
|
|
|
pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "mcpx-aci");
|
2018-03-24 08:04:15 +00:00
|
|
|
|
|
|
|
/* GPU! */
|
|
|
|
nv2a_init(agp_bus, PCI_DEVFN(0, 0), ram_memory);
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
if (pci_bus_out) {
|
|
|
|
*pci_bus_out = pci_bus;
|
|
|
|
}
|
|
|
|
if (isa_bus_out) {
|
|
|
|
*isa_bus_out = isa_bus;
|
|
|
|
}
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
static void xbox_machine_options(MachineClass *m)
|
2018-03-24 08:04:15 +00:00
|
|
|
{
|
2018-06-26 21:45:02 +00:00
|
|
|
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,
|
2018-09-26 09:03:42 +00:00
|
|
|
m->default_cpu_type = X86_CPU_TYPE_NAME("pentium3");
|
2018-06-26 21:45:02 +00:00
|
|
|
|
|
|
|
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";
|
|
|
|
}
|
2018-03-24 08:04:15 +00:00
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
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);
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
|
|
|
|
2019-09-03 18:30:24 +00:00
|
|
|
static char *machine_get_avpack(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
XboxMachineState *ms = XBOX_MACHINE(obj);
|
|
|
|
|
|
|
|
return g_strdup(ms->avpack);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void machine_set_avpack(Object *obj, const char *value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
XboxMachineState *ms = XBOX_MACHINE(obj);
|
|
|
|
|
|
|
|
if (!xbox_smc_avpack_to_reg(value, NULL)) {
|
|
|
|
error_setg(errp, "-machine avpack=%s: unsupported option", value);
|
|
|
|
xbox_smc_append_avpack_hint(errp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(ms->avpack);
|
|
|
|
ms->avpack = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
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,
|
2020-08-25 21:44:56 +00:00
|
|
|
machine_set_bootrom);
|
2018-06-26 21:45:02 +00:00
|
|
|
object_property_set_description(obj, "bootrom",
|
2020-08-25 21:44:56 +00:00
|
|
|
"Xbox bootrom file");
|
2018-06-26 21:45:02 +00:00
|
|
|
|
2019-09-03 18:30:24 +00:00
|
|
|
object_property_add_str(obj, "avpack", machine_get_avpack,
|
2020-08-25 21:44:56 +00:00
|
|
|
machine_set_avpack);
|
2019-09-03 18:30:24 +00:00
|
|
|
object_property_set_description(obj, "avpack",
|
2020-08-25 21:44:56 +00:00
|
|
|
"Xbox video connector: composite (default), scart, svideo, vga, rfu, hdtv, none");
|
|
|
|
object_property_set_str(obj, "avpack", "composite", &error_fatal);
|
2019-09-03 18:30:24 +00:00
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
object_property_add_bool(obj, "short-animation",
|
|
|
|
machine_get_short_animation,
|
2020-08-25 21:44:56 +00:00
|
|
|
machine_set_short_animation);
|
2018-06-26 21:45:02 +00:00
|
|
|
object_property_set_description(obj, "short-animation",
|
2020-08-25 21:44:56 +00:00
|
|
|
"Skip Xbox boot animation");
|
|
|
|
object_property_set_bool(obj, "short-animation", false, &error_fatal);
|
2018-06-26 21:45:02 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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 },
|
|
|
|
{ }
|
|
|
|
},
|
2018-03-24 08:04:15 +00:00
|
|
|
};
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
static void pc_machine_init_xbox(void)
|
|
|
|
{
|
|
|
|
type_register(&pc_machine_type_xbox);
|
2018-03-24 08:04:15 +00:00
|
|
|
}
|
|
|
|
|
2018-06-26 21:45:02 +00:00
|
|
|
type_init(pc_machine_init_xbox)
|