[PATCH] Let arches provide serial infos to kgdb

Tom Rini
2004-01-16T22:18:52Z

Hello. The following is against kgdb-2.0.3, and allows for
architectures to provide different serial infos to the 8250 stub. This
patch doesn't allow for (yet) registers to be shifted, but that's my
next step. With the following patch applied (and some other bits that
I'm not done with) I can hookup kgdb on one of my PPC boxes and get a
backtrace.

--- 1.1/drivers/serial/kgdb_8250.c Wed Jan 14 15:16:15 2004
+++ edited/drivers/serial/kgdb_8250.c Fri Jan 16 14:27:03 2004
@@ -20,6 +20,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
+#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/serialP.h>
#include <linux/config.h>
@@ -48,24 +49,55 @@
static int kgdb8250_got_dollar = -3, kgdb8250_got_H = -3,
kgdb8250_interrupt_iteration = 0;

+/* We only allow for 4 ports to be registered. We default to standard
+ * PC values. */
+static struct uart_port rs_table[4] = {
+ { .line = 0x3f8, .irq = 4 },
+ { .line = 0x2f8, .irq = 3 },
+ { .line = 0x3e8, .irq = 4 },
+ { .line = 0x2e8, .irq = 3 },
+};
+static void (*serial_outb)(unsigned char, unsigned long);
+static unsigned long (*serial_inb)(unsigned long);
+
extern void set_debug_traps(void) ; /* GDB routine */
int serial8250_release_irq(int irq);

int kgdb8250_irq;
-int kgdb8250_port;
+unsigned long kgdb8250_port;

static int initialized = -1;

int kgdb8250_baud = 115200;
int kgdb8250_ttyS;

+static unsigned long direct_inb(unsigned long addr)
+{
+ return readb(addr);
+}
+
+static void direct_outb(unsigned char val, unsigned long addr)
+{
+ writeb(val, 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);
+}
+
/*
* Get a byte from the hardware data buffer and return it
*/
static int read_data_bfr(void)
{
- if (inb(kgdb8250_port + UART_LSR) & UART_LSR_DR)
- return(inb(kgdb8250_port + UART_RX));
+ if (serial_inb(kgdb8250_port + UART_LSR) & UART_LSR_DR)
+ return(serial_inb(kgdb8250_port + UART_RX));

return( -1 ) ;

@@ -99,9 +133,9 @@
*/
static void kgdb8250_write_char(int chr)
{
- while ( !(inb(kgdb8250_port + UART_LSR) & UART_LSR_THRE) ) ;
+ while ( !(serial_inb(kgdb8250_port + UART_LSR) & UART_LSR_THRE) ) ;

- outb(chr, kgdb8250_port+UART_TX);
+ serial_outb(chr, kgdb8250_port+UART_TX);

} /* write_char */

@@ -135,7 +169,7 @@
do
{
chr = read_data_bfr();
- iir = inb(kgdb8250_port + UART_IIR);
+ iir = serial_inb(kgdb8250_port + UART_IIR);
if (chr < 0) continue ;

/* Check whether gdb sent interrupt */
@@ -272,17 +306,17 @@
* and set speed.
*/
cval = 0x3;
- outb(cval | UART_LCR_DLAB, kgdb8250_port + UART_LCR); /* set DLAB */
- outb(quot & 0xff, kgdb8250_port + UART_DLL); /* LS of divisor */
- outb(quot >> 8, kgdb8250_port + UART_DLM); /* MS of divisor */
- outb(cval, kgdb8250_port + UART_LCR); /* reset DLAB */
- outb(UART_IER_RDI, kgdb8250_port + UART_IER); /* turn on interrupts*/
- outb(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, kgdb8250_port + UART_MCR);
+ serial_outb(cval | UART_LCR_DLAB, kgdb8250_port + UART_LCR); /* set DLAB */
+ serial_outb(quot & 0xff, kgdb8250_port + UART_DLL); /* LS of divisor */
+ serial_outb(quot >> 8, kgdb8250_port + UART_DLM); /* MS of divisor */
+ serial_outb(cval, kgdb8250_port + UART_LCR); /* reset DLAB */
+ serial_outb(UART_IER_RDI, kgdb8250_port + UART_IER); /* turn on interrupts*/
+ serial_outb(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, kgdb8250_port + UART_MCR);

/*
* If we read 0xff from the LSR, there is no UART here.
*/
- if (inb(kgdb8250_port + UART_LSR) == 0xff)
+ if (serial_inb(kgdb8250_port + UART_LSR) == 0xff)
return -1;
return 0;
}
@@ -294,25 +328,18 @@
/*
* Set port and irq number.
*/
- switch(kgdb8250_ttyS)
+ kgdb8250_irq = rs_table[kgdb8250_ttyS].irq;
+ switch(rs_table[kgdb8250_ttyS].iotype)
{
- case 0:
- default:
- kgdb8250_port = 0x3f8;
- kgdb8250_irq = 4;
- break;
- case 1:
- kgdb8250_port = 0x2f8;
- kgdb8250_irq = 3;
- break;
- case 2:
- kgdb8250_port = 0x3e8;
- kgdb8250_irq = 4;
- break;
- case 3:
- kgdb8250_port = 0x2e8;
- kgdb8250_irq = 3;
+ case SERIAL_IO_MEM:
+ kgdb8250_port = (unsigned long)rs_table[kgdb8250_ttyS].membase;
+ serial_inb = direct_inb;
+ serial_outb = direct_outb;
break;
+ default:
+ kgdb8250_port = rs_table[kgdb8250_ttyS].line;
+ serial_inb = io_inb;
+ serial_outb = io_outb;
}

#ifdef CONFIG_SERIAL_8250
@@ -334,6 +361,15 @@

return 0;

+}
+
+void
+kgdb8250_add_port(int i, struct uart_port *serial_req)
+{
+ rs_table[i].iotype = serial_req->iotype;
+ rs_table[i].line = serial_req->line;
+ rs_table[i].membase = serial_req->membase;
+ rs_table[i].regshift = serial_req->regshift;
}

struct kgdb_serial kgdb8250_serial = {

--
Tom Rini