LWN.net Logo

8250 uart driver for KGDB

From:  Tom Rini <trini@kernel.crashing.org>
To:  akpm@osdl.org
Subject:  [patch 4/8] 8250 uart driver for KGDB
Date:  Fri, 29 Oct 2004 11:33:42 -0700
Cc:  linux-kernel@vger.kernel.org, trini@kernel.crashing.org, rmk@arm.linux.org.uk


Cc: Russell King <rmk@arm.linux.org.uk>
This adds an 8250 uart driver for KGDB and adds a hook into 8250.c to
unregister a port based on the IRQ, serial8250_release_irq().  We use
serial8250_unregister_port() to do the real work here, however.  Note
that we can't use unregister_port in kgdb_8250.c since we don't know
what the 'port' is, in 8250 terms, only the IRQ.  The other change is
that we have SERIAL_8250_NR_UARTS always be defined if KGDB_8250.

---

 linux-2.6.10-rc1-trini/drivers/serial/8250.c        |   39 +
 linux-2.6.10-rc1-trini/drivers/serial/Kconfig       |    4 
 linux-2.6.10-rc1-trini/drivers/serial/Makefile      |    1 
 linux-2.6.10-rc1-trini/drivers/serial/kgdb_8250.c   |  477 ++++++++++++++++++++
 linux-2.6.10-rc1-trini/drivers/serial/serial_core.c |    6 
 linux-2.6.10-rc1-trini/lib/Kconfig.debug            |  101 ++++
 6 files changed, 625 insertions(+), 3 deletions(-)

diff -puN drivers/serial/8250.c~8250 drivers/serial/8250.c
--- linux-2.6.10-rc1/drivers/serial/8250.c~8250	2004-10-29 11:26:44.964330757 -0700
+++ linux-2.6.10-rc1-trini/drivers/serial/8250.c	2004-10-29 11:26:44.977327706 -0700
@@ -1348,12 +1348,17 @@ static void serial8250_break_ctl(struct 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
+static int released_irq = -1;
+
 static int serial8250_startup(struct uart_port *port)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 	unsigned long flags;
 	int retval;
 
+	if (up->port.irq == released_irq)
+		return -EBUSY;
+
 	up->capabilities = uart_config[up->port.type].flags;
 	up->mcr = 0;
 
@@ -1990,6 +1995,9 @@ serial8250_register_ports(struct uart_dr
 	for (i = 0; i < UART_NR; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 
+		if (up->port.irq == released_irq)
+			continue;
+
 		up->port.line = i;
 		up->port.ops = &serial8250_pops;
 		up->port.dev = dev;
@@ -2327,6 +2335,9 @@ int serial8250_register_port(struct uart
 	struct uart_8250_port *uart;
 	int ret = -ENOSPC;
 
+	if (port->line == released_irq)
+		return -EBUSY;
+
 	down(&serial_sem);
 
 	uart = serial8250_find_match_or_unused(port);
@@ -2376,6 +2387,34 @@ void serial8250_unregister_port(int line
 }
 EXPORT_SYMBOL(serial8250_unregister_port);
 
+/**
+ *	serial8250_release_irq - remove a 16x50 serial port at runtime based
+ *	on IRQ
+ *	@irq: IRQ number
+ *
+ *	Remove one serial port.  This may not be called from interrupt
+ *	context.  This is called when the caller know the IRQ of the
+ *	port they want, but not where it is in our table.  This allows
+ *	for one port, based on IRQ, to be permanently released from us.
+ */
+
+int serial8250_release_irq(int irq)
+{
+        struct uart_8250_port *up;
+	int ttyS;
+
+	if (released_irq != -1)
+		return -EBUSY;
+
+	released_irq = irq;
+	for (ttyS = 0; ttyS < UART_NR; ttyS++){
+		up =  &serial8250_ports[ttyS];
+		if (up->port.irq == irq && (irq_lists + irq)->head)
+			serial8250_unregister_port(up->port.line);
+        }
+	return 0;
+}
+
 static int __init serial8250_init(void)
 {
 	int ret, i;
diff -puN drivers/serial/Kconfig~8250 drivers/serial/Kconfig
--- linux-2.6.10-rc1/drivers/serial/Kconfig~8250	2004-10-29 11:26:44.966330288 -0700
+++ linux-2.6.10-rc1-trini/drivers/serial/Kconfig	2004-10-29 11:26:44.978327471 -0700
@@ -86,8 +86,8 @@ config SERIAL_8250_ACPI
 	  namespace, say Y here.  If unsure, say N.
 
 config SERIAL_8250_NR_UARTS
-	int "Maximum number of non-legacy 8250/16550 serial ports"
-	depends on SERIAL_8250
+	int "Maximum number of non-legacy 8250/16550 serial ports" if SERIAL_8250
+	depends on SERIAL_8250 || KGDB_8250
 	default "4"
 	---help---
 	  Set this to the number of non-legacy serial ports you want
diff -puN drivers/serial/Makefile~8250 drivers/serial/Makefile
--- linux-2.6.10-rc1/drivers/serial/Makefile~8250	2004-10-29 11:26:44.967330053 -0700
+++ linux-2.6.10-rc1-trini/drivers/serial/Makefile	2004-10-29 11:26:44.978327471 -0700
@@ -42,3 +42,4 @@ obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += s
 obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
 obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
 obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
+obj-$(CONFIG_KGDB_8250) += kgdb_8250.o
diff -puN /dev/null drivers/serial/kgdb_8250.c
--- /dev/null	2004-10-25 00:35:20.587727328 -0700
+++ linux-2.6.10-rc1-trini/drivers/serial/kgdb_8250.c	2004-10-29 11:26:44.979327236 -0700
@@ -0,0 +1,477 @@
+/*
+ * 8250 interface for kgdb.
+ *
+ * This is a merging of many different drivers, and all of the people have
+ * had an impact in some form or another:
+ *
+ * Amit Kale <amitkale@emsyssoft.com>, David Grothe <dave@gcom.com>,
+ * Scott Foehner <sfoehner@engr.sgi.com>, George Anzinger <george@mvista.com>,
+ * Robert Walsh <rjwalsh@durables.org>, wangdi <wangdi@clusterfs.com>,
+ * San Mehat, Tom Rini <trini@mvista.com>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/serialP.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/serial.h>		/* For BASE_BAUD and SERIAL_PORT_DFNS */
+
+#define GDB_BUF_SIZE	512	/* power of 2, please */
+
+/* Speed of the UART. */
+#if defined(CONFIG_KGDB_9600BAUD)
+static int kgdb8250_baud = 9600;
+#elif defined(CONFIG_KGDB_19200BAUD)
+static int kgdb8250_baud = 19200;
+#elif defined(CONFIG_KGDB_38400BAUD)
+static int kgdb8250_baud = 38400;
+#elif defined(CONFIG_KGDB_57600BAUD)
+static int kgdb8250_baud = 57600;
+#else
+static int kgdb8250_baud = 115200;	/* Start with this if not given */
+#endif
+
+/* Index of the UART, matches ttySX naming. */
+#if defined(CONFIG_KGDB_TTYS1)
+static int kgdb8250_ttyS = 1;
+#elif defined(CONFIG_KGDB_TTYS2)
+static int kgdb8250_ttyS = 2;
+#elif defined(CONFIG_KGDB_TTYS3)
+static int kgdb8250_ttyS = 3;
+#else
+static int kgdb8250_ttyS = 0;		/* Start with this if not given */
+#endif
+
+static char kgdb8250_buf[GDB_BUF_SIZE];
+static atomic_t kgdb8250_buf_in_cnt;
+static int kgdb8250_buf_out_inx;
+
+/* Old-style serial definitions, if existant, and a counter. */
+static int old_rs_table_copied;
+static struct serial_state old_rs_table[] = {
+#ifdef SERIAL_PORT_DFNS
+	SERIAL_PORT_DFNS
+#endif
+};
+
+/* Our internal table of UARTS. */
+#define UART_NR	(ARRAY_SIZE(old_rs_table) + CONFIG_SERIAL_8250_NR_UARTS)
+static struct uart_port kgdb8250_ports[UART_NR] = {
+#ifndef CONFIG_KGDB_SIMPLE_SERIAL
+	{
+#if defined(CONFIG_KGDB_IRQ) && defined(CONFIG_KGDB_PORT)
+		.irq		= CONFIG_KGDB_IRQ,
+		.iobase		= CONFIG_KGDB_PORT,
+		.iotype		= UPIO_PORT,
+#endif
+#ifdef CONFIG_KGDB_IOMEMBASE
+		.membase	= (unsigned char *)CONFIG_KGDB_IOMEMBASE,
+		.iotype		= UPIO_MEM,
+#endif
+	},
+#endif
+};
+
+/* Macros to easily get what we want from kgdb8250_ports[kgdb8250_ttyS] */
+#define CURRENTPORT		kgdb8250_ports[kgdb8250_ttyS]
+#define KGDB8250_IRQ		CURRENTPORT.irq
+#define KGDB8250_REG_SHIFT	CURRENTPORT.regshift
+
+/* Base of the UART. */
+static unsigned long kgdb8250_addr;
+/* Pointers for I/O. */
+static void (*serial_outb) (unsigned char val, unsigned long addr);
+static unsigned long (*serial_inb) (unsigned long addr);
+
+/* Forward declarations. */
+static int kgdb8250_init(void);
+extern int serial8250_release_irq(int irq);
+
+extern atomic_t debugger_active;
+
+static unsigned long
+direct_inb(unsigned long addr)
+{
+	return readb((void *)addr);
+}
+
+static void
+direct_outb(unsigned char val, unsigned long addr)
+{
+	writeb(val, (void *)addr);
+}
+
+static unsigned long
+io_inb(unsigned long port)
+{
+	return inb(port);
+}
+
+static void
+io_outb(unsigned char val, unsigned long port)
+{
+	outb(val, port);
+}
+
+/*
+ * Wait until the interface can accept a char, then write it.
+ */
+static void
+kgdb_put_debug_char(int chr)
+{
+	while (!(serial_inb(kgdb8250_addr + (UART_LSR << KGDB8250_REG_SHIFT)) &
+		UART_LSR_THRE))
+		;
+
+	serial_outb(chr, kgdb8250_addr + (UART_TX << KGDB8250_REG_SHIFT));
+}
+
+/*
+ * Get a byte from the hardware data buffer and return it
+ */
+static int
+read_data_bfr(void)
+{
+	char it = serial_inb(kgdb8250_addr + (UART_LSR << KGDB8250_REG_SHIFT));
+
+	if (it & UART_LSR_DR)
+		return serial_inb(kgdb8250_addr +
+				(UART_RX << KGDB8250_REG_SHIFT));
+
+	/*
+	 * If we have a framing error assume somebody messed with
+	 * our uart.  Reprogram it and send '-' both ways...
+	 */
+	if (it & 0xc) {
+		kgdb8250_init();
+		kgdb_put_debug_char('-');
+		return '-';
+	}
+
+	return -1;
+}
+
+/*
+ * Get a char if available, return -1 if nothing available.
+ * Empty the receive buffer first, then look at the interface hardware.
+ */
+
+static int
+kgdb_get_debug_char(void)
+{
+	int retchr;
+	unsigned long flags;
+	local_irq_save(flags);
+
+	/* intr routine has q'd chars */
+	if (atomic_read(&kgdb8250_buf_in_cnt) != 0) {
+		retchr = kgdb8250_buf[kgdb8250_buf_out_inx++];
+		kgdb8250_buf_out_inx &= (GDB_BUF_SIZE - 1);
+		atomic_dec(&kgdb8250_buf_in_cnt);
+		goto out;
+	}
+
+	do {
+		retchr = read_data_bfr();
+	} while (retchr < 0);
+
+out:
+	local_irq_restore(flags);
+
+	return retchr;
+}
+
+/*
+ * This is the receiver interrupt routine for the GDB stub.
+ * All that we need to do is verify that the interrupt happened on the
+ * line we're in charge of.  If this is true, schedule a breakpoint and
+ * return.
+ */
+static irqreturn_t
+kgdb8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	char iir;
+
+	if (irq != KGDB8250_IRQ)
+		return IRQ_NONE;
+        /*
+         * If  there is some other CPU in KGDB then this is a
+         * spurious interrupt. so return without even checking a byte
+         */
+        if (atomic_read(&debugger_active))
+               return IRQ_NONE;
+
+	iir = serial_inb(kgdb8250_addr + (UART_IIR << KGDB8250_REG_SHIFT));
+	if (iir & UART_IIR_RDI)
+		kgdb_schedule_breakpoint();
+
+	return IRQ_HANDLED;
+}
+
+/*
+ *  Returns:
+ *	0 on success, 1 on failure.
+ */
+static int
+kgdb8250_init(void)
+{
+	unsigned cval;
+	int bits = 8;
+	int parity = 'n';
+	int cflag = CREAD | HUPCL | CLOCAL;
+	char ier = UART_IER_RDI;
+
+	/*
+	 *      Now construct a cflag setting.
+	 */
+	switch (kgdb8250_baud) {
+	case 1200:
+		cflag |= B1200;
+		break;
+	case 2400:
+		cflag |= B2400;
+		break;
+	case 4800:
+		cflag |= B4800;
+		break;
+	case 19200:
+		cflag |= B19200;
+		break;
+	case 38400:
+		cflag |= B38400;
+		break;
+	case 57600:
+		cflag |= B57600;
+		break;
+	case 115200:
+		cflag |= B115200;
+		break;
+	default:
+		kgdb8250_baud = 9600;
+		/* Fall through */
+	case 9600:
+		cflag |= B9600;
+		break;
+	}
+	switch (bits) {
+	case 7:
+		cflag |= CS7;
+		break;
+	default:
+	case 8:
+		cflag |= CS8;
+		break;
+	}
+	switch (parity) {
+	case 'o':
+	case 'O':
+		cflag |= PARODD;
+		break;
+	case 'e':
+	case 'E':
+		cflag |= PARENB;
+		break;
+	}
+
+	/*
+	 *      Divisor, bytesize and parity
+	 *
+	 */
+
+	cval = cflag & (CSIZE | CSTOPB);
+	cval >>= 4;
+	if (cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+
+	/* Disable UART interrupts, set DTR and RTS high and set speed. */
+	cval = 0x3;
+	/* set DLAB */
+	serial_outb(cval | UART_LCR_DLAB, kgdb8250_addr +
+			(UART_LCR << KGDB8250_REG_SHIFT));
+	/* LS */
+	serial_outb(BASE_BAUD / kgdb8250_baud & 0xff, kgdb8250_addr +
+			(UART_DLL << KGDB8250_REG_SHIFT));
+	/* MS  */
+	serial_outb(BASE_BAUD / kgdb8250_baud >> 8, kgdb8250_addr +
+			(UART_DLM << KGDB8250_REG_SHIFT));
+	/* reset DLAB */
+	serial_outb(cval, kgdb8250_addr + (UART_LCR << KGDB8250_REG_SHIFT));
+
+	/*
+	 * XScale-specific bits that need to be set
+	 */
+	if (CURRENTPORT.type == PORT_XSCALE)
+		ier |= UART_IER_UUE | UART_IER_RTOIE;
+
+	/* turn on interrupts */
+	serial_outb(ier, kgdb8250_addr + (UART_IER << KGDB8250_REG_SHIFT));
+	serial_outb(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS,
+		    kgdb8250_addr + (UART_MCR << KGDB8250_REG_SHIFT));
+
+	/*
+	 *      If we read 0xff from the LSR, there is no UART here.
+	 */
+	if (serial_inb(kgdb8250_addr + (UART_LSR << KGDB8250_REG_SHIFT)) ==
+			0xff)
+		return -1;
+	return 0;
+}
+
+/*
+ * Copy the old serial_state table to our uart_port table if we haven't
+ * had values specifically configured in.  We need to make sure this only
+ * happens once.
+ */
+static void
+kgdb8250_copy_rs_table(void)
+{
+#ifdef CONFIG_KGDB_SIMPLE_SERIAL
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(old_rs_table); i++) {
+		kgdb8250_ports[i].iobase = old_rs_table[i].port;
+		kgdb8250_ports[i].irq = irq_canonicalize(old_rs_table[i].irq);
+		kgdb8250_ports[i].uartclk = old_rs_table[i].baud_base * 16;
+		kgdb8250_ports[i].membase = old_rs_table[i].iomem_base;
+		kgdb8250_ports[i].iotype = old_rs_table[i].io_type;
+		kgdb8250_ports[i].regshift = old_rs_table[i].iomem_reg_shift;
+	}
+#endif
+
+	old_rs_table_copied = 1;
+}
+
+/*
+ * Perform static initalization tasks which we need to always do,
+ * even if KGDB isn't going to be invoked immediately.
+ */
+static int
+kgdb8250_local_init(void)
+{
+	if (old_rs_table_copied == 0)
+		kgdb8250_copy_rs_table();
+
+	switch (CURRENTPORT.iotype) {
+	case UPIO_MEM:
+		if (CURRENTPORT.mapbase) {
+			if (!request_mem_region(CURRENTPORT.mapbase,
+						8 << KGDB8250_REG_SHIFT,
+						"kgdb"))
+				return 1;	/* Failed. */
+		}
+		if (CURRENTPORT.flags & UPF_IOREMAP) {
+			CURRENTPORT.membase = ioremap(CURRENTPORT.mapbase,
+					8 << KGDB8250_REG_SHIFT);
+			if (!CURRENTPORT.membase)
+				return 1;	/* Failed. */
+		}
+		kgdb8250_addr = (unsigned long)CURRENTPORT.membase;
+		serial_outb = direct_outb;
+		serial_inb = direct_inb;
+		break;
+	case UPIO_PORT:
+	default:
+		kgdb8250_addr = CURRENTPORT.iobase;
+		serial_outb = io_outb;
+		serial_inb = io_inb;
+	}
+
+	return 0;
+}
+
+static int
+kgdb_init_io(void)
+{
+	if (kgdb8250_local_init())
+		return -1;
+
+#ifdef CONFIG_SERIAL_8250
+	if (serial8250_release_irq(KGDB8250_IRQ))
+		return -1;
+#endif
+
+	if (kgdb8250_init() == -1)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Hookup our IRQ line.  We will already have been initialized at
+ * this point.
+ */
+static void __init kgdb8250_hookup_irq(void)
+{
+	request_irq(KGDB8250_IRQ, kgdb8250_interrupt, SA_SHIRQ,
+			"GDB-stub", &CURRENTPORT);
+}
+
+struct kgdb_io kgdb_io_ops = {
+	.read_char = kgdb_get_debug_char,
+	.write_char = kgdb_put_debug_char,
+	.init = kgdb_init_io,
+	.late_init = kgdb8250_hookup_irq,
+};
+
+void
+kgdb8250_add_port(int i, struct uart_port *serial_req)
+{
+	/* Copy the old table in if needed. */
+	if (old_rs_table_copied == 0)
+		kgdb8250_copy_rs_table();
+
+	/* Copy the whole thing over. */
+	memcpy(&kgdb8250_ports[i], serial_req, sizeof(struct uart_port));
+}
+
+/*
+ * Syntax for this cmdline option is "kgdb8250=ttyno,baudrate"
+ * with ",irq,iomembase" tacked on the end on IA64.
+ */
+static int __init
+kgdb8250_opt(char *str)
+{
+	if (*str < '0' || *str > '3')
+		goto errout;
+	kgdb8250_ttyS = *str - '0';
+	str++;
+	if (*str != ',')
+		goto errout;
+	str++;
+	kgdb8250_baud = simple_strtoul(str, &str, 10);
+	if (kgdb8250_baud != 9600 && kgdb8250_baud != 19200 &&
+	    kgdb8250_baud != 38400 && kgdb8250_baud != 57600 &&
+	    kgdb8250_baud != 115200)
+		goto errout;
+
+#ifdef CONFIG_IA64
+	if (*str == ',') {
+		str++;
+		KGDB8250_IRQ = simple_strtoul(str, &str, 10);
+		if (*str == ',') {
+			str++;
+			CURRENTPORT.iotype = SERIAL_IO_MEM;
+			CURRENTPORT.membase =
+				(unsigned char *)simple_strtoul(str, &str, 0);
+		}
+	}
+#endif
+
+	return 0;
+
+errout:
+	printk(KERN_ERR "Invalid syntax for option kgdb8250=\n");
+	return 1;
+}
+early_param("kgdb8250", kgdb8250_opt);
diff -puN drivers/serial/serial_core.c~8250 drivers/serial/serial_core.c
--- linux-2.6.10-rc1/drivers/serial/serial_core.c~8250	2004-10-29 11:26:44.970329349 -0700
+++ linux-2.6.10-rc1-trini/drivers/serial/serial_core.c	2004-10-29 11:26:44.981326767 -0700
@@ -903,7 +903,11 @@ uart_tiocmset(struct tty_struct *tty, st
 static void uart_break_ctl(struct tty_struct *tty, int break_state)
 {
 	struct uart_state *state = tty->driver_data;
-	struct uart_port *port = state->port;
+	struct uart_port *port;
+
+	if (!state)
+		return;
+	port = state->port;
 
 	BUG_ON(!kernel_locked());
 
diff -puN lib/Kconfig.debug~8250 lib/Kconfig.debug
--- linux-2.6.10-rc1/lib/Kconfig.debug~8250	2004-10-29 11:26:44.972328879 -0700
+++ linux-2.6.10-rc1-trini/lib/Kconfig.debug	2004-10-29 11:32:57.089929849 -0700
@@ -124,3 +124,104 @@ config KGDB
 	  Documentation of kernel debugger available at
 	  http://kgdb.sourceforge.net
 	  This is only useful for kernel hackers. If unsure, say N.
+
+choice
+	prompt "Method for KGDB communication"
+	depends on KGDB
+	default KGDB_8250
+	help
+	  There are a number of different ways in which you can communicate
+	  with KGDB.  The oldest is using a serial driver.  A newer method
+	  is to use UDP packets and a special network driver.
+
+config KGDB_8250
+	bool "KGDB: On generic serial port (8250)"
+	help
+	  Uses generic serial port (8250) for kgdb. This is independent of the
+	  option 9250/16550 and compatible serial port.
+
+endchoice
+
+config KGDB_SIMPLE_SERIAL
+	bool "Simple selection of KGDB serial port"
+	depends on KGDB_8250
+	help
+	  If you say Y here, you will only have to pick the baud rate
+	  and serial port (ttyS) that you wish to use for KGDB.  If you
+	  say N, you will have provide the I/O port and IRQ number.  Note
+	  that if your serial ports are iomapped, then you must say Y here.
+	  If in doubt, say Y.
+
+choice
+	depends on KGDB_8250
+    	prompt "Debug serial port BAUD"
+	default KGDB_115200BAUD
+	help
+	  Gdb and the kernel stub need to agree on the baud rate to be
+	  used.  Some systems (x86 family at this writing) allow this to
+	  be configured.
+
+config KGDB_9600BAUD
+	bool "9600"
+
+config KGDB_19200BAUD
+	bool "19200"
+
+config KGDB_38400BAUD
+	bool "38400"
+
+config KGDB_57600BAUD
+	bool "57600"
+
+config KGDB_115200BAUD
+	bool "115200"
+endchoice
+
+choice
+	prompt "Serial port for KGDB"
+	depends on KGDB_SIMPLE_SERIAL
+	default KGDB_TTYS0
+
+config KGDB_TTYS0
+	bool "ttyS0"
+
+config KGDB_TTYS1
+	bool "ttyS1"
+
+config KGDB_TTYS2
+	bool "ttyS2"
+
+config KGDB_TTYS3
+	bool "ttyS3"
+
+endchoice
+
+config KGDB_IOMEMBASE
+	hex "hex MMIO address of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && IA64
+	help
+	  Some systems (IA64) don't access ports through legacy I/O port
+	  space.  Instead an MMIO address is used to access the UART.
+	  There aren't any standard addresses on most system.  The value
+	  is platform dependent.
+
+config KGDB_PORT
+	hex "hex I/O port address of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
+	default  3f8
+	help
+	  Some systems (x86 family at this writing) allow the port
+	  address to be configured.  The number entered is assumed to be
+	  hex, don't put 0x in front of it.  The standard address are:
+	  COM1 3f8 , irq 4 and COM2 2f8 irq 3.  Setserial /dev/ttySx
+	  will tell you what you have.  It is good to test the serial
+	  connection with a live system before trying to debug.
+
+config KGDB_IRQ
+	int "IRQ of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
+	default 4
+	help
+	  This is the irq for the debug port.  If everything is working
+	  correctly and the kernel has interrupts on a control C to the
+	  port should cause a break into the kernel debug stub.
_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Copyright © 2004, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds