3044 lines
91 KiB
Plaintext
3044 lines
91 KiB
Plaintext
----------------------------------------------------------------------
|
|
Patch name: patch.plugins3
|
|
Author: Bryce Denney
|
|
Date: Wed Dec 12 17:56:11 EST 2001
|
|
|
|
Detailed description:
|
|
This patch replaces the Bochs keyboard with a slightly modified version
|
|
of the plex86 keyboard device, which is implemented as a plugin. This
|
|
is sort of a proof of concept, rather than anything that I'm about to
|
|
check in. It uses GNU libtool to compile the plex86 keyboard code into
|
|
a shared library, and installs that shared library in
|
|
/tmp/bochslib/libplex-keyboard.so. Then the new code in plugin.cc (which
|
|
is adapted from the plex86 plugin code) loads the libplex-keyboard library
|
|
during initialization and installs the plex86 keyboard instead of the
|
|
bochs keyboard.
|
|
|
|
I chose the keyboard because it takes about 2 seconds to test that it's
|
|
basically working, and because the bochs and plex86 implementations hadn't
|
|
changed very much since they split.
|
|
|
|
If you look at plex-keyboard.cc and plex-keyboard.h, it is fundamentally the
|
|
same as the current plex86 code. I have changed lots of names from bx_* to
|
|
plex_* just to reduce confusion and mayhem when I was compiling with both
|
|
kbd implementations. I didn't change anything except to get it to compile.
|
|
|
|
Patch was created with:
|
|
cvs diff -u
|
|
Apply patch to what version:
|
|
cvs current as of 12/12/2001
|
|
Instructions:
|
|
To patch, go to main bochs directory.
|
|
Type "patch -p0 < THIS_PATCH_FILE".
|
|
----------------------------------------------------------------------
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/Makefile.in,v
|
|
retrieving revision 1.62
|
|
diff -u -r1.62 Makefile.in
|
|
--- Makefile.in 2001/12/10 21:31:20 1.62
|
|
+++ Makefile.in 2001/12/13 02:31:09
|
|
@@ -78,7 +78,7 @@
|
|
CXXFLAGS = @CXXFLAGS@ $(MCH_CFLAGS) $(FLA_FLAGS)
|
|
|
|
LDFLAGS = @LDFLAGS@
|
|
-LIBS = @LIBS@
|
|
+LIBS = @LIBS@ -ldl
|
|
# To compile with readline:
|
|
# linux needs just -lreadline
|
|
# solaris needs -lreadline -lcurses
|
|
@@ -123,6 +123,7 @@
|
|
NONINLINE_OBJS = \
|
|
logio.o \
|
|
main.o \
|
|
+ plugin.o \
|
|
load32bitOShack.o \
|
|
state_file.o \
|
|
pc_system.o \
|
|
@@ -140,7 +141,7 @@
|
|
INSTRUMENT_LIB = @INSTRUMENT_DIR@/libinstrument.a
|
|
FPU_LIB = fpu/libfpu.a
|
|
READLINE_LIB = @READLINE_LIB@
|
|
-EXTRA_LINK_OPTS = @EXTRA_LINK_OPTS@
|
|
+EXTRA_LINK_OPTS = @EXTRA_LINK_OPTS@ -ldl
|
|
|
|
BX_OBJS = @NONINLINE_VAR@
|
|
|
|
@@ -158,12 +159,12 @@
|
|
|
|
@EXTERNAL_DEPENDENCY@
|
|
|
|
-bochs@EXE@: @IODEV_LIB_VAR@ @DEBUGGER_VAR@ \
|
|
+bochs@EXE@: @IODEV_LIB_VAR@ iodev/libplex-keyboard.la @DEBUGGER_VAR@ \
|
|
cpu/libcpu.a memory/libmemory.a gui/libgui.a \
|
|
@DISASM_VAR@ @INSTRUMENT_VAR@ @DYNAMIC_VAR@ $(BX_OBJS) \
|
|
$(SIMX86_OBJS) \
|
|
$(FPU_LIB)
|
|
- @LINK@ $(BX_OBJS) \
|
|
+ libtool --mode=link @LINK@ -export-dynamic $(BX_OBJS) \
|
|
$(SIMX86_OBJS) \
|
|
iodev/libiodev.a \
|
|
cpu/libcpu.a memory/libmemory.a gui/libgui.a \
|
|
@@ -191,6 +192,9 @@
|
|
echo '// This file is generated by "make bxversion.h"' >> bxversion.h
|
|
echo "#define VER_STRING \"$(VER_STRING)\"" >> bxversion.h
|
|
echo "#define REL_STRING \"$(REL_STRING)\"" >> bxversion.h
|
|
+
|
|
+iodev/libplex-keyboard.la::
|
|
+ make -C iodev libplex-keyboard.la
|
|
|
|
iodev/libiodev.a::
|
|
cd iodev @COMMAND_SEPARATOR@
|
|
Index: bochs.h
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/bochs.h,v
|
|
retrieving revision 1.56
|
|
diff -u -r1.56 bochs.h
|
|
--- bochs.h 2001/12/12 10:43:36 1.56
|
|
+++ bochs.h 2001/12/13 02:31:10
|
|
@@ -73,6 +73,7 @@
|
|
#include "osdep.h" /* platform dependent includes and defines */
|
|
#include "debug/debug.h"
|
|
#include "bxversion.h"
|
|
+#include "plugin.h"
|
|
|
|
#include "gui/siminterface.h"
|
|
|
|
Index: main.cc
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/main.cc,v
|
|
retrieving revision 1.80
|
|
diff -u -r1.80 main.cc
|
|
--- main.cc 2001/12/12 10:43:36 1.80
|
|
+++ main.cc 2001/12/13 02:31:13
|
|
@@ -118,7 +118,9 @@
|
|
// if after init, notify the GUI
|
|
if (set && SIM->get_init_done ()) {
|
|
bx_gui.mouse_enabled_changed (val!=0);
|
|
- bx_keyboard.mouse_enabled_changed (val!=0);
|
|
+ // FIXME: while adding plugin support, I'm not going to bother
|
|
+ // with this function for now.
|
|
+ //bx_keyboard.mouse_enabled_changed (val!=0);
|
|
}
|
|
break;
|
|
case BXP_PARPORT1_ENABLE:
|
|
@@ -913,6 +915,10 @@
|
|
#else
|
|
|
|
bx_init_hardware();
|
|
+
|
|
+ BX_INFO (("Now I will load the plex86 keyboard plugin..."));
|
|
+ bx_init_plugin ();
|
|
+ BX_INFO (("Done loading the plex86 keyboard plugin"));
|
|
|
|
if (bx_options.load32bitOSImage.OwhichOS->get ()) {
|
|
void bx_load32bitOSimagehack(void);
|
|
Index: plugin.cc
|
|
===================================================================
|
|
RCS file: plugin.cc
|
|
diff -N plugin.cc
|
|
--- /dev/null Thu May 24 22:33:05 2001
|
|
+++ plugin.cc Wed Dec 12 18:31:15 2001
|
|
@@ -0,0 +1,841 @@
|
|
+/*
|
|
+ * plex86: run multiple x86 operating systems concurrently
|
|
+ * Copyright (C) 1999-2000 The plex86 developers team
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library; if not, write to the Free Software
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+ */
|
|
+
|
|
+#include "bochs.h"
|
|
+#include "plugin.h"
|
|
+
|
|
+#define LOG_THIS genlog->
|
|
+
|
|
+Bit32u (* pluginGetCMOSReg)(unsigned reg) = 0;
|
|
+void (* pluginSetCMOSReg)(unsigned reg, Bit32u val) = 0;
|
|
+void (* pluginMouseMotion)(int d_x, int d_y, unsigned button_state) = 0;
|
|
+void (* pluginGenScancode)(Bit32u scancode) = 0;
|
|
+plugin_t *plugins = NULL; /* Head of the linked list of plugins */
|
|
+static void plugin_init_one(plugin_t *plugin);
|
|
+
|
|
+#if 0
|
|
+/************************************************************************/
|
|
+/* Plugin initialization / deinitialization */
|
|
+/************************************************************************/
|
|
+
|
|
+
|
|
+/* Some builtin (default pass-through) Write-Cache functions, when
|
|
+ * no Write-Cache plugins are loaded to override these. These are
|
|
+ * strict pass-through functions
|
|
+ */
|
|
+
|
|
+static Bit64u builtinWCLSeek(int fd, Bit64u off64, int whence);
|
|
+static unsigned builtinWCRead(int fd, void *buffer, unsigned len);
|
|
+static unsigned builtinWCWrite(int fd, void *buffer, unsigned len);
|
|
+static void builtinWCCommit(int fd);
|
|
+
|
|
+static Bit32u builtinHDReadHandler(Bit32u address,
|
|
+ unsigned io_len);
|
|
+static void builtinHDWriteHandler(Bit32u address,
|
|
+ Bit32u value, unsigned io_len);
|
|
+static void builtinVGARedrawArea(unsigned x0, unsigned y0,
|
|
+ unsigned width, unsigned height);
|
|
+
|
|
+
|
|
+pluginCallbacks_t pluginCallbacks;
|
|
+
|
|
+plugin_t *plugins = NULL; /* Head of the linked list of plugins */
|
|
+void (*pluginHRQHackCallback)(void);
|
|
+unsigned pluginHRQ = 0;
|
|
+
|
|
+extern int filehdl; /* File handle for /dev/plex86 */
|
|
+
|
|
+Bit32u (* pluginGetCMOSReg)(unsigned reg) = 0;
|
|
+void (* pluginSetCMOSReg)(unsigned reg, Bit32u val) = 0;
|
|
+void (* pluginCMOSChecksum)(void) = 0;
|
|
+void (* pluginMouseMotion)(int d_x, int d_y, unsigned button_state) = 0;
|
|
+void (* pluginGenScancode)(Bit32u scancode) = 0;
|
|
+unsigned (* pluginRegisterDMAChannel)(
|
|
+ unsigned channel,
|
|
+ void (* dma_read)(Bit8u *data_byte),
|
|
+ void (* dma_write)(Bit8u *data_byte)
|
|
+ ) = 0;
|
|
+void (* pluginDMASetDRQ)(unsigned channel, unsigned val) = 0;
|
|
+unsigned (* pluginDMAGetTC)(void) = 0;
|
|
+
|
|
+Bit32u (* pluginHDReadHandler)(Bit32u address,
|
|
+ unsigned io_len) = 0;
|
|
+void (* pluginHDWriteHandler)(Bit32u address,
|
|
+ Bit32u value, unsigned io_len) = 0;
|
|
+void (* pluginVGARedrawArea)(unsigned x0, unsigned y0,
|
|
+ unsigned width, unsigned height) = 0;
|
|
+
|
|
+bx_debug_t bx_dbg; // xxx Fix me, bochs hack
|
|
+bx_options_t bx_options; // xxx Fix me, bochs hack
|
|
+
|
|
+// xxx Fix me, bochs hack
|
|
+ void
|
|
+bx_panic(char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+#if 0
|
|
+ if (bx_logfd) {
|
|
+ fprintf(bx_logfd, "panic, ");
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ vfprintf(bx_logfd, fmt, ap);
|
|
+ va_end(ap);
|
|
+ }
|
|
+#endif
|
|
+ fprintf(stderr, "bochs: panic, ");
|
|
+ va_start(ap, fmt);
|
|
+ vfprintf(stderr, fmt, ap);
|
|
+ va_end(ap);
|
|
+
|
|
+ plugin_abort ();
|
|
+}
|
|
+
|
|
+// xxx Fix me, bochs hack
|
|
+ void
|
|
+bx_printf(char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+#if 0
|
|
+ if (bx_logfd) {
|
|
+ va_start(ap, fmt);
|
|
+ vfprintf(bx_logfd, fmt, ap);
|
|
+ va_end(ap);
|
|
+ }
|
|
+#endif
|
|
+ fprintf(stderr, "bochs: ");
|
|
+ va_start(ap, fmt);
|
|
+ vfprintf(stderr, fmt, ap);
|
|
+ va_end(ap);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#if 0
|
|
+void
|
|
+plugin_init_all (void)
|
|
+{
|
|
+ plugin_t *plugin;
|
|
+
|
|
+ for (plugin = plugins; plugin; plugin = plugin->next)
|
|
+ {
|
|
+ char *arg_ptr = plugin->args;
|
|
+
|
|
+ /* process the command line */
|
|
+ plugin->argc = 0;
|
|
+ while (plugin->argc < MAX_ARGC)
|
|
+ {
|
|
+ while (*arg_ptr && isspace (*arg_ptr))
|
|
+ arg_ptr++;
|
|
+
|
|
+ if (!*arg_ptr)
|
|
+ break;
|
|
+ plugin->argv[plugin->argc++] = arg_ptr;
|
|
+
|
|
+ while (*arg_ptr && !isspace (*arg_ptr))
|
|
+ arg_ptr++;
|
|
+
|
|
+ if (!*arg_ptr)
|
|
+ break;
|
|
+ *arg_ptr++ = '\0';
|
|
+ }
|
|
+
|
|
+ /* initialize the plugin */
|
|
+ if (plugin->init (plugin, plugin->argc, plugin->argv))
|
|
+ {
|
|
+ fprintf (stderr, "Plugin initialization failed for %s\n", plugin->name);
|
|
+ plugin_abort();
|
|
+ }
|
|
+
|
|
+ plugin->initialized = 1;
|
|
+ }
|
|
+
|
|
+ return;
|
|
+}
|
|
+#endif
|
|
+
|
|
+
|
|
+ plugin_t *
|
|
+plugin_unload(plugin_t *plugin)
|
|
+{
|
|
+ int i;
|
|
+ plugin_t *dead_plug;
|
|
+
|
|
+ if (plugin->initialized)
|
|
+ plugin->fini ();
|
|
+
|
|
+ for (i=0; i<256; i++)
|
|
+ plugin_free_intr (plugin, i);
|
|
+
|
|
+ dlclose (plugin->handle);
|
|
+ free (plugin->name);
|
|
+ free (plugin->args);
|
|
+
|
|
+ dead_plug = plugin;
|
|
+ plugin = plugin->next;
|
|
+ free (dead_plug);
|
|
+
|
|
+ return plugin;
|
|
+}
|
|
+
|
|
+
|
|
+void
|
|
+plugin_fini_all (void)
|
|
+{
|
|
+ plugin_t *plugin;
|
|
+
|
|
+ for (plugin = plugins; plugin; plugin = plugin_unload (plugin));
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+#if 0
|
|
+#define BX_MAX_IRQS 16
|
|
+#define BX_NO_IRQ -1
|
|
+const char *irq_handler_name[BX_MAX_IRQS];
|
|
+
|
|
+ for (i=0; i < BX_MAX_IRQS; i++) {
|
|
+ irq_handler_name[i] = NULL;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ void
|
|
+pluginUnregisterIRQ(unsigned irq, const char *name)
|
|
+{
|
|
+#warning "Finish pluginUnregisterIRQ"
|
|
+#if 0
|
|
+ if (irq >= BX_MAX_IRQS) {
|
|
+ bx_panic("IO device %s tried to unregister IRQ %d above %u\n",
|
|
+ name, irq, (unsigned) BX_MAX_IRQS-1);
|
|
+ }
|
|
+
|
|
+ if (!irq_handler_name[irq]) {
|
|
+ bx_printf("IO device %s tried to unregister IRQ %d, not registered\n",
|
|
+ name, irq);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (strcmp(irq_handler_name[irq], name)) {
|
|
+ bx_printf("IRQ %u not registered to %s but to %s\n", irq,
|
|
+ name, irq_handler_name[irq]);
|
|
+ return;
|
|
+ }
|
|
+ irq_handler_name[irq] = NULL;
|
|
+#endif
|
|
+}
|
|
+
|
|
+
|
|
+/************************************************************************/
|
|
+/* Software interrupt handling */
|
|
+/************************************************************************/
|
|
+
|
|
+static struct intr_t
|
|
+{
|
|
+ plugin_t *plugin;
|
|
+ handler_t handler;
|
|
+ struct intr_t *next;
|
|
+}
|
|
+*ints[256]; /* Heads of linked lists for each int */
|
|
+
|
|
+
|
|
+int
|
|
+plugin_alloc_intr (plugin_t *plugin, handler_t handler, int vec)
|
|
+{
|
|
+ struct intr_t *intr;
|
|
+
|
|
+ for (intr = ints[vec]; intr != NULL; intr = intr->next)
|
|
+ {
|
|
+ if (intr->plugin == plugin)
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (ints[vec] == NULL && vm_alloc_intr (vec))
|
|
+ return -1;
|
|
+
|
|
+ intr = malloc (sizeof (struct intr_t));
|
|
+ intr->plugin = plugin;
|
|
+ intr->handler = handler;
|
|
+ intr->next = ints[vec];
|
|
+ ints[vec] = intr;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+ void
|
|
+plugin_free_intr (plugin_t *plugin, int vec)
|
|
+{
|
|
+ struct intr_t *intr, *dummy;
|
|
+
|
|
+ if ((intr = ints[vec]) == NULL)
|
|
+ return;
|
|
+
|
|
+ if (intr->plugin == plugin)
|
|
+ {
|
|
+ dummy = intr;
|
|
+ ints[vec] = intr->next;
|
|
+ free (dummy);
|
|
+ }
|
|
+ else
|
|
+ for (; intr != NULL; intr = intr->next)
|
|
+ {
|
|
+ if (intr->next == NULL)
|
|
+ break;
|
|
+
|
|
+ if (intr->next->plugin == plugin)
|
|
+ {
|
|
+ dummy = intr->next;
|
|
+ intr->next = intr->next->next;
|
|
+ free (dummy);
|
|
+
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ints[vec] == NULL)
|
|
+ vm_release_intr (vec);
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+
|
|
+ int
|
|
+plugin_emulate_int(int vec)
|
|
+{
|
|
+ struct intr_t *intr;
|
|
+ int reflect = 0;
|
|
+
|
|
+ for (intr = ints[vec]; intr != NULL; intr = intr->next)
|
|
+ {
|
|
+ if (intr->handler (EVT_INT, vec, 0, 0, NULL))
|
|
+ reflect = 1;
|
|
+ }
|
|
+
|
|
+ return reflect;
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+/************************************************************************/
|
|
+/* VM control */
|
|
+/************************************************************************/
|
|
+
|
|
+void
|
|
+plugin_abort (void)
|
|
+{
|
|
+ vm_abort ();
|
|
+ return;
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+/************************************************************************/
|
|
+/* Plugin pending */
|
|
+/************************************************************************/
|
|
+
|
|
+/*
|
|
+ * NOTE: This code was explicitly written to be reentrant using atomic
|
|
+ * XCHG, because it will usually be called from signal handlers and
|
|
+ * the like. None of the other plugin functions are reentrant, so
|
|
+ * a plugin wanting to perform plugin operations after reception
|
|
+ * of a signal should always use these functions to pend for CPU
|
|
+ * time.
|
|
+ */
|
|
+
|
|
+
|
|
+/************************************************************************/
|
|
+/* */
|
|
+/************************************************************************/
|
|
+
|
|
+void (*memMapFunct)(Bit32u, unsigned, unsigned, Bit32u *) = NULL;
|
|
+
|
|
+ void
|
|
+plugin_register_mem_map_IO( void (*f)(Bit32u, unsigned, unsigned, Bit32u *),
|
|
+ Bit32u range0, Bit32u range1)
|
|
+{
|
|
+ memMapFunct = f;
|
|
+}
|
|
+
|
|
+
|
|
+/************************************************************************/
|
|
+/* Timing control */
|
|
+/************************************************************************/
|
|
+
|
|
+static void (*save_funct)(Bit64u) = NULL;
|
|
+static void (*periodic_funct)(void) = NULL;
|
|
+
|
|
+
|
|
+ void
|
|
+plugin_register_elapsed(void (*funct)(Bit64u))
|
|
+{
|
|
+ save_funct = funct;
|
|
+}
|
|
+
|
|
+ void
|
|
+plugin_register_periodic(void (*funct)(void))
|
|
+{
|
|
+ periodic_funct = funct;
|
|
+}
|
|
+
|
|
+
|
|
+ void
|
|
+plugin_call_elapsed( Bit64u elapsed )
|
|
+{
|
|
+ if (save_funct)
|
|
+ save_funct(elapsed);
|
|
+}
|
|
+
|
|
+ void
|
|
+plugin_handle_periodic(void)
|
|
+{
|
|
+ static Bit64u prev_user_usec = 0;
|
|
+ Bit64u new_user_usec;
|
|
+ volatile extern Bit64u user_time_usec;
|
|
+
|
|
+ if (!periodic_funct) return;
|
|
+
|
|
+#warning "fix: need exclusive access to variable used by async handler"
|
|
+ new_user_usec = user_time_usec;
|
|
+ if ( (new_user_usec - prev_user_usec) >= 500000 ) {
|
|
+ prev_user_usec = new_user_usec;
|
|
+ periodic_funct();
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+/************************************************************************/
|
|
+/* Plugin system: plex86 startup function */
|
|
+/************************************************************************/
|
|
+
|
|
+#define ZERO_ARRAY(a) memset (a, 0, sizeof(a))
|
|
+
|
|
+ void
|
|
+plugin_startup(void)
|
|
+{
|
|
+ ZERO_ARRAY(ints);
|
|
+
|
|
+ /* Register builtin Write-Cache functions, so we have some defaults
|
|
+ * until overloaded by plugins
|
|
+ */
|
|
+ pluginRegisterWriteCache(builtinWCLSeek, builtinWCRead, builtinWCWrite,
|
|
+ builtinWCCommit);
|
|
+ pluginGetCMOSReg = builtinGetCMOSReg;
|
|
+ pluginSetCMOSReg = builtinSetCMOSReg;
|
|
+ pluginCMOSChecksum = builtinCMOSChecksum;
|
|
+ pluginMouseMotion = builtinMouseMotion;
|
|
+ pluginGenScancode = builtinGenScancode;
|
|
+ pluginRegisterDMAChannel = builtinRegisterDMAChannel;
|
|
+ pluginDMASetDRQ = builtinDMASetDRQ;
|
|
+ pluginDMAGetTC = builtinDMAGetTC;
|
|
+
|
|
+ pluginHDReadHandler = builtinHDReadHandler;
|
|
+ pluginHDWriteHandler = builtinHDWriteHandler;
|
|
+
|
|
+ pluginVGARedrawArea = builtinVGARedrawArea;
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinCMOSChecksum(void)
|
|
+{
|
|
+ fprintf(stderr, "builtinCMOSChecksum called, no CMOS plugin loaded?\n");
|
|
+ vm_abort();
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinMouseMotion(int d_x, int d_y, unsigned button_state)
|
|
+{
|
|
+ fprintf(stderr, "builtinMouseMotion called, not overloaded by keyboard"
|
|
+ " plugin?\n");
|
|
+ vm_abort();
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinGenScancode(Bit32u scancode)
|
|
+{
|
|
+ fprintf(stderr, "builtinGenScancode called, not overloaded by keyboard"
|
|
+ " plugin?\n");
|
|
+ vm_abort();
|
|
+}
|
|
+
|
|
+ unsigned
|
|
+builtinRegisterDMAChannel(
|
|
+ unsigned channel,
|
|
+ void (* dma_read)(Bit8u *data_byte),
|
|
+ void (* dma_write)(Bit8u *data_byte)
|
|
+ )
|
|
+{
|
|
+ fprintf(stderr, "builtinRegisterDMAChannel called, not overloaded by DMA"
|
|
+ " plugin?\n");
|
|
+ vm_abort();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinDMASetDRQ(unsigned channel, unsigned val)
|
|
+{
|
|
+ fprintf(stderr, "builtinDMASetDRQ( called, not overloaded by DMA"
|
|
+ " plugin?\n");
|
|
+ vm_abort();
|
|
+}
|
|
+
|
|
+ unsigned
|
|
+builtinDMAGetTC(void)
|
|
+{
|
|
+ fprintf(stderr, "builtinDMAGetTC called, not overloaded by DMA"
|
|
+ " plugin?\n");
|
|
+ vm_abort();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+ Bit32u
|
|
+builtinHDReadHandler(Bit32u address, unsigned io_len)
|
|
+{
|
|
+ fprintf(stderr, "builtinHDReadHandler called, HD plugin not loaded?"
|
|
+ " plugin?\n");
|
|
+ vm_abort();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinHDWriteHandler(Bit32u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+ fprintf(stderr, "builtinHDWriteHandler called, HD plugin not loaded?"
|
|
+ " plugin?\n");
|
|
+ vm_abort();
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinVGARedrawArea(unsigned x0, unsigned y0,
|
|
+ unsigned width, unsigned height)
|
|
+{
|
|
+}
|
|
+
|
|
+ Bit64u
|
|
+builtinWCLSeek(int fd, Bit64u off64, int whence)
|
|
+{
|
|
+ return( lseek(fd, (off_t) off64, whence) );
|
|
+}
|
|
+
|
|
+ unsigned
|
|
+builtinWCRead(int fd, void *buffer, unsigned len)
|
|
+{
|
|
+ return( read(fd, buffer, len) );
|
|
+}
|
|
+
|
|
+ unsigned
|
|
+builtinWCWrite(int fd, void *buffer, unsigned len)
|
|
+{
|
|
+ return( write(fd, buffer, len) );
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinWCCommit(int fd)
|
|
+{
|
|
+ fprintf(stderr, "builtin Write-Cache Commit (nop)\n");
|
|
+}
|
|
+
|
|
+
|
|
+// xxx Fix these
|
|
+int plugin_emulate_inport(int port, int op_size, int count, void *loc)
|
|
+{
|
|
+ fprintf(stderr, "plugin_emulate_inport:\n");
|
|
+ vm_abort();
|
|
+}
|
|
+
|
|
+int plugin_emulate_outport(int port, int op_size, int count, void *loc)
|
|
+{
|
|
+ fprintf(stderr, "plugin_emulate_outport:\n");
|
|
+ vm_abort();
|
|
+}
|
|
+
|
|
+ void
|
|
+pluginTriggerIRQ(unsigned irq)
|
|
+{
|
|
+ int ret;
|
|
+ irqMsg_t irqMsg;
|
|
+
|
|
+ irqMsg.irq = irq;
|
|
+ irqMsg.on = 1;
|
|
+
|
|
+ ret = ioctl(filehdl, PLEX86_IRQ, &irqMsg);
|
|
+ if (ret == -1) {
|
|
+ perror ("ioctl PLEX86_IRQ: ");
|
|
+ vm_abort();
|
|
+ }
|
|
+}
|
|
+
|
|
+ void
|
|
+pluginUntriggerIRQ(unsigned irq)
|
|
+{
|
|
+ int ret;
|
|
+ irqMsg_t irqMsg;
|
|
+
|
|
+ irqMsg.irq = irq;
|
|
+ irqMsg.on = 0;
|
|
+
|
|
+ ret = ioctl(filehdl, PLEX86_IRQ, &irqMsg);
|
|
+ if (ret == -1) {
|
|
+ perror ("ioctl PLEX86_IRQ: ");
|
|
+ vm_abort();
|
|
+ }
|
|
+}
|
|
+
|
|
+ void
|
|
+pluginSetHRQ(unsigned val)
|
|
+{
|
|
+ pluginHRQ = val;
|
|
+}
|
|
+
|
|
+ void
|
|
+pluginSetHRQHackCallback( void (*callback)(void) )
|
|
+{
|
|
+ pluginHRQHackCallback = callback;
|
|
+}
|
|
+
|
|
+ void
|
|
+pluginResetSignal(unsigned sig)
|
|
+{
|
|
+ fprintf(stderr, "pluginResetSignal: unimplemented\n");
|
|
+ vm_abort();
|
|
+}
|
|
+#endif
|
|
+
|
|
+ Bit32u
|
|
+builtinGetCMOSReg(unsigned reg)
|
|
+{
|
|
+ Bit8u val = bx_cmos.s.reg[reg];
|
|
+ BX_INFO(("plugin reading cmos register 0x%02x = 0x%02x", reg, val));
|
|
+ return val;
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinSetCMOSReg(unsigned reg, Bit32u val)
|
|
+{
|
|
+ BX_ASSERT (reg >= 0 && reg < BX_NUM_CMOS_REGS);
|
|
+ bx_cmos.s.reg[reg] = val;
|
|
+ BX_INFO(("plugin writing 0x%02x to cmos register 0x%02x", val, reg));
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinMouseMotion(int d_x, int d_y, unsigned button_state)
|
|
+{
|
|
+ BX_PANIC(("builtinMouseMotion called, not overloaded by keyboard"
|
|
+ " plugin?\n"));
|
|
+ abort();
|
|
+}
|
|
+
|
|
+ void
|
|
+builtinGenScancode(Bit32u scancode)
|
|
+{
|
|
+ BX_PANIC(("builtinGenScancode called, not overloaded by keyboard"
|
|
+ " plugin?\n"));
|
|
+ abort();
|
|
+}
|
|
+
|
|
+
|
|
+#define KBD_PLUGIN "/tmp/bochslib/libplex-keyboard.so"
|
|
+int bx_init_plugin ()
|
|
+{
|
|
+ pluginGetCMOSReg = builtinGetCMOSReg;
|
|
+ pluginSetCMOSReg = builtinSetCMOSReg;
|
|
+ pluginMouseMotion = builtinMouseMotion;
|
|
+ pluginGenScancode = builtinGenScancode;
|
|
+ plugin_load (KBD_PLUGIN, "");
|
|
+ /*
|
|
+ void *handle = dlopen (KBD_PLUGIN, RTLD_LAZY);
|
|
+ if (!handle) {
|
|
+ BX_ERROR (("could not open kbd plugin %s", KBD_PLUGIN));
|
|
+ BX_PANIC (("dlopen error: %s", dlerror ()));
|
|
+ exit (1);
|
|
+ }
|
|
+ */
|
|
+ BX_INFO (("opened keyboard library"));
|
|
+}
|
|
+
|
|
+ void
|
|
+plugin_load (char *name, char *args)
|
|
+{
|
|
+ plugin_t *plugin;
|
|
+ const char *plug_err;
|
|
+
|
|
+ plugin = (plugin_t *)malloc (sizeof (plugin_t));
|
|
+ if (!plugin)
|
|
+ {
|
|
+ perror ("malloc");
|
|
+ exit (1);
|
|
+ }
|
|
+
|
|
+ plugin->name = name;
|
|
+ plugin->args = args;
|
|
+ plugin->initialized = 0;
|
|
+
|
|
+ plugin->handle = dlopen (name, RTLD_LAZY);
|
|
+ if (!plugin->handle)
|
|
+ {
|
|
+ fputs (dlerror (), stderr);
|
|
+ exit (1);
|
|
+ }
|
|
+
|
|
+ plugin->init =
|
|
+ (int (*)(struct _plugin_t *, int, char *[])) /* monster typecast */
|
|
+ dlsym (plugin->handle, PLUGIN_INIT);
|
|
+ if ((plug_err = dlerror ()) != NULL)
|
|
+ {
|
|
+ BX_PANIC (("could not find init: %s", plug_err));
|
|
+ plugin_abort ();
|
|
+ }
|
|
+
|
|
+ plugin->fini = (void (*)(void)) dlsym (plugin->handle, PLUGIN_FINI);
|
|
+ if ((plug_err = dlerror ()) != NULL)
|
|
+ {
|
|
+ BX_PANIC (("could not find fini: %s", plug_err));
|
|
+ plugin_abort ();
|
|
+ }
|
|
+
|
|
+ /* Insert plugin at the _end_ of the plugin linked list. */
|
|
+ plugin->next = NULL;
|
|
+
|
|
+ if (!plugins)
|
|
+ {
|
|
+ /* Empty list, this become the first entry. */
|
|
+ plugins = plugin;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Non-empty list. Add to end. */
|
|
+ plugin_t *temp = plugins;
|
|
+
|
|
+ while (temp->next)
|
|
+ temp = temp->next;
|
|
+
|
|
+ temp->next = plugin;
|
|
+ }
|
|
+
|
|
+plugin_init_one(plugin);
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+void
|
|
+plugin_init_one(plugin_t *plugin)
|
|
+{
|
|
+ char *arg_ptr = plugin->args;
|
|
+
|
|
+ /* process the command line */
|
|
+ plugin->argc = 0;
|
|
+ while (plugin->argc < MAX_ARGC)
|
|
+ {
|
|
+ while (*arg_ptr && isspace (*arg_ptr))
|
|
+ arg_ptr++;
|
|
+
|
|
+ if (!*arg_ptr)
|
|
+ break;
|
|
+ plugin->argv[plugin->argc++] = arg_ptr;
|
|
+
|
|
+ while (*arg_ptr && !isspace (*arg_ptr))
|
|
+ arg_ptr++;
|
|
+
|
|
+ if (!*arg_ptr)
|
|
+ break;
|
|
+ *arg_ptr++ = '\0';
|
|
+ }
|
|
+
|
|
+ /* initialize the plugin */
|
|
+ if (plugin->init (plugin, plugin->argc, plugin->argv))
|
|
+ {
|
|
+ fprintf (stderr, "Plugin initialization failed for %s\n", plugin->name);
|
|
+ plugin_abort();
|
|
+ }
|
|
+
|
|
+ plugin->initialized = 1;
|
|
+}
|
|
+
|
|
+void
|
|
+plugin_abort (void)
|
|
+{
|
|
+ BX_PANIC (("plugin load aborted"));
|
|
+ abort();
|
|
+}
|
|
+
|
|
+ void
|
|
+pluginRegisterIRQ(unsigned irq, const char *name)
|
|
+{
|
|
+#warning "Finish pluginRegisterIRQ"
|
|
+ BX_ERROR(("pluginRegisterIRQ not complete"));
|
|
+
|
|
+#if 0
|
|
+ if (irq >= BX_MAX_IRQS) {
|
|
+ bx_panic("IO device %s registered with IRQ=%d above %u\n",
|
|
+ name, irq, (unsigned) BX_MAX_IRQS-1);
|
|
+ }
|
|
+ if (irq_handler_name[irq]) {
|
|
+ bx_panic("IRQ %u conflict, %s with %s\n", irq,
|
|
+ irq_handler_name[irq], name);
|
|
+ }
|
|
+ irq_handler_name[irq] = name;
|
|
+#endif
|
|
+}
|
|
+
|
|
+ int
|
|
+pluginRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
|
|
+ unsigned base, const char *name, unsigned len)
|
|
+{
|
|
+ BX_ASSERT (len==1);
|
|
+ bx_devices.register_io_read_handler (thisPtr, callback, base, name);
|
|
+ BX_INFO(("plugin registered I/O read address at %04x", base));
|
|
+}
|
|
+
|
|
+ int
|
|
+pluginRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
|
|
+ unsigned base, const char *name, unsigned len)
|
|
+{
|
|
+ BX_ASSERT (len==1);
|
|
+ bx_devices.register_io_write_handler (thisPtr, callback, base, name);
|
|
+ BX_INFO(("plugin registered I/O write address at %04x", base));
|
|
+}
|
|
+
|
|
+int
|
|
+pluginRegisterTimer(void *this_ptr, void (*funct)(void *),
|
|
+ Bit32u useconds, Boolean continuous, Boolean active)
|
|
+{
|
|
+ int id = bx_pc_system.register_timer (this_ptr, funct, useconds, continuous, active);
|
|
+ BX_INFO (("plugin registered timer %d", id));
|
|
+ return id;
|
|
+}
|
|
+
|
|
+void
|
|
+pluginActivateTimer(unsigned id, Bit32u usec, Boolean continuous)
|
|
+{
|
|
+ bx_pc_system.activate_timer (id, usec, continuous);
|
|
+ BX_INFO(("plugin activated timer %d", id));
|
|
+}
|
|
+
|
|
+void
|
|
+pluginTriggerIRQ(unsigned irq)
|
|
+{
|
|
+ BX_INFO(("plugin triggered irq %d", irq));
|
|
+ bx_pic.trigger_irq (irq);
|
|
+}
|
|
+
|
|
+
|
|
Index: plugin.h
|
|
===================================================================
|
|
RCS file: plugin.h
|
|
diff -N plugin.h
|
|
--- /dev/null Thu May 24 22:33:05 2001
|
|
+++ plugin.h Wed Dec 12 18:31:15 2001
|
|
@@ -0,0 +1,338 @@
|
|
+/*
|
|
+ * plex86: run multiple x86 operating systems concurrently
|
|
+ * Copyright (C) 1999-2000 The plex86 developers team
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library; if not, write to the Free Software
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+ */
|
|
+
|
|
+#ifndef __PLUGIN_H
|
|
+#define __PLUGIN_H
|
|
+
|
|
+#ifdef __cplusplus
|
|
+extern "C" {
|
|
+#endif
|
|
+
|
|
+#define BX_EVENT_MOUSE_MOTION(dx, dy, state) \
|
|
+ ((*pluginMouseMotion)(dx, dy, state))
|
|
+#define BX_EVENT_GEN_SCANCODE(scancode) \
|
|
+ ((*pluginGenScancode)(scancode))
|
|
+
|
|
+#include <dlfcn.h>
|
|
+
|
|
+#define PLUGIN_INIT "plugin_init"
|
|
+#define PLUGIN_FINI "plugin_fini"
|
|
+
|
|
+#define MAX_ARGC 10
|
|
+
|
|
+typedef enum
|
|
+{
|
|
+ EVT_INPORT, EVT_OUTPORT, EVT_INT
|
|
+} event_t;
|
|
+
|
|
+typedef int (*handler_t)
|
|
+ (event_t event, int data, int op_size, int count, void *loc);
|
|
+
|
|
+typedef Bit32u (*ioReadHandler_t)(void *, Bit32u, unsigned);
|
|
+typedef void (*ioWriteHandler_t)(void *, Bit32u, Bit32u, unsigned);
|
|
+
|
|
+typedef struct _plugin_t
|
|
+{
|
|
+ int initialized;
|
|
+ void *handle;
|
|
+ int argc;
|
|
+ char *name, *args, *argv[MAX_ARGC];
|
|
+ int (*init)(struct _plugin_t *plugin, int argc, char *argv[]);
|
|
+ void (*fini)(void);
|
|
+ struct _plugin_t *next;
|
|
+} plugin_t;
|
|
+
|
|
+extern plugin_t *plugins;
|
|
+
|
|
+void plugin_startup (void);
|
|
+void plugin_load (char *name, char *args);
|
|
+plugin_t *plugin_unload (plugin_t *plugin);
|
|
+void plugin_init_all (void);
|
|
+void plugin_fini_all (void);
|
|
+
|
|
+
|
|
+/* === IO port stuff === */
|
|
+int pluginRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
|
|
+ unsigned base, const char *name, unsigned len);
|
|
+int pluginRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
|
|
+ unsigned base, const char *name, unsigned len);
|
|
+
|
|
+/* === IRQ stuff === */
|
|
+extern void pluginRegisterIRQ(unsigned irq, const char *name);
|
|
+extern void pluginUnregisterIRQ(unsigned irq, const char *name);
|
|
+extern void pluginTriggerIRQ(unsigned irq);
|
|
+extern void pluginUntriggerIRQ(unsigned irq);
|
|
+
|
|
+
|
|
+/* === CMOS query/set stuff === */
|
|
+
|
|
+/* These are function pointers. At startup time, they are set to
|
|
+ * builtin default handlers which will cause an abort if called.
|
|
+ * A CMOS plugin should set these pointers to real handler functions.
|
|
+ */
|
|
+extern Bit32u (* pluginGetCMOSReg)(unsigned reg);
|
|
+extern void (* pluginSetCMOSReg)(unsigned reg, Bit32u val);
|
|
+extern void (* pluginCMOSChecksum)(void);
|
|
+
|
|
+
|
|
+/* === A20 enable line stuff === */
|
|
+extern unsigned pluginGetA20E(void);
|
|
+extern void pluginSetA20E(unsigned val);
|
|
+
|
|
+
|
|
+/* === Keyboard/Mouse input stuff === */
|
|
+extern void (* pluginMouseMotion)(int d_x, int d_y, unsigned button_state);
|
|
+extern void (* pluginGenScancode)(Bit32u scancode);
|
|
+
|
|
+
|
|
+/* === DMA stuff === */
|
|
+extern unsigned (* pluginRegisterDMAChannel)(
|
|
+ unsigned channel,
|
|
+ void (* dma_read)(Bit8u *data_byte),
|
|
+ void (* dma_write)(Bit8u *data_byte)
|
|
+ );
|
|
+extern void (* pluginDMASetDRQ)(unsigned channel, unsigned val);
|
|
+extern unsigned (* pluginDMAGetTC)(void);
|
|
+
|
|
+/* === Hard drive / floppy port sharing hack === */
|
|
+extern Bit32u (* pluginHDReadHandler)(Bit32u address,
|
|
+ unsigned io_len);
|
|
+extern void (* pluginHDWriteHandler)(Bit32u address,
|
|
+ Bit32u value, unsigned io_len);
|
|
+
|
|
+/* === VGA stuff === */
|
|
+extern void (* pluginVGARedrawArea)(unsigned x0, unsigned y0,
|
|
+ unsigned width, unsigned height);
|
|
+
|
|
+#if 0
|
|
+/* === Mega hacks for bochs IO devices === */
|
|
+void bx_printf(char *fmt, ...);
|
|
+void bx_panic(char *fmt, ...);
|
|
+
|
|
+typedef struct {
|
|
+ Boolean floppy;
|
|
+ Boolean keyboard;
|
|
+ Boolean video;
|
|
+ Boolean disk;
|
|
+ Boolean pit;
|
|
+ Boolean pic;
|
|
+ Boolean bios;
|
|
+ Boolean cmos;
|
|
+ Boolean interrupts;
|
|
+ Boolean exceptions;
|
|
+ Boolean unsupported;
|
|
+ Boolean temp;
|
|
+ Boolean reset;
|
|
+ Boolean debugger;
|
|
+ Boolean mouse;
|
|
+ Boolean io;
|
|
+ Boolean xms;
|
|
+ Boolean v8086;
|
|
+ Boolean paging;
|
|
+ Boolean creg;
|
|
+ Boolean dreg;
|
|
+ Boolean dma;
|
|
+ Boolean unsupported_io;
|
|
+ Boolean serial;
|
|
+ Boolean cdrom;
|
|
+#ifdef MAGIC_BREAKPOINT
|
|
+ Boolean magic_break_enabled;
|
|
+#endif /* MAGIC_BREAKPOINT */
|
|
+ void* record_io;
|
|
+ } bx_debug_t;
|
|
+
|
|
+
|
|
+typedef struct {
|
|
+ char path[512];
|
|
+ unsigned type;
|
|
+ unsigned initial_status;
|
|
+ } bx_floppy_options;
|
|
+
|
|
+typedef struct {
|
|
+ Boolean present;
|
|
+ char path[512];
|
|
+ unsigned int cylinders;
|
|
+ unsigned int heads;
|
|
+ unsigned int spt;
|
|
+ } bx_disk_options;
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ Boolean present;
|
|
+ char dev[512];
|
|
+ Boolean inserted;
|
|
+} bx_cdrom_options;
|
|
+
|
|
+typedef struct {
|
|
+ char *path;
|
|
+ unsigned long address;
|
|
+ } bx_rom_options;
|
|
+
|
|
+typedef struct {
|
|
+ char *path;
|
|
+ } bx_vgarom_options;
|
|
+
|
|
+typedef struct {
|
|
+ size_t megs;
|
|
+ } bx_mem_options;
|
|
+
|
|
+typedef struct {
|
|
+ char *path;
|
|
+ Boolean cmosImage;
|
|
+ unsigned int time0;
|
|
+ } bx_cmos_options;
|
|
+
|
|
+typedef struct {
|
|
+ int valid;
|
|
+ unsigned ioaddr;
|
|
+ unsigned irq;
|
|
+ unsigned char macaddr[6];
|
|
+ char *ethmod;
|
|
+ char *ethdev;
|
|
+ } bx_ne2k_options;
|
|
+
|
|
+typedef struct {
|
|
+ char *midifile, *wavefile, *logfile;
|
|
+ unsigned int midimode, wavemode, loglevel;
|
|
+ Bit32u dmatimer;
|
|
+ } bx_sb16_options;
|
|
+
|
|
+typedef struct {
|
|
+ bx_floppy_options floppya;
|
|
+ bx_floppy_options floppyb;
|
|
+ bx_disk_options diskc;
|
|
+ bx_disk_options diskd;
|
|
+ bx_cdrom_options cdromd;
|
|
+ bx_sb16_options sb16;
|
|
+ char bootdrive[2];
|
|
+ unsigned long vga_update_interval;
|
|
+ unsigned long keyboard_serial_delay;
|
|
+ unsigned long floppy_command_delay;
|
|
+ unsigned long ips;
|
|
+ Boolean mouse_enabled;
|
|
+ Boolean private_colormap;
|
|
+ Boolean i440FXSupport;
|
|
+ bx_cmos_options cmos;
|
|
+ bx_ne2k_options ne2k;
|
|
+ Boolean newHardDriveSupport;
|
|
+ } bx_options_t;
|
|
+
|
|
+extern bx_options_t bx_options;
|
|
+extern bx_debug_t bx_dbg;
|
|
+#endif
|
|
+
|
|
+
|
|
+int plugin_emulate_inport (int port, int op_size, int count, void *loc);
|
|
+int plugin_emulate_outport (int port, int op_size, int count, void *loc);
|
|
+int plugin_alloc_intr (plugin_t *plugin, handler_t handler, int vec);
|
|
+void plugin_free_intr (plugin_t *plugin, int vec);
|
|
+int plugin_emulate_int (int vec);
|
|
+
|
|
+typedef void (*plugin_pending_t)(void);
|
|
+int plugin_acknowledge_intr (void);
|
|
+void plugin_enqueue (plugin_pending_t func);
|
|
+void plugin_handle_pending (void);
|
|
+void plugin_register_elapsed(void (*funct)(Bit64u));
|
|
+void plugin_register_periodic(void (*funct)(void));
|
|
+void plugin_register_mem_map_IO(
|
|
+ void (*f)(Bit32u, unsigned, unsigned, Bit32u *),
|
|
+ Bit32u, Bit32u);
|
|
+void plugin_call_elapsed (Bit64u elapsed);
|
|
+void plugin_handle_periodic(void);
|
|
+int pluginRegisterTimer(void *this_ptr, void (*funct)(void *),
|
|
+ Bit32u useconds, Boolean continuous,
|
|
+ Boolean active);
|
|
+void pluginActivateTimer(unsigned id, Bit32u usec, Boolean continuous);
|
|
+void pluginDeactivateTimer(unsigned id);
|
|
+void pluginSetHRQ(unsigned val);
|
|
+void pluginSetHRQHackCallback( void (*callback)(void) );
|
|
+
|
|
+void pluginResetSignal(unsigned sig);
|
|
+
|
|
+extern Bit32u builtinGetCMOSReg(unsigned reg);
|
|
+extern void builtinSetCMOSReg(unsigned reg, Bit32u val);
|
|
+extern void builtinCMOSChecksum(void);
|
|
+extern void builtinMouseMotion(int d_x, int d_y, unsigned button_state);
|
|
+extern void builtinGenScancode(Bit32u scancode);
|
|
+extern unsigned builtinRegisterDMAChannel(
|
|
+ unsigned channel,
|
|
+ void (* dma_read)(Bit8u *data_byte),
|
|
+ void (* dma_write)(Bit8u *data_byte)
|
|
+ );
|
|
+extern void builtinDMASetDRQ(unsigned channel, unsigned val);
|
|
+extern unsigned builtinDMAGetTC(void);
|
|
+
|
|
+extern void (*pluginHRQHackCallback)(void);
|
|
+extern unsigned pluginHRQ;
|
|
+
|
|
+extern void (*memMapFunct)(Bit32u, unsigned, unsigned, Bit32u *);
|
|
+
|
|
+void plugin_abort (void);
|
|
+
|
|
+/* Atomic XCHG for reentrant function plugin_enqueue() */
|
|
+#define XCHG(x,y) \
|
|
+ ({ \
|
|
+ typeof(x) p; \
|
|
+ asm ( "xchg %0, %1" : "=r" (p) : "m" (x), "0" (y) : "memory" ); \
|
|
+ p; \
|
|
+ })
|
|
+
|
|
+typedef struct {
|
|
+ Bit64u (*wcLSeek)(int fd, Bit64u off64, int whence);
|
|
+ unsigned (*wcRead)(int fd, void *buffer, unsigned len);
|
|
+ unsigned (*wcWrite)(int fd, void *buffer, unsigned len);
|
|
+ void (*wcCommit)(int fd);
|
|
+ } pluginCallbacks_t;
|
|
+
|
|
+extern pluginCallbacks_t pluginCallbacks;
|
|
+
|
|
+#define pluginRegisterWriteCache(LS, R, W, C) \
|
|
+ ({ \
|
|
+ pluginCallbacks.wcLSeek = LS; \
|
|
+ pluginCallbacks.wcRead = R; \
|
|
+ pluginCallbacks.wcWrite = W; \
|
|
+ pluginCallbacks.wcCommit = C; \
|
|
+ })
|
|
+
|
|
+#define pluginWCLSeek(fd, off64, whence) \
|
|
+ pluginCallbacks.wcLSeek(fd, off64, whence)
|
|
+
|
|
+#define pluginWCRead(fd, buffer, len) \
|
|
+ pluginCallbacks.wcRead(fd, buffer, len)
|
|
+
|
|
+#define pluginWCWrite(fd, buffer, len) \
|
|
+ pluginCallbacks.wcWrite(fd, buffer, len)
|
|
+
|
|
+#define pluginWCCommit(fd) \
|
|
+ pluginCallbacks.wcCommit(fd)
|
|
+
|
|
+// FIXME: called from bochs main (hack)
|
|
+int bx_init_plugin ();
|
|
+
|
|
+// every plugin must define these, within the extern"C" block, so that
|
|
+// a non-mangled function symbol is available in the shared library.
|
|
+void plugin_fini(void);
|
|
+int plugin_init(plugin_t *plugin, int argc, char *argv[]);
|
|
+
|
|
+
|
|
+#ifdef __cplusplus
|
|
+};
|
|
+#endif
|
|
+
|
|
+#endif /* __PLUGIN_H */
|
|
Index: gui/x.cc
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/gui/x.cc,v
|
|
retrieving revision 1.24
|
|
diff -u -r1.24 x.cc
|
|
--- gui/x.cc 2001/12/08 13:42:55 1.24
|
|
+++ gui/x.cc 2001/12/13 02:31:17
|
|
@@ -24,7 +24,6 @@
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
-
|
|
extern "C" {
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
@@ -765,7 +764,7 @@
|
|
warp_cursor(warp_home_x-current_x, warp_home_y-current_y);
|
|
|
|
//BX_INFO(("xxx: MOUSE_MOTION: dx=%d, dy=%d", (int) dx, (int) dy));
|
|
- bx_devices.keyboard->mouse_motion( dx, dy, mouse_button_state);
|
|
+ BX_EVENT_MOUSE_MOTION (dx, dy, mouse_button_state);
|
|
//if (warped) {
|
|
// prev_x = current_x = -1;
|
|
// prev_y = current_y = -1;
|
|
@@ -930,7 +929,7 @@
|
|
if (press_release)
|
|
key_event |= BX_KEY_RELEASED;
|
|
|
|
- bx_devices.keyboard->gen_scancode(key_event);
|
|
+ BX_EVENT_GEN_SCANCODE(key_event);
|
|
}
|
|
|
|
|
|
Index: iodev/Makefile.in
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/iodev/Makefile.in,v
|
|
retrieving revision 1.12
|
|
diff -u -r1.12 Makefile.in
|
|
--- iodev/Makefile.in 2001/12/07 21:56:15 1.12
|
|
+++ iodev/Makefile.in 2001/12/13 02:31:18
|
|
@@ -63,7 +63,7 @@
|
|
floppy.o \
|
|
harddrv.o \
|
|
@IODEBUG_OBJS@ \
|
|
- keyboard.o \
|
|
+ \
|
|
parallel.o \
|
|
serial.o \
|
|
$(VIDEO_OBJS) \
|
|
@@ -85,7 +85,13 @@
|
|
.@CPP_SUFFIX@.o:
|
|
$(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@
|
|
|
|
+all: libiodev.a libplex-keyboard.la
|
|
|
|
+libplex-keyboard.la: plex-keyboard.cc plex-keyboard.h
|
|
+ libtool --mode=compile $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $(BX_INCDIRS) plex-keyboard.cc
|
|
+ libtool --mode=link $(CXX) plex-keyboard.lo -o libplex-keyboard.la -rpath /tmp/bochslib
|
|
+ -mkdir /tmp/bochslib
|
|
+ libtool --mode=install cp libplex-keyboard.la /tmp/bochslib
|
|
|
|
libiodev.a: $(BX_OBJS)
|
|
@RMCOMMAND@ libiodev.a
|
|
Index: iodev/devices.cc
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/iodev/devices.cc,v
|
|
retrieving revision 1.18
|
|
diff -u -r1.18 devices.cc
|
|
--- iodev/devices.cc 2001/10/03 13:10:38 1.18
|
|
+++ iodev/devices.cc 2001/12/13 02:31:18
|
|
@@ -56,7 +56,8 @@
|
|
pci = NULL;
|
|
#endif
|
|
pit = NULL;
|
|
- keyboard = NULL;
|
|
+ // disable so I can use the plex86 keyboard plugin
|
|
+ //keyboard = NULL;
|
|
dma = NULL;
|
|
floppy = NULL;
|
|
cmos = NULL;
|
|
@@ -171,8 +172,9 @@
|
|
dma = &bx_dma;
|
|
dma->init(this);
|
|
|
|
- keyboard = &bx_keyboard;
|
|
- keyboard->init(this, cmos);
|
|
+ //disable so I can use plex86 keyboard plugin
|
|
+ //keyboard = &bx_keyboard;
|
|
+ //keyboard->init(this, cmos);
|
|
|
|
#if BX_IODEBUG_SUPPORT
|
|
iodebug = &bx_iodebug;
|
|
@@ -305,6 +307,23 @@
|
|
}
|
|
#endif
|
|
|
|
+#if 1
|
|
+ // separate calls to bx_gui.handle_events from the keyboard code.
|
|
+ {
|
|
+ static int multiple=0;
|
|
+ if ( ++multiple==10)
|
|
+ {
|
|
+ multiple=0;
|
|
+ bx_gui.handle_events();
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
+#if 0
|
|
+ // the plex86 keyboard has its own timer handler and triggers IRQs on its
|
|
+ // own, so while using the plex86 keyboard plugin, this code is not needed.
|
|
+ // Except, that the keyboard->periodic() function happens to call
|
|
+ // bx_gui.handle_events for all GUI events.
|
|
retval = keyboard->periodic( TIMER_DELTA );
|
|
if (retval & 0x01) {
|
|
if (bx_dbg.keyboard)
|
|
@@ -313,6 +332,7 @@
|
|
}
|
|
if (retval & 0x02)
|
|
pic->trigger_irq(12);
|
|
+#endif
|
|
|
|
#if BX_SUPPORT_APIC
|
|
// update local APIC timers
|
|
Index: iodev/iodev.h
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/iodev/iodev.h,v
|
|
retrieving revision 1.10
|
|
diff -u -r1.10 iodev.h
|
|
--- iodev/iodev.h 2001/10/03 13:10:38 1.10
|
|
+++ iodev/iodev.h 2001/12/13 02:31:20
|
|
@@ -39,7 +39,7 @@
|
|
|
|
|
|
class bx_pit_c;
|
|
-class bx_keyb_c;
|
|
+//class bx_keyb_c;
|
|
class bx_dma_c;
|
|
class bx_floppy_ctrl_c;
|
|
class bx_cmos_c;
|
|
@@ -98,7 +98,7 @@
|
|
bx_ioapic_c *ioapic;
|
|
bx_pci_c *pci;
|
|
bx_pit_c *pit;
|
|
- bx_keyb_c *keyboard;
|
|
+ //bx_keyb_c *keyboard;
|
|
bx_dma_c *dma;
|
|
bx_floppy_ctrl_c *floppy;
|
|
bx_cmos_c *cmos;
|
|
@@ -162,7 +162,8 @@
|
|
#if BX_IODEBUG_SUPPORT
|
|
# include "iodev/iodebug.h"
|
|
#endif
|
|
-#include "iodev/keyboard.h"
|
|
+// maybe should be disabled while testing plex86 keyboard plugin
|
|
+//#include "iodev/keyboard.h"
|
|
#include "iodev/parallel.h"
|
|
#include "iodev/pic.h"
|
|
#include "iodev/pit.h"
|
|
Index: iodev/plex-keyboard.cc
|
|
===================================================================
|
|
RCS file: iodev/plex-keyboard.cc
|
|
diff -N iodev/plex-keyboard.cc
|
|
--- /dev/null Thu May 24 22:33:05 2001
|
|
+++ iodev/plex-keyboard.cc Wed Dec 12 18:31:21 2001
|
|
@@ -0,0 +1,1360 @@
|
|
+// Copyright (C) 2000 MandrakeSoft S.A.
|
|
+//
|
|
+// MandrakeSoft S.A.
|
|
+// 43, rue d'Aboukir
|
|
+// 75002 Paris - France
|
|
+// http://www.linux-mandrake.com/
|
|
+// http://www.mandrakesoft.com/
|
|
+//
|
|
+// This library is free software; you can redistribute it and/or
|
|
+// modify it under the terms of the GNU Lesser General Public
|
|
+// License as published by the Free Software Foundation; either
|
|
+// version 2 of the License, or (at your option) any later version.
|
|
+//
|
|
+// This library is distributed in the hope that it will be useful,
|
|
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+// Lesser General Public License for more details.
|
|
+//
|
|
+// You should have received a copy of the GNU Lesser General Public
|
|
+// License along with this library; if not, write to the Free Software
|
|
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+
|
|
+
|
|
+// Now features proper implementation of keyboard opcodes 0xF4 to 0xF6
|
|
+// Silently ignores PS/2 keyboard extensions (0xF7 to 0xFD)
|
|
+// Explicit panic on resend (0xFE)
|
|
+//
|
|
+// Emmanuel Marty <core@ggi-project.org>
|
|
+
|
|
+
|
|
+#include "bochs.h"
|
|
+#include "plex-keyboard.h"
|
|
+
|
|
+
|
|
+//FIXME
|
|
+#define LOG_THIS genlog->
|
|
+//FIXME
|
|
+#define bx_printf printf
|
|
+#define bx_panic printf
|
|
+
|
|
+#define MOUSE_MODE_RESET 10
|
|
+#define MOUSE_MODE_STREAM 11
|
|
+#define MOUSE_MODE_REMOTE 12
|
|
+#define MOUSE_MODE_WRAP 13
|
|
+
|
|
+
|
|
+#if BX_USE_KEY_SMF
|
|
+plex_keyb_c plex_keyboard;
|
|
+#define this (&plex_keyboard)
|
|
+#endif
|
|
+
|
|
+ int
|
|
+plugin_init(plugin_t *plugin, int argc, char *argv[])
|
|
+{
|
|
+ plex_keyb_c *keyboard;
|
|
+
|
|
+#if BX_USE_KEY_SMF
|
|
+ keyboard = &plex_keyboard;
|
|
+#else
|
|
+ keyboard = new plex_keyb_c();
|
|
+#endif
|
|
+ keyboard->init();
|
|
+
|
|
+ return(0); // Success
|
|
+}
|
|
+
|
|
+ void
|
|
+plugin_fini(void)
|
|
+{
|
|
+}
|
|
+
|
|
+ static void
|
|
+keybMouseMotion(int dx, int dy, unsigned mouse_button_state)
|
|
+{
|
|
+ plex_keyboard.mouse_motion( dx, dy, mouse_button_state);
|
|
+}
|
|
+
|
|
+ static void
|
|
+keybGenScancode(Bit32u key_event)
|
|
+{
|
|
+ plex_keyboard.gen_scancode(key_event);
|
|
+}
|
|
+
|
|
+
|
|
+plex_keyb_c::plex_keyb_c(void)
|
|
+{
|
|
+ // constructor
|
|
+ // should zero out state info here???
|
|
+ memset( &s, 0, sizeof(s) );
|
|
+ pluginMouseMotion = keybMouseMotion;
|
|
+ pluginGenScancode = keybGenScancode;
|
|
+}
|
|
+
|
|
+plex_keyb_c::~plex_keyb_c(void)
|
|
+{
|
|
+ // destructor
|
|
+}
|
|
+
|
|
+
|
|
+// flush internal buffer and reset keyboard settings to power-up condition
|
|
+ void
|
|
+plex_keyb_c::resetinternals(Boolean powerup)
|
|
+{
|
|
+ Bit32u i;
|
|
+
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.num_elements = 0;
|
|
+ for (i=0; i<BX_KBD_ELEMENTS; i++)
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.buffer[i] = 0;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.head = 0;
|
|
+
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 0;
|
|
+
|
|
+ if (powerup) {
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 0;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.delay = 1; // 500 mS
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.repeat_rate = 0x0b; // 10.9 chars/sec
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::init(void)
|
|
+{
|
|
+ Bit32u i;
|
|
+
|
|
+ pluginRegisterIRQ(1, "8042 Keyboard controller");
|
|
+
|
|
+ pluginRegisterIOReadHandler(this, read_handler,
|
|
+ 0x0060, "8042 Keyboard controller", 1);
|
|
+ pluginRegisterIOReadHandler(this, read_handler,
|
|
+ 0x0064, "8042 Keyboard controller", 1);
|
|
+ pluginRegisterIOWriteHandler(this, write_handler,
|
|
+ 0x0060, "8042 Keyboard controller", 1);
|
|
+ pluginRegisterIOWriteHandler(this, write_handler,
|
|
+ 0x0064, "8042 Keyboard controller", 1);
|
|
+ PLEX_KEY_THIS timer_handle = pluginRegisterTimer( this, timer_handler,
|
|
+ (unsigned) bx_options.Okeyboard_serial_delay->get (), 0, 0);
|
|
+
|
|
+ resetinternals(1);
|
|
+
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.led_status = 0;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1;
|
|
+
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.num_elements = 0;
|
|
+ for (i=0; i<BX_MOUSE_BUFF_SIZE; i++)
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.buffer[i] = 0;
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.head = 0;
|
|
+
|
|
+ PLEX_KEY_THIS s.kbd_controller.pare = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.tim = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.keyl = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.c_d = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.sysf = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.inpb = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 0;
|
|
+
|
|
+ PLEX_KEY_THIS s.kbd_controller.scan_convert = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.allow_irq1 = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.allow_irq12 = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_output_buffer = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_output_buffer = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.last_comm = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
|
|
+
|
|
+ // Mouse initialization stuff
|
|
+ PLEX_KEY_THIS s.mouse.sample_rate = 100; // reports per second
|
|
+ PLEX_KEY_THIS s.mouse.resolution_cpmm = 4; // 4 counts per millimeter
|
|
+ PLEX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */
|
|
+ PLEX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET;
|
|
+ PLEX_KEY_THIS s.mouse.enable = 0;
|
|
+
|
|
+ for (i=0; i<BX_KBD_CONTROLLER_QSIZE; i++)
|
|
+ PLEX_KEY_THIS s.controller_Q[i] = 0;
|
|
+ PLEX_KEY_THIS s.controller_Qsize = 0;
|
|
+ PLEX_KEY_THIS s.controller_Qsource = 0;
|
|
+
|
|
+ PLEX_KEY_THIS s.timer_pending = 0;
|
|
+
|
|
+ // mouse port installed on system board
|
|
+ pluginSetCMOSReg( 0x14, pluginGetCMOSReg(0x14) | 0x04 );
|
|
+}
|
|
+
|
|
+#define RETURN(x) do { ret = (x); goto read_return; } while (0)
|
|
+
|
|
+ // static IO port read callback handler
|
|
+ // redirects to non-static class handler to avoid virtual functions
|
|
+
|
|
+ Bit32u
|
|
+plex_keyb_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
|
|
+{
|
|
+#if !BX_USE_KEY_SMF
|
|
+ plex_keyb_c *class_ptr = (plex_keyb_c *) this_ptr;
|
|
+
|
|
+ return( class_ptr->read(address, io_len) );
|
|
+}
|
|
+
|
|
+
|
|
+ Bit32u
|
|
+plex_keyb_c::read(Bit32u address, unsigned io_len)
|
|
+{
|
|
+#else
|
|
+ UNUSED(this_ptr);
|
|
+#endif // !BX_USE_KEY_SMF
|
|
+
|
|
+ Bit32u ret = 0;
|
|
+
|
|
+ if (io_len > 1)
|
|
+ BX_PANIC(("kbd: io read to address %08x, len=%u\n",
|
|
+ (unsigned) address, (unsigned) io_len));
|
|
+
|
|
+
|
|
+//bx_printf("# KBD: read from port 0x%04x\n", (unsigned) address);
|
|
+
|
|
+ if (address == 0x60) { /* output buffer */
|
|
+ Bit8u val;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.auxb) { /* mouse byte available */
|
|
+ val = PLEX_KEY_THIS s.kbd_controller.aux_output_buffer;
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_output_buffer = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 0;
|
|
+
|
|
+ if (PLEX_KEY_THIS s.controller_Qsize) {
|
|
+ unsigned i;
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_output_buffer = PLEX_KEY_THIS s.controller_Q[0];
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 1;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq12)
|
|
+ pluginTriggerIRQ(12);
|
|
+ for (i=0; i<PLEX_KEY_THIS s.controller_Qsize-1; i++) {
|
|
+ // move Q elements towards head of queue by one
|
|
+ PLEX_KEY_THIS s.controller_Q[i] = PLEX_KEY_THIS s.controller_Q[i+1];
|
|
+ }
|
|
+ PLEX_KEY_THIS s.controller_Qsize--;
|
|
+ }
|
|
+
|
|
+//bx_printf("mouse: ___io_read aux = 0x%02x\n", (unsigned) val);
|
|
+
|
|
+ activate_timer();
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: READ(%02x) = %02x\n", (unsigned) address,
|
|
+ (unsigned) val);
|
|
+ RETURN(val);
|
|
+ }
|
|
+ else if (PLEX_KEY_THIS s.kbd_controller.outb) { /* kbd byte available */
|
|
+ val = PLEX_KEY_THIS s.kbd_controller.kbd_output_buffer;
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_output_buffer = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 0;
|
|
+//bx_printf("# ___io_read kbd\n");
|
|
+
|
|
+ if (PLEX_KEY_THIS s.controller_Qsize) {
|
|
+ unsigned i;
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_output_buffer = PLEX_KEY_THIS s.controller_Q[0];
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 1;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq1)
|
|
+ pluginTriggerIRQ(1);
|
|
+ for (i=0; i<PLEX_KEY_THIS s.controller_Qsize-1; i++) {
|
|
+ // move Q elements towards head of queue by one
|
|
+ PLEX_KEY_THIS s.controller_Q[i] = PLEX_KEY_THIS s.controller_Q[i+1];
|
|
+ }
|
|
+ PLEX_KEY_THIS s.controller_Qsize--;
|
|
+ }
|
|
+
|
|
+ activate_timer();
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: READ(%02x) = %02x\n", (unsigned) address,
|
|
+ (unsigned) val);
|
|
+ RETURN(val);
|
|
+ }
|
|
+ else {
|
|
+ if (bx_dbg.keyboard) {
|
|
+ bx_printf("KBD: num_elements = %d\n", PLEX_KEY_THIS s.kbd_internal_buffer.num_elements);
|
|
+ bx_printf("KBD: read from port 60h with outb empty\n");
|
|
+ }
|
|
+ val = 0;
|
|
+ RETURN(val);
|
|
+ }
|
|
+ }
|
|
+
|
|
+#if BX_CPU_LEVEL >= 2
|
|
+ else if (address == 0x64) { /* status register */
|
|
+ Bit8u val;
|
|
+
|
|
+ val = (PLEX_KEY_THIS s.kbd_controller.pare << 7) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.tim << 6) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.auxb << 5) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.keyl << 4) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.c_d << 3) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.sysf << 2) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.inpb << 1) |
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb;
|
|
+ RETURN(val);
|
|
+ }
|
|
+
|
|
+#else /* BX_CPU_LEVEL > 0 */
|
|
+ /* XT MODE, System 8255 Mode Register */
|
|
+ else if (address == 0x64) { /* status register */
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: IO read from port 64h, system 8255 mode register\n");
|
|
+ RETURN(PLEX_KEY_THIS s.kbd_controller.outb);
|
|
+ }
|
|
+#endif /* BX_CPU_LEVEL > 0 */
|
|
+
|
|
+ else {
|
|
+ BX_PANIC(("KBD: unknown address in io read to keyboard port %x\n",
|
|
+ (unsigned) address));
|
|
+ RETURN(0); /* keep compiler happy */
|
|
+ }
|
|
+
|
|
+ read_return:
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("keyboard: 8-bit read from %04x = %02x\n", (unsigned)address, ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
+ // static IO port write callback handler
|
|
+ // redirects to non-static class handler to avoid virtual functions
|
|
+
|
|
+ void
|
|
+plex_keyb_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+#if !BX_USE_KEY_SMF
|
|
+ plex_keyb_c *class_ptr = (plex_keyb_c *) this_ptr;
|
|
+
|
|
+ class_ptr->write(address, value, io_len);
|
|
+}
|
|
+
|
|
+ void
|
|
+plex_keyb_c::write( Bit32u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+#else
|
|
+ UNUSED(this_ptr);
|
|
+#endif // !BX_USE_KEY_SMF
|
|
+ Bit8u command_byte;
|
|
+
|
|
+ if (io_len > 1)
|
|
+ BX_PANIC(("kbd: io write to address %08x, len=%u\n",
|
|
+ (unsigned) address, (unsigned) io_len));
|
|
+
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("keyboard: 8-bit write to %04x = %02x\n", (unsigned)address, (unsigned)value);
|
|
+
|
|
+
|
|
+//bx_printf("# KBD: WRITE(%02x) = %02x\n", (unsigned) address,
|
|
+// (unsigned) value);
|
|
+
|
|
+ switch (address) {
|
|
+ case 0x60: // input buffer
|
|
+ // if expecting data byte from command last sent to port 64h
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.expecting_port60h) {
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
|
|
+ // data byte written last to 0x60
|
|
+ PLEX_KEY_THIS s.kbd_controller.c_d = 0;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.inpb) {
|
|
+ bx_panic("KBD: write to port 60h, not ready for write\n");
|
|
+ }
|
|
+ switch (PLEX_KEY_THIS s.kbd_controller.last_comm) {
|
|
+ case 0x60: // write command byte
|
|
+ {
|
|
+ Boolean scan_convert, disable_keyboard,
|
|
+ disable_aux;
|
|
+
|
|
+ scan_convert = (value >> 6) & 0x01;
|
|
+ disable_aux = (value >> 5) & 0x01;
|
|
+ disable_keyboard = (value >> 4) & 0x01;
|
|
+ PLEX_KEY_THIS s.kbd_controller.sysf = (value >> 2) & 0x01;
|
|
+ PLEX_KEY_THIS s.kbd_controller.allow_irq1 = (value >> 0) & 0x01;
|
|
+ PLEX_KEY_THIS s.kbd_controller.allow_irq12 = (value >> 1) & 0x01;
|
|
+ set_kbd_clock_enable(!disable_keyboard);
|
|
+ set_aux_clock_enable(!disable_aux);
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq12 && PLEX_KEY_THIS s.kbd_controller.auxb)
|
|
+ pluginTriggerIRQ(12);
|
|
+ else if (PLEX_KEY_THIS s.kbd_controller.allow_irq1 && PLEX_KEY_THIS s.kbd_controller.outb)
|
|
+ pluginTriggerIRQ(1);
|
|
+
|
|
+//bx_printf("# allow_irq12 set to %u\n", (unsigned)
|
|
+// PLEX_KEY_THIS s.kbd_controller.allow_irq12);
|
|
+ if ( !scan_convert )
|
|
+ bx_printf("keyboard: (mch) scan convert turned off\n");
|
|
+
|
|
+ // (mch) NT needs this
|
|
+ PLEX_KEY_THIS s.kbd_controller.scan_convert = scan_convert;
|
|
+ }
|
|
+ break;
|
|
+ case 0xd1: // write output port
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: write output port with value %02xh\n",
|
|
+ (unsigned) value);
|
|
+ BX_SET_ENABLE_A20( (value & 0x02) != 0 );
|
|
+ if (!(value & 0x01)) BX_PANIC(("KBD: IO write: processor reset requested!\n"));
|
|
+ break;
|
|
+ case 0xd4: // Write to mouse
|
|
+ // I don't think this enables the AUX clock
|
|
+ //set_aux_clock_enable(1); // enable aux clock line
|
|
+ kbd_ctrl_to_mouse(value);
|
|
+ // ??? should I reset to previous value of aux enable?
|
|
+ break;
|
|
+
|
|
+ case 0xd3: // write mouse output buffer
|
|
+ // Queue in mouse output buffer
|
|
+ controller_enQ(value, 1);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ BX_PANIC(("KBD: === unsupported write to port 60h(lastcomm=%02x): %02x\n",
|
|
+ (unsigned) PLEX_KEY_THIS s.kbd_controller.last_comm, (unsigned) value));
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ // data byte written last to 0x60
|
|
+ PLEX_KEY_THIS s.kbd_controller.c_d = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
|
|
+ /* pass byte to keyboard */
|
|
+ /* ??? should conditionally pass to mouse device here ??? */
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0) {
|
|
+ bx_printf("KBD: keyboard disabled & send of byte %02x to kbd\n",
|
|
+ (unsigned) value);
|
|
+ }
|
|
+ kbd_ctrl_to_kbd(value);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case 0x64: // control register
|
|
+ // command byte written last to 0x64
|
|
+ PLEX_KEY_THIS s.kbd_controller.c_d = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.last_comm = value;
|
|
+ // most commands NOT expecting port60 write next
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
|
|
+
|
|
+ switch (value) {
|
|
+ case 0x20: // get keyboard command byte
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: get keyboard command byte\n");
|
|
+ // controller output buffer must be empty
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+bx_panic("kbd: OUTB set and command 0x%02x encountered\n", value);
|
|
+ break;
|
|
+ }
|
|
+ command_byte =
|
|
+ (PLEX_KEY_THIS s.kbd_controller.scan_convert << 6) |
|
|
+ ((!PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled) << 5) |
|
|
+ ((!PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled) << 4) |
|
|
+ (0 << 3) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.sysf << 2) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.allow_irq12 << 1) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.allow_irq1 << 0);
|
|
+ controller_enQ(command_byte, 0);
|
|
+ break;
|
|
+ case 0x60: // write command byte
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: write command byte\n");
|
|
+ // following byte written to port 60h is command byte
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
|
|
+ break;
|
|
+
|
|
+ case 0xa1:
|
|
+ bx_printf ("KBD: Dummy out Green PC for now : 0xa1\n");
|
|
+ break;
|
|
+
|
|
+ case 0xa7: // disable the aux device
|
|
+ set_aux_clock_enable(0);
|
|
+ if (bx_dbg.keyboard) bx_printf("KBD: aux device disabled\n");
|
|
+ break;
|
|
+ case 0xa8: // enable the aux device
|
|
+ set_aux_clock_enable(1);
|
|
+ if (bx_dbg.keyboard) bx_printf("KBD: aux device enabled\n");
|
|
+ break;
|
|
+ case 0xa9: // Test Mouse Port
|
|
+ // controller output buffer must be empty
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+bx_panic("kbd: OUTB set and command 0x%02x encountered\n", value);
|
|
+ break;
|
|
+ }
|
|
+ controller_enQ(0x00, 0); // no errors detected
|
|
+ break;
|
|
+ case 0xaa: // motherboard controller self test
|
|
+ if (bx_dbg.keyboard) bx_printf("KBD: Self Test\n");
|
|
+ // controller output buffer must be empty
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+bx_panic("kbd: OUTB set and command 0x%02x encountered\n", value);
|
|
+ break;
|
|
+ }
|
|
+ // (mch) Why is this commented out??? Enabling
|
|
+ PLEX_KEY_THIS s.kbd_controller.sysf = 1; // self test complete
|
|
+ controller_enQ(0x55, 0); // controller OK
|
|
+ break;
|
|
+ case 0xab: // Interface Test
|
|
+ // controller output buffer must be empty
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+bx_panic("kbd: OUTB set and command 0x%02x encountered\n", value);
|
|
+ break;
|
|
+ }
|
|
+ controller_enQ(0x00, 0);
|
|
+ break;
|
|
+ case 0xad: // disable keyboard
|
|
+ set_kbd_clock_enable(0);
|
|
+ if (bx_dbg.keyboard) bx_printf("KBD: keyboard disabled\n");
|
|
+ break;
|
|
+ case 0xae: // enable keyboard
|
|
+ set_kbd_clock_enable(1);
|
|
+ if (bx_dbg.keyboard) bx_printf("KBD: keyboard enabled\n");
|
|
+ break;
|
|
+ case 0xc0: // read input port
|
|
+ // controller output buffer must be empty
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+bx_panic("kbd: OUTB set and command 0x%02x encountered\n", value);
|
|
+ break;
|
|
+ }
|
|
+ // keyboard power normal
|
|
+ controller_enQ(0x00, 0);
|
|
+ break;
|
|
+ case 0xd0: // read output port: next byte read from port 60h
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: io write to port 64h, command d0h (partial)\n");
|
|
+ // controller output buffer must be empty
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+bx_panic("kbd: OUTB set and command 0x%02x encountered\n", value);
|
|
+ break;
|
|
+ }
|
|
+ controller_enQ(
|
|
+ (PLEX_KEY_THIS s.kbd_controller.auxb << 5) |
|
|
+ (PLEX_KEY_THIS s.kbd_controller.outb << 4) |
|
|
+ (BX_GET_ENABLE_A20() << 1) |
|
|
+ 0x01, 0);
|
|
+ break;
|
|
+
|
|
+ case 0xd1: // write output port: next byte written to port 60h
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: write output port\n");
|
|
+ // following byte to port 60h written to output port
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
|
|
+ break;
|
|
+
|
|
+ case 0xd3: // write mouse output buffer
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
|
|
+ break;
|
|
+
|
|
+ case 0xd4: // write to mouse
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("KBD: io write 0x64: command = 0xD4 (write to mouse)\n");
|
|
+ // following byte written to port 60h
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
|
|
+ break;
|
|
+
|
|
+ case 0xd2: // write keyboard output buffer
|
|
+ case 0xdd: // Disable A20 Address Line
|
|
+ case 0xdf: // Enable A20 Address Line
|
|
+ case 0xc1: // Continuous Input Port Poll, Low
|
|
+ case 0xc2: // Continuous Input Port Poll, High
|
|
+ case 0xe0: // Read Test Inputs
|
|
+ bx_panic("KBD: io write 0x64: command = %02xh\n", (unsigned) value);
|
|
+ break;
|
|
+
|
|
+ case 0xfe: // System Reset, transition to real mode
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: system reset\n");
|
|
+ bx_panic("system reset via KBD ctrl command FEh\n");
|
|
+ // Use bx_pc_system if necessary bx_cpu.reset_cpu();
|
|
+ pluginResetSignal( 0 );
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ if (value==0xff || (value>=0xf0 && value<=0xfd)) {
|
|
+ /* useless pulse output bit commands ??? */
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: io write to port 64h, useless command %02x\n",
|
|
+ (unsigned) value);
|
|
+ return;
|
|
+ }
|
|
+ bx_panic("KBD: unsupported io write to keyboard port %x, value = %x\n",
|
|
+ (unsigned) address, (unsigned) value);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default: bx_panic("KBD: unknown address in plex_keyb_c::write()\n");
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::gen_scancode(Bit32u key)
|
|
+{
|
|
+ Bit8u scancode;
|
|
+
|
|
+ if (bx_dbg.record_io) {
|
|
+ //fprintf((FILE*)bx_dbg.record_io, "gen_scancode %lld %x\n", bx_pc_system.time_ticks(), key);
|
|
+ }
|
|
+
|
|
+ if (!PLEX_KEY_THIS s.kbd_controller.scan_convert)
|
|
+ bx_panic("keyboard: gen_scancode with scan_convert cleared\n");
|
|
+
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: gen_scancode(): scancode: %08x\n", (unsigned) key);
|
|
+
|
|
+ // Ignore scancode if keyboard clock is driven low
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0)
|
|
+ return;
|
|
+
|
|
+ // Ignore scancode if scanning is disabled
|
|
+ if (PLEX_KEY_THIS s.kbd_internal_buffer.scanning_enabled==0)
|
|
+ return;
|
|
+
|
|
+ // should deal with conversions from KSCAN to system scan codes here
|
|
+
|
|
+ switch (key & 0xff) {
|
|
+ case BX_KEY_CTRL_L: scancode = 0x1d; break;
|
|
+ case BX_KEY_CTRL_R: scancode = 0x1d; break;
|
|
+ case BX_KEY_SHIFT_L: scancode = 0x2a; break;
|
|
+ case BX_KEY_SHIFT_R: scancode = 0x36; break;
|
|
+ case BX_KEY_ESC: scancode = 0x01; break;
|
|
+
|
|
+ case BX_KEY_ALT_L: scancode = 0x38; break;
|
|
+
|
|
+ case BX_KEY_A: scancode = 0x1e; break;
|
|
+ case BX_KEY_B: scancode = 0x30; break;
|
|
+ case BX_KEY_C: scancode = 0x2e; break;
|
|
+ case BX_KEY_D: scancode = 0x20; break;
|
|
+ case BX_KEY_E: scancode = 0x12; break;
|
|
+ case BX_KEY_F: scancode = 0x21; break;
|
|
+ case BX_KEY_G: scancode = 0x22; break;
|
|
+ case BX_KEY_H: scancode = 0x23; break;
|
|
+ case BX_KEY_I: scancode = 0x17; break;
|
|
+ case BX_KEY_J: scancode = 0x24; break;
|
|
+ case BX_KEY_K: scancode = 0x25; break;
|
|
+ case BX_KEY_L: scancode = 0x26; break;
|
|
+ case BX_KEY_M: scancode = 0x32; break;
|
|
+ case BX_KEY_N: scancode = 0x31; break;
|
|
+ case BX_KEY_O: scancode = 0x18; break;
|
|
+ case BX_KEY_P: scancode = 0x19; break;
|
|
+ case BX_KEY_Q: scancode = 0x10; break;
|
|
+ case BX_KEY_R: scancode = 0x13; break;
|
|
+ case BX_KEY_S: scancode = 0x1f; break;
|
|
+ case BX_KEY_T: scancode = 0x14; break;
|
|
+ case BX_KEY_U: scancode = 0x16; break;
|
|
+ case BX_KEY_V: scancode = 0x2f; break;
|
|
+ case BX_KEY_W: scancode = 0x11; break;
|
|
+ case BX_KEY_X: scancode = 0x2d; break;
|
|
+ case BX_KEY_Y: scancode = 0x15; break;
|
|
+ case BX_KEY_Z: scancode = 0x2c; break;
|
|
+
|
|
+ case BX_KEY_0: scancode = 0x0b; break;
|
|
+ case BX_KEY_1: scancode = 0x02; break;
|
|
+ case BX_KEY_2: scancode = 0x03; break;
|
|
+ case BX_KEY_3: scancode = 0x04; break;
|
|
+ case BX_KEY_4: scancode = 0x05; break;
|
|
+ case BX_KEY_5: scancode = 0x06; break;
|
|
+ case BX_KEY_6: scancode = 0x07; break;
|
|
+ case BX_KEY_7: scancode = 0x08; break;
|
|
+ case BX_KEY_8: scancode = 0x09; break;
|
|
+ case BX_KEY_9: scancode = 0x0a; break;
|
|
+
|
|
+ case BX_KEY_SPACE: scancode = 0x39; break;
|
|
+ case BX_KEY_SINGLE_QUOTE: scancode = 0x28; break;
|
|
+ case BX_KEY_COMMA: scancode = 0x33; break;
|
|
+ case BX_KEY_PERIOD: scancode = 0x34; break;
|
|
+ case BX_KEY_SLASH: scancode = 0x35; break;
|
|
+
|
|
+ case BX_KEY_SEMICOLON: scancode = 0x27; break;
|
|
+ case BX_KEY_EQUALS: scancode = 0x0d; break;
|
|
+
|
|
+ case BX_KEY_LEFT_BRACKET: scancode = 0x1a; break;
|
|
+ case BX_KEY_BACKSLASH: scancode = 0x2b; break;
|
|
+ case BX_KEY_RIGHT_BRACKET: scancode = 0x1b; break;
|
|
+ case BX_KEY_MINUS: scancode = 0x0c; break;
|
|
+ case BX_KEY_GRAVE: scancode = 0x29; break;
|
|
+
|
|
+ case BX_KEY_BACKSPACE: scancode = 0x0e; break;
|
|
+ case BX_KEY_ENTER: scancode = 0x1c; break;
|
|
+ case BX_KEY_TAB: scancode = 0x0f; break;
|
|
+
|
|
+ case BX_KEY_LEFT:
|
|
+ //bx_printf("# Grey left-arrow key not on 83-key keyboard\n");
|
|
+ scancode = 0x4b; break;
|
|
+ case BX_KEY_RIGHT:
|
|
+ //bx_printf("# Grey right-arrow key not on 83-key keyboard\n");
|
|
+ scancode = 0x4d; break;
|
|
+ case BX_KEY_UP:
|
|
+ //bx_printf("# Grey up-arrow key not on 83-key keyboard\n");
|
|
+ scancode = 0x48; break;
|
|
+ case BX_KEY_DOWN:
|
|
+ //bx_printf("# Grey down-arrow key not on 83-key keyboard\n");
|
|
+ scancode = 0x50; break;
|
|
+
|
|
+ case BX_KEY_KP_LEFT: scancode = 0x4b; break;
|
|
+ case BX_KEY_KP_RIGHT: scancode = 0x4d; break;
|
|
+ case BX_KEY_KP_UP: scancode = 0x48; break;
|
|
+ case BX_KEY_KP_DOWN: scancode = 0x50; break;
|
|
+
|
|
+ case BX_KEY_INSERT:
|
|
+ bx_printf("# Grey insert key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_DELETE:
|
|
+ bx_printf("# Grey delete key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_HOME:
|
|
+ bx_printf("# Grey home key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_END:
|
|
+ bx_printf("# Grey end key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_PAGE_UP:
|
|
+ bx_printf("# Grey page-up key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_PAGE_DOWN:
|
|
+ bx_printf("# Grey page-down key not on 83-key keyboard\n");
|
|
+ return;
|
|
+
|
|
+ case BX_KEY_KP_INSERT: scancode = 0x52; break;
|
|
+ case BX_KEY_KP_DELETE: scancode = 0x53; break;
|
|
+ case BX_KEY_KP_HOME: scancode = 0x47; break;
|
|
+ case BX_KEY_KP_END: scancode = 0x4f; break;
|
|
+ case BX_KEY_KP_PAGE_UP: scancode = 0x49; break;
|
|
+ case BX_KEY_KP_PAGE_DOWN: scancode = 0x51; break;
|
|
+
|
|
+ case BX_KEY_KP_ADD: scancode = 0x4e; break;
|
|
+ case BX_KEY_KP_SUBTRACT: scancode = 0x4a; break;
|
|
+ case BX_KEY_KP_5: scancode = 0x4c; break;
|
|
+ case BX_KEY_KP_ENTER:
|
|
+ bx_printf("# Grey Enter key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_KP_MULTIPLY:
|
|
+ bx_printf("# Grey Multiply key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_KP_DIVIDE:
|
|
+ bx_printf("# Grey Divide key not on 83-key keyboard\n");
|
|
+ return;
|
|
+ case BX_KEY_NUM_LOCK: scancode = 0x45; break;
|
|
+
|
|
+ case BX_KEY_F1: scancode = 0x3b; break;
|
|
+ case BX_KEY_F2: scancode = 0x3c; break;
|
|
+ case BX_KEY_F3: scancode = 0x3d; break;
|
|
+ case BX_KEY_F4: scancode = 0x3e; break;
|
|
+ case BX_KEY_F5: scancode = 0x3f; break;
|
|
+ case BX_KEY_F6: scancode = 0x40; break;
|
|
+ case BX_KEY_F7: scancode = 0x41; break;
|
|
+ case BX_KEY_F8: scancode = 0x42; break;
|
|
+ case BX_KEY_F9: scancode = 0x43; break;
|
|
+ case BX_KEY_F10: scancode = 0x44; break;
|
|
+
|
|
+ default:
|
|
+ bx_printf("# plex_keyb_c::gen_scancode : Unhandled %u\n",
|
|
+ (unsigned) key);
|
|
+ return;
|
|
+ }
|
|
+ if (key & BX_KEY_RELEASED)
|
|
+ scancode |= 0x80;
|
|
+ kbd_enQ(scancode);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::set_kbd_clock_enable(Bit8u value)
|
|
+{
|
|
+ Boolean prev_kbd_clock_enabled;
|
|
+
|
|
+ if (value==0) {
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled = 0;
|
|
+ }
|
|
+ else {
|
|
+ /* is another byte waiting to be sent from the keyboard ? */
|
|
+ prev_kbd_clock_enabled = PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled;
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled = 1;
|
|
+
|
|
+ if (prev_kbd_clock_enabled==0 && PLEX_KEY_THIS s.kbd_controller.outb==0) {
|
|
+ activate_timer();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::set_aux_clock_enable(Bit8u value)
|
|
+{
|
|
+ Boolean prev_aux_clock_enabled;
|
|
+
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("set_aux_clock_enable(%u)\n", (unsigned) value);
|
|
+ if (value==0) {
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled = 0;
|
|
+ }
|
|
+ else {
|
|
+ /* is another byte waiting to be sent from the keyboard ? */
|
|
+ prev_aux_clock_enabled = PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled;
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled = 1;
|
|
+ if (prev_aux_clock_enabled==0 && PLEX_KEY_THIS s.kbd_controller.outb==0)
|
|
+ activate_timer();
|
|
+ }
|
|
+}
|
|
+
|
|
+ Bit8u
|
|
+plex_keyb_c::get_kbd_enable(void)
|
|
+{
|
|
+#ifdef BX_DEBUG
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: get_kbd_enable(): getting kbd_clock_enabled of: %02x\n",
|
|
+ (unsigned) PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled);
|
|
+#endif
|
|
+
|
|
+ return(PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled);
|
|
+}
|
|
+
|
|
+ void
|
|
+plex_keyb_c::controller_enQ(Bit8u data, unsigned source)
|
|
+{
|
|
+ // source is 0 for keyboard, 1 for mouse
|
|
+
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("controller_enQ(%02x)\n", (unsigned) data);
|
|
+
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb)
|
|
+ bx_printf("KBD: controller_enQ(): OUTB set!\n");
|
|
+
|
|
+ // see if we need to Q this byte from the controller
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+ if (PLEX_KEY_THIS s.controller_Qsize >= BX_KBD_CONTROLLER_QSIZE)
|
|
+ bx_panic("KBD: controller_enq(): controller_Q full!\n");
|
|
+ PLEX_KEY_THIS s.controller_Q[PLEX_KEY_THIS s.controller_Qsize++] = data;
|
|
+ PLEX_KEY_THIS s.controller_Qsource = source;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (source == 0) { // keyboard
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_output_buffer = data;
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.inpb = 0;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq1)
|
|
+ pluginTriggerIRQ(1);
|
|
+ }
|
|
+ else { // mouse
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_output_buffer = data;
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.inpb = 0;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq12)
|
|
+ pluginTriggerIRQ(12);
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+plex_keyb_c::kbd_enQ_imm(Bit8u val)
|
|
+{
|
|
+ int tail;
|
|
+
|
|
+ if (PLEX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) {
|
|
+ bx_panic("KBD: internal keyboard buffer full (imm)\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* enqueue scancode in multibyte internal keyboard buffer */
|
|
+ tail = (PLEX_KEY_THIS s.kbd_internal_buffer.head + PLEX_KEY_THIS s.kbd_internal_buffer.num_elements) %
|
|
+ BX_KBD_ELEMENTS;
|
|
+
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_output_buffer = val;
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 1;
|
|
+
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq1)
|
|
+ pluginTriggerIRQ(1);
|
|
+}
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::kbd_enQ(Bit8u scancode)
|
|
+{
|
|
+ int tail;
|
|
+
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("enQ(%02x)\n", (unsigned) scancode);
|
|
+
|
|
+ if (PLEX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) {
|
|
+ bx_printf("KBD: internal keyboard buffer full, ignoring scancode.(%02x)\n",
|
|
+ (unsigned) scancode);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* enqueue scancode in multibyte internal keyboard buffer */
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: enQ: putting scancode %02x in internal buffer\n",
|
|
+ (unsigned) scancode);
|
|
+ tail = (PLEX_KEY_THIS s.kbd_internal_buffer.head + PLEX_KEY_THIS s.kbd_internal_buffer.num_elements) %
|
|
+ BX_KBD_ELEMENTS;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.buffer[tail] = scancode;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.num_elements++;
|
|
+
|
|
+ if (!PLEX_KEY_THIS s.kbd_controller.outb && PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled) {
|
|
+ activate_timer();
|
|
+//bx_printf("# activating timer...\n");
|
|
+ return;
|
|
+ }
|
|
+//bx_printf("# not activating timer...\n");
|
|
+//bx_printf("# allow_irq1 = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.allow_irq1);
|
|
+//bx_printf("# outb = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.outb);
|
|
+//bx_printf("# clock_enab = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled);
|
|
+//bx_printf("# out_buffer = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.kbd_output_buffer);
|
|
+}
|
|
+
|
|
+ Boolean
|
|
+plex_keyb_c::mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3)
|
|
+{
|
|
+ if ((PLEX_KEY_THIS s.mouse_internal_buffer.num_elements + 3) >= BX_MOUSE_BUFF_SIZE) {
|
|
+ return(0); /* buffer doesn't have the space */
|
|
+ }
|
|
+
|
|
+//bx_printf("mouse: enQ_packet(%02x, %02x, %02x)\n",
|
|
+// (unsigned) b1, (unsigned) b2, (unsigned) b3);
|
|
+
|
|
+ mouse_enQ(b1);
|
|
+ mouse_enQ(b2);
|
|
+ mouse_enQ(b3);
|
|
+ return(1);
|
|
+}
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::mouse_enQ(Bit8u mouse_data)
|
|
+{
|
|
+ int tail;
|
|
+
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("mouse_enQ(%02x)\n", (unsigned) mouse_data);
|
|
+
|
|
+ if (PLEX_KEY_THIS s.mouse_internal_buffer.num_elements >= BX_MOUSE_BUFF_SIZE) {
|
|
+ bx_printf("mouse: internal mouse buffer full, ignoring mouse data.(%02x)\n",
|
|
+ (unsigned) mouse_data);
|
|
+ return;
|
|
+ }
|
|
+//bx_printf("# mouse_enq() aux_clock_enabled = %u\n",
|
|
+// (unsigned) PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled);
|
|
+
|
|
+ /* enqueue mouse data in multibyte internal mouse buffer */
|
|
+ tail = (PLEX_KEY_THIS s.mouse_internal_buffer.head + PLEX_KEY_THIS s.mouse_internal_buffer.num_elements) %
|
|
+ BX_MOUSE_BUFF_SIZE;
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.buffer[tail] = mouse_data;
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.num_elements++;
|
|
+
|
|
+ if (!PLEX_KEY_THIS s.kbd_controller.outb && PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled) {
|
|
+ activate_timer();
|
|
+//bx_printf("# activating timer...\n");
|
|
+ return;
|
|
+ }
|
|
+//bx_printf("# not activating timer...\n");
|
|
+//bx_printf("# allow_irq12= %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.allow_irq12);
|
|
+//bx_printf("# outb = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.outb);
|
|
+//bx_printf("# clock_enab = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled);
|
|
+//bx_printf("# out_buffer = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.aux_output_buffer);
|
|
+}
|
|
+
|
|
+ void
|
|
+plex_keyb_c::kbd_ctrl_to_kbd(Bit8u value)
|
|
+{
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: controller passed byte %02xh to keyboard\n");
|
|
+
|
|
+ if (PLEX_KEY_THIS s.kbd_internal_buffer.expecting_typematic) {
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 0;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.delay = (value >> 5) & 0x03;
|
|
+ switch (PLEX_KEY_THIS s.kbd_internal_buffer.delay) {
|
|
+ case 0: bx_printf("KBD: setting delay to 250 mS\n"); break;
|
|
+ case 1: bx_printf("KBD: setting delay to 250 mS\n"); break;
|
|
+ case 2: bx_printf("KBD: setting delay to 250 mS\n"); break;
|
|
+ case 3: bx_printf("KBD: setting delay to 250 mS\n"); break;
|
|
+ }
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.repeat_rate = value & 0x1f;
|
|
+ bx_printf("KBD: setting repeat rate to %u\n", (unsigned) value);
|
|
+ kbd_enQ(0xFA); // send ACK
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (PLEX_KEY_THIS s.kbd_internal_buffer.expecting_led_write) {
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 0;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.led_status = value;
|
|
+ BX_INFO(("KBD: LED status set to %02x\n",
|
|
+ (unsigned) PLEX_KEY_THIS s.kbd_internal_buffer.led_status));
|
|
+ kbd_enQ(0xFA); // send ACK %%%
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ switch (value) {
|
|
+ case 0x00: // ??? ignore and let OS timeout with no response
|
|
+ kbd_enQ(0xFA); // send ACK %%%
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0x05: // ???
|
|
+ // (mch) trying to get this to work...
|
|
+ PLEX_KEY_THIS s.kbd_controller.sysf = 1;
|
|
+ kbd_enQ_imm(0xfe);
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xed: // LED Write
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 1;
|
|
+ kbd_enQ(0xFA); // send ACK %%%
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xee: // echo
|
|
+ kbd_enQ(0xEE); // return same byte (EEh) as echo diagnostic
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xf0: // set scancode - let OS time out
|
|
+ bx_printf("KBD: set scancode command received\n");
|
|
+ return;
|
|
+
|
|
+ case 0xf2: // identify keyboard
|
|
+ bx_printf("KBD: indentify keyboard command received\n");
|
|
+ kbd_enQ(0xFA); // AT sends ACK, MFII sends ACK+ABh+41h
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xf3: // typematic info
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 1;
|
|
+ bx_printf("KBD: setting typematic info\n");
|
|
+ kbd_enQ(0xFA); // send ACK
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xf4: // flush scancodes buffer and modes, then enable keyboard
|
|
+ resetinternals(0);
|
|
+ kbd_enQ(0xFA); // send ACK
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1;
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xf5: // reset keyboard to power-up settings and disable scanning
|
|
+ resetinternals(1);
|
|
+ kbd_enQ(0xFA); // send ACK
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 0;
|
|
+ bx_printf ("KBD: reset-disable command received\n");
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xf6: // reset keyboard to power-up settings and enable scanning
|
|
+ resetinternals(1);
|
|
+ kbd_enQ(0xFA); // send ACK
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1;
|
|
+ bx_printf ("KBD: reset-enable command received\n");
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xf7: // PS/2 Set All Keys To Typematic
|
|
+ case 0xf8: // PS/2 Set All Keys to Make/Break
|
|
+ case 0xf9: // PS/2 PS/2 Set All Keys to Make
|
|
+ case 0xfa: // PS/2 Set All Keys to Typematic Make/Break
|
|
+ case 0xfb: // PS/2 Set Key Type to Typematic
|
|
+ case 0xfc: // PS/2 Set Key Type to Make/Break
|
|
+ case 0xfd: // PS/2 Set Key Type to Make
|
|
+ // Silently ignore and let the OS timeout, for now.
|
|
+ // If anyone has code around that makes use of that, I can
|
|
+ // provide documentation on their behavior (ask core@ggi-project.org)
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xfe: // resend. aiiee.
|
|
+ bx_panic ("KBD: got 0xFE (resend)\n");
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+ case 0xff: // reset: internal keyboard reset and afterwards the BAT
|
|
+ bx_printf("KBD: rest command received\n");
|
|
+ kbd_enQ(0xFA); // send ACK
|
|
+ kbd_enQ(0xAA); // BAT test passed
|
|
+ return;
|
|
+ break;
|
|
+
|
|
+case 0xd3:
|
|
+ kbd_enQ(0xfa);
|
|
+ return;
|
|
+
|
|
+ default:
|
|
+ bx_panic("KBD: kbd_ctrl_to_kbd(): got value of %02x\n",
|
|
+ (unsigned) value);
|
|
+ kbd_enQ(0xFA); /* send ACK ??? */
|
|
+ return;
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+ void
|
|
+plex_keyb_c::timer_handler(void *this_ptr)
|
|
+{
|
|
+ plex_keyb_c *class_ptr = (plex_keyb_c *) this_ptr;
|
|
+
|
|
+ class_ptr->periodic( bx_options.Okeyboard_serial_delay->get () );
|
|
+}
|
|
+
|
|
+ void
|
|
+plex_keyb_c::periodic( Bit32u usec_delta )
|
|
+{
|
|
+ PLEX_KEY_THIS s.timer_pending = 0;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.outb) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* nothing in outb, look for possible data xfer from keyboard or mouse */
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.kbd_clock_enabled && PLEX_KEY_THIS s.kbd_internal_buffer.num_elements) {
|
|
+//bx_printf("# servicing keyboard code\n");
|
|
+ if (bx_dbg.keyboard)
|
|
+ bx_printf("KBD: service_keyboard: key in internal buffer waiting\n");
|
|
+ PLEX_KEY_THIS s.kbd_controller.kbd_output_buffer =
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.buffer[PLEX_KEY_THIS s.kbd_internal_buffer.head];
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 0;
|
|
+//bx_printf("# ___kbd::periodic kbd\n");
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.head = (PLEX_KEY_THIS s.kbd_internal_buffer.head + 1) %
|
|
+ BX_KBD_ELEMENTS;
|
|
+ PLEX_KEY_THIS s.kbd_internal_buffer.num_elements--;
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq1)
|
|
+ pluginTriggerIRQ(1);
|
|
+ }
|
|
+ else if (PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled && PLEX_KEY_THIS s.mouse_internal_buffer.num_elements) {
|
|
+//bx_printf("# servicing mouse code\n");
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("KBD: service_keyboard: key in internal buffer waiting\n");
|
|
+ PLEX_KEY_THIS s.kbd_controller.aux_output_buffer =
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.buffer[PLEX_KEY_THIS s.mouse_internal_buffer.head];
|
|
+
|
|
+ PLEX_KEY_THIS s.kbd_controller.outb = 1;
|
|
+ PLEX_KEY_THIS s.kbd_controller.auxb = 1;
|
|
+//bx_printf("# ___kbd:periodic aux\n");
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.head = (PLEX_KEY_THIS s.mouse_internal_buffer.head + 1) %
|
|
+ BX_MOUSE_BUFF_SIZE;
|
|
+ PLEX_KEY_THIS s.mouse_internal_buffer.num_elements--;
|
|
+//bx_printf("# allow12 = %u\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.allow_irq12);
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.allow_irq12)
|
|
+ pluginTriggerIRQ(12);
|
|
+ }
|
|
+ else {
|
|
+//bx_printf("# servicing no code\n");
|
|
+ if (bx_dbg.keyboard) {
|
|
+ bx_printf("KBD: service_keyboard(): no keys waiting\n");
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::activate_timer(void)
|
|
+{
|
|
+ if (PLEX_KEY_THIS s.timer_pending == 0) {
|
|
+ PLEX_KEY_THIS s.timer_pending = 1;
|
|
+ pluginActivateTimer( PLEX_KEY_THIS timer_handle,
|
|
+ (unsigned) bx_options.Okeyboard_serial_delay->get (), 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::kbd_ctrl_to_mouse(Bit8u value)
|
|
+{
|
|
+bx_printf("MOUSE: kbd_ctrl_to_mouse(%02xh)\n", (unsigned) value);
|
|
+bx_printf(" enable = %u\n", (unsigned) PLEX_KEY_THIS s.mouse.enable);
|
|
+bx_printf(" allow_irq12 = %u\n",
|
|
+ (unsigned) PLEX_KEY_THIS s.kbd_controller.allow_irq12);
|
|
+bx_printf(" aux_clock_enabled = %u\n",
|
|
+ (unsigned) PLEX_KEY_THIS s.kbd_controller.aux_clock_enabled);
|
|
+//bx_printf("# MOUSE: kbd_ctrl_to_mouse(%02xh)\n", (unsigned) value);
|
|
+
|
|
+ // an ACK (0xFA) is always the first response to any valid input
|
|
+ // received from the system other than Set-Wrap-Mode & Resend-Command
|
|
+
|
|
+
|
|
+ if (PLEX_KEY_THIS s.kbd_controller.expecting_mouse_parameter) {
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0;
|
|
+ switch (PLEX_KEY_THIS s.kbd_controller.last_mouse_command) {
|
|
+ case 0xf3: // Set Mouse Sample Rate
|
|
+ PLEX_KEY_THIS s.mouse.sample_rate = value;
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Sampling rate set: %d Hz\n", value);
|
|
+ controller_enQ(0xFA, 1); // ack
|
|
+ break;
|
|
+
|
|
+ case 0xe8: // Set Mouse Resolution
|
|
+ switch (value) {
|
|
+ case 0:
|
|
+ PLEX_KEY_THIS s.mouse.resolution_cpmm = 1;
|
|
+ break;
|
|
+ case 1:
|
|
+ PLEX_KEY_THIS s.mouse.resolution_cpmm = 2;
|
|
+ break;
|
|
+ case 2:
|
|
+ PLEX_KEY_THIS s.mouse.resolution_cpmm = 4;
|
|
+ break;
|
|
+ case 3:
|
|
+ PLEX_KEY_THIS s.mouse.resolution_cpmm = 8;
|
|
+ break;
|
|
+ default:
|
|
+ bx_panic("[mouse] Unknown resolution %d\n", value);
|
|
+ break;
|
|
+ }
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Resolution set to %d counts per mm\n",
|
|
+ PLEX_KEY_THIS s.mouse.resolution_cpmm);
|
|
+
|
|
+ controller_enQ(0xFA, 1); // ack
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ bx_panic("MOUSE: unknown last command (%02xh)\n", (unsigned) PLEX_KEY_THIS s.kbd_controller.last_mouse_command);
|
|
+ }
|
|
+ } else {
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0;
|
|
+ PLEX_KEY_THIS s.kbd_controller.last_mouse_command = value;
|
|
+ switch ( value ) {
|
|
+ case 0xe6: // Set Mouse Scaling to 1:1
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ PLEX_KEY_THIS s.mouse.scaling = 2;
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Scaling set to 1:1\n");
|
|
+ break;
|
|
+
|
|
+ case 0xe7: // Set Mouse Scaling to 2:1
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ PLEX_KEY_THIS s.mouse.scaling = 2;
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Scaling set to 2:1\n");
|
|
+ break;
|
|
+
|
|
+ case 0xe8: // Set Mouse Resolution
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1;
|
|
+ break;
|
|
+
|
|
+ case 0xf2: // Read Device Type
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ controller_enQ(0x00, 1); // Device ID
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Read mouse ID\n");
|
|
+ break;
|
|
+
|
|
+ case 0xf3: // Set Mouse Sample Rate (sample rate written to port 60h)
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ PLEX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1;
|
|
+ break;
|
|
+
|
|
+ case 0xf4: // Enable (in stream mode)
|
|
+ PLEX_KEY_THIS s.mouse.enable = 1;
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Mouse enabled (stream mode)\n");
|
|
+ break;
|
|
+
|
|
+ case 0xf5: // Disable (in stream mode)
|
|
+ PLEX_KEY_THIS s.mouse.enable = 0;
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Mouse disabled (stream mode)\n");
|
|
+ break;
|
|
+
|
|
+ case 0xff: // Reset
|
|
+ PLEX_KEY_THIS s.mouse.sample_rate = 100; /* reports per second (default) */
|
|
+ PLEX_KEY_THIS s.mouse.resolution_cpmm = 4; /* 4 counts per millimeter (default) */
|
|
+ PLEX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */
|
|
+ PLEX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET;
|
|
+ PLEX_KEY_THIS s.mouse.enable = 0;
|
|
+ /* (mch) NT expects an ack here */
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ controller_enQ(0xAA, 1); // completion code
|
|
+ controller_enQ(0x00, 1); // ID code (normal mouse, wheelmouse has id 0x3)
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Mouse reset\n");
|
|
+ break;
|
|
+
|
|
+ case 0xe9: // Get mouse information
|
|
+ // should we ack here? (mch): Yes
|
|
+ controller_enQ(0xFA, 1); // ACK
|
|
+ controller_enQ(PLEX_KEY_THIS s.mouse.get_status_byte(), 1); // status
|
|
+ controller_enQ(PLEX_KEY_THIS s.mouse.get_resolution_byte(), 1); // resolution
|
|
+ controller_enQ(PLEX_KEY_THIS s.mouse.sample_rate, 1); // sample rate
|
|
+ if (bx_dbg.mouse)
|
|
+ bx_printf("[mouse] Get mouse information\n");
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ bx_panic("MOUSE: kbd_ctrl_to_mouse(%02xh)\n", (unsigned) value);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+ void
|
|
+plex_keyb_c::mouse_motion(int delta_x, int delta_y, unsigned button_state)
|
|
+{
|
|
+ Bit8u b1, b2, b3;
|
|
+
|
|
+ // If mouse events are disabled on the GUI headerbar, don't
|
|
+ // generate any mouse data
|
|
+ if (bx_options.Omouse_enabled->get ()==0)
|
|
+ return;
|
|
+
|
|
+ if ( PLEX_KEY_THIS s.mouse.enable==0 )
|
|
+ return;
|
|
+
|
|
+ // scale down the motion
|
|
+ if ( (delta_x < -1) || (delta_x > 1) )
|
|
+ delta_x /= 2;
|
|
+ if ( (delta_y < -1) || (delta_y > 1) )
|
|
+ delta_y /= 2;
|
|
+
|
|
+ //bx_printf("# MOUSE: Dx=%d Dy=%d\n",
|
|
+ // delta_x, delta_y);
|
|
+
|
|
+ b1 = (button_state & 0x0f) | 0x08; // bit3 always set
|
|
+
|
|
+ PLEX_KEY_THIS s.mouse.button_status = button_state & 0x3;
|
|
+
|
|
+ if ( (delta_x>=0) && (delta_x<=255) ) {
|
|
+ b2 = delta_x;
|
|
+ }
|
|
+ else if ( delta_x > 255 ) {
|
|
+ b2 = 0xff;
|
|
+ }
|
|
+ else if ( delta_x >= -256 ) {
|
|
+ b2 = delta_x;
|
|
+ b1 |= 0x10;
|
|
+ }
|
|
+ else {
|
|
+ b2 = 0x00;
|
|
+ b1 |= 0x10;
|
|
+ }
|
|
+
|
|
+ if ( (delta_y>=0) && (delta_y<=255) ) {
|
|
+ b3 = delta_y;
|
|
+ }
|
|
+ else if ( delta_y > 255 ) {
|
|
+ b3 = 0xff;
|
|
+ }
|
|
+ else if ( delta_y >= -256 ) {
|
|
+ b3 = delta_y;
|
|
+ b1 |= 0x20;
|
|
+ }
|
|
+ else {
|
|
+ b3 = 0x00;
|
|
+ b1 |= 0x20;
|
|
+ }
|
|
+ mouse_enQ_packet(b1, b2, b3);
|
|
+}
|
|
+
|
|
+
|
|
+ void
|
|
+plex_keyb_c::put_scancode( unsigned char *code, int count )
|
|
+{
|
|
+ for ( int i = 0 ; i < count ; i++ ) {
|
|
+ kbd_enQ( code[i] );
|
|
+ }
|
|
+
|
|
+ return;
|
|
+}
|
|
Index: iodev/plex-keyboard.h
|
|
===================================================================
|
|
RCS file: plex-keyboard.h
|
|
diff -N iodev/plex-keyboard.h
|
|
--- /dev/null Thu May 24 22:33:05 2001
|
|
+++ iodev/plex-keyboard.h Wed Dec 12 18:31:21 2001
|
|
@@ -0,0 +1,183 @@
|
|
+// Copyright (C) 2000 MandrakeSoft S.A.
|
|
+//
|
|
+// MandrakeSoft S.A.
|
|
+// 43, rue d'Aboukir
|
|
+// 75002 Paris - France
|
|
+// http://www.linux-mandrake.com/
|
|
+// http://www.mandrakesoft.com/
|
|
+//
|
|
+// This library is free software; you can redistribute it and/or
|
|
+// modify it under the terms of the GNU Lesser General Public
|
|
+// License as published by the Free Software Foundation; either
|
|
+// version 2 of the License, or (at your option) any later version.
|
|
+//
|
|
+// This library is distributed in the hope that it will be useful,
|
|
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+// Lesser General Public License for more details.
|
|
+//
|
|
+// You should have received a copy of the GNU Lesser General Public
|
|
+// License along with this library; if not, write to the Free Software
|
|
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+
|
|
+
|
|
+
|
|
+#ifndef _PLEX_PCKEY_H
|
|
+#define _PLEX_PCKEY_H
|
|
+
|
|
+
|
|
+#define BX_KBD_ELEMENTS 16
|
|
+#define BX_MOUSE_BUFF_SIZE 48
|
|
+
|
|
+
|
|
+
|
|
+#if BX_USE_KEY_SMF
|
|
+# define BX_KEY_SMF static
|
|
+# define PLEX_KEY_THIS plex_keyboard.
|
|
+#else
|
|
+# define BX_KEY_SMF
|
|
+# define PLEX_KEY_THIS this->
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+class plex_keyb_c {
|
|
+public:
|
|
+ plex_keyb_c(void);
|
|
+ ~plex_keyb_c(void);
|
|
+ BX_KEY_SMF void init(void);
|
|
+ BX_KEY_SMF void gen_scancode(Bit32u scancode);
|
|
+ BX_KEY_SMF Bit8u get_kbd_enable(void);
|
|
+ BX_KEY_SMF void mouse_motion(int delta_x, int delta_y, unsigned button_state);
|
|
+ BX_KEY_SMF void mouse_button(unsigned mouse_state);
|
|
+ BX_KEY_SMF void periodic( Bit32u usec_delta );
|
|
+ BX_KEY_SMF void put_scancode( unsigned char *code, int count );
|
|
+
|
|
+private:
|
|
+
|
|
+ static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
|
|
+ static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
|
|
+#if !BX_USE_KEY_SMF
|
|
+ void write(Bit32u address, Bit32u value, unsigned io_len);
|
|
+ Bit32u read(Bit32u address, unsigned io_len);
|
|
+#endif
|
|
+
|
|
+ struct {
|
|
+ struct {
|
|
+ /* status bits */
|
|
+ Boolean pare;
|
|
+ Boolean tim;
|
|
+ Boolean auxb;
|
|
+ Boolean keyl;
|
|
+ Boolean c_d; /* 1=command to port 64h, 0=data to port 60h */
|
|
+ Boolean sysf;
|
|
+ Boolean inpb;
|
|
+ Boolean outb;
|
|
+
|
|
+ Boolean scan_convert;
|
|
+ Boolean kbd_clock_enabled;
|
|
+ Boolean aux_clock_enabled;
|
|
+ Boolean allow_irq1;
|
|
+ Boolean allow_irq12;
|
|
+ Bit8u kbd_output_buffer;
|
|
+ Bit8u aux_output_buffer;
|
|
+ Bit8u last_comm;
|
|
+ Bit8u expecting_port60h;
|
|
+ Bit8u expecting_mouse_parameter;
|
|
+ Bit8u last_mouse_command;
|
|
+ } kbd_controller;
|
|
+
|
|
+ struct mouseStruct {
|
|
+ Bit8u sample_rate;
|
|
+ Bit8u resolution_cpmm; // resolution in counts per mm
|
|
+ Bit8u scaling;
|
|
+ Bit8u mode;
|
|
+ Boolean enable;
|
|
+
|
|
+ Bit8u get_status_byte ()
|
|
+ {
|
|
+ Bit8u ret = 0;
|
|
+ // we're always in stream mode (right?)
|
|
+ ret |= (enable << 5);
|
|
+ ret |= (scaling == 1) ? 0 : (1 << 4);
|
|
+ ret |= ((button_status & 0x1) << 2);
|
|
+ ret |= ((button_status & 0x2) << 0);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ Bit8u get_resolution_byte ()
|
|
+ {
|
|
+ Bit8u ret = 0;
|
|
+
|
|
+ switch (resolution_cpmm) {
|
|
+ case 1:
|
|
+ ret = 0;
|
|
+ break;
|
|
+
|
|
+ case 2:
|
|
+ ret = 1;
|
|
+ break;
|
|
+
|
|
+ case 4:
|
|
+ ret = 2;
|
|
+ break;
|
|
+
|
|
+ case 8:
|
|
+ ret = 3;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ //FIXME
|
|
+ genlog->panic ("[mouse] invalid resolution_cpmm");
|
|
+ };
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ Bit8u button_status;
|
|
+ } mouse;
|
|
+
|
|
+ struct {
|
|
+ int num_elements;
|
|
+ Bit8u buffer[BX_KBD_ELEMENTS];
|
|
+ int head;
|
|
+ Boolean expecting_typematic;
|
|
+ Boolean expecting_led_write;
|
|
+ Bit8u delay;
|
|
+ Bit8u repeat_rate;
|
|
+ Bit8u led_status;
|
|
+ Boolean scanning_enabled;
|
|
+ } kbd_internal_buffer;
|
|
+
|
|
+ struct {
|
|
+ int num_elements;
|
|
+ Bit8u buffer[BX_MOUSE_BUFF_SIZE];
|
|
+ int head;
|
|
+ } mouse_internal_buffer;
|
|
+#define BX_KBD_CONTROLLER_QSIZE 5
|
|
+ Bit8u controller_Q[BX_KBD_CONTROLLER_QSIZE];
|
|
+ unsigned controller_Qsize;
|
|
+ unsigned controller_Qsource; // 0=keyboard, 1=mouse
|
|
+ unsigned timer_pending;
|
|
+ } s; // State information for saving/loading
|
|
+
|
|
+ BX_KEY_SMF void resetinternals(Boolean powerup);
|
|
+ BX_KEY_SMF void set_kbd_clock_enable(Bit8u value);
|
|
+ BX_KEY_SMF void set_aux_clock_enable(Bit8u value);
|
|
+ BX_KEY_SMF void kbd_ctrl_to_kbd(Bit8u value);
|
|
+ BX_KEY_SMF void kbd_ctrl_to_mouse(Bit8u value);
|
|
+ BX_KEY_SMF void kbd_enQ(Bit8u scancode);
|
|
+ BX_KEY_SMF void kbd_enQ_imm(Bit8u val);
|
|
+ BX_KEY_SMF void activate_timer(void);
|
|
+ BX_KEY_SMF void controller_enQ(Bit8u data, unsigned source);
|
|
+ BX_KEY_SMF Boolean mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3);
|
|
+ BX_KEY_SMF void mouse_enQ(Bit8u mouse_data);
|
|
+ static void timer_handler(void *);
|
|
+ void timer(void);
|
|
+ int timer_handle;
|
|
+ };
|
|
+
|
|
+#if BX_USE_KEY_SMF
|
|
+extern plex_keyb_c plex_keyboard;
|
|
+#endif
|
|
+
|
|
+#endif // #ifndef _PLEX_PCKEY_H
|