Bochs/bochs/patches/patch.plugins3

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