- implemented new mechanism to update device config parameters that depend on
each other. Devices can register a handler to update it's state after runtime configuration. The new method update_runtime_options() executes all registered device handlers before the simulation continues. - USB host controllers now using the new mechanism to handle the runtime device change (replaces the previous timer-based implementation). TODO: floppy and cdrom could use this feature, too) - improved USB device change messages
This commit is contained in:
parent
778154b3b2
commit
cb8faeee52
@ -45,6 +45,12 @@ bx_list_c *root_param = NULL;
|
||||
// bx_keyboard.s.internal_buffer[4] (or whatever) directly. -Bryce
|
||||
//
|
||||
|
||||
typedef struct _rt_conf_entry_t {
|
||||
void *device;
|
||||
rt_conf_handler_t handler;
|
||||
struct _rt_conf_entry_t *next;
|
||||
} rt_conf_entry_t;
|
||||
|
||||
typedef struct _user_option_t {
|
||||
const char *name;
|
||||
user_option_parser_t parser;
|
||||
@ -58,6 +64,7 @@ class bx_real_sim_c : public bx_simulator_interface_c {
|
||||
const char *registered_ci_name;
|
||||
config_interface_callback_t ci_callback;
|
||||
void *ci_callback_data;
|
||||
rt_conf_entry_t *rt_conf_entries;
|
||||
user_option_t *user_options;
|
||||
int init_done;
|
||||
int enabled;
|
||||
@ -148,6 +155,8 @@ public:
|
||||
void *userdata);
|
||||
virtual int configuration_interface(const char* name, ci_command_t command);
|
||||
virtual int begin_simulation(int argc, char *argv[]);
|
||||
virtual bx_bool register_runtime_config_handler(void *dev, rt_conf_handler_t handler);
|
||||
virtual void update_runtime_options();
|
||||
virtual void set_sim_thread_func(is_sim_thread_func_t func) {}
|
||||
virtual bx_bool is_sim_thread();
|
||||
virtual void set_debug_gui(bx_bool val) { wx_debug_gui = val; }
|
||||
@ -317,6 +326,7 @@ bx_real_sim_c::bx_real_sim_c()
|
||||
quit_context = NULL;
|
||||
exit_code = 0;
|
||||
param_id = BXP_NEW_PARAM_ID;
|
||||
rt_conf_entries = NULL;
|
||||
user_options = NULL;
|
||||
}
|
||||
|
||||
@ -790,6 +800,43 @@ int bx_real_sim_c::begin_simulation(int argc, char *argv[])
|
||||
return bx_begin_simulation(argc, argv);
|
||||
}
|
||||
|
||||
bx_bool bx_real_sim_c::register_runtime_config_handler(void *dev, rt_conf_handler_t handler)
|
||||
{
|
||||
rt_conf_entry_t *rt_conf_entry;
|
||||
|
||||
rt_conf_entry = (rt_conf_entry_t *)malloc(sizeof(rt_conf_entry_t));
|
||||
if (rt_conf_entry == NULL) {
|
||||
BX_PANIC(("can't allocate rt_conf_entry_t"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_conf_entry->device = dev;
|
||||
rt_conf_entry->handler = handler;
|
||||
rt_conf_entry->next = NULL;
|
||||
|
||||
if (rt_conf_entries == NULL) {
|
||||
rt_conf_entries = rt_conf_entry;
|
||||
} else {
|
||||
rt_conf_entry_t *temp = rt_conf_entries;
|
||||
|
||||
while (temp->next) {
|
||||
temp = temp->next;
|
||||
}
|
||||
temp->next = rt_conf_entry;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bx_real_sim_c::update_runtime_options()
|
||||
{
|
||||
rt_conf_entry_t *temp = rt_conf_entries;
|
||||
|
||||
while (temp != NULL) {
|
||||
temp->handler(temp->device);
|
||||
temp = temp->next;
|
||||
}
|
||||
}
|
||||
|
||||
bx_bool bx_real_sim_c::is_sim_thread()
|
||||
{
|
||||
if (is_sim_thread_func == NULL) return 1;
|
||||
|
@ -566,6 +566,7 @@ enum ci_return_t {
|
||||
};
|
||||
typedef int (*config_interface_callback_t)(void *userdata, ci_command_t command);
|
||||
typedef BxEvent* (*bxevent_handler)(void *theclass, BxEvent *event);
|
||||
typedef void (*rt_conf_handler_t)(void *this_ptr);
|
||||
typedef Bit32s (*user_option_parser_t)(const char *context, int num_params, char *params[]);
|
||||
typedef Bit32s (*user_option_save_t)(FILE *fp);
|
||||
|
||||
@ -686,6 +687,8 @@ public:
|
||||
void *userdata) {}
|
||||
virtual int configuration_interface(const char* name, ci_command_t command) {return -1; }
|
||||
virtual int begin_simulation(int argc, char *argv[]) {return -1;}
|
||||
virtual bx_bool register_runtime_config_handler(void *dev, rt_conf_handler_t handler) {return 0;}
|
||||
virtual void update_runtime_options() {}
|
||||
typedef bx_bool (*is_sim_thread_func_t)();
|
||||
is_sim_thread_func_t is_sim_thread_func;
|
||||
virtual void set_sim_thread_func(is_sim_thread_func_t func) {
|
||||
|
@ -522,7 +522,10 @@ int bx_config_interface(int menu)
|
||||
case BX_CI_RT_INST_TR: NOT_IMPLEMENTED(choice); break;
|
||||
case BX_CI_RT_USB: do_menu(BXPN_MENU_RUNTIME_USB); break;
|
||||
case BX_CI_RT_MISC: do_menu(BXPN_MENU_RUNTIME_MISC); break;
|
||||
case BX_CI_RT_CONT: fprintf(stderr, "Continuing simulation\n"); return 0;
|
||||
case BX_CI_RT_CONT:
|
||||
SIM->update_runtime_options();
|
||||
fprintf(stderr, "Continuing simulation\n");
|
||||
return 0;
|
||||
case BX_CI_RT_QUIT:
|
||||
fprintf(stderr, "You chose quit on the configuration interface.\n");
|
||||
bx_user_quit = 1;
|
||||
|
@ -638,6 +638,9 @@ static BOOL CALLBACK MainMenuDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM
|
||||
}
|
||||
break;
|
||||
case IDOK:
|
||||
if (runtime) {
|
||||
SIM->update_runtime_options();
|
||||
}
|
||||
EndDialog(hDlg, 1);
|
||||
break;
|
||||
case IDCANCEL:
|
||||
|
@ -1053,6 +1053,7 @@ void MyFrame::OnPauseResumeSim(wxCommandEvent& WXUNUSED(event))
|
||||
wxCriticalSectionLocker lock(sim_thread_lock);
|
||||
if (sim_thread) {
|
||||
if (sim_thread->IsPaused()) {
|
||||
SIM->update_runtime_options();
|
||||
simStatusChanged(Resume);
|
||||
sim_thread->Resume();
|
||||
} else {
|
||||
|
@ -154,7 +154,7 @@ public:
|
||||
virtual void after_restore_state() {}
|
||||
virtual void cancel_packet(USBPacket *p) {}
|
||||
virtual bx_bool set_option(const char *option) {return 0;}
|
||||
virtual void timer() {}
|
||||
virtual void runtime_config() {}
|
||||
|
||||
bx_bool get_connected() {return d.connected;}
|
||||
usbdev_type get_type() {return d.type;}
|
||||
|
@ -625,22 +625,24 @@ void usb_hub_device_c::usb_set_connect_status(Bit8u port, int type, bx_bool conn
|
||||
}
|
||||
}
|
||||
|
||||
void usb_hub_device_c::timer()
|
||||
void usb_hub_device_c::runtime_config()
|
||||
{
|
||||
int i;
|
||||
int i, hubnum;
|
||||
char pname[6];
|
||||
|
||||
for (i = 0; i < hub.n_ports; i++) {
|
||||
// forward timer tick
|
||||
if (hub.usb_port[i].device != NULL) {
|
||||
hub.usb_port[i].device->timer();
|
||||
}
|
||||
// device change support
|
||||
if ((hub.device_change & (1 << i)) != 0) {
|
||||
hubnum = atoi(hub.config->get_name()+6);
|
||||
BX_INFO(("USB hub #%d, port #%d: device connect", hubnum, i+1));
|
||||
sprintf(pname, "port%d", i + 1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, hub.config));
|
||||
hub.device_change &= ~(1 << i);
|
||||
}
|
||||
// forward to connected device
|
||||
if (hub.usb_port[i].device != NULL) {
|
||||
hub.usb_port[i].device->runtime_config();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -664,8 +666,8 @@ const char *usb_hub_device_c::hub_param_handler(bx_param_string_c *param, int se
|
||||
portnum = atoi(port->get_name()+4) - 1;
|
||||
bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none")));
|
||||
if ((portnum >= 0) && (portnum < hub->hub.n_ports)) {
|
||||
BX_INFO(("USB hub #%d, port #%d experimental device change", hubnum, portnum+1));
|
||||
if (empty && (hub->hub.usb_port[portnum].PortStatus & PORT_STAT_CONNECTION)) {
|
||||
BX_INFO(("USB hub #%d, port #%d: device disconnect", hubnum, portnum+1));
|
||||
if (hub->hub.usb_port[portnum].device != NULL) {
|
||||
type = hub->hub.usb_port[portnum].device->get_type();
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
virtual int handle_data(USBPacket *p);
|
||||
virtual void register_state_specific(bx_list_c *parent);
|
||||
virtual void after_restore_state();
|
||||
virtual void timer();
|
||||
virtual void runtime_config();
|
||||
|
||||
private:
|
||||
struct {
|
||||
|
@ -164,6 +164,9 @@ void bx_usb_ohci_c::init(void)
|
||||
DEV_register_timer(this, iolight_timer_handler, 5000, 0,0, "OHCI i/o light");
|
||||
}
|
||||
BX_OHCI_THIS hub.iolight_counter = 0;
|
||||
|
||||
// register handler for correct device connect handling after runtime config
|
||||
SIM->register_runtime_config_handler(BX_OHCI_THIS_PTR, runtime_config_handler);
|
||||
BX_OHCI_THIS hub.device_change = 0;
|
||||
|
||||
BX_INFO(("USB OHCI initialized"));
|
||||
@ -1002,8 +1005,6 @@ void bx_usb_ohci_c::usb_frame_timer(void)
|
||||
struct OHCI_ED cur_ed;
|
||||
Bit32u address, ed_address;
|
||||
Bit16u zero = 0;
|
||||
int i;
|
||||
char pname[6];
|
||||
|
||||
if (BX_OHCI_THIS hub.op_regs.HcControl.hcfs == 2) {
|
||||
// set remaining to the interval amount.
|
||||
@ -1105,19 +1106,6 @@ do_iso_eds:
|
||||
}
|
||||
|
||||
} // end run schedule
|
||||
|
||||
for (i = 0; i < BX_N_USB_OHCI_PORTS; i++) {
|
||||
// forward timer tick
|
||||
if (BX_OHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
BX_OHCI_THIS hub.usb_port[i].device->timer();
|
||||
}
|
||||
// device change support
|
||||
if ((BX_OHCI_THIS hub.device_change & (1 << i)) != 0) {
|
||||
sprintf(pname, "port%d", i + 1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_OHCI)));
|
||||
BX_OHCI_THIS hub.device_change &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bx_usb_ohci_c::process_ed(struct OHCI_ED *ed, const Bit32u ed_address)
|
||||
@ -1363,6 +1351,32 @@ void bx_usb_ohci_c::iolight_timer()
|
||||
}
|
||||
}
|
||||
|
||||
void bx_usb_ohci_c::runtime_config_handler(void *this_ptr)
|
||||
{
|
||||
bx_usb_ohci_c *class_ptr = (bx_usb_ohci_c *) this_ptr;
|
||||
class_ptr->runtime_config();
|
||||
}
|
||||
|
||||
void bx_usb_ohci_c::runtime_config(void)
|
||||
{
|
||||
int i;
|
||||
char pname[6];
|
||||
|
||||
for (i = 0; i < BX_N_USB_OHCI_PORTS; i++) {
|
||||
// device change support
|
||||
if ((BX_OHCI_THIS hub.device_change & (1 << i)) != 0) {
|
||||
BX_INFO(("USB port #%d: device connect", i+1));
|
||||
sprintf(pname, "port%d", i + 1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_OHCI)));
|
||||
BX_OHCI_THIS hub.device_change &= ~(1 << i);
|
||||
}
|
||||
// forward to connected device
|
||||
if (BX_OHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
BX_OHCI_THIS hub.usb_port[i].device->runtime_config();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pci configuration space read callback handler
|
||||
Bit32u bx_usb_ohci_c::pci_read_handler(Bit8u address, unsigned io_len)
|
||||
{
|
||||
@ -1486,8 +1500,8 @@ const char *bx_usb_ohci_c::usb_param_handler(bx_param_string_c *param, int set,
|
||||
portnum = atoi((param->get_parent())->get_name()+4) - 1;
|
||||
bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none")));
|
||||
if ((portnum >= 0) && (portnum < BX_N_USB_OHCI_PORTS)) {
|
||||
BX_INFO(("USB port #%d experimental device change", portnum+1));
|
||||
if (empty && BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.ccs) {
|
||||
BX_INFO(("USB port #%d: device disconnect", portnum+1));
|
||||
if (BX_OHCI_THIS hub.usb_port[portnum].device != NULL) {
|
||||
type = BX_OHCI_THIS hub.usb_port[portnum].device->get_type();
|
||||
}
|
||||
|
@ -297,6 +297,8 @@ private:
|
||||
static void iolight_timer_handler(void *);
|
||||
void iolight_timer(void);
|
||||
|
||||
static void runtime_config_handler(void *);
|
||||
void runtime_config(void);
|
||||
};
|
||||
|
||||
#endif // BX_IODEV_USB_OHCI_H
|
||||
|
@ -136,6 +136,9 @@ void bx_usb_uhci_c::init(void)
|
||||
DEV_register_timer(this, iolight_timer_handler, 5000, 0,0, "UHCI i/o light");
|
||||
}
|
||||
BX_UHCI_THIS hub.iolight_counter = 0;
|
||||
|
||||
// register handler for correct device connect handling after runtime config
|
||||
SIM->register_runtime_config_handler(BX_UHCI_THIS_PTR, runtime_config_handler);
|
||||
BX_UHCI_THIS hub.device_change = 0;
|
||||
|
||||
BX_INFO(("USB UHCI initialized"));
|
||||
@ -638,7 +641,6 @@ void bx_usb_uhci_c::usb_timer_handler(void *this_ptr)
|
||||
void bx_usb_uhci_c::usb_timer(void)
|
||||
{
|
||||
int i;
|
||||
char pname[6];
|
||||
|
||||
// If the "global reset" bit was set by software
|
||||
if (BX_UHCI_THIS global_reset) {
|
||||
@ -814,19 +816,6 @@ void bx_usb_uhci_c::usb_timer(void)
|
||||
// If in Global_Suspend mode and any of usb_port[i] bits 6,3, or 1 are set,
|
||||
// we need to issue a Global_Resume (set the global resume bit).
|
||||
// However, since we don't do anything, let's not.
|
||||
|
||||
for (i = 0; i < BX_N_USB_UHCI_PORTS; i++) {
|
||||
// forward timer tick
|
||||
if (BX_UHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
BX_UHCI_THIS hub.usb_port[i].device->timer();
|
||||
}
|
||||
// device change support
|
||||
if ((BX_UHCI_THIS hub.device_change & (1 << i)) != 0) {
|
||||
sprintf(pname, "port%d", i + 1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_UHCI)));
|
||||
BX_UHCI_THIS hub.device_change &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bx_bool bx_usb_uhci_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td) {
|
||||
@ -961,6 +950,32 @@ void bx_usb_uhci_c::iolight_timer()
|
||||
}
|
||||
}
|
||||
|
||||
void bx_usb_uhci_c::runtime_config_handler(void *this_ptr)
|
||||
{
|
||||
bx_usb_uhci_c *class_ptr = (bx_usb_uhci_c *) this_ptr;
|
||||
class_ptr->runtime_config();
|
||||
}
|
||||
|
||||
void bx_usb_uhci_c::runtime_config(void)
|
||||
{
|
||||
int i;
|
||||
char pname[6];
|
||||
|
||||
for (i = 0; i < BX_N_USB_UHCI_PORTS; i++) {
|
||||
// device change support
|
||||
if ((BX_UHCI_THIS hub.device_change & (1 << i)) != 0) {
|
||||
BX_INFO(("USB port #%d: device connect", i+1));
|
||||
sprintf(pname, "port%d", i + 1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_UHCI)));
|
||||
BX_UHCI_THIS hub.device_change &= ~(1 << i);
|
||||
}
|
||||
// forward to connected device
|
||||
if (BX_UHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
BX_UHCI_THIS hub.usb_port[i].device->runtime_config();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pci configuration space read callback handler
|
||||
Bit32u bx_usb_uhci_c::pci_read_handler(Bit8u address, unsigned io_len)
|
||||
{
|
||||
@ -1100,8 +1115,8 @@ const char *bx_usb_uhci_c::usb_param_handler(bx_param_string_c *param, int set,
|
||||
portnum = atoi((param->get_parent())->get_name()+4) - 1;
|
||||
bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none")));
|
||||
if ((portnum >= 0) && (portnum < BX_N_USB_UHCI_PORTS)) {
|
||||
BX_INFO(("USB port #%d experimental device change", portnum+1));
|
||||
if (empty && BX_UHCI_THIS hub.usb_port[portnum].status) {
|
||||
BX_INFO(("USB port #%d: device disconnect", portnum+1));
|
||||
if (BX_UHCI_THIS hub.usb_port[portnum].device != NULL) {
|
||||
type = BX_UHCI_THIS hub.usb_port[portnum].device->get_type();
|
||||
}
|
||||
|
@ -228,6 +228,8 @@ private:
|
||||
static void iolight_timer_handler(void *);
|
||||
void iolight_timer(void);
|
||||
|
||||
static void runtime_config_handler(void *);
|
||||
void runtime_config(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user