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;

Reply via email to