Skip to contentSkip to conversation

Let arches provide serial infos to kgdb

PATCH New Tom Rini 1 participant 1 message Jan 16, 2004

lore
Share & tools
lore

Tom Rini

author
#0 lore raw

PATCH 1/1 Let arches provide serial infos to kgdb

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.

drivers/serial/kgdb_8250.c +64 -30
@@ -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 = {
Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/