summaryrefslogtreecommitdiff
path: root/viengoos
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2009-02-22 00:41:54 +0100
committerNeal H. Walfield <neal@gnu.org>2009-02-22 00:41:54 +0100
commitcb4f05cfe9a7a0488de93dbd6c8012cf5fc72a82 (patch)
tree046b19a6348760892728896337752ce2f7ad7a56 /viengoos
parent6c3113baf2483a43ad5e4f35ca9af9c51b66c43a (diff)
Add support to break into the kernel on escape.
Diffstat (limited to 'viengoos')
-rw-r--r--viengoos/bottom-half.c23
-rw-r--r--viengoos/sysdeps/generic/output-serial.c41
2 files changed, 53 insertions, 11 deletions
diff --git a/viengoos/bottom-half.c b/viengoos/bottom-half.c
index 50be852..3bb081f 100644
--- a/viengoos/bottom-half.c
+++ b/viengoos/bottom-half.c
@@ -26,25 +26,30 @@ void
bottom_half_register (struct bottom_half *bh)
{
assert (! bh->next);
+ assert (bh != bottom_halves);
do
bh->next = bottom_halves;
- while (! __sync_val_compare_and_swap (&bottom_halves, bh->next, bh));
+ while (__sync_val_compare_and_swap (&bottom_halves, bh->next, bh)
+ != bh->next);
}
void
bottom_half_run_hard (void)
{
- for (;;)
- {
- struct bottom_half *bh;
+ struct bottom_half *bh;
+
+ do
+ bh = bottom_halves;
+ while (bh && !__sync_val_compare_and_swap (&bottom_halves, bh, 0));
- do
- bh = bottom_halves;
- while (bh && !__sync_val_compare_and_swap (&bottom_halves, bh, bh->next));
+ if (! bh)
+ return;
- if (! bh)
- break;
+ struct bottom_half *next = bh;
+ while ((bh = next))
+ {
+ next = bh->next;
bh->next = 0;
bh->callback (bh);
diff --git a/viengoos/sysdeps/generic/output-serial.c b/viengoos/sysdeps/generic/output-serial.c
index 3df0ddc..8d40887 100644
--- a/viengoos/sysdeps/generic/output-serial.c
+++ b/viengoos/sysdeps/generic/output-serial.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include "output.h"
+#include "bottom-half.h"
/* The base I/O ports for the serial device ports COM1 and COM2. */
@@ -65,6 +66,11 @@
#define UART_SPEED_DEFAULT UART_SPEED_MAX
+static void check_for_escape_bottom_half_handler (struct bottom_half *bh);
+static struct bottom_half check_for_escape_bottom_half
+ = { .callback = check_for_escape_bottom_half_handler };
+static struct output_driver *driver;
+
static void
serial_init (struct output_driver *device, const char *driver_cfg)
{
@@ -153,6 +159,12 @@ serial_init (struct output_driver *device, const char *driver_cfg)
inb (UART_MCR);
inb (UART_LSR);
inb (UART_MSR);
+
+ if (! driver)
+ {
+ driver = device;
+ bottom_half_register (&check_for_escape_bottom_half);
+ }
}
@@ -169,12 +181,22 @@ serial_putchar (struct output_driver *device, int chr)
}
static int
+serial_getchar_nonblocking (struct output_driver *device)
+{
+ if ((inb (UART_LSR)) & UART_LSR_DR)
+ return inb (UART_DR);
+
+ return -1;
+}
+
+static int
serial_getchar (struct output_driver *device)
{
- while (!((inb (UART_LSR)) & UART_LSR_DR))
+ int c;
+ while ((c = serial_getchar_nonblocking (device)) == -1)
;
- return inb (UART_DR);
+ return c;
}
struct output_driver serial_output =
@@ -185,3 +207,18 @@ struct output_driver serial_output =
serial_putchar,
serial_getchar
};
+
+static void
+check_for_escape_bottom_half_handler (struct bottom_half *bh)
+{
+ assert (bh == &check_for_escape_bottom_half);
+ assert (driver);
+
+ int c;
+ if (unlikely ((c = serial_getchar_nonblocking (driver)))
+ && unlikely (c == 0x1b))
+ vg_debugger ();
+
+ bottom_half_register (bh);
+}
+