diff options
Diffstat (limited to 'tools/ioemu/gui/siminterface.h')
-rw-r--r-- | tools/ioemu/gui/siminterface.h | 1460 |
1 files changed, 1460 insertions, 0 deletions
diff --git a/tools/ioemu/gui/siminterface.h b/tools/ioemu/gui/siminterface.h new file mode 100644 index 0000000000..9a028470c8 --- /dev/null +++ b/tools/ioemu/gui/siminterface.h @@ -0,0 +1,1460 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: siminterface.h,v 1.113.2.2 2004/02/06 22:14:35 danielg4 Exp $ +///////////////////////////////////////////////////////////////////////// +// +// Before I can describe what this file is for, I have to make the +// distinction between a configuration interface (CI) and the VGA display +// window (VGAW). I will try to avoid the term 'GUI' because it is unclear +// if that means CI or VGAW, and because not all interfaces are graphical +// anyway. +// +// The traditional Bochs screen is a window with a large VGA display panel and +// a series of buttons (floppy, cdrom, snapshot, power). Over the years, we +// have collected many implementations of the VGAW for different environments +// and platforms; each implementation is in a separate file under gui/*: +// x.cc, win32.cc, beos.cc, macintosh.cc, etc. The files gui.h and gui.cc +// define the platform independent part of the VGAW, leaving about 15 methods +// of the bx_gui_c class undefined. The platform dependent file must +// implement the remaining 15 methods. +// +// The configuration interface is relatively new, started by Bryce Denney in +// June 2001. The CI is intended to allow the user to edit a variety of +// configuration and runtime options. Some options, such as memory size or +// enabling the ethernet card, should only be changed before the simulation +// begins; others, such as floppy disk image, instructions per second, and +// logging options can be safely changed at runtime. The CI allows the user to +// make these changes. Before the CI existed, only a few things could be +// changed at runtime, all linked to clicking on the VGAW buttons. +// +// At the time that the CI was conceived, we were still debating what form the +// user interface part would take: stdin/stdout menus, a graphical application +// with menus and dialogs running in a separate thread, or even a tiny web +// server that you can connect to with a web browser. As a result the +// interface to the CI was designed so that the user interface of the CI +// could be replaced easily at compile time, or maybe even at runtime via +// a plugin architecture. To this end, we kept a clear separation between +// the user interface code and the siminterface, the code that interfaces with +// the simulator. The same siminterface is used all the time, while +// different implementations of the CI can be switched in reasonably easily. +// Only the CI code uses library specific graphics and I/O functions; the +// siminterface deals in portable abstractions and callback functions. +// The first CI implementation was a series of text mode menus implemented in +// control.cc. +// +// The configuration interface MUST use the siminterface methods to access the +// simulator. It should not modify settings in some device with code like +// bx_floppy.s.media[2].heads = 17. If such access is needed, then a +// siminterface method should be written to make the change on the CI's behalf. +// This separation is enforced by the fact that the CI does not even include +// bochs.h. You'll notice that control.cc include osdep.h, control.h, and +// siminterface.h, so it doesn't know what bx_floppy or bx_cpu_c are. I'm sure +// some people will say is overly restrictive and/or annoying. When I set it +// up this way, we were still talking about making the CI in a seperate +// process, where direct method calls would be impossible. Also, we have been +// considering turning devices into plugin modules which are dynamically +// linked. Any direct references to something like bx_floppy.s.media[2].heads +// would have to be reworked before a plugin interface was possible as well. +// +// The siminterface is the glue between the CI and the simulator. There is +// just one global instance of the siminterface object, which can be referred +// to by the global variable bx_simulator_interface_c *SIM; The base class +// bx_simulator_interface_c, contains only virtual functions and it defines the +// interface that the CI 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). If you were writing a user interface in a separate process, you +// could define a subclass of bx_simulator_interface_c called +// bx_siminterface_proxy_c which opens up a network port and turns all method +// calls into network sends and receives. Because the interface is defined +// entirely by the base class, the code that calls the methods would not know +// the difference. +// +// An important part of the siminterface implementation is the use of parameter +// classes, or bx_param_*. The parameter classes are described below, where +// they are declared. Search for "parameter classes" below for detals. +// +// Also this header file declares data structures for certain events that pass +// between the siminterface and the CI. Search for "event structures" below. + + + +////////////////////////////////////////////////////// +// BX_UI_TEXT should be set to 1 when the text mode configuration interface +// is compiled in. This gives each type of parameter a text_print and text_ask +// method (defined in gui/control.cc) so that you can call text_ask() on any +// kind of parameter to ask the user to edit the value. +// +// I have been considering whether to use the same strategy for the +// wxWindows interface, but I'm not sure if I like it. One problem is +// that in order to declare member functions that are useful for +// wxWindows, the wxWindows header files would have to be included +// before the param object definitions. That means that all the +// wxwindows headers would have be included when compiling every +// single bochs file. One of the things I like about the separation +// between the simulator and CI is that the two parts can be +// compiled without any knowledge of the other. Bochs doesn't include +// <wx.h>, and the wxwindows CI (wxmain.cc) doesn't need to include <bochs.h>. +// Aside from making compiles faster, this enforces the use of the siminterface +// so it keeps the interface clean (important when we may have multiple UI +// implementations for example). This argues for keeping UI-specific +// structures out of the simulator interface. It certainly works ok for the +// text interface, but that's because FILE* is standard and portable. +#define BX_UI_TEXT 1 + +////////////////////////////////////////////////////// + +// list of possible types for bx_param_c and descendant objects +typedef enum { + BXT_OBJECT = 201, + BXT_PARAM, + BXT_PARAM_NUM, + BXT_PARAM_BOOL, + BXT_PARAM_ENUM, + BXT_PARAM_STRING, + BXT_LIST +} bx_objtype; + +// list if parameter id values. The actual values are not important; +// it's only important that they all be different from each other. +typedef enum { + BXP_NULL = 301, + BXP_IPS, + BXP_REALTIME_PIT, + BXP_TEXT_SNAPSHOT_CHECK, + BXP_VGA_UPDATE_INTERVAL, + BXP_MOUSE_ENABLED, + BXP_MEM_SIZE, + BXP_ROM_PATH, + BXP_ROM_ADDRESS, + BXP_VGA_ROM_PATH, + BXP_OPTROM1_PATH, + BXP_OPTROM2_PATH, + BXP_OPTROM3_PATH, + BXP_OPTROM4_PATH, + BXP_OPTROM1_ADDRESS, + BXP_OPTROM2_ADDRESS, + BXP_OPTROM3_ADDRESS, + BXP_OPTROM4_ADDRESS, + BXP_KBD_SERIAL_DELAY, + BXP_KBD_PASTE_DELAY, + BXP_KBD_TYPE, + BXP_FLOPPY_CMD_DELAY, + BXP_FLOPPYA_DEVTYPE, + BXP_FLOPPYA_PATH, + BXP_FLOPPYA_TYPE, + BXP_FLOPPYA_STATUS, + BXP_FLOPPYA, + BXP_FLOPPYB_DEVTYPE, + BXP_FLOPPYB_PATH, + BXP_FLOPPYB_TYPE, + BXP_FLOPPYB_STATUS, + BXP_FLOPPYB, + + BXP_ATA0_MENU, + BXP_ATA1_MENU, + BXP_ATA2_MENU, + BXP_ATA3_MENU, +#define BXP_ATAx_MENU(i) (BXP_ATA0_MENU + (i)) + BXP_ATA0, + BXP_ATA1, + BXP_ATA2, + BXP_ATA3, +#define BXP_ATAx(i) (BXP_ATA0 + (i)) + BXP_ATA0_PRESENT, + BXP_ATA1_PRESENT, + BXP_ATA2_PRESENT, + BXP_ATA3_PRESENT, +#define BXP_ATAx_PRESENT(i) (BXP_ATA0_PRESENT + (i)) + BXP_ATA0_IOADDR1, + BXP_ATA1_IOADDR1, + BXP_ATA2_IOADDR1, + BXP_ATA3_IOADDR1, +#define BXP_ATAx_IOADDR1(i) (BXP_ATA0_IOADDR1 + (i)) + BXP_ATA0_IOADDR2, + BXP_ATA1_IOADDR2, + BXP_ATA2_IOADDR2, + BXP_ATA3_IOADDR2, +#define BXP_ATAx_IOADDR2(i) (BXP_ATA0_IOADDR2 + (i)) + BXP_ATA0_IRQ, + BXP_ATA1_IRQ, + BXP_ATA2_IRQ, + BXP_ATA3_IRQ, +#define BXP_ATAx_IRQ(i) (BXP_ATA0_IRQ + (i)) + + BXP_ATA0_MASTER, + BXP_ATA0_SLAVE, + BXP_ATA1_MASTER, + BXP_ATA1_SLAVE, + BXP_ATA2_MASTER, + BXP_ATA2_SLAVE, + BXP_ATA3_MASTER, + BXP_ATA3_SLAVE, +#define BXP_ATAx_DEVICE(i, s) (BXP_ATA0_MASTER + (2*(i)) + (s)) + +#define BXP_PARAMS_PER_ATA_DEVICE 12 + + BXP_ATA0_MASTER_PRESENT, + BXP_ATA0_SLAVE_PRESENT, + BXP_ATA1_MASTER_PRESENT, + BXP_ATA1_SLAVE_PRESENT, + BXP_ATA2_MASTER_PRESENT, + BXP_ATA2_SLAVE_PRESENT, + BXP_ATA3_MASTER_PRESENT, + BXP_ATA3_SLAVE_PRESENT, +#define BXP_ATAx_DEVICE_PRESENT(i, s) (BXP_ATA0_MASTER_PRESENT + (2*(i)) + (s)) + + BXP_ATA0_MASTER_TYPE, + BXP_ATA0_SLAVE_TYPE, + BXP_ATA1_MASTER_TYPE, + BXP_ATA1_SLAVE_TYPE, + BXP_ATA2_MASTER_TYPE, + BXP_ATA2_SLAVE_TYPE, + BXP_ATA3_MASTER_TYPE, + BXP_ATA3_SLAVE_TYPE, +#define BXP_ATAx_DEVICE_TYPE(i, s) (BXP_ATA0_MASTER_TYPE + (2*(i)) + (s)) + + BXP_ATA0_MASTER_MODE, + BXP_ATA0_SLAVE_MODE, + BXP_ATA1_MASTER_MODE, + BXP_ATA1_SLAVE_MODE, + BXP_ATA2_MASTER_MODE, + BXP_ATA2_SLAVE_MODE, + BXP_ATA3_MASTER_MODE, + BXP_ATA3_SLAVE_MODE, +#define BXP_ATAx_DEVICE_MODE(i, s) (BXP_ATA0_MASTER_MODE + (2*(i)) + (s)) + + BXP_ATA0_MASTER_PATH, + BXP_ATA0_SLAVE_PATH, + BXP_ATA1_MASTER_PATH, + BXP_ATA1_SLAVE_PATH, + BXP_ATA2_MASTER_PATH, + BXP_ATA2_SLAVE_PATH, + BXP_ATA3_MASTER_PATH, + BXP_ATA3_SLAVE_PATH, +#define BXP_ATAx_DEVICE_PATH(i, s) (BXP_ATA0_MASTER_PATH + (2*(i)) + (s)) + + BXP_ATA0_MASTER_CYLINDERS, + BXP_ATA0_SLAVE_CYLINDERS, + BXP_ATA1_MASTER_CYLINDERS, + BXP_ATA1_SLAVE_CYLINDERS, + BXP_ATA2_MASTER_CYLINDERS, + BXP_ATA2_SLAVE_CYLINDERS, + BXP_ATA3_MASTER_CYLINDERS, + BXP_ATA3_SLAVE_CYLINDERS, +#define BXP_ATAx_DEVICE_CYLINDERS(i, s) (BXP_ATA0_MASTER_CYLINDERS + (2*(i)) + (s)) + + BXP_ATA0_MASTER_HEADS, + BXP_ATA0_SLAVE_HEADS, + BXP_ATA1_MASTER_HEADS, + BXP_ATA1_SLAVE_HEADS, + BXP_ATA2_MASTER_HEADS, + BXP_ATA2_SLAVE_HEADS, + BXP_ATA3_MASTER_HEADS, + BXP_ATA3_SLAVE_HEADS, +#define BXP_ATAx_DEVICE_HEADS(i, s) (BXP_ATA0_MASTER_HEADS + (2*(i)) + (s)) + + BXP_ATA0_MASTER_SPT, + BXP_ATA0_SLAVE_SPT, + BXP_ATA1_MASTER_SPT, + BXP_ATA1_SLAVE_SPT, + BXP_ATA2_MASTER_SPT, + BXP_ATA2_SLAVE_SPT, + BXP_ATA3_MASTER_SPT, + BXP_ATA3_SLAVE_SPT, +#define BXP_ATAx_DEVICE_SPT(i, s) (BXP_ATA0_MASTER_SPT + (2*(i)) + (s)) + + BXP_ATA0_MASTER_STATUS, + BXP_ATA0_SLAVE_STATUS, + BXP_ATA1_MASTER_STATUS, + BXP_ATA1_SLAVE_STATUS, + BXP_ATA2_MASTER_STATUS, + BXP_ATA2_SLAVE_STATUS, + BXP_ATA3_MASTER_STATUS, + BXP_ATA3_SLAVE_STATUS, +#define BXP_ATAx_DEVICE_STATUS(i, s) (BXP_ATA0_MASTER_STATUS + (2*(i)) + (s)) + + BXP_ATA0_MASTER_MODEL, + BXP_ATA0_SLAVE_MODEL, + BXP_ATA1_MASTER_MODEL, + BXP_ATA1_SLAVE_MODEL, + BXP_ATA2_MASTER_MODEL, + BXP_ATA2_SLAVE_MODEL, + BXP_ATA3_MASTER_MODEL, + BXP_ATA3_SLAVE_MODEL, +#define BXP_ATAx_DEVICE_MODEL(i, s) (BXP_ATA0_MASTER_MODEL + (2*(i)) + (s)) + + BXP_ATA0_MASTER_BIOSDETECT, + BXP_ATA0_SLAVE_BIOSDETECT, + BXP_ATA1_MASTER_BIOSDETECT, + BXP_ATA1_SLAVE_BIOSDETECT, + BXP_ATA2_MASTER_BIOSDETECT, + BXP_ATA2_SLAVE_BIOSDETECT, + BXP_ATA3_MASTER_BIOSDETECT, + BXP_ATA3_SLAVE_BIOSDETECT, +#define BXP_ATAx_DEVICE_BIOSDETECT(i, s) (BXP_ATA0_MASTER_BIOSDETECT + (2*(i)) + (s)) + + BXP_ATA0_MASTER_TRANSLATION, + BXP_ATA0_SLAVE_TRANSLATION, + BXP_ATA1_MASTER_TRANSLATION, + BXP_ATA1_SLAVE_TRANSLATION, + BXP_ATA2_MASTER_TRANSLATION, + BXP_ATA2_SLAVE_TRANSLATION, + BXP_ATA3_MASTER_TRANSLATION, + BXP_ATA3_SLAVE_TRANSLATION, +#define BXP_ATAx_DEVICE_TRANSLATION(i, s) (BXP_ATA0_MASTER_TRANSLATION + (2*(i)) + (s)) + + BXP_ATA0_MASTER_JOURNAL, + BXP_ATA0_SLAVE_JOURNAL, + BXP_ATA1_MASTER_JOURNAL, + BXP_ATA1_SLAVE_JOURNAL, + BXP_ATA2_MASTER_JOURNAL, + BXP_ATA2_SLAVE_JOURNAL, + BXP_ATA3_MASTER_JOURNAL, + BXP_ATA3_SLAVE_JOURNAL, +#define BXP_ATAx_DEVICE_JOURNAL(i, s) (BXP_ATA0_MASTER_JOURNAL + (2*(i)) + (s)) + +#define BXP_PARAMS_PER_SERIAL_PORT 2 + BXP_COM1_ENABLED, + BXP_COM1_PATH, + BXP_COM2_ENABLED, + BXP_COM2_PATH, + BXP_COM3_ENABLED, + BXP_COM3_PATH, + BXP_COM4_ENABLED, + BXP_COM4_PATH, +#define BXP_PARAMS_PER_USB_HUB 3 + BXP_USB1_ENABLED, + BXP_USB1_IOADDR, + BXP_USB1_IRQ, + BXP_PRIVATE_COLORMAP, + BXP_FULLSCREEN, + BXP_SCREENMODE, + BXP_I440FX_SUPPORT, + BXP_NEWHARDDRIVESUPPORT, + BXP_LOG_FILENAME, + BXP_LOG_PREFIX, + BXP_DEBUGGER_LOG_FILENAME, + BXP_CMOS_PATH, + BXP_CMOS_IMAGE, + BXP_CLOCK, + BXP_CLOCK_TIME0, + BXP_CLOCK_SYNC, + BXP_LOAD32BITOS_WHICH, + BXP_LOAD32BITOS_PATH, + BXP_LOAD32BITOS_IOLOG, + BXP_LOAD32BITOS_INITRD, + BXP_LOAD32BITOS, + BXP_BOOTDRIVE, + BXP_FLOPPYSIGCHECK, + BXP_MENU_MAIN, + BXP_MENU_MEMORY, + BXP_MENU_INTERFACE, + BXP_MENU_DISK, + BXP_MENU_SERIAL_PARALLEL, + BXP_MENU_SOUND, + BXP_MENU_KEYBOARD, + BXP_MENU_MISC, + BXP_MENU_MISC_2, + BXP_MENU_RUNTIME, + BXP_MAX_IPS, + BXP_NE2K_PRESENT, + BXP_NE2K_IOADDR, + BXP_NE2K_IRQ, + BXP_NE2K_MACADDR, + BXP_NE2K_ETHMOD, + BXP_NE2K_ETHDEV, + BXP_NE2K_SCRIPT, + BXP_NE2K, + BXP_SB16_PRESENT, + BXP_SB16_MIDIFILE, + BXP_SB16_WAVEFILE, + BXP_SB16_LOGFILE, + BXP_SB16_MIDIMODE, + BXP_SB16_WAVEMODE, + BXP_SB16_LOGLEVEL, + BXP_SB16_DMATIMER, + BXP_SB16, +#define BXP_PARAMS_PER_PARALLEL_PORT 2 + BXP_PARPORT1_ENABLED, + BXP_PARPORT1_OUTFILE, + BXP_PARPORT2_ENABLED, + BXP_PARPORT2_OUTFILE, + BXP_KEYBOARD_USEMAPPING, + BXP_KEYBOARD_MAP, + BXP_KEYBOARD, + BXP_USER_SHORTCUT, + BXP_ASK_FOR_PATHNAME, // for general file selection dialog + BXP_BOCHS_START, // How Bochs starts + // experiment: add params for CPU registers + BXP_CPU_PARAMETERS, + BXP_CPU_EAX, + BXP_CPU_EBX, + BXP_CPU_ECX, + BXP_CPU_EDX, + BXP_CPU_EBP, + BXP_CPU_ESI, + BXP_CPU_EDI, + BXP_CPU_ESP, + BXP_CPU_EIP, + BXP_CPU_SEG_CS, + BXP_CPU_SEG_DS, + BXP_CPU_SEG_SS, + BXP_CPU_SEG_ES, + BXP_CPU_SEG_FS, + BXP_CPU_SEG_GS, + BXP_CPU_SEG_LDTR, + BXP_CPU_SEG_TR, + BXP_CPU_GDTR_BASE, + BXP_CPU_GDTR_LIMIT, + BXP_CPU_IDTR_BASE, + BXP_CPU_IDTR_LIMIT, + BXP_CPU_EFLAGS, + BXP_CPU_EFLAGS_ID, + BXP_CPU_EFLAGS_VIP, + BXP_CPU_EFLAGS_VIF, + BXP_CPU_EFLAGS_AC, + BXP_CPU_EFLAGS_VM, + BXP_CPU_EFLAGS_RF, + BXP_CPU_EFLAGS_NT, + BXP_CPU_EFLAGS_IOPL, + BXP_CPU_EFLAGS_OF, + BXP_CPU_EFLAGS_DF, + BXP_CPU_EFLAGS_IF, + BXP_CPU_EFLAGS_TF, + BXP_CPU_EFLAGS_SF, + BXP_CPU_EFLAGS_ZF, + BXP_CPU_EFLAGS_AF, + BXP_CPU_EFLAGS_PF, + BXP_CPU_EFLAGS_CF, + BXP_CPU_DR0, + BXP_CPU_DR1, + BXP_CPU_DR2, + BXP_CPU_DR3, + BXP_CPU_DR6, + BXP_CPU_DR7, + BXP_CPU_TR3, + BXP_CPU_TR4, + BXP_CPU_TR5, + BXP_CPU_TR6, + BXP_CPU_TR7, + BXP_CPU_CR0, + BXP_CPU_CR1, + BXP_CPU_CR2, + BXP_CPU_CR3, + BXP_CPU_CR4, + // a few parameters for the keyboard + BXP_KBD_PARAMETERS, + BXP_KBD_PARE, + BXP_KBD_TIM , + BXP_KBD_AUXB, + BXP_KBD_KEYL, + BXP_KBD_C_D, + BXP_KBD_SYSF, + BXP_KBD_INPB, + BXP_KBD_OUTB, + BXP_KBD_TIMER_PENDING, + BXP_KBD_IRQ1_REQ, + BXP_KBD_IRQ12_REQ, +#if BX_DEBUGGER + // in debugger, is the simulation running (continue command) or waiting. + // This is only modified by debugger code, not by the user. + BXP_DEBUG_RUNNING, +#endif + BXP_SEL_CONFIG_INTERFACE, + BXP_SEL_DISPLAY_LIBRARY, + BXP_THIS_IS_THE_LAST // used to determine length of list +} bx_id; + +// use x=1,2,3,4 +#define BXP_COMx_ENABLED(x) \ + (bx_id)(BXP_COM1_ENABLED + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT)) +#define BXP_COMx_PATH(x) \ + (bx_id)(BXP_COM1_PATH + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT)) + +// use x=1 +#define BXP_USBx_ENABLED(x) \ + (bx_id)(BXP_USB1_ENABLED + (((x)-1)*BXP_PARAMS_PER_USB_HUB)) +#define BXP_USBx_IOADDR(x) \ + (bx_id)(BXP_USB1_IOADDR + (((x)-1)*BXP_PARAMS_PER_USB_HUB)) +#define BXP_USBx_IRQ(x) \ + (bx_id)(BXP_USB1_IRQ + (((x)-1)*BXP_PARAMS_PER_USB_HUB)) + +// use x=1,2 +#define BXP_PARPORTx_ENABLED(x) \ + (bx_id)(BXP_PARPORT1_ENABLED + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT)) +#define BXP_PARPORTx_OUTFILE(x) \ + (bx_id)(BXP_PARPORT1_OUTFILE + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT)) + +typedef enum { + BX_TOOLBAR_UNDEFINED, + BX_TOOLBAR_FLOPPYA, + BX_TOOLBAR_FLOPPYB, + BX_TOOLBAR_CDROMD, + BX_TOOLBAR_RESET, + BX_TOOLBAR_POWER, + BX_TOOLBAR_COPY, + BX_TOOLBAR_PASTE, + BX_TOOLBAR_SNAPSHOT, + BX_TOOLBAR_CONFIG, + BX_TOOLBAR_MOUSE_EN, + BX_TOOLBAR_USER +} bx_toolbar_buttons; + +// Log level defines +typedef enum { + LOGLEV_DEBUG = 0, + LOGLEV_INFO, + LOGLEV_ERROR, + LOGLEV_PANIC, + LOGLEV_PASS, + N_LOGLEV +} bx_log_levels; + +// types of reset +#define BX_RESET_SOFTWARE 10 +#define BX_RESET_HARDWARE 11 + +//cdrom +#define BX_EJECTED 10 +#define BX_INSERTED 11 + +// boot devices +#define BX_BOOT_FLOPPYA 0 +#define BX_BOOT_DISKC 1 +#define BX_BOOT_CDROM 2 + +// loader hack +#define Load32bitOSNone 0 +#define Load32bitOSLinux 1 +#define Load32bitOSNullKernel 2 // being developed for plex86 +#define Load32bitOSLast 2 + +/////////////////////////////////////////////////////////////////// +// event structures for communication between simulator and CI +/////////////////////////////////////////////////////////////////// +// Because the CI (configuration interface) might be in a different +// thread or even a different process, we pass events encoded in data +// structures to it instead of just calling functions. Each type of +// event is declared as a different structure, and then all those +// structures are squished into a union in BxEvent. (BTW, this is +// almost exactly how X windows event structs work.) +// +// These are simple structs, unblemished by C++ methods and tricks. +// No matter what event type it is, we allocate a BxEvent for each +// one, as opposed to trying to save a few bytes on small events by +// allocating only the bytes necessary for it. This makes it easy and +// fast to store events in a queue, like this +// BxEvent event_queue[MAX_EVENTS]; +// +// Events come in two varieties: synchronous and asynchronous. We +// have to worry about sync and async events because the CI and the +// simulation may be running in different threads. An async event is +// the simplest. Whichever thread originates the event just builds +// the data structure, sends it, and then continues with its business. +// Async events can go in either direction. Synchronous events +// require the other thread to "respond" before the originating thread +// can continue. It's like a function with a return value; you can't +// continue until you get the return value back. +// +// Examples: +// +// async event: In the wxWindows implementation, both the CI and the +// VGAW operate in the wxWindows GUI thread. When the user presses a +// key, wxWindows sends a wxKeyEvent to the VGAW event handler code in +// wx.cc. The VGAW handler then builds a BxEvent with +// type=BX_ASYNC_EVT_KEY, and fills in the bx_key and raw_scancode +// fields. The asynchronous event is placed on the event_queue for +// the simulator, then the VGAW handler returns. (With wxWindows and +// many other graphical libaries, the event handler must return +// quickly because the window will not be updated until it's done.) +// Some time later, the simulator reaches the point where it checks +// for new events from the user (actually controlled by +// bx_keyb_c::periodic() in iodev/keyboard.cc) and calls +// bx_gui.handle_events(). Then all the events in the queue are +// processed by the simulator. There is no "response" sent back to +// the originating thread. +// +// sync event: Sometimes the simulator reaches a point where it needs +// to ask the user how to proceed. In this case, the simulator sends +// a synchronous event because it requires a response before it can +// continue. It builds an event structure, perhaps with type +// BX_SYNC_EVT_ASK_PARAM, sends it to the user interface +// using the event handler function defined by set_notify_callback(), +// and pauses the simulation. The user interface asks the user the +// question, and puts the answer into the BxEvent.retcode field. The +// event handler function returns the modified BxEvent with retcode +// filled in, and the simulation continues. The details of this +// transaction can be complicated if the simulation and CI are not +// in the same thread, but the behavior is as described. +// + +///// types and definitions used in event structures + +#define BX_EVT_IS_ASYNC(type) ((type) > __ALL_EVENTS_BELOW_ARE_ASYNC__) + +typedef enum { + __ALL_EVENTS_BELOW_ARE_SYNCHRONOUS__ = 2000, + BX_SYNC_EVT_GET_PARAM, // CI -> simulator -> CI + BX_SYNC_EVT_ASK_PARAM, // simulator -> CI -> simulator + BX_SYNC_EVT_TICK, // simulator -> CI, wait for response. + BX_SYNC_EVT_LOG_ASK, // simulator -> CI, wait for response. + BX_SYNC_EVT_GET_DBG_COMMAND, // simulator -> CI, wait for response. + __ALL_EVENTS_BELOW_ARE_ASYNC__, + BX_ASYNC_EVT_KEY, // vga window -> simulator + BX_ASYNC_EVT_MOUSE, // vga window -> simulator + BX_ASYNC_EVT_SET_PARAM, // CI -> simulator + BX_ASYNC_EVT_LOG_MSG, // simulator -> CI + BX_ASYNC_EVT_DBG_MSG, // simulator -> CI + BX_ASYNC_EVT_VALUE_CHANGED, // simulator -> CI + BX_ASYNC_EVT_TOOLBAR, // CI -> simulator + BX_ASYNC_EVT_REFRESH // simulator -> CI +} BxEventType; + +typedef union { + Bit32s s32; + char *charptr; +} AnyParamVal; + +// Define substructures which make up the interior of BxEvent. The +// substructures, such as BxKeyEvent or BxMouseEvent, should never be +// allocated on their own. They are only intended to be used within +// the union in the BxEvent structure. + +// Event type: BX_SYNC_EVT_TICK +// +// A tick event is synchronous, sent from the simulator to the GUI. The +// event doesn't do anything visible. Primarily it gives the GUI a chance +// to tell the simulator to quit, if necessary. There may be other uses +// for the tick in the future, such as giving some kind of regular +// status report or mentioning watched values that changed, but so far +// it's just for that one thing. There is no data associated with a +// tick event. + +// Event type: BX_ASYNC_EVT_KEY +// +// A key event can be sent from the VGA window to the Bochs simulator. +// It is asynchronous. +typedef struct { + // what was pressed? This is a BX_KEY_* value. For key releases, + // BX_KEY_RELEASED is ORed with the base BX_KEY_*. + Bit32u bx_key; + bx_bool raw_scancode; +} BxKeyEvent; + +// Event type: BX_ASYNC_EVT_MOUSE +// +// A mouse event can be sent from the VGA window to the Bochs +// simulator. It is asynchronous. Currently unused because mouse +// events aren't implemented in our wxWindows code yet. +typedef struct { + // type is BX_EVT_MOUSE + Bit16s dx, dy; // mouse motion delta + Bit8u buttons; // which buttons are pressed. + // bit 0: 1=left button down, 0=up + // bit 1: 1=right button down, 0=up +} BxMouseEvent; + +// Event type: BX_SYNC_EVT_GET_PARAM, BX_ASYNC_EVT_SET_PARAM +// +// Parameter set/get events are initiated by the CI, since Bochs can +// always access the parameters directly. So far, I haven't used +// these event types. In the CI I just call +// SIM->get_param(parameter_id) to get a pointer to the bx_param_c +// object and then call the get/set methods. This is okay for +// configuration since bochs is not running. However it could be +// dangerous for the GUI thread to poke around in Bochs structures +// while the thread is running. For these cases, I may have to be +// more careful and actually build get/set events and place them on +// Bochs's event queue to be processed during SIM->periodic() or +// something. +typedef struct { + // type is BX_EVT_GET_PARAM, BX_EVT_SET_PARAM + class bx_param_c *param; // pointer to param structure + AnyParamVal val; +} BxParamEvent; + +// Event type: BX_SYNC_EVT_ASK_PARAM +// Synchronous event sent from the simulator to the CI. This tells the +// CI to ask the user to choose the value of a parameter. The CI may +// need to discover the type of parameter so that it can use the right +// kind of graphical display. The BxParamEvent is used for these events +// too. +// FIXME: at the moment the GUI implements the ASK_PARAM event for just +// a few parameter types. I need to implement the event for all parameter +// types. + +// Event type: BX_ASYNC_EVT_VALUE_CHANGED +// +// Asynchronous event sent from the simulator to the CI, telling it that +// some value that it (hopefully) cares about has changed. This isn't +// being used yet, but a good example is in a debugger interface, you might +// want to maintain a reasonably current display of the PC or some other +// simulation state. The CI would set some kind of event mask (which +// doesn't exist now of course) and then when certain values change, the +// simulator would send this event so that the CI can update. We may need +// some kind of "flow control" since the simulator will be able to produce +// new events much faster than the gui can accept them. + +// Event type: BX_ASYNC_EVT_LOG_MSG (unused) +// +// Asynchronous event from the simulator to the CI. When a BX_PANIC, +// BX_ERROR, BX_INFO, or BX_DEBUG is found in the simulator code, this +// event type can be used to inform the CI of the condition. There is +// no point in sending messages to the CI that will not be displayed; these +// would only slow the simulation. So we will need some mechanism for +// choosing what kinds of events will be delivered to the CI. Normally, +// you wouldn't want to look at the log unless something is going wrong. +// At that point, you might want to open up a window to watch the debug +// messages from one or two devices only. +// +// Idea: Except for panics that require user attention to continue, it +// might be most efficient to just append log messages to a file. +// When the user wants to look at the log messages, the gui can reopen +// the file (read only), skip to the end, and look backward for a +// reasonable number of lines to display (200?). This allows it to +// skip over huge bursts of log entries without allocating memory, +// synchronizing threads, etc. for each. +typedef struct { + Bit8u level; + const char *prefix; + const char *msg; +} BxLogMsgEvent; + +// Event type: BX_ASYNC_EVT_DBG_MSG (unused) +// +// Also uses BxLogMsgEvent, but this is a message to be displayed in +// the debugger history window. + +// Event type: BX_SYNC_EVT_LOG_ASK +// +// This is a synchronous version of BX_ASYNC_EVT_LOG_MSG, which is used +// when the "action=ask" setting is used. If the simulator runs into a +// panic, it sends a synchronous BX_SYNC_EVT_LOG_ASK to the CI to be +// displayed. The CI shows a dialog that asks if the user wants to +// continue, quit, etc. and sends the answer back to the simulator. +// This event also uses BxLogMsgEvent. +enum { + BX_LOG_ASK_CHOICE_CONTINUE, + BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS, + BX_LOG_ASK_CHOICE_DIE, + BX_LOG_ASK_CHOICE_DUMP_CORE, + BX_LOG_ASK_CHOICE_ENTER_DEBUG, + BX_LOG_ASK_N_CHOICES +}; + +// Event type: BX_SYNC_EVT_GET_DBG_COMMAND +// +// This is a synchronous event sent from the simulator to the debugger +// requesting the next action. In a text mode debugger, this would prompt +// the user for the next command. When a new command is ready, the +// synchronous event is sent back with its fields filled in. +typedef struct { + char *command; // null terminated string. allocated by debugger interface + // with new operator, freed by simulator with delete. +} BxDebugCommand; + + + +// Event type: BX_EVT_TOOLBAR +// Asynchronous event from the VGAW to the simulator, sent when the user +// clicks on a toolbar button. This may one day become something more +// general, like a command event, but at the moment it's only needed for +// the toolbar events. +typedef struct { + bx_toolbar_buttons button; + bool on; // for toggling buttons, on=true means the toolbar button is + // pressed. on=false means it is not pressed. +} BxToolbarEvent; + +// The BxEvent structure should be used for all events. Every event has +// a type and a spot for a return code (only used for synchronous events). +typedef struct { + BxEventType type; // what kind is this? + Bit32s retcode; // sucess or failure. only used for synchronous events. + union { + BxKeyEvent key; + BxMouseEvent mouse; + BxParamEvent param; + BxLogMsgEvent logmsg; + BxToolbarEvent toolbar; + BxDebugCommand debugcmd; + } u; +} BxEvent; + + +//////////////////////////////////////////////////////////////////// +// parameter classes: bx_param_c and family +//////////////////////////////////////////////////////////////////// +// +// All variables that can be configured through the CI are declared as +// "parameters" or objects of type bx_param_*. There is a bx_param_* +// class for each type of data that the user would need to see and +// edit, e.g. integer, boolean, enum, string, filename, or list of +// other parameters. The purpose of the bx_param_* class, in addition +// to storing the parameter's value, is to hold the name, description, +// and constraints on the value. The bx_param_* class should hold +// everything that the CI would need to display the value and allow +// the user to modify it. For integer parameters, the minimum and +// maximum allowed value can be defined, and the base in which it +// should be displayed and interpreted. For enums, the +// bx_param_enum_c structure includes the list of values which the +// parameter can have. +// +// Also, some parameter classes support get/set callback functions to +// allow arbitrary code to be executed when the parameter is get/set. +// An example of where this is useful: if you disable the NE2K card, +// the set() handler for that parameter can tell the user interface +// that the NE2K's irq, I/O address, and mac address should be +// disabled (greyed out, hidden, or made inaccessible). The get/set +// methods can also check if the set() value is acceptable using +// whatever means and override it. +// +// The parameter concept is similar to the use of parameters in JavaBeans. + +class bx_object_c; +class bx_param_c; +class bx_param_num_c; +class bx_param_enum_c; +class bx_param_bool_c; +class bx_param_string_c; +class bx_param_filename_c; +class bx_list_c; + +class BOCHSAPI bx_object_c { +private: + bx_id id; + bx_objtype type; +protected: + void set_type (bx_objtype type); +public: + bx_object_c (bx_id id); + bx_id get_id () { return id; } + Bit8u get_type () { return type; } +}; + +class BOCHSAPI bx_param_c : public bx_object_c { + BOCHSAPI_CYGONLY static const char *default_text_format; +protected: + char *name; + char *description; + char *label; // label string for text menus and gui dialogs + const char *text_format; // printf format string. %d for ints, %s for strings, etc. + char *ask_format; // format string for asking for a new value + int runtime_param; + int enabled; +public: + bx_param_c (bx_id id, char *name, char *description); + void set_format (const char *format) {text_format = format;} + const char *get_format () {return text_format;} + void set_ask_format (char *format) {ask_format = format; } + char *get_ask_format () {return ask_format;} + void set_label (char *text) {label = text;} + char *get_label () {return label;} + void set_runtime_param (int val) { runtime_param = val; } + int get_runtime_param () { return runtime_param; } + char *get_name () { return name; } + char *get_description () { return description; } + int get_enabled () { return enabled; } + virtual void set_enabled (int enabled) { this->enabled = enabled; } + void reset () {} + int getint () {return -1;} + static const char* set_default_format (const char *f); + static const char *get_default_format () { return default_text_format; } + virtual bx_list_c *get_dependent_list () { return NULL; } +#if BX_UI_TEXT + virtual void text_print (FILE *fp) {} + virtual int text_ask (FILE *fpin, FILE *fpout) {return -1;} +#endif +}; + +typedef Bit64s (*param_event_handler)(class bx_param_c *, int set, Bit64s val); +typedef int (*param_enable_handler)(class bx_param_c *, int en); + +class BOCHSAPI bx_param_num_c : public bx_param_c { + BOCHSAPI_CYGONLY static Bit32u default_base; + // The dependent_list is initialized to NULL. If dependent_list is modified + // to point to a bx_list_c of other parameters, the set() method of + // bx_param_bool_c will enable those parameters when this bool is true, and + // disable them when this bool is false. + bx_list_c *dependent_list; + void update_dependents (); +protected: + Bit64s min, max, initial_val; + union _uval_ { + Bit64s number; // used by bx_param_num_c + Bit64s *p64bit; // used by bx_shadow_num_c + Bit32s *p32bit; // used by bx_shadow_num_c + Bit16s *p16bit; // used by bx_shadow_num_c + Bit8s *p8bit; // used by bx_shadow_num_c + bx_bool *pbool; // used by bx_shadow_bool_c + } val; + param_event_handler handler; + param_enable_handler enable_handler; + int base; + Bit32u options; +public: + enum { + // When a bx_param_num_c is displayed in dialog, USE_SPIN_CONTROL controls + // whether a spin control should be used instead of a simple text control. + USE_SPIN_CONTROL = (1<<0) + } bx_numopt_bits; + bx_param_num_c (bx_id id, + char *name, + char *description, + Bit64s min, Bit64s max, Bit64s initial_val); + void reset (); + void set_handler (param_event_handler handler); + void set_enable_handler (param_enable_handler handler); + virtual bx_list_c *get_dependent_list () { return dependent_list; } + void set_dependent_list (bx_list_c *l); + virtual void set_enabled (int enabled); + virtual Bit32s get () { return (Bit32s) get64(); } + virtual Bit64s get64 (); + virtual void set (Bit64s val); + void set_base (int base) { this->base = base; } + void set_initial_val (Bit64s initial_val); + int get_base () { return base; } + void set_range (Bit64u min, Bit64u max); + Bit64s get_min () { return min; } + Bit64s get_max () { return max; } + static Bit32u set_default_base (Bit32u val); + static Bit32u get_default_base () { return default_base; } + void set_options (Bit32u options) { this->options = options; } + Bit32u get_options () { return options; } +#if BX_UI_TEXT + virtual void text_print (FILE *fp); + virtual int text_ask (FILE *fpin, FILE *fpout); +#endif +}; + +// a bx_shadow_num_c is like a bx_param_num_c except that it doesn't +// store the actual value with its data. Instead, it uses val.p32bit +// to keep a pointer to the actual data. This is used to register +// existing variables as parameters, without have to access it via +// set/get methods. +class BOCHSAPI bx_shadow_num_c : public bx_param_num_c { + Bit8u varsize; // must be 64, 32, 16, or 8 + Bit8u lowbit; // range of bits associated with this param + Bit64u mask; // mask is ANDed with value before it is returned from get +public: + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit64s *ptr_to_real_val, + Bit8u highbit = 63, + Bit8u lowbit = 0); + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit64u *ptr_to_real_val, + Bit8u highbit = 63, + Bit8u lowbit = 0); + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit32s *ptr_to_real_val, + Bit8u highbit = 31, + Bit8u lowbit = 0); + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit32u *ptr_to_real_val, + Bit8u highbit = 31, + Bit8u lowbit = 0); + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit16s *ptr_to_real_val, + Bit8u highbit = 15, + Bit8u lowbit = 0); + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit16u *ptr_to_real_val, + Bit8u highbit = 15, + Bit8u lowbit = 0); + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit8s *ptr_to_real_val, + Bit8u highbit = 7, + Bit8u lowbit = 0); + bx_shadow_num_c (bx_id id, + char *name, + char *description, + Bit8u *ptr_to_real_val, + Bit8u highbit = 7, + Bit8u lowbit = 0); + virtual Bit64s get64 (); + virtual void set (Bit64s val); +}; + +class BOCHSAPI bx_param_bool_c : public bx_param_num_c { + // many boolean variables are used to enable/disable modules. In the + // user interface, the enable variable should enable/disable all the + // other parameters associated with that module. +public: + bx_param_bool_c (bx_id id, + char *name, + char *description, + Bit64s initial_val); +#if BX_UI_TEXT + virtual void text_print (FILE *fp); + virtual int text_ask (FILE *fpin, FILE *fpout); +#endif +}; + +// a bx_shadow_bool_c is a shadow param based on bx_param_bool_c. +class BOCHSAPI bx_shadow_bool_c : public bx_param_bool_c { + // each bit of a bitfield can be a separate value. bitnum tells which + // bit is used. get/set will only modify that bit. + Bit8u bitnum; +public: + bx_shadow_bool_c (bx_id id, + char *name, + char *description, + bx_bool *ptr_to_real_val, + Bit8u bitnum = 0); + virtual Bit64s get64 (); + virtual void set (Bit64s val); +}; + + +class BOCHSAPI bx_param_enum_c : public bx_param_num_c { + char **choices; +public: + bx_param_enum_c (bx_id id, + char *name, + char *description, + char **choices, + Bit64s initial_val, + Bit64s value_base = 0); + char *get_choice (int n) { return choices[n]; } + int find_by_name (const char *string); + bool set_by_name (const char *string); +#if BX_UI_TEXT + virtual void text_print (FILE *fp); + virtual int text_ask (FILE *fpin, FILE *fpout); +#endif +}; + +typedef char* (*param_string_event_handler)(class bx_param_string_c *, int set, char *val, int maxlen); + +class BOCHSAPI bx_param_string_c : public bx_param_c { + int maxsize; + char *val, *initial_val; + param_string_event_handler handler; + param_enable_handler enable_handler; + bx_param_num_c *options; + char separator; +public: + enum { + RAW_BYTES = 1, // use binary text editor, like MAC addr + IS_FILENAME = 2, // 1=yes it's a filename, 0=not a filename. + // Some guis have a file browser. This + // bit suggests that they use it. + SAVE_FILE_DIALOG = 4 // Use save dialog opposed to open file dialog + } bx_string_opt_bits; + bx_param_string_c (bx_id id, + char *name, + char *description, + char *initial_val, + int maxsize=-1); + virtual ~bx_param_string_c (); + void reset (); + void set_handler (param_string_event_handler handler); + void set_enable_handler (param_enable_handler handler); + virtual void set_enabled (int enabled); + Bit32s get (char *buf, int len); + char *getptr () {return val; } + void set (char *buf); + bx_bool equals (const char *buf); + bx_param_num_c *get_options () { return options; } + void set_separator (char sep) {separator = sep; } + char get_separator () {return separator; } + int get_maxsize () {return maxsize; } +#if BX_UI_TEXT + virtual void text_print (FILE *fp); + virtual int text_ask (FILE *fpin, FILE *fpout); +#endif +}; + +// Declare a filename class. It is identical to a string, except that +// it initializes the options differently. This is just a shortcut +// for declaring a string param and setting the options with IS_FILENAME. +class BOCHSAPI bx_param_filename_c : public bx_param_string_c { +public: + bx_param_filename_c (bx_id id, + char *name, + char *description, + char *initial_val, + int maxsize=-1); +}; + +class BOCHSAPI bx_list_c : public bx_param_c { +private: + // just a list of bx_param_c objects. size tells current number of + // objects in the list, and maxsize tells how many list items are + // allocated in the constructor. + bx_param_c **list; + int size, maxsize; + // options is a bit field whose bits are defined by bx_listopt_bits ORed + // together. Options is a bx_param so that if necessary the bx_list could + // install a handler to cause get/set of options to have side effects. + bx_param_num_c *options; + // for a menu, the value of choice before the call to "ask" is default. + // After ask, choice holds the value that the user chose. Choice defaults + // to 1 in the constructor. + bx_param_num_c *choice; + // title of the menu or series + bx_param_string_c *title; + // if the menu shows a "return to previous menu" type of choice, + // this controls where that choice will go. + bx_param_c *parent; + void init (); +public: + enum { + // When a bx_list_c is displayed as a menu, SHOW_PARENT controls whether or + // not the menu shows a "Return to parent menu" choice or not. + SHOW_PARENT = (1<<0), + // Some lists are best displayed shown as menus, others as a series of + // related questions. This bit suggests to the CI that the series of + // questions format is preferred. + SERIES_ASK = (1<<1), + // When a bx_list_c is displayed in a dialog, USE_TAB_WINDOW suggests + // to the CI that each item in the list should be shown as a separate + // tab. This would be most appropriate when each item is another list + // of parameters. + USE_TAB_WINDOW = (1<<2), + // When a bx_list_c is displayed in a dialog, the list name is used as the + // label of the group box if USE_BOX_TITLE is set. This is only necessary if + // more than one list appears in a dialog box. + USE_BOX_TITLE = (1<<3) + } bx_listopt_bits; + bx_list_c (bx_id id, int maxsize); + bx_list_c (bx_id id, char *name, char *description, bx_param_c **init_list); + bx_list_c (bx_id id, char *name, char *description, int maxsize); + virtual ~bx_list_c(); + bx_list_c *clone (); + void add (bx_param_c *param); + bx_param_c *get (int index); + int get_size () { return size; } + bx_param_num_c *get_options () { return options; } + void set_options (bx_param_num_c *newopt) { options = newopt; } + bx_param_num_c *get_choice () { return choice; } + bx_param_string_c *get_title () { return title; } + void set_parent (bx_param_c *newparent) { parent = newparent; } + bx_param_c *get_parent () { return parent; } +#if BX_UI_TEXT + virtual void text_print (FILE *); + virtual int text_ask (FILE *fpin, FILE *fpout); +#endif +}; + +//////////////////////////////////////////////////////////////// + + +// These are the different start modes. +enum { + // Just start the simulation without running the configuration interface + // at all, unless something goes wrong. + BX_QUICK_START = 200, + // Run the configuration interface. The default action will be to load a + // configuration file. This makes sense if a config file could not be + // loaded, either because it wasn't found or because it had errors. + BX_LOAD_START, + // Run the configuration interface. The default action will be to + // edit the configuration. + BX_EDIT_START, + // Run the configuration interface, but make the default action be to + // start the simulation. + BX_RUN_START +}; + +#define BX_FLOPPY_NONE 10 // floppy not present +#define BX_FLOPPY_1_2 11 // 1.2M 5.25" +#define BX_FLOPPY_1_44 12 // 1.44M 3.5" +#define BX_FLOPPY_2_88 13 // 2.88M 3.5" +#define BX_FLOPPY_720K 14 // 720K 3.5" +#define BX_FLOPPY_360K 15 // 360K 5.25" +#define BX_FLOPPY_160K 16 // 160K 5.25" +#define BX_FLOPPY_180K 17 // 180K 5.25" +#define BX_FLOPPY_320K 18 // 320K 5.25" +#define BX_FLOPPY_LAST 18 // last legal value of floppy type + +#define BX_FLOPPY_GUESS 20 // decide based on image size + +#define BX_ATA_DEVICE_DISK 0 +#define BX_ATA_DEVICE_CDROM 1 +#define BX_ATA_DEVICE_LAST 1 + +#define BX_ATA_BIOSDETECT_NONE 0 +#define BX_ATA_BIOSDETECT_AUTO 1 +#define BX_ATA_BIOSDETECT_CMOS 2 + +#define BX_ATA_TRANSLATION_NONE 0 +#define BX_ATA_TRANSLATION_LBA 1 +#define BX_ATA_TRANSLATION_LARGE 2 +#define BX_ATA_TRANSLATION_RECHS 3 +#define BX_ATA_TRANSLATION_AUTO 4 +#define BX_ATA_TRANSLATION_LAST 4 + +#define BX_ATA_MODE_FLAT 0 +#define BX_ATA_MODE_CONCAT 1 +#define BX_ATA_MODE_EXTDISKSIM 2 +#define BX_ATA_MODE_DLL_HD 3 +#define BX_ATA_MODE_SPARSE 4 +#define BX_ATA_MODE_VMWARE3 5 +#define BX_ATA_MODE_UNDOABLE 6 +#define BX_ATA_MODE_GROWING 7 +#define BX_ATA_MODE_VOLATILE 8 +#define BX_ATA_MODE_LAST 8 +//#define BX_ATA_MODE_Z_UNDOABLE 9 +//#define BX_ATA_MODE_Z_VOLATILE 10 +//#define BX_ATA_MODE_SPLIT 6 + +#define BX_CLOCK_SYNC_NONE 0 +#define BX_CLOCK_SYNC_REALTIME 1 +#define BX_CLOCK_SYNC_SLOWDOWN 2 +#define BX_CLOCK_SYNC_BOTH 3 +#define BX_CLOCK_SYNC_LAST 3 + +#define BX_CLOCK_TIME0_LOCAL 1 +#define BX_CLOCK_TIME0_UTC 2 + +BOCHSAPI extern char *bochs_start_names[]; +BOCHSAPI extern int n_bochs_start_names; +BOCHSAPI extern char *floppy_type_names[]; +BOCHSAPI extern int floppy_type_n_sectors[]; +BOCHSAPI extern int n_floppy_type_names; +BOCHSAPI extern char *floppy_status_names[]; +BOCHSAPI extern int n_floppy_status_names; +BOCHSAPI extern char *floppy_bootdisk_names[]; +BOCHSAPI extern int n_floppy_bootdisk_names; +BOCHSAPI extern char *loader_os_names[]; +BOCHSAPI extern int n_loader_os_names; +BOCHSAPI extern char *keyboard_type_names[]; +BOCHSAPI extern int n_keyboard_type_names; +BOCHSAPI extern char *atadevice_type_names[]; +BOCHSAPI extern int n_atadevice_type_names; +BOCHSAPI extern char *atadevice_mode_names[]; +BOCHSAPI extern int n_atadevice_mode_names; +BOCHSAPI extern char *atadevice_status_names[]; +BOCHSAPI extern int n_atadevice_status_names; +BOCHSAPI extern char *atadevice_biosdetect_names[]; +BOCHSAPI extern int n_atadevice_biosdetect_names; +BOCHSAPI extern char *atadevice_translation_names[]; +BOCHSAPI extern int n_atadevice_translation_names; +BOCHSAPI extern char *clock_sync_names[]; +BOCHSAPI extern int clock_sync_n_names; + +typedef struct { + bx_param_enum_c *Odevtype; + bx_param_string_c *Opath; + bx_param_enum_c *Otype; + bx_param_enum_c *Ostatus; + } bx_floppy_options; + +typedef struct { + bx_list_c *Omenu; + bx_param_bool_c *Opresent; + bx_param_enum_c *Otype; + bx_param_enum_c *Omode; + bx_param_string_c *Opath; + bx_param_string_c *Ojournal; + bx_param_num_c *Ocylinders; + bx_param_num_c *Oheads; + bx_param_num_c *Ospt; + bx_param_enum_c *Ostatus; + bx_param_string_c *Omodel; + bx_param_enum_c *Obiosdetect; + bx_param_enum_c *Otranslation; + } bx_atadevice_options; + +typedef struct { + bx_param_bool_c *Oenabled; + bx_param_string_c *Odev; + } bx_serial_options; + +typedef struct { + bx_param_bool_c *Oenabled; + bx_param_num_c *Oioaddr; + bx_param_num_c *Oirq; + } bx_usb_options; + + +//////////////////////////////////////////////////////////////////// +// base class simulator interface, contains just virtual functions. +// I'm not longer sure that having a base class is going to be of any +// use... -Bryce + +#include <setjmp.h> + +enum ci_command_t { CI_START, CI_RUNTIME_CONFIG, CI_SHUTDOWN }; +enum ci_return_t { + CI_OK, // normal return value + CI_ERR_NO_TEXT_CONSOLE // err: can't work because there's no text console + }; +typedef int (*config_interface_callback_t)(void *userdata, ci_command_t command); + +// bx_gui->set_display_mode() changes the mode between the configuration +// interface and the simulation. This is primarily intended for display +// libraries which have a full-screen mode such as SDL, term, and svgalib. The +// display mode is set to DISP_MODE_CONFIG before displaying any configuration +// menus, for panics that requires user input, when entering the debugger, etc. +// It is set to DISP_MODE_SIM when the Bochs simulation resumes. The constants +// are defined here so that configuration interfaces can use them with the +// bx_simulator_interface_c::set_display_mode() method. +enum disp_mode_t { DISP_MODE_CONFIG=100, DISP_MODE_SIM }; + +class BOCHSAPI bx_simulator_interface_c { +public: + bx_simulator_interface_c (); + virtual void set_quit_context (jmp_buf *context) {} + virtual int get_init_done () { return -1; } + virtual int set_init_done (int n) {return -1;} + virtual void get_param_id_range (int *min, int *max) {} + virtual int register_param (bx_id id, bx_param_c *it) {return -1;} + virtual void reset_all_param () {} + virtual bx_param_c *get_param (bx_id id) {return NULL;} + virtual bx_param_num_c *get_param_num (bx_id id) {return NULL;} + virtual bx_param_string_c *get_param_string (bx_id id) {return NULL;} + virtual bx_param_bool_c *get_param_bool (bx_id id) {return NULL;} + virtual bx_param_enum_c *get_param_enum (bx_id id) {return NULL;} + 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 int get_default_log_action (int level) {return -1;} + virtual void set_default_log_action (int level, int action) {} + virtual char *get_action_name (int action) {return 0;} + virtual const char *get_log_level_name (int level) {return 0;} + virtual int get_max_log_level () {return -1;} + + // exiting is somewhat complicated! The preferred way to exit bochs is + // to call BX_EXIT(exitcode). That is defined to call + // SIM->quit_sim(exitcode). The quit_sim function first calls + // the cleanup functions in bochs so that it can destroy windows + // and free up memory, then sends a notify message to the CI + // telling it that bochs has stopped. + virtual void quit_sim (int code) {} + + virtual int get_exit_code () { return 0; } + + virtual int get_default_rc (char *path, int len) {return -1;} + virtual int read_rc (char *path) {return -1;} + virtual int write_rc (char *rc, int overwrite) {return -1;} + virtual int get_log_file (char *path, int len) {return -1;} + virtual int set_log_file (char *path) {return -1;} + virtual int get_log_prefix (char *prefix, int len) {return -1;} + virtual int set_log_prefix (char *prefix) {return -1;} + virtual int get_debugger_log_file (char *path, int len) {return -1;} + virtual int set_debugger_log_file (char *path) {return -1;} + virtual int get_floppy_options (int drive, bx_floppy_options *out) {return -1;} + virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *where = NULL) {return -1;} + virtual char *get_floppy_type_name (int type) {return NULL;} + + // The CI calls set_notify_callback to register its event handler function. + // This event handler function is called whenever the simulator needs to + // send an event to the CI. For example, if the simulator hits a panic and + // wants to ask the user how to proceed, it would call the CI event handler + // to ask the CI to display a dialog. + // + // NOTE: At present, the standard VGAW buttons (floppy, snapshot, power, + // etc.) are displayed and handled by gui.cc, not by the CI or siminterface. + // gui.cc uses its own callback functions to implement the behavior of + // the buttons. Some of these implementations call the siminterface. + typedef BxEvent* (*bxevent_handler)(void *theclass, BxEvent *event); + virtual void set_notify_callback (bxevent_handler func, void *arg) {} + virtual void get_notify_callback (bxevent_handler *func, void **arg) {} + + // send an event from the simulator to the CI. + virtual BxEvent* sim_to_ci_event (BxEvent *event) {return NULL;} + + // called from simulator when it hits serious errors, to ask if the user + // wants to continue or not + virtual int log_msg (const char *prefix, int level, const char *msg) {return -1;} + + // tell the CI to ask the user for the value of a parameter. + virtual int ask_param (bx_id param) {return -1;} + + // ask the user for a pathname + virtual int ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags) {return -1;} + // called at a regular interval, currently by the keyboard handler. + virtual void periodic () {} + virtual int create_disk_image (const char *filename, int sectors, bx_bool overwrite) {return -3;} + // Tell the configuration interface (CI) that some parameter values have + // changed. The CI will reread the parameters and change its display if it's + // appropriate. Maybe later: mention which params have changed to save time. + virtual void refresh_ci () {} + // forces a vga update. This was added so that a debugger can force + // a vga update when single stepping, without having to wait thousands + // of cycles for the normal vga refresh triggered by iodev/keyboard.cc. + virtual void refresh_vga () {} + // forces a call to bx_gui.handle_events. This was added so that a debugger + // can force the gui events to be handled, so that interactive things such + // as a toolbar click will be processed. + virtual void handle_events () {} + // return first hard disk in ATA interface + virtual bx_param_c *get_first_cdrom () {return NULL;} + // return first cdrom in ATA interface + virtual bx_param_c *get_first_hd () {return NULL;} +#if BX_DEBUGGER + // for debugger: same behavior as pressing control-C + virtual void debug_break () {} + virtual void debug_interpret_cmd (char *cmd) {} + virtual char *debug_get_next_command () {return NULL;} + virtual void debug_puts (const char *text) {} +#endif + virtual void register_configuration_interface ( + const char* name, + config_interface_callback_t callback, + 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;} + typedef 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) { + is_sim_thread_func = func; + } + virtual bool is_sim_thread () {return true;} + virtual bool is_wx_selected () {return false;} + // provide interface to bx_gui->set_display_mode() method for config + // interfaces to use. + virtual void set_display_mode (disp_mode_t newmode) {} + virtual bool test_for_text_console () { return true; } +}; + +BOCHSAPI extern bx_simulator_interface_c *SIM; + +BOCHSAPI extern void bx_init_siminterface (); +BOCHSAPI extern int bx_init_main (int argc, char *argv[]); + +#if defined(__WXMSW__) || defined(WIN32) +// Just to provide HINSTANCE, etc. in files that have not included bochs.h. +// I don't like this at all, but I don't see a way around it. +#include <windows.h> +#endif + +// define structure to hold data that is passed into our main function. +typedef struct BOCHSAPI { + // standard argc,argv + int argc; + char **argv; +#ifdef WIN32 + char initial_dir[MAX_PATH]; +#endif +#ifdef __WXMSW__ + // these are only used when compiling with wxWindows. This gives us a + // place to store the data that was passed to WinMain. + HINSTANCE hInstance; + HINSTANCE hPrevInstance; + LPSTR m_lpCmdLine; + int nCmdShow; +#endif +} bx_startup_flags_t; + +BOCHSAPI extern bx_startup_flags_t bx_startup_flags; +BOCHSAPI extern bx_bool bx_user_quit; |