Index: ddb/db_trap.c
===================================================================
RCS file: /home/ncvs/src/sys/ddb/db_trap.c,v
retrieving revision 1.15
diff -u -r1.15 db_trap.c
--- ddb/db_trap.c	8 Jul 2001 04:56:05 -0000	1.15
+++ ddb/db_trap.c	3 Nov 2002 23:25:46 -0000
@@ -34,6 +34,7 @@
 /*
  * Trap entry point to kernel debugger.
  */
+#include "opt_ddb.h"
 #include <sys/param.h>
 #include <sys/systm.h>
 
@@ -74,3 +75,69 @@
 
 	db_restart_at_pc(watchpt);
 }
+
+#ifdef GDB_AUTO_ENTER
+#include <sys/linker_set.h>
+#include <sys/sysctl.h>
+#include <sys/ctype.h>
+static enum {
+	STATE_NONE,
+	STATE_DATA,
+	STATE_CHKSUM1,
+	STATE_CHKSUM2,
+} gdb_auto_state;
+#define MAX_GDB_PACKET_LEN 16
+
+int gdb_auto_enter = 0;
+SYSCTL_INT(_debug, OID_AUTO, gdb_auto_enter, CTLFLAG_RW, &gdb_auto_enter, 0,
+	   "Enter GDB automatically after receiving a valid frame");
+
+/* Return non-zero if we see a valid GDB packet */
+int
+gdb_state_machine(char c)
+{
+	static int gdb_plen;
+	int ret;
+
+	ret = 0;
+	switch (gdb_auto_state) {
+	case STATE_NONE:
+		if (c == '$') {
+			gdb_plen++;
+			gdb_auto_state = STATE_DATA;
+		}
+		break;
+	case STATE_DATA:
+		if (++gdb_plen < MAX_GDB_PACKET_LEN - 1) {
+			if (c == '#')
+				gdb_auto_state = STATE_CHKSUM1;
+		} else {
+			gdb_plen = 0;
+		}
+		break;
+	case STATE_CHKSUM1:
+	case STATE_CHKSUM2:
+		if (++gdb_plen <= MAX_GDB_PACKET_LEN && isxdigit(c)) {
+			if (gdb_auto_state == STATE_CHKSUM1) {
+				gdb_auto_state = STATE_CHKSUM2;
+			} else {
+				/* Found a complete packet */
+				KASSERT(gdb_auto_state == STATE_CHKSUM2,
+					("invalid gdb_auto state"));
+				ret = 1;
+				gdb_auto_state = STATE_NONE;
+				gdb_plen = 0;
+			}
+		} else {
+			gdb_auto_state = STATE_NONE;
+			gdb_plen = 0;
+		}
+		break;
+	default:
+		panic("unknown gdb_auto_state 0x%x", gdb_auto_state);
+		/* NOTREACHED */
+	}
+
+	return (ret);
+}
+#endif /* GDB_AUTO_ENTER */
Index: ddb/ddb.h
===================================================================
RCS file: /home/ncvs/src/sys/ddb/ddb.h,v
retrieving revision 1.30
diff -u -r1.30 ddb.h
--- ddb/ddb.h	21 Sep 2002 17:29:36 -0000	1.30
+++ ddb/ddb.h	3 Nov 2002 23:19:29 -0000
@@ -161,4 +161,7 @@
 extern cn_putc_t *gdb_putc;
 #endif
 
+extern int gdb_auto_enter;
+extern int gdb_state_machine(char c);
+
 #endif /* !_DDB_DDB_H_ */
Index: dev/sio/sio.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sio/sio.c,v
retrieving revision 1.382
diff -u -r1.382 sio.c
--- dev/sio/sio.c	11 Oct 2002 20:22:20 -0000	1.382
+++ dev/sio/sio.c	3 Nov 2002 23:19:17 -0000
@@ -71,6 +71,10 @@
 #include <sys/rman.h>
 #include <sys/timepps.h>
 #include <sys/uio.h>
+#include <sys/cons.h>
+#if DDB > 0
+#include <ddb/ddb.h>
+#endif
 
 #include <isa/isavar.h>
 
@@ -1123,13 +1127,14 @@
 		}
 		if (ret)
 			device_printf(dev, "could not activate interrupt\n");
-#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \
-    defined(ALT_BREAK_TO_DEBUGGER))
+#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) ||	\
+    defined(ALT_BREAK_TO_DEBUGGER) ||			\
+    defined(GDB_AUTO_ENTER))
 		/*
 		 * Enable interrupts for early break-to-debugger support
-		 * on the console.
+		 * on the console and/or gdb port.
 		 */
-		if (ret == 0 && unit == comconsole)
+		if (ret == 0 && (unit == comconsole || unit == siogdbunit))
 			outb(siocniobase + com_ier, IER_ERXRDY | IER_ERLS |
 			    IER_EMSC);
 #endif
@@ -1381,14 +1386,15 @@
 	sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
 	tp = com->tp;
 
-#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \
-    defined(ALT_BREAK_TO_DEBUGGER))
+#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) ||	\
+    defined(ALT_BREAK_TO_DEBUGGER) ||			\
+    defined(GDB_AUTO_ENTER))
 	/*
 	 * Leave interrupts enabled and don't clear DTR if this is the
 	 * console. This allows us to detect break-to-debugger events
 	 * while the console device is closed.
 	 */
-	if (com->unit != comconsole)
+	if (com->unit != comconsole || com->unit != siogdbunit)
 #endif
 	{
 		sio_setreg(com, com_ier, 0);
@@ -1746,7 +1752,8 @@
 				recv_data = 0;
 			else
 				recv_data = inb(com->data_port);
-#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER)
+#ifdef DDB
+#ifdef ALT_BREAK_TO_DEBUGGER
 			/*
 			 * Solaris implements a new BREAK which is initiated
 			 * by a character sequence CR ~ ^b which is similar
@@ -1778,7 +1785,17 @@
 				} else
 					brk_state1 = 0;
 			}
-#endif
+#endif /* ALT_BREAK_TO_DEBUGGER */
+#ifdef GDB_AUTO_ENTER
+			if (gdb_auto_enter != 0 && com->unit == siogdbunit) {
+				if (gdb_state_machine(recv_data) != 0) {
+					boothowto |= RB_GDB;
+					breakpoint();
+					goto cont;
+				}
+			}
+#endif /* GDB_AUTO_ENTER */
+#endif /* DDB */
 			if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
 				/*
 				 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
@@ -2733,8 +2750,6 @@
 /*
  * Following are all routines needed for SIO to act as console
  */
-#include <sys/cons.h>
-
 struct siocnstate {
 	u_char	dlbl;
 	u_char	dlbh;
Index: conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.364
diff -u -r1.364 options
--- conf/options	18 Nov 2002 06:17:07 -0000	1.364
+++ conf/options	24 Nov 2002 00:44:19 -0000
@@ -87,6 +87,7 @@
 DDB_UNATTENDED
 GDB_REMOTE_CHAT	opt_ddb.h
 GDBSPEED	opt_ddb.h
+GDB_AUTO_ENTER	opt_ddb.h
 NO_GEOM		opt_geom.h
 GEOM_AES	opt_geom.h
 GEOM_BDE	opt_geom.h
