diff --git a/hw/xbox/smbus.h b/hw/xbox/smbus.h index d2ac6ab72e..5e3b4f8229 100644 --- a/hw/xbox/smbus.h +++ b/hw/xbox/smbus.h @@ -31,6 +31,7 @@ void smbus_adm1032_init(I2CBus *smbus, int address); bool xbox_smc_avpack_to_reg(const char *avpack, uint8_t *value); void xbox_smc_append_avpack_hint(Error **errp); +void xbox_smc_append_smc_version_hint(Error **errp); void xbox_smc_power_button(void); void xbox_smc_eject_button(void); void xbox_smc_update_tray_state(void); diff --git a/hw/xbox/smbus_xbox_smc.c b/hw/xbox/smbus_xbox_smc.c index 5069998940..cc09ad3bda 100644 --- a/hw/xbox/smbus_xbox_smc.c +++ b/hw/xbox/smbus_xbox_smc.c @@ -91,10 +91,11 @@ #define SMC_REG_SCRATCH 0x1b #define SMC_REG_SCRATCH_SHORT_ANIMATION 0x04 -static const char smc_version_string[] = "P01"; +#define SMC_VERSION_LENGTH 3 typedef struct SMBusSMCDevice { SMBusDevice smbusdev; + char *version_string; int version_string_index; uint8_t cmd; uint8_t traystate_reg; @@ -164,8 +165,8 @@ static uint8_t smc_receive_byte(SMBusDevice *dev) switch (cmd) { case SMC_REG_VER: - return smc_version_string[ - smc->version_string_index++ % (sizeof(smc_version_string) - 1)]; + return smc->version_string[ + smc->version_string_index++ % SMC_VERSION_LENGTH]; case SMC_REG_TRAYSTATE: return smc->traystate_reg; @@ -233,11 +234,18 @@ void xbox_smc_append_avpack_hint(Error **errp) error_append_hint(errp, "Valid options are: composite, scart, svideo, vga, rfu, hdtv (default), none\n"); } +void xbox_smc_append_smc_version_hint(Error **errp) +{ + error_append_hint(errp, "Valid versions must have 3 characters total\n"); +} + static void smbus_smc_realize(DeviceState *dev, Error **errp) { SMBusSMCDevice *smc = XBOX_SMC(dev); char *avpack; + char *smc_version; + smc->version_string = NULL; smc->version_string_index = 0; smc->traystate_reg = 0; smc->avpack_reg = 0; /* Default value for Chihiro machine */ @@ -259,6 +267,16 @@ static void smbus_smc_realize(DeviceState *dev, Error **errp) g_free(avpack); } + smc_version = object_property_get_str(qdev_get_machine(), "smc-version", NULL); + if (smc_version) { + if (strlen(smc_version) != SMC_VERSION_LENGTH) { + error_setg(errp, "Unsupported SMC version string '%s'", smc_version); + xbox_smc_append_smc_version_hint(errp); + } + smc->version_string = g_strdup(smc_version); + g_free(smc_version); + } + xbox_smc_update_tray_state(); } diff --git a/hw/xbox/xbox.c b/hw/xbox/xbox.c index df54dc237a..9ace1b79e6 100644 --- a/hw/xbox/xbox.c +++ b/hw/xbox/xbox.c @@ -422,6 +422,28 @@ static bool machine_get_short_animation(Object *obj, Error **errp) return ms->short_animation; } +static char *machine_get_smc_version(Object *obj, Error **errp) +{ + XboxMachineState *ms = XBOX_MACHINE(obj); + + return g_strdup(ms->smc_version); +} + +static void machine_set_smc_version(Object *obj, const char *value, + Error **errp) +{ + XboxMachineState *ms = XBOX_MACHINE(obj); + + if (strlen(value) != 3) { + error_setg(errp, "-machine smc-version=%s: unsupported option", value); + xbox_smc_append_smc_version_hint(errp); + return; + } + + g_free(ms->smc_version); + ms->smc_version = g_strdup(value); +} + static inline void xbox_machine_initfn(Object *obj) { object_property_add_str(obj, "bootrom", machine_get_bootrom, @@ -442,6 +464,12 @@ static inline void xbox_machine_initfn(Object *obj) "Skip Xbox boot animation"); object_property_set_bool(obj, "short-animation", false, &error_fatal); + object_property_add_str(obj, "smc-version", machine_get_smc_version, + machine_set_smc_version); + object_property_set_description(obj, "smc-version", + "Set the SMC version number, default is P01"); + object_property_set_str(obj, "smc-version", "P01", &error_fatal); + } static void xbox_machine_class_init(ObjectClass *oc, void *data) diff --git a/hw/xbox/xbox.h b/hw/xbox/xbox.h index 5ec777ca49..665872faac 100644 --- a/hw/xbox/xbox.h +++ b/hw/xbox/xbox.h @@ -45,6 +45,7 @@ typedef struct XboxMachineState { char *bootrom; char *avpack; bool short_animation; + char *smc_version; } XboxMachineState; typedef struct XboxMachineClass {