Attached is another plugin patch. It replaces
the previous one. I added unaligned writes and
fixed some bugs. As far as I'm concerned, this
one's ready to be included in the code base.
Someone should check that I didn't make any
stupid mistake (but then again, I guess we'll
notice if I did ;)).
PS, I can't find the string write routines
anymore. Have they disappeared ? (right now
only writes with count=1 occur...)
-- Ramon
diff -Nur plex86-old/kernel/nexus.S plex86/kernel/nexus.S
--- plex86-old/kernel/nexus.S Mon Jul 31 19:30:49 2000
+++ plex86/kernel/nexus.S Mon Jul 31 19:32:06 2000
@@ -185,7 +185,7 @@
// Switch to monitor stack and CS
// and jump to the monitor-side nexus page
lss (MON_STACK_INFO)(%ebx), %esp
- ljmp *(MON_JMP_INFO)(%ebx)
+ ljmp (MON_JMP_INFO)(%ebx)
.globl __mon_cs
__mon_cs:
@@ -280,7 +280,7 @@
// Restore host stack and CS
lss (HOST_STACK_INFO)(%ebx), %esp
- ljmp *(HOST_JMP_INFO)(%ebx)
+ ljmp (HOST_JMP_INFO)(%ebx)
__host_cs:
// Clear busy bit of the host TSS and switch to it
diff -Nur plex86-old/user/plugin.c plex86/user/plugin.c
--- plex86-old/user/plugin.c Mon Jul 31 19:30:49 2000
+++ plex86/user/plugin.c Wed Aug 2 20:02:17 2000
@@ -26,45 +26,14 @@
#include "plugin.h"
-#define BOVERLP(base1,range1,base2,range2) \
- ((base2 >= base1) && (base2 < (base1+range1)))
-
-#define TOVERLP(base1,range1,base2,range2) \
- (((base2+range2) > base1) && ((base2+range2) <= (base1+range1)))
-
-#define OVERLP(base1,range1,base2,range2) \
- (BOVERLP(base1,range1,base2,range2) ||
TOVERLP(base1,range1,base2,range2))
-
-
/************************************************************************/
-/* Declarations */
-/************************************************************************/
-
-static int plugin_emulate_int (int data, int op_size, int count, void *loc);
-
-static int plugin_alloc_int (event_t event, handler_t handler, int base, int range);
-static void plugin_free_int (callback_t *callback);
-
-
-
-/************************************************************************/
-/* Structures / Variables */
+/* Plugin initialization / deinitialization */
/************************************************************************/
-plugin_t *plugins = NULL; /* Head of the linked list of plugins */
-
-callback_t *ioreads = NULL; /* Head of I/O read callback list */
-callback_t *iowrites = NULL; /* Head of I/O write callback list */
-callback_t *ints = NULL; /* Head of interrupt callback list */
-
-static void (*save_funct)(Bit64u) = NULL;
+plugin_t *plugins = NULL; /* Head of the linked list of plugins */
-/************************************************************************/
-/* Plugin initialization / deinitialization */
-/************************************************************************/
-
void
plugin_load (char *name, char *args)
{
@@ -80,7 +49,6 @@
plugin->name = name;
plugin->args = args;
- plugin->callbacks = NULL;
plugin->initialized = 0;
plugin->handle = dlopen (name, RTLD_LAZY);
@@ -104,19 +72,25 @@
exit (1);
}
- // Insert plugin at the _end_ of the plugin linked list.
+
+ /* 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 {
- plugin_t *temp = plugins;
- // Non-empty list. Add to end.
- while (temp->next)
- temp = temp->next;
- temp->next = plugin;
- }
+
+ 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;
+ }
return;
}
@@ -167,14 +141,16 @@
plugin_t *
plugin_unload (plugin_t *plugin)
{
+ int i;
plugin_t *dead_plug;
- callback_t *dead_call;
if (plugin->initialized)
plugin->fini ();
- for (dead_call = plugin->callbacks; dead_call; dead_call = dead_call->next_plug)
- plugin_free (dead_call);
+ plugin_free_inp (plugin, 0, 65536);
+ plugin_free_outp (plugin, 0, 65536);
+ for (i=0; i<256; i++)
+ plugin_free_intr (plugin, i);
dlclose (plugin->handle);
free (plugin->name);
@@ -201,319 +177,535 @@
/************************************************************************/
-/* Resource allocation */
+/* I/O port handling */
/************************************************************************/
-callback_t *
-plugin_alloc (plugin_t *plugin, event_t event, handler_t handler, int base, int range)
-{
- callback_t **list, *callback, *call2;
- int (*plugin_evt_alloc) (event_t event, handler_t handler, int base, int range) =
NULL;
-
+/*
+ * I/O ports are allocated in a three-layered structure. There is one
+ * layer for 4-byte allocations, one layer for 2-byte allocations, and
+ * one layer with 1-byte allocations. When an I/O port is allocated,
+ * the bottom (1-byte) layer is always updated. It is then checked
+ * whether the plugin has allocated two consecutive I/O ports (and they
+ * do not cross an alignment boundary), in which case the plugin is
+ * also entered into the layer above it. The top layer is updated in
+ * the case of the allocation of four consecutive ports (with correct
+ * alignment).
+ *
+ * When an I/O event comes in, we start at the layer which corresponds
+ * to the opsize of the event (bottom layer for inb/outb, middle layer
+ * for inw/outw, etc.) If this layer contains an entry, the event is
+ * send to the appropiate handler and we're finished. If not, we break
+ * up the request into two pieces and go down to the next layer.
+ * Of course, the event is broken up immediately if it is not properly
+ * aligned.
+ *
+ * Note: unlike interrupts, only one device can allocate an I/O port
+ * at any time (otherwise we have a conflict!).
+ */
- if (range == 0)
- {
- return NULL;
- }
+#define PORTS 65536
+static struct ioport_t
+{
+ plugin_t *plugin;
+ handler_t handler;
+}
+ilayer0[PORTS >> 0] = {{ NULL, NULL }}, /* input Single-byte aligns */
+olayer0[PORTS >> 0] = {{ NULL, NULL }}; /* output Single-byte aligns */
- switch (event)
- {
- case EVT_INPORT:
- list = &ioreads;
- break;
+static handler_t
+ ilayer1[PORTS >> 1] = { NULL }, /* input Word alignment */
+ olayer1[PORTS >> 1] = { NULL }, /* output Word alignment */
+ ilayer2[PORTS >> 2] = { NULL }, /* input Dword alignment */
+ olayer2[PORTS >> 2] = { NULL }; /* output Dword alignment */
- case EVT_OUTPORT:
- list = &iowrites;
- break;
+static int
+io_sift_alloc_inp (plugin_t *plugin, handler_t handler, int port)
+{
+ if (ilayer0[port].plugin != NULL)
+ return -1;
- case EVT_INT:
- list = &ints;
- plugin_evt_alloc = plugin_alloc_int;
- break;
+ ilayer0[port].plugin = plugin;
+ ilayer0[port].handler = handler;
- default:
- fprintf (stderr, "Error: plugin %s attempted to allocate non-implemented
resource. Ignoring\n", plugin->name);
- return NULL;
+ if (ilayer0[port | 0x1].handler == ilayer0[port & ~0x1].handler)
+ {
+ ilayer1[port >> 1] = handler;
}
+ if (ilayer1[(port >> 1) | 0x1] == ilayer1[(port >> 1) & ~0x1])
+ {
+ ilayer2[port >> 2] = handler;
+ }
- /* look for conflicting allocation */
+ return 0;
+}
- if (conflict[event])
- for (call2 = *list; call2; call2 = call2->next_type)
- if (OVERLP(call2->base, call2->range, base, range))
- {
- fprintf (stderr, "Conflict: plugin %s attempted to allocate busy
resource. Ignoring\n", plugin->name);
- return NULL;
- }
+static int
+io_sift_alloc_outp (plugin_t *plugin, handler_t handler, int port)
+{
+ if (olayer0[port].plugin != NULL)
+ return -1;
+ olayer0[port].plugin = plugin;
+ olayer0[port].handler = handler;
- /* do event-specific allocation */
+ if (olayer0[port | 0x1].handler == olayer0[port & ~0x1].handler)
+ {
+ olayer1[port >> 1] = handler;
+ }
- if (plugin_evt_alloc && plugin_evt_alloc (event, handler, base, range))
- return NULL;
+ if (olayer1[(port >> 1) | 0x1] == olayer1[(port >> 1) & ~0x1])
+ {
+ olayer2[port >> 2] = handler;
+ }
+ return 0;
+}
- /* allocate plugin */
+static int
+io_sift_free_inp (plugin_t *plugin, int port)
+{
+ if (ilayer0[port].plugin != plugin)
+ return -1;
- callback = malloc (sizeof (callback_t));
- callback->type = event;
- callback->handler = handler;
- callback->base = base;
- callback->range = range;
- callback->plugin = plugin;
+ ilayer0[port].plugin = NULL;
+ ilayer0[port].handler = NULL;
+ ilayer1[port >> 1] = NULL;
+ ilayer2[port >> 2] = NULL;
- /* put callback in linked list IN ORDER (this is important !!) */
+ return 0;
+}
- call2 = *list;
- if (call2 == NULL || base <= call2->base)
- {
- callback->next_type = *list;
- *list = callback;
- }
- else
- for (; ; call2 = call2->next_type)
- if (call2->next_type == NULL || base <= call2->next_type->base)
- {
- callback->next_type = call2->next_type;
- call2->next_type = callback;
- break;
- }
+static int
+io_sift_free_outp (plugin_t *plugin, int port)
+{
+ if (olayer0[port].plugin != plugin)
+ return -1;
+ olayer0[port].plugin = NULL;
+ olayer0[port].handler = NULL;
- /* we're done!! */
+ olayer1[port >> 1] = NULL;
+ olayer2[port >> 2] = NULL;
- return callback;
+ return 0;
}
-
-void
-plugin_free (callback_t *callback)
+static void
+io_rearrange_data (int op_size, int count, void *data)
+/*
+ * We need io_rearrange_data() in order to split the data stream into
+ * muliple data streams, which we use when we drop down a layer (see
+ * plugin_emulate_inport() for more details). This is the idea:
+ * initially the data consist of low byte/word (o), high byte/word (x),
+ * in this order:
+ * oxoxoxoxox...
+ * We want to rearrange it to look like
+ * ooooo...xxxxx...
+ * The algorithm used is simple but it work (check this for
+ * yourself by drawing strings like the ones above on a piece of
+ * paper and exchanging the o's and x's).
+ */
{
- callback_t **list, *next;
+#define EXCHG(dt,a,b) \
+ { dt tmp; tmp = *(dt *)a; *(dt *)a = *(dt *)b; *(dt *)b = tmp; }
+ int i, j;
- switch (callback->type)
- {
- case EVT_INPORT:
- list = &ioreads;
- break;
+ if (count == 1)
+ return;
- case EVT_OUTPORT:
- list = &iowrites;
+ switch (op_size)
+ {
+ case 4:
+ for (i = 1; i < count; i++)
+ for (j = 0; j < i; j++)
+ EXCHG (short,
+ & ((short *) data)[2 * i - j],
+ & ((short *) data)[2 * i - 1 - j]);
break;
- case EVT_INT:
- list = &ints;
- plugin_free_int (callback);
+ case 2:
+ for (i = 1; i < count; i++)
+ for (j = 0; j < i; j++)
+ EXCHG (char,
+ & ((char *) data)[2 * i - j],
+ & ((char *) data)[2 * i - 1 - j]);
break;
default:
- fprintf (stderr, "Error: attempted to free non-implemented resource.
Ignoring\n");
- return;
}
+ return;
- /* look for callback in callback list */
-
- if (*list == callback)
- *list = callback->next_type;
- else
- for (next = *list; next; next = next->next_type)
- if (next->next_type == callback)
- next->next_type = callback->next_type;
-
-
- /* look for callback in plugin list */
-
- if (callback->plugin->callbacks == callback)
- callback->plugin->callbacks = callback->next_plug;
- else
- for (next = callback->plugin->callbacks; next; next = next->next_plug)
- if (next->next_plug == callback)
- next->next_plug = callback->next_type;
+#undef EXCHG
+}
- /* clean up callback */
+int
+plugin_alloc_inp (plugin_t *plugin, handler_t handler, int base, int range)
+{
+ int port;
- free (callback);
+ if (base+range > PORTS)
+ {
+ return -1;
+ }
+ for (port = base; port < base+range; port++)
+ {
+ if (ilayer0[port].plugin != NULL)
+ return -1;
+ }
- /* we're done!! */
+ for (port = base; port < base+range; port++)
+ {
+ io_sift_alloc_inp (plugin, handler, port);
+ }
- return;
+ return 0;
}
int
-plugin_alloc_int (event_t event, handler_t handler, int base, int range)
+plugin_alloc_outp (plugin_t *plugin, handler_t handler, int base, int range)
{
- int i;
+ int port;
- for (i = base; i < base+range; i++)
- if (vm_alloc_intr (i))
- {
- int j;
+ if (base+range > PORTS)
+ {
+ return -1;
+ }
- for (j = base; j < i; j++)
- vm_release_intr (j);
+ for (port = base; port < base+range; port++)
+ {
+ if (olayer0[port].plugin != NULL)
+ return -1;
+ }
- return 1;
- }
+ for (port = base; port < base+range; port++)
+ {
+ io_sift_alloc_outp (plugin, handler, port);
+ }
return 0;
}
+
void
-plugin_free_int (callback_t *callback)
+plugin_free_inp (plugin_t *plugin, int base, int range)
{
- int j;
+ int port;
- for (j = callback->base; j < callback->base+callback->range; j++)
- vm_release_intr (j);
+ if (base+range > PORTS)
+ {
+ return;
+ }
+
+ for (port = base; port < base+range; port++)
+ {
+ io_sift_free_inp (plugin, port);
+ }
return;
}
-
-/************************************************************************/
-/* Event handling (plugin needs to handle evt / plugin generates evt) */
-/************************************************************************/
-
- int
-plugin_emulate (event_t event, int data, int op_size, int count, void *loc)
+void
+plugin_free_outp (plugin_t *plugin, int base, int range)
{
- switch (event)
- {
- case EVT_INPORT:
- return plugin_emulate_inport (data, op_size, count, loc);
-
- case EVT_OUTPORT:
- return plugin_emulate_outport (data, op_size, count, loc);
+ int port;
- case EVT_INT:
- return plugin_emulate_int (data, op_size, count, loc);
+ if (base+range > PORTS)
+ {
+ return;
+ }
- default:
- fprintf (stderr, "Error: emulation of event %d not supported. Ignoring\n",
(int) event);
- return 0;
+ for (port = base; port < base+range; port++)
+ {
+ io_sift_free_outp (plugin, port);
}
+
+ return;
}
- int
-plugin_emulate_inport (int data, int op_size, int count, void *loc)
+int
+plugin_emulate_inport (int port, int op_size, int count, void *loc)
{
- callback_t *next = ioreads;
+ int i;
+ int split = 1, split2 = 0;
- unsigned handled = 0;
- for (; next; next = next->next_type)
+ if ((port & (op_size - 1)) == 0)
{
- int range;
+ /* Aligned I/O, let's sift through the layers. */
- if (BOVERLP(next->base, next->range, data, op_size))
+ switch (op_size)
{
- /* Find top limit */
- if ((data + op_size) > (next->base + next->range))
- range = next->base + next->range - data;
+ case 4:
+ if (ilayer2[port >> 2] != NULL)
+ {
+ ilayer2[port >> 2] (EVT_INPORT, port, 4, count, loc);
+ break;
+ }
+
+ /* Rearrange data from 1 * op_size=4 to 2 * op_size=2 */
+
+ io_rearrange_data (4, count, loc);
+
+ /* Fallthrough to next layer */
+
+ split = 2;
+
+ case 2:
+ for (i = 0; i < split; i++)
+ {
+ if (ilayer1[(port >> 1) + i] != NULL)
+ {
+ ilayer1[(port >> 1) + i] (EVT_INPORT,
+ port + i * 2,
+ 2,
+ count,
+ loc + i * count * 2);
+ }
+ else
+ {
+ split2 |= (i + 1);
+ io_rearrange_data (2, count, loc + i * count * 2);
+ }
+ }
+
+ if (split2 == 0)
+ break;
+
+ /* Fallthrough to next layer */
+
+ if (split2 == 3)
+ split = 4;
+ else if (split2 == 2)
+ {
+ port += 2;
+ loc += count * 2;
+ }
else
- range = op_size;
+ split = 2;
- next->handler (EVT_INPORT, data, range, count, loc);
- handled = 1;
+ case 1:
+ for (i = 0; i < split; i++)
+ {
+ if (ilayer0[port + i].handler != NULL)
+ {
+ ilayer0[port + i].handler (EVT_INPORT,
+ port + i,
+ 1,
+ count,
+ loc + i * count);
+ }
+ }
}
- else
- if (TOVERLP(next->base, next->range, data, op_size))
- {
- /* We know base doesn't overlap, so use next->base as bottom limit.
- We do need to recalculate the offset, though, and adjust loc */
-
- int ofs = next->base - data;
- range = op_size - ofs;
+ }
+ else
+ {
+ /* Unaligned write, do it slow & simple, who cares */
- next->handler (EVT_INPORT, next->base, range, count, loc + ofs);
- handled = 1;
+ for (i = 0; i < count * op_size; i++)
+ {
+ if (ilayer0[port + (i % op_size)].handler != NULL)
+ {
+ ilayer0[port + (i % op_size)].handler (EVT_INPORT,
+ port + (i % op_size),
+ 1, 1,
+ loc + i);
+ }
}
}
-if (!handled) {
- unsigned i;
- fprintf(stderr, "inport 0x%x\n", data);
- for (i=0; i<op_size; i++)
- ((unsigned char *) loc)[i] = 0xff;
- }
return 0;
}
- int
-plugin_emulate_outport (int data, int op_size, int count, void *loc)
+int
+plugin_emulate_outport (int port, int op_size, int count, void *loc)
{
- callback_t *next = iowrites;
+ int i;
+ int split = 1, split2 = 0;
- unsigned handled = 0;
- for (; next; next = next->next_type)
+ if ((port & (op_size - 1)) == 0)
{
- int range;
+ /* Aligned I/O, let's sift through the layers. */
- if (BOVERLP(next->base, next->range, data, op_size))
+ switch (op_size)
{
- /* Find top limit */
- if ((data + op_size) > (next->base + next->range))
- range = next->base + next->range - data;
+ case 4:
+ if (olayer2[port >> 2] != NULL)
+ {
+ olayer2[port >> 2] (EVT_OUTPORT, port, 4, count, loc);
+ break;
+ }
+
+ /* Rearrange data from 1 * op_size=4 to 2 * op_size=2 */
+
+ io_rearrange_data (4, count, loc);
+
+ /* Fallthrough to next layer */
+
+ split = 2;
+
+ case 2:
+ for (i = 0; i < split; i++)
+ {
+ if (olayer1[(port >> 1) + i] != NULL)
+ {
+ olayer1[(port >> 1) + i] (EVT_OUTPORT,
+ port + i * 2,
+ 2,
+ count,
+ loc + i * count * 2);
+ }
+ else
+ {
+ split2 |= (i + 1);
+ io_rearrange_data (2, count, loc + i * count * 2);
+ }
+ }
+
+ if (split2 == 0)
+ break;
+
+ /* Fallthrough to next layer */
+
+ if (split2 == 3)
+ split = 4;
+ else if (split2 == 2)
+ {
+ port += 2;
+ loc += count * 2;
+ }
else
- range = op_size;
+ split = 2;
- next->handler (EVT_OUTPORT, data, range, count, loc);
- handled = 1;
+ case 1:
+ for (i = 0; i < split; i++)
+ {
+ if (olayer0[port + i].handler != NULL)
+ {
+ olayer0[port + i].handler (EVT_OUTPORT,
+ port + i,
+ 1,
+ count,
+ loc + i * count);
+ }
+ }
}
- else
- if (TOVERLP(next->base, next->range, data, op_size))
+ }
+ else
+ {
+ /* Unaligned write, do it slow & simple, who cares */
+
+ for (i = 0; i < count * op_size; i++)
{
- /* We know base doesn't overlap, so use next->base as bottom limit.
- We do need to recalculate the offset, though, and adjust loc */
+ if (olayer0[port + (i % op_size)].handler != NULL)
+ {
+ olayer0[port + (i % op_size)].handler (EVT_OUTPORT,
+ port + (i % op_size),
+ 1, 1,
+ loc + i);
+ }
+ }
+ }
- int ofs = next->base - data;
- range = op_size - ofs;
+ return 0;
+}
- next->handler (EVT_OUTPORT, next->base, range, count, loc + ofs);
- handled = 1;
- }
+
+
+/************************************************************************/
+/* Software interrupt handling */
+/************************************************************************/
+
+static struct intr_t
+{
+ plugin_t *plugin;
+ handler_t handler;
+ struct intr_t *next;
+}
+*ints[256] = { NULL }; /* 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 (!handled)
- fprintf(stderr, "outport 0x%x\n", data);
+
+ 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;
}
- int
-plugin_emulate_int (int data, int op_size, int count, void *loc)
+void
+plugin_free_intr (plugin_t *plugin, int vec)
{
- callback_t *next = ints;
- int reflect = 0;
+ struct intr_t *intr, *dummy;
- UNUSED(count);
- UNUSED(loc);
- UNUSED(op_size);
+ if ((intr = ints[vec]) == NULL)
+ return;
- do
+ if (intr->plugin == plugin)
{
- for (; next; next = next->next_type)
- if (data >= next->base && data < (next->base+next->range))
+ dummy = intr;
+ ints[vec] = intr->next;
+ free (dummy);
+ }
+ else
+ for (; intr != NULL; intr = intr->next)
+ {
+ if (intr->next == NULL)
break;
- if (!next)
- 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;
+}
- if (next->handler (EVT_INT, data, 0, 0, NULL))
- reflect = 1;
- next = next->next_type;
- } while (!conflict[EVT_INT]);
+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;
}
@@ -521,7 +713,7 @@
/************************************************************************/
-/* Interrupt handling */
+/* Hardware interrupt handling */
/************************************************************************/
static iac_handler_t plugin_iac_handler = NULL;
@@ -540,7 +732,7 @@
if (plugin_iac_handler)
{
fprintf (stderr, "Two interrupt sources announced!\n");
- vm_abort();
+ vm_abort ();
}
plugin_iac_handler = handler;
@@ -553,10 +745,10 @@
if (!plugin_iac_handler)
{
fprintf (stderr, "No interrupt source was announced!\n");
- vm_abort();
+ vm_abort ();
}
- return plugin_iac_handler();
+ return plugin_iac_handler ();
}
@@ -578,7 +770,16 @@
/* Plugin pending */
/************************************************************************/
-struct 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.
+ */
+
+static struct plugin_pending
{
void (*func)(void);
struct plugin_pending *next;
@@ -613,15 +814,25 @@
return;
}
- void
-plugin_register_elapsed( void (*funct)(Bit64u) )
+
+
+/************************************************************************/
+/* Timing control */
+/************************************************************************/
+
+static void (*save_funct)(Bit64u) = NULL;
+
+
+void
+plugin_register_elapsed (void (*funct)(Bit64u))
{
- save_funct = funct;
+ save_funct = funct;
}
- void
-plugin_call_elapsed( Bit64u elapsed )
+
+void
+plugin_call_elapsed (Bit64u elapsed)
{
- if (save_funct)
- save_funct(elapsed);
+ if (save_funct)
+ save_funct (elapsed);
}
diff -Nur plex86-old/user/plugin.h plex86/user/plugin.h
--- plex86-old/user/plugin.h Mon Jul 31 19:30:49 2000
+++ plex86/user/plugin.h Mon Jul 31 23:59:16 2000
@@ -34,27 +34,12 @@
typedef enum
{
- EVT_INPORT, EVT_OUTPORT, EVT_INT,
- EVT_MAX
+ EVT_INPORT, EVT_OUTPORT, EVT_INT
} event_t;
-static const int conflict[EVT_MAX] = { 1, 1, 1, };
-
typedef int (*handler_t)
(event_t event, int data, int op_size, int count, void *loc);
-struct _plugin_t;
-
-typedef struct _callback_t
-{
- event_t type;
- handler_t handler;
- int base, range;
- struct _plugin_t *plugin;
- struct _callback_t *next_type;
- struct _callback_t *next_plug;
-} callback_t;
-
typedef struct _plugin_t
{
int initialized;
@@ -63,7 +48,6 @@
char *name, *args, *argv[MAX_ARGC];
int (*init)(struct _plugin_t *plugin, int argc, char *argv[]);
void (*fini)(void);
- callback_t *callbacks;
struct _plugin_t *next;
} plugin_t;
@@ -74,11 +58,15 @@
void plugin_init_all (void);
void plugin_fini_all (void);
-callback_t *plugin_alloc (plugin_t *plugin, event_t event, handler_t handler, int
base, int range);
-void plugin_free (callback_t *callback);
-int plugin_emulate (event_t event, int data, int op_size, int count, void *loc);
-int plugin_emulate_inport (int data, int op_size, int count, void *loc);
-int plugin_emulate_outport (int data, int op_size, int count, void *loc);
+int plugin_alloc_inp (plugin_t *plugin, handler_t handler, int base, int range);
+int plugin_alloc_outp (plugin_t *plugin, handler_t handler, int base, int range);
+void plugin_free_inp (plugin_t *plugin, int base, int range);
+void plugin_free_outp (plugin_t *plugin, int base, int range);
+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 int (*iac_handler_t)(void);
typedef void (*plugin_pending_t)(void);
@@ -87,8 +75,8 @@
void plugin_announce_iac_handler (iac_handler_t handler);
void plugin_enqueue (plugin_pending_t func);
void plugin_handle_pending (void);
-void plugin_register_elapsed( void (*funct)(Bit64u) );
-void plugin_call_elapsed( Bit64u elapsed );
+void plugin_register_elapsed (void (*funct)(Bit64u));
+void plugin_call_elapsed (Bit64u elapsed);
void plugin_abort (void);
diff -Nur plex86-old/user/plugins/bochs/iodev/devices.cc
plex86/user/plugins/bochs/iodev/devices.cc
--- plex86-old/user/plugins/bochs/iodev/devices.cc Mon Jul 31 19:30:49 2000
+++ plex86/user/plugins/bochs/iodev/devices.cc Tue Aug 1 00:06:54 2000
@@ -457,7 +457,7 @@
read_handler_id[addr] = handle;
#ifdef PLEX86
- plugin_alloc (bx_plugin, EVT_INPORT, bx_plex86_io, (int) addr, 1);
+ plugin_alloc_inp (bx_plugin, bx_plex86_io, (int) addr, 1);
#endif //PLEX86
}
@@ -502,7 +502,7 @@
write_handler_id[addr] = handle;
#ifdef PLEX86
- plugin_alloc (bx_plugin, EVT_OUTPORT, bx_plex86_io, (int) addr, 1);
+ plugin_alloc_outp (bx_plugin, bx_plex86_io, (int) addr, 1);
#endif //PLEX86
}
diff -Nur plex86-old/user/plugins/ice/server.c plex86/user/plugins/ice/server.c
--- plex86-old/user/plugins/ice/server.c Mon Jul 31 19:30:49 2000
+++ plex86/user/plugins/ice/server.c Tue Aug 1 00:16:26 2000
@@ -31,24 +31,27 @@
int old_thread_from_wait;
int port_num;
-callback_t *ice_exceptions;
+plugin_t *ice_plugin;
int
plugin_init (plugin_t *plugin, int argc, char *argv[])
{
+ int i;
+
if (argc < 1)
{
fprintf (stderr, "ice: usage: plugin = plugin-ice.so port");
return 1;
}
- port_num = atoi (argv[0]);
+ ice_plugin = plugin;
+ port_num = atoi (argv[0]);
- if (!(ice_exceptions = plugin_alloc (plugin, EVT_INT, mywait, 0, 17)))
- {
- fprintf(stderr, "ice: failed allocation of exceptions; aborting\n");
- return 1;
- }
+ for (i = 0; i < 17; i++)
+ if (! plugin_alloc_intr (plugin, mywait, i))
+ {
+ fprintf(stderr, "ice: warning: failed allocation of interrupt 0x%x\n", i);
+ }
fetch_inferior_registers (0);
@@ -61,7 +64,11 @@
void
plugin_fini (void)
{
- plugin_free (ice_exceptions);
+ int i;
+
+ for (i = 0; i < 17; i++)
+ plugin_free_intr (ice_plugin, i);
+
remote_close ();
return;
}
diff -Nur plex86-old/user/user.c plex86/user/user.c
--- plex86-old/user/user.c Mon Jul 31 19:30:49 2000
+++ plex86/user/user.c Tue Aug 1 00:04:40 2000
@@ -236,7 +236,7 @@
case VMMessageIOInRequest:
{
IO_msg_t *io_msg = (IO_msg_t *) user_msgs.msg;
- plugin_emulate (EVT_INPORT, io_msg->port, io_msg->len, 1, &io_msg->data);
+ plugin_emulate_inport (io_msg->port, io_msg->len, 1, &io_msg->data);
// Change message type; most data stays the same
user_msgs.header.msg_type = VMMessageIOInResponse;
@@ -246,7 +246,7 @@
case VMMessageIOOutRequest:
{
IO_msg_t *io_msg = (IO_msg_t *) user_msgs.msg;
- plugin_emulate (EVT_OUTPORT, io_msg->port, io_msg->len, 1, &io_msg->data);
+ plugin_emulate_outport (io_msg->port, io_msg->len, 1, &io_msg->data);
// No response required
user_msgs.header.msg_type = VMMessageRunGuest;
@@ -267,7 +267,7 @@
case VMMessageIntRequest:
{
INT_msg_t *int_msg = (INT_msg_t *) user_msgs.msg;
- int_msg->reflect = plugin_emulate (EVT_INT, int_msg->vector, 0, 0, NULL);
+ int_msg->reflect = plugin_emulate_int (int_msg->vector);
user_msgs.header.msg_type = VMMessageIntResponse;
break;