# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1221216227 -3600
# Node ID 982e6fce0e4796f53fe80891b3b0352d7b214ce4
# Parent 31e06b3ccf53ea3fc4a2e3f6ef2b2d630ed0b584
Check the existence of serial port before using
Signed-off-by: Huacai Chen <huacai.chen@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/common/gdbstub.c | 15 ++++++++++++---
xen/drivers/char/console.c | 14 +++++++++++---
xen/drivers/char/ns16550.c | 34 ++++++++++++++++++++++++++++++++++
xen/drivers/char/serial.c | 10 ++++------
4 files changed, 61 insertions(+), 12 deletions(-)
diff -r 31e06b3ccf53 -r 982e6fce0e47 xen/common/gdbstub.c
--- a/xen/common/gdbstub.c Fri Sep 12 10:41:51 2008 +0100
+++ b/xen/common/gdbstub.c Fri Sep 12 11:43:47 2008 +0100
@@ -65,7 +65,7 @@ static void gdb_smp_pause(void);
static void gdb_smp_pause(void);
static void gdb_smp_resume(void);
-static char opt_gdb[30] = "none";
+static char opt_gdb[30];
string_param("gdb", opt_gdb);
static void gdbstub_console_puts(const char *str);
@@ -625,10 +625,19 @@ void __init
void __init
initialise_gdb(void)
{
+ if ( *opt_gdb == '\0' )
+ return;
+
gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
- if ( gdb_ctx->serhnd != -1 )
- printk("GDB stub initialised.\n");
+ if ( gdb_ctx->serhnd == -1 )
+ {
+ printk("Bad gdb= option '%s'\n", opt_gdb);
+ return;
+ }
+
serial_start_sync(gdb_ctx->serhnd);
+
+ printk("GDB stub initialised.\n");
}
static void gdb_pause_this_cpu(void *unused)
diff -r 31e06b3ccf53 -r 982e6fce0e47 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c Fri Sep 12 10:41:51 2008 +0100
+++ b/xen/drivers/char/console.c Fri Sep 12 11:43:47 2008 +0100
@@ -543,10 +543,18 @@ void __init init_console(void)
{
if ( *p == ',' )
p++;
- if ( strncmp(p, "com", 3) == 0 )
- sercon_handle = serial_parse_handle(p);
- else if ( strncmp(p, "vga", 3) == 0 )
+ if ( !strncmp(p, "vga", 3) )
vga_init();
+ else if ( strncmp(p, "com", 3) ||
+ (sercon_handle = serial_parse_handle(p)) == -1 )
+ {
+ char *q = strchr(p, ',');
+ if ( q != NULL )
+ *q = '\0';
+ printk("Bad console= option '%s'\n", p);
+ if ( q != NULL )
+ *q = ',';
+ }
}
serial_set_rx_handler(sercon_handle, serial_rx);
diff -r 31e06b3ccf53 -r 982e6fce0e47 xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c Fri Sep 12 10:41:51 2008 +0100
+++ b/xen/drivers/char/ns16550.c Fri Sep 12 11:43:47 2008 +0100
@@ -82,6 +82,7 @@ static struct ns16550 {
#define MCR_DTR 0x01 /* Data Terminal Ready */
#define MCR_RTS 0x02 /* Request to Send */
#define MCR_OUT2 0x08 /* OUT2: interrupt mask */
+#define MCR_LOOP 0x10 /* Enable loopback test mode */
/* Line Status Register */
#define LSR_DR 0x01 /* Data ready */
@@ -293,6 +294,37 @@ static int __init parse_parity_char(int
return PARITY_SPACE;
}
return 0;
+}
+
+static int check_existence(struct ns16550 *uart)
+{
+ unsigned char status, scratch, scratch2, scratch3;
+
+ /*
+ * Do a simple existence test first; if we fail this,
+ * there's no point trying anything else.
+ */
+ scratch = ns_read_reg(uart, IER);
+ ns_write_reg(uart, IER, 0);
+
+ /*
+ * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+ * 16C754B) allow only to modify them if an EFR bit is set.
+ */
+ scratch2 = ns_read_reg(uart, IER) & 0x0f;
+ ns_write_reg(uart, IER, 0x0F);
+ scratch3 = ns_read_reg(uart, IER) & 0x0f;
+ ns_write_reg(uart, IER, scratch);
+ if ( (scratch2 != 0) || (scratch3 != 0x0F) )
+ return 0;
+
+ /*
+ * Check to see if a UART is really there.
+ * Use loopback test mode.
+ */
+ ns_write_reg(uart, MCR, MCR_LOOP | 0x0A);
+ status = ns_read_reg(uart, MSR) & 0xF0;
+ return (status == 0x90);
}
#define PARSE_ERR(_f, _a...) \
@@ -357,6 +389,8 @@ static void __init ns16550_parse_port_co
PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
if ( uart->io_base == 0 )
PARSE_ERR("I/O base address must be specified.");
+ if ( !check_existence(uart) )
+ PARSE_ERR("16550-compatible serial UART not present");
/* Register with generic serial driver. */
serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
diff -r 31e06b3ccf53 -r 982e6fce0e47 xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Fri Sep 12 10:41:51 2008 +0100
+++ b/xen/drivers/char/serial.c Fri Sep 12 11:43:47 2008 +0100
@@ -258,11 +258,7 @@ int serial_parse_handle(char *conf)
{
int handle;
- /* Silently fail if user has explicitly requested no serial I/O. */
- if ( strcmp(conf, "none") == 0 )
- return -1;
-
- if ( strncmp(conf, "com", 3) != 0 )
+ if ( strncmp(conf, "com", 3) )
goto fail;
switch ( conf[3] )
@@ -277,6 +273,9 @@ int serial_parse_handle(char *conf)
goto fail;
}
+ if ( !com[handle].driver )
+ goto fail;
+
if ( conf[4] == 'H' )
handle |= SERHND_HI;
else if ( conf[4] == 'L' )
@@ -287,7 +286,6 @@ int serial_parse_handle(char *conf)
return handle;
fail:
- printk("ERROR: bad serial-interface specification '%s'\n", conf);
return -1;
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|