diff options
author | Neal H. Walfield <neal@gnu.org> | 2009-02-22 00:41:54 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@gnu.org> | 2009-02-22 00:41:54 +0100 |
commit | cb4f05cfe9a7a0488de93dbd6c8012cf5fc72a82 (patch) | |
tree | 046b19a6348760892728896337752ce2f7ad7a56 /viengoos | |
parent | 6c3113baf2483a43ad5e4f35ca9af9c51b66c43a (diff) |
Add support to break into the kernel on escape.
Diffstat (limited to 'viengoos')
-rw-r--r-- | viengoos/bottom-half.c | 23 | ||||
-rw-r--r-- | viengoos/sysdeps/generic/output-serial.c | 41 |
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); +} + |