- add a layer of abstraction between the text-mode control panel in

gui/control.cc and the simulator.  Now all communication between
  the control panel and the rest of bochs goes through an object
  called bx_simulator_interface_c.
This commit is contained in:
Bryce Denney 2001-06-08 07:20:07 +00:00
parent b26e2fb362
commit f2af827a63
7 changed files with 276 additions and 42 deletions

View File

@ -82,6 +82,8 @@ extern "C" {
#include "debug/debug.h"
#include "bxversion.h"
#include "gui/siminterface.h"
//
// some macros to interface the CPU and memory to external environment
// so that these functions can be redirected to the debugger when
@ -316,6 +318,7 @@ class iofunctions {
#define CPU13LOG 38
#define CPU14LOG 39
#define CPU15LOG 40
#define CTRLLOG 41
public:
@ -377,6 +380,7 @@ public:
"CPUd",
"CPUe",
"CPUf",
"CTRL"
};
return logclass[i];
}
@ -551,16 +555,17 @@ extern bx_devices_c bx_devices;
#define BX_RESET_SOFTWARE 10
#define BX_RESET_HARDWARE 11
#define BX_PATHNAME_LEN 512
typedef struct {
char path[512];
char path[BX_PATHNAME_LEN];
unsigned type;
unsigned initial_status;
} bx_floppy_options;
typedef struct {
Boolean present;
char path[512];
char path[BX_PATHNAME_LEN];
unsigned int cylinders;
unsigned int heads;
unsigned int spt;
@ -569,7 +574,7 @@ typedef struct {
struct bx_cdrom_options
{
Boolean present;
char dev[512];
char dev[BX_PATHNAME_LEN];
Boolean inserted;
};

View File

@ -47,7 +47,7 @@ GUI_OBJS_MACOS = macintosh.o
GUI_OBJS_NOGUI = nogui.o
GUI_OBJS_TERM = term.o
GUI_OBJS_RFB = rfb.o
GUI_OBJS = gui.o control.o @GUI_OBJS@
GUI_OBJS = gui.o control.o siminterface.o @GUI_OBJS@
BX_INCDIRS = -I.. -I../iodev -I../@INSTRUMENT_DIR@
LOCAL_CXXFLAGS =
@ -59,7 +59,7 @@ LOCAL_CXXFLAGS =
BX_GUI_OBJS = $(GUI_OBJS)
BX_INCLUDES = iodev.h control.h
BX_INCLUDES = iodev.h control.h siminterface.h
.@CPP_SUFFIX@.o:
$(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@

View File

@ -1,13 +1,72 @@
#include "bochs.h"
/*
* gui/control.cc
* $Id: control.cc,v 1.2 2001-06-08 07:20:07 bdenney Exp $
*
* This is code for a text-mode control panel. Note that this file
* does NOT include bochs.h. Instead, it does all of its contact with
* the simulator through an object called SIM, defined in siminterface.cc
* and siminterface.h. This separation adds an extra layer of method
* calls before any work can be done, but the benefit is that the compiler
* enforces the rules. I can guarantee that control.cc doesn't call any
* I/O device objects directly, for example, because the bx_devices symbol
* isn't even defined in this context.
*
#define LOG_THIS genlog->
Musings by Bryce:
Now that there are some capabilities here, start moving toward the desired
model of separation of gui and simulator. Design a method-call interface
between objects which could later be turned into a network protocol.
void bx_control_panel_entry ()
{
bx_control_panel_main ();
Most messages go from the control panel to bochs, with bochs sending a response
back. Examples: turn on debug event logging for the PIC, or set IPS to
1.5million. Others kinds of messages go from bochs to the control panel.
Example: errors such as "disk image not found", status information such as the
current CPU state.
But because of the nature of a control panel, most information flows from
the control panel to Bochs. I think we can take advantage of this to
simplify the protocol. The GUI can ask bochs to do things and get a
response back. Bochs can tell the GUI something, but will not get a
response back.
The control panel should exist before the Bochs simulator starts, so that the
user can get their settings right before booting up a simulator. Once
bochs has begun, some settings can no longer be changed, such as how much
memory there is. Others can be changed at any time, like the value of IPS
or the name of the floppy disk images. If you had the bochs simulator
as a shared library, the GUI could let you choose which version of the
simulator library to load (one with debugging or SMP support or not,
for example).
When the control panel connects to Bochs, each needs to learn what the other
can do. Some versions of Bochs will have cdrom support, others will not.
Design a simple and general way for the two parties to describe what they
can do, so that the GUI can grey-out some menu choices, and Bochs knows
what the GUI can handle. I think Bochs should provide a list of
capabilities in something like the form of:
typedef struct { Bit16u id; String name; } bx_capability_t;
Only the negotiation of capabilities uses the string name, and for everything
else the 16-bit id is used (use htons() if sending over network). Each
capability is like a function that can be called on the remote object,
and each function needs an input list and a return value.
Hmm.... This sounds like reinventing function calls. Next I'm going to
say we need to implement prototypes and type checking.
*/
extern "C" {
#include <stdio.h>
#include <ctype.h>
#include <string.h>
}
#include "siminterface.h"
#define BX_PANIC(x) printf x
void bx_floppy_change ();
void bx_ips_change ();
void bx_log_options ();
/******************************************************************/
/* lots of code stolen from bximage.c */
@ -190,8 +249,8 @@ void bx_control_panel_main ()
fprintf (stderr, "Continuing simulation\n");
return;
case 11:
BX_PANIC(("You chose quit on the control panel"));
exit(1);
fprintf (stderr, "You chose quit on the control panel.\n");
SIM->quit_sim ();
break;
default:
fprintf (stderr, "Menu choice %d not implemented.\n", choice);
@ -202,31 +261,29 @@ void bx_control_panel_main ()
void bx_floppy_change ()
{
int which;
if (ask_int ("Change floppy 0 or 1? [0] ", 0, 1, 0, &which) < 0)
int drive;
if (ask_int ("Change floppy 0 or 1? [0] ", 0, 1, 0, &drive) < 0)
return;
char oldpath[1024], newpath[1024];
strcpy (oldpath, (which)? bx_options.floppyb.path : bx_options.floppya.path);
SIM->get_floppy_path (drive, oldpath, 1024);
char prompt[1024];
sprintf (prompt, "Enter new pathname: [%s] ", oldpath);
if (ask_string (prompt, oldpath, newpath) < 0)
return;
fprintf (stderr, "Changing floppy %d to new path %s\n", which, newpath);
strcpy ((which)? bx_options.floppyb.path : bx_options.floppya.path, newpath);
// notify
bx_devices.floppy->set_media_status (which, 0);
bx_devices.floppy->set_media_status (which, 1);
fprintf (stderr, "Changing floppy %d to new path %s\n", drive, newpath);
SIM->set_floppy_options (drive, 0, newpath);
SIM->set_floppy_options (drive, 1, newpath);
}
void bx_ips_change ()
{
char prompt[1024];
sprintf (prompt, "Type a new value for ips: [%d] ", bx_options.ips);
int oldips = SIM->getips ();
sprintf (prompt, "Type a new value for ips: [%d] ", oldips);
int newips;
if (ask_int (prompt, 1, 1<<30, bx_options.ips, &newips) < 0)
if (ask_int (prompt, 1, 1<<30, oldips, &newips) < 0)
return;
bx_options.ips = newips;
SIM->setips (newips);
}
static void bx_print_log_action_table ()
@ -235,11 +292,11 @@ static void bx_print_log_action_table ()
fprintf (stderr, "Current log settings:\n");
fprintf (stderr, " Debug Info Error Panic\n");
fprintf (stderr, "ID Device Action Action Action Action\n");
for (int i=0; i<io->get_n_logfns (); i++) {
logfunc_t *logfn = io->get_logfn (i);
fprintf (stderr, "%3d. %s ", i, logfn->getprefix ());
for (int j=0; j<MAX_LOGLEV; j++) {
fprintf (stderr, "%10s ", io->getaction (logfn->getonoff(j)));
int i, imax=SIM->get_n_log_modules ();
for (int i=0; i<imax; i++) {
fprintf (stderr, "%3d. %s ", i, SIM->get_prefix (i));
for (int j=0; j<SIM->get_max_log_level (); j++) {
fprintf (stderr, "%10s ", SIM->get_action_name (SIM->get_log_action (i, j)));
}
fprintf (stderr, "\n");
}
@ -254,19 +311,18 @@ void bx_log_options ()
while (!done) {
bx_print_log_action_table ();
int id, level, action;
int maxid = io->get_n_logfns ();
int maxid = SIM->get_n_log_modules ();
if (ask_int (log_options_prompt1, -1, maxid-1, -1, &id) < 0)
return;
if (id < 0) return;
logfunc_t *logfn = io->get_logfn (id);
fprintf (stderr, "Editing log options for the device %s\n", logfn->getprefix ());
for (level=0; level<MAX_LOGLEV; level++) {
fprintf (stderr, "Editing log options for the device %s\n", SIM->get_prefix (id));
for (level=0; level<SIM->get_max_log_level (); level++) {
char prompt[1024];
int default_action = logfn->getonoff (level);
sprintf (prompt, "Enter action for %s event: [%s] ", io->getlevel(level), io->getaction (default_action));
int default_action = SIM->get_log_action (id, level);
sprintf (prompt, "Enter action for %s event: [%s] ", SIM->get_log_level_name (level), SIM->get_action_name(default_action));
if (ask_menu (prompt, 3, log_level_choices, default_action, &action)<0)
return;
logfn->setonoff (level, action);
SIM->set_log_action (id, level, action);
}
}
}

View File

@ -1,5 +1 @@
void bx_control_panel_entry ();
void bx_control_panel_main ();
void bx_floppy_change ();
void bx_ips_change ();
void bx_log_options ();

View File

@ -51,6 +51,7 @@ bx_gui_c::bx_gui_c(void)
bx_gui_c::init(int argc, char **argv, unsigned tilewidth, unsigned tileheight)
{
specific_init(&bx_gui, argc, argv, tilewidth, tileheight, BX_HEADER_BAR_Y);
init_siminterface ();
// Define some bitmaps to use in the headerbar
BX_GUI_THIS floppyA_bmap_id = create_bitmap(bx_floppya_bmap,
@ -175,8 +176,7 @@ bx_gui_c::power_handler(void)
void
bx_gui_c::snapshot_handler(void)
{
BX_INFO(( "# SNAPSHOT callback (unimplemented)." ));
bx_control_panel_entry ();
bx_control_panel_main ();
}
void

140
bochs/gui/siminterface.cc Normal file
View File

@ -0,0 +1,140 @@
/*
* gui/siminterface.cc
* $Id: siminterface.cc,v 1.1 2001-06-08 07:20:07 bdenney Exp $
*
* Defines the actual link between bx_simulator_interface_c methods
* and the simulator. This file includes bochs.h because it needs
* access to bx_options and other simulator objecst and methods.
*
*/
#include "bochs.h"
// this dummy only exists for purposes of log functions. It would be
// lovely to get rid of it.
class siminterface_dummy_c : public logfunctions {
dummy () {
setprefix("[CTRL]"); // control panel
settype(CTRLLOG);
}
};
siminterface_dummy_c siminterface_dummy;
bx_simulator_interface_c *SIM = NULL;
#define LOG_THIS siminterface_dummy.
class bx_real_sim_c : public bx_simulator_interface_c {
void get_floppy_path (int drive, char *buffer, int size);
int get_floppy_present (int drive);
void set_floppy_options (int drive, int present, char *path);
int getips ();
void setips (int ips);
int get_n_log_modules ();
char *get_prefix (int mod);
int get_log_action (int mod, int level);
void set_log_action (int mod, int level, int action);
char *get_action_name (int action);
char *get_log_level_name (int level);
int get_max_log_level ();
void quit_sim ();
};
void init_siminterface ()
{
fprintf (stderr, "INIT Interface\n");
if (SIM == NULL) {
BX_INFO (("init_siminterface"));
SIM = new bx_real_sim_c();
}
}
bx_simulator_interface_c::bx_simulator_interface_c ()
{
}
void
bx_real_sim_c::get_floppy_path (int drive, char *buffer, int size)
{
strncpy (buffer,
(drive==0)? bx_options.floppya.path : bx_options.floppyb.path,
size);
}
int
bx_real_sim_c::get_floppy_present (int drive)
{
BX_ASSERT(0);
}
void
bx_real_sim_c::set_floppy_options (int drive, int present, char *path)
{
bx_devices.floppy->set_media_status (drive, present);
strncpy (
(drive==0)? bx_options.floppya.path : bx_options.floppyb.path,
path,
BX_PATHNAME_LEN);
}
int
bx_real_sim_c::getips ()
{
return bx_options.ips;
}
void
bx_real_sim_c::setips (int ips)
{
bx_options.ips = ips;
}
int
bx_real_sim_c::get_n_log_modules ()
{
return io->get_n_logfns ();
}
char *
bx_real_sim_c::get_prefix (int mod)
{
logfunc_t *logfn = io->get_logfn (mod);
return logfn->getprefix ();
}
int
bx_real_sim_c::get_log_action (int mod, int level)
{
logfunc_t *logfn = io->get_logfn (mod);
return logfn->getonoff (level);
}
void
bx_real_sim_c::set_log_action (int mod, int level, int action)
{
logfunc_t *logfn = io->get_logfn (mod);
return logfn->setonoff (level, action);
}
char *
bx_real_sim_c::get_action_name (int action)
{
return io->getaction (action);
}
char *
bx_real_sim_c::get_log_level_name (int level)
{
return io->getlevel (level);
}
int
bx_real_sim_c::get_max_log_level ()
{
return MAX_LOGLEV;
}
void
bx_real_sim_c::quit_sim () {
BX_PANIC (("Quit simulation command"));
::exit (0);
}

37
bochs/gui/siminterface.h Normal file
View File

@ -0,0 +1,37 @@
/*
* gui/siminterface.h
* $Id: siminterface.h,v 1.1 2001-06-08 07:20:07 bdenney Exp $
*
* Interface to the simulator, currently only used by control.cc.
* The base class bx_simulator_interface_c, contains only virtual functions
* and it defines the interface that control.cc is allowed to use.
* In siminterface.cc, a class called bx_real_sim_c is defined with
* bx_simulator_interface_c as its parent class. Bx_real_sim_c
* implements each of the functions. The separation into parent class
* and child class leaves the possibility of making a different child
* class that talks to the simulator in a different way (networking
* for example).
*
*/
class bx_simulator_interface_c {
public:
bx_simulator_interface_c ();
virtual void get_floppy_path (int drive, char *buffer, int size) {}
virtual int get_floppy_present (int drive) {return -1;}
virtual void set_floppy_options (int drive, int present, char *path) {}
virtual int getips () {return -1;}
virtual void setips (int ips) {}
virtual int get_n_log_modules () {return -1;}
virtual char *get_prefix (int mod) {return 0;}
virtual int get_log_action (int mod, int level) {return -1;}
virtual void set_log_action (int mod, int level, int action) {}
virtual char *get_action_name (int action) {return 0;}
virtual char *get_log_level_name (int level) {return 0;}
virtual int get_max_log_level () {return -1;}
virtual void quit_sim () {}
};
extern bx_simulator_interface_c *SIM;
extern void init_siminterface ();