<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream/src</tt></b></td></tr>
<tr><td><tt><a href="#file1">gdbserver.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+37</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">65fd19c07e2e -> 3edc4bdd7c0b</td></tr>
</table>
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
GDB: Support ^C interruption from GDB
 - postpone dreamcast_run() until after the IO callback returns (callback
   won't be called again until the callback returns, so blocks all input)
 - generate stop notifications when the DC stops, regardless of where the
   stop originates.
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gdbserver.c</b></big> <small id="info" style="color: #888888;" >65fd19c07e2e -> 3edc4bdd7c0b</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gdbserver.c
+++ lxdream/src/gdbserver.c
@@ -26,9 +26,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include <glib.h>
 #include <arpa/inet.h>
 #include "lxdream.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "dream.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "dreamcast.h"
 #include "ioutil.h"
 #include "cpu.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "gui.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #define DEFAULT_BUFFER_SIZE 1024
 #define BUFFER_SIZE_MARGIN 32
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -50,9 +52,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int buf_posn;
 };
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static GList *gdb_server_conn_list = NULL;
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void gdb_server_free( gpointer data )
 {
     struct gdb_server *server = (struct gdb_server *)data;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    gdb_server_conn_list = g_list_remove(gdb_server_conn_list, server);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     free((char *)server->peer_name);
     free(server->buf);
     free(data);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -209,8 +214,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         gdb_send_frame( server, "S05", 3 );
         break;
     case 'c': /* Continue */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        dreamcast_run();
-        gdb_send_frame( server, "S05", 3 );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        gui_do_later(dreamcast_run);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         break;
     case 'g': /* Read all general registers */
         gdb_print_registers( server, buf, sizeof(buf), 0, server->cpu->num_gpr_regs );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -422,6 +426,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 continue;
             } else if( server->buf[i] == '-' ) {
                 /* Request retransmit */
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            } else if( server->buf[i] == '\003' ) { /* Control-C */
+                if( dreamcast_is_running() ) {
+                    dreamcast_stop();
+                }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             } /* Anything else is noise */
         } else if( server->buf[i] == '#' ) {
             frame_len = i - frame_start - 1;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -496,11 +504,33 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         chan_serv->buf_size = 1024;
         chan_serv->buf_posn = 0;
         io_register_tcp_listener( conn_fd, gdb_server_data_callback, chan_serv, gdb_server_free );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        gdb_server_conn_list = g_list_append(gdb_server_conn_list, chan_serv);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         INFO( "GDB connected from %s", chan_serv->peer_name );
     }
     return TRUE;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void gdb_server_notify_stopped( struct gdb_server *server )
+{
+    gdb_send_frame( server, "S05", 3 );
+}
+
+/**
+ * stop handler to generate notifications to all connected clients
+ */
+void gdb_server_on_stop()
+{
+    GList *ptr;
+    for( ptr = gdb_server_conn_list; ptr != NULL; ptr = ptr->next ) {
+        gdb_server_notify_stopped( (struct gdb_server *)ptr->data );
+    }
+}
+
+static gboolean module_registered = FALSE;
+static struct dreamcast_module gdb_server_module = {
+        "gdbserver", NULL, NULL, NULL, NULL, gdb_server_on_stop, NULL, NULL };
+
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Bind a network port for a GDB remote server for the specified cpu. The
  * port is registered for the system network callback.
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -514,6 +544,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 gboolean gdb_init_server( const char *interface, int port, cpu_desc_t cpu, gboolean mmu )
 {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( !module_registered ) {
+        dreamcast_register_module( &gdb_server_module );
+        module_registered = TRUE;
+    }
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int fd = io_create_server_socket( interface, port );
     if( fd == -1 ) {
         return FALSE;
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>