From 7da8cfa4b07905483fbca6810fdaeef2f732c20c Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Fri, 28 Aug 2015 17:37:38 +0000 Subject: [PATCH] Fixed save/restore support of the USB subsystem when using an external hub with devices conected at runtime. - Added restore handler support for the bx_list_c class. If a handler is registered, it will be called after restoring all of the list's members. - USB hub: add special lists to the port state and add pointers to the runtime-only options for each port. The restore handler of this list calls init_device() to make sure all connected devices can be restored. - Call restore_logopts() after restoring hardware to make sure all saved modules have been created. - TODO: the USB cdrom also needs a fix for it's runtime-only options. --- bochs/gui/paramtree.cc | 15 +++++++++++++++ bochs/gui/paramtree.h | 7 +++++++ bochs/gui/siminterface.cc | 4 +++- bochs/iodev/usb/usb_hub.cc | 26 +++++++++++++++++++++++++- bochs/iodev/usb/usb_hub.h | 1 + bochs/main.cc | 13 ++++++------- 6 files changed, 57 insertions(+), 9 deletions(-) diff --git a/bochs/gui/paramtree.cc b/bochs/gui/paramtree.cc index 6ea103dc8..520327685 100644 --- a/bochs/gui/paramtree.cc +++ b/bochs/gui/paramtree.cc @@ -940,6 +940,7 @@ bx_list_c::bx_list_c(bx_param_c *parent, const char *name) this->parent = (bx_list_c *)parent; this->parent->add(this); } + this->restore_handler = NULL; init(""); } @@ -955,6 +956,7 @@ bx_list_c::bx_list_c(bx_param_c *parent, const char *name, const char *title) this->parent = (bx_list_c *)parent; this->parent->add(this); } + this->restore_handler = NULL; init(title); } @@ -972,6 +974,7 @@ bx_list_c::bx_list_c(bx_param_c *parent, const char *name, const char *title, bx this->parent = (bx_list_c *)parent; this->parent->add(this); } + this->restore_handler = NULL; init(title); } @@ -1137,3 +1140,15 @@ void bx_list_c::set_runtime_param(int val) } } } + +void bx_list_c::set_restore_handler(void *devptr, list_restore_handler restore) +{ + sr_devptr = devptr; + restore_handler = restore; +} + +void bx_list_c::restore() +{ + if (restore_handler) + (*restore_handler)(sr_devptr, this); +} diff --git a/bochs/gui/paramtree.h b/bochs/gui/paramtree.h index 04e4e74b0..3617c31ae 100644 --- a/bochs/gui/paramtree.h +++ b/bochs/gui/paramtree.h @@ -446,6 +446,8 @@ typedef struct _bx_listitem_t { struct _bx_listitem_t *next; } bx_listitem_t; +typedef void (*list_restore_handler)(void *devptr, class bx_list_c *); + class BOCHSAPI bx_list_c : public bx_param_c { protected: // chained list of bx_listitem_t @@ -458,6 +460,9 @@ protected: // title of the menu or series char *title; void init(const char *list_title); + // save / restore support + void *sr_devptr; + list_restore_handler restore_handler; public: enum { // When a bx_list_c is displayed as a menu, SHOW_PARENT controls whether or @@ -505,6 +510,8 @@ public: virtual void clear(); virtual void remove(const char *name); virtual void set_runtime_param(int val); + void set_restore_handler(void *devptr, list_restore_handler restore); + void restore(); #if BX_USE_TEXTCONFIG virtual void text_print(FILE *); virtual int text_ask(FILE *fpin, FILE *fpout); diff --git a/bochs/gui/siminterface.cc b/bochs/gui/siminterface.cc index 7e3cca999..44bfadfdf 100644 --- a/bochs/gui/siminterface.cc +++ b/bochs/gui/siminterface.cc @@ -1236,14 +1236,16 @@ bx_bool bx_real_sim_c::restore_bochs_param(bx_list_c *root, const char *sr_path, while (ptr) { if (i == 0) { if (!strcmp(ptr, "}")) { + base->restore(); base = (bx_list_c*)base->get_parent(); break; } else { param = get_param(ptr, base); + strncpy(pname, ptr, 80); } } else if (i == 2) { if (param == NULL) { - BX_PANIC(("cannot find param!")); + BX_PANIC(("cannot find param '%s'!", pname)); } else { if (param->get_type() != BXT_LIST) { diff --git a/bochs/iodev/usb/usb_hub.cc b/bochs/iodev/usb/usb_hub.cc index 185ec4457..cd71833a2 100644 --- a/bochs/iodev/usb/usb_hub.cc +++ b/bochs/iodev/usb/usb_hub.cc @@ -166,6 +166,8 @@ static const Bit8u bx_hub_hub_descriptor[] = static int hub_count = 0; +void usb_hub_restore_handler(void *dev, bx_list_c *conf); + usb_hub_device_c::usb_hub_device_c(Bit8u ports) { int i; @@ -229,12 +231,17 @@ void usb_hub_device_c::register_state_specific(bx_list_c *parent) { Bit8u i; char portnum[6]; - bx_list_c *port; + bx_list_c *port, *pconf, *config; hub.state = new bx_list_c(parent, "hub", "USB HUB Device State"); for (i=0; iget_by_name(portnum); + config = new bx_list_c(port, portnum); + config->add(pconf->get_by_name("device")); + config->add(pconf->get_by_name("options")); + config->set_restore_handler(this, usb_hub_restore_handler); new bx_shadow_num_c(port, "PortStatus", &hub.usb_port[i].PortStatus, BASE_HEX); new bx_shadow_num_c(port, "PortChange", &hub.usb_port[i].PortChange, BASE_HEX); // empty list for USB device state @@ -685,4 +692,21 @@ const char *usb_hub_device_c::hub_param_handler(bx_param_string_c *param, int se return val; } +#undef LOG_THIS +#define LOG_THIS + +void usb_hub_restore_handler(void *dev, bx_list_c *conf) +{ + ((usb_hub_device_c*)dev)->restore_handler(conf); +} + +void usb_hub_device_c::restore_handler(bx_list_c *conf) +{ + int i; + const char *pname = conf->get_name(); + + i = atoi(&pname[4]) - 1; + init_device(i, (bx_list_c*)SIM->get_param(pname, hub.config)); +} + #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB diff --git a/bochs/iodev/usb/usb_hub.h b/bochs/iodev/usb/usb_hub.h index 3068d36f1..44d44b3d6 100644 --- a/bochs/iodev/usb/usb_hub.h +++ b/bochs/iodev/usb/usb_hub.h @@ -44,6 +44,7 @@ public: virtual void register_state_specific(bx_list_c *parent); virtual void after_restore_state(); virtual void runtime_config(); + void restore_handler(bx_list_c *conf); private: struct { diff --git a/bochs/main.cc b/bochs/main.cc index fd89f3f5a..c8a1c0fd0 100644 --- a/bochs/main.cc +++ b/bochs/main.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2014 The Bochs Project +// Copyright (C) 2001-2015 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1391,12 +1391,7 @@ void bx_init_hardware() SIM->opt_plugin_ctrl("*", 0); bx_pc_system.register_state(); DEV_register_state(); - if (SIM->get_param_bool(BXPN_RESTORE_FLAG)->get()) { - if (!SIM->restore_logopts()) { - BX_PANIC(("cannot restore log options")); - SIM->get_param_bool(BXPN_RESTORE_FLAG)->set(0); - } - } else { + if (!SIM->get_param_bool(BXPN_RESTORE_FLAG)->get()) { bx_set_log_actions_by_device(1); } @@ -1405,6 +1400,10 @@ void bx_init_hardware() if (SIM->get_param_bool(BXPN_RESTORE_FLAG)->get()) { if (SIM->restore_hardware()) { + if (!SIM->restore_logopts()) { + BX_PANIC(("cannot restore log options")); + SIM->get_param_bool(BXPN_RESTORE_FLAG)->set(0); + } bx_sr_after_restore_state(); } else { BX_PANIC(("cannot restore hardware state"));