summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2016-04-08 18:39:38 +1000
committerChris Johns <chrisj@rtems.org>2016-05-11 11:45:01 +1000
commit014292a164b8bb5286b6c7dae7c37a469ef6f0cc (patch)
treec7343485ef520fc71f36e5cf8271e08a2c1de789 /c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
parentbsp/qoriq: Add portal clear functions (diff)
downloadrtems-014292a164b8bb5286b6c7dae7c37a469ef6f0cc.tar.bz2
i386/pc386: Add support for the gdb stub to use available console drivers.
Move the gdb stub from the i386 UART code to use the libchip drivers. Use any ports discovered during the probes. Add gdb control to the boot command line. Change the device naming to the full device path, not a partial path. For example /dev/com1.
Diffstat (limited to '')
-rw-r--r--c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c195
1 files changed, 136 insertions, 59 deletions
diff --git a/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c b/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
index 121eef1828..25a153ff93 100644
--- a/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
+++ b/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
@@ -1,23 +1,102 @@
/*
+ * Copyright (c) 2016.
+ * Chris Johns <chrisj@rtems.org>
+ *
* This software is Copyright (C) 1998 by T.sqware - all rights limited
* It is provided in to the public domain "as is", can be freely modified
* as far as this copyight notice is kept unchanged, but does not imply
* an endorsement by T.sqware of the product in which it is included.
*/
-#include <rtems/system.h>
-#include <rtems/score/cpu.h>
#include <bsp.h>
#include <bsp/irq.h>
-#include <uart.h>
-#include <assert.h>
+#include <libchip/serial.h>
+
+#include "../../../shared/console_private.h"
int putDebugChar(int ch); /* write a single character */
int getDebugChar(void); /* read and return a single char */
+/* Check is any characters received are a ^C */
+int i386_gdb_uart_ctrl_c_check(void);
+
+/* Raw interrupt handler. */
+void i386_gdb_uart_isr(void);
+
/* assign an exception handler */
void exceptionHandler(int, void (*handler)(void));
+/* User supplied remote debug option. */
+extern int remote_debug;
+
+/* Current uart and port used by the gdb stub */
+static int uart_current;
+static console_tbl* port_current;
+
+/*
+ * Interrupt service routine for all, it does it check whether ^C is received
+ * if yes it will flip TF bit before returning.
+ *
+ * Note: it should be installed as raw interrupt handler.
+ *
+ * Warning: I do not like the use of the global data, I am not
+ * sure if this is SMP safe.
+ */
+int i386_gdb_uart_isr_regsav[4] RTEMS_UNUSED;
+__asm__ (".p2align 4");
+__asm__ (".text");
+__asm__ (".globl i386_gdb_uart_isr");
+__asm__ ("i386_gdb_uart_isr:");
+__asm__ (" pusha"); /* Push all */
+__asm__ (" call i386_gdb_uart_ctrl_c_check"); /* Look for ^C */
+__asm__ (" movl %eax, i386_gdb_uart_isr_regsav"); /* Save eax */
+__asm__ (" popa"); /* Pop all */
+__asm__ (" xchgl %eax, i386_gdb_uart_isr_regsav"); /* Exchange eax */
+__asm__ (" cmpl $0, %eax"); /* 1 == ^C */
+__asm__ (" je i386_gdb_uart_isr_1"); /* branch if 0 */
+__asm__ (" movl %ebx, i386_gdb_uart_isr_regsav + 4"); /* Save ebx */
+__asm__ (" movl %edx, i386_gdb_uart_isr_regsav + 8"); /* Save edx */
+__asm__ (" popl %ebx"); /* Pop eip */
+__asm__ (" popl %edx"); /* Pop cs */
+__asm__ (" popl %eax"); /* Pop flags */
+__asm__ (" orl $0x100, %eax"); /* Modify it */
+__asm__ (" pushl %eax"); /* Push it back */
+__asm__ (" pushl %edx"); /* Push cs */
+__asm__ (" pushl %ebx"); /* Push eip */
+__asm__ (" movl i386_gdb_uart_isr_regsav + 4, %ebx"); /* Restore ebx */
+__asm__ (" movl i386_gdb_uart_isr_regsav + 8, %edx"); /* Restore edx */
+__asm__ ("i386_gdb_uart_isr_1:");
+__asm__ (" movb $0x20, %al");
+__asm__ (" outb %al, $0x20");
+__asm__ (" movl i386_gdb_uart_isr_regsav, %eax"); /* Restore eax */
+__asm__ (" iret"); /* Done */
+
+static int gdb_hello_index;
+static const char const* gdb_hello = "+";
+
+int i386_gdb_uart_ctrl_c_check(void)
+{
+ if (port_current) {
+ int c = 0;
+ while (c >= 0) {
+ c = port_current->pDeviceFns->deviceRead(uart_current);
+ if (c == 3) {
+ gdb_hello_index = 0;
+ return 1;
+ } else if (gdb_hello[gdb_hello_index] == (char) c) {
+ ++gdb_hello_index;
+ if (gdb_hello[gdb_hello_index] == '\0') {
+ gdb_hello_index = 0;
+ return 1;
+ }
+ } else {
+ gdb_hello_index = 0;
+ }
+ }
+ }
+ return 0;
+}
+
static void
nop(const rtems_raw_irq_connect_data* notused)
{
@@ -29,10 +108,12 @@ isOn(const rtems_raw_irq_connect_data* notused)
return 1;
}
-void BSP_loop(int uart);
-
-/* Current uart used by gdb stub */
-static int uart_current = 0;
+int i386_stub_glue_uart(void)
+{
+ if (port_current == NULL)
+ return -1;
+ return uart_current;
+}
/*
* Initialize glue code linking i386-stub with the rest of
@@ -41,12 +122,19 @@ static int uart_current = 0;
void
i386_stub_glue_init(int uart)
{
- assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
+ rtems_device_minor_number minor = (rtems_device_minor_number) uart;
+
+ port_current = console_find_console_entry(NULL, 0, &minor);
+
+ if (port_current == NULL) {
+ printk("GDB: invalid minor number for UART\n");
+ return;
+ }
uart_current = uart;
- /* BSP_uart_init(uart, 38400, CHR_8_BITS, 0, 0, 0);*/
- BSP_uart_init(uart, 115200, CHR_8_BITS, 0, 0, 0);
+ /* Intialise the UART, assuming polled drivers */
+ port_current->pDeviceFns->deviceInitialize(uart);
}
static void BSP_uart_on(const rtems_raw_irq_connect_data* used)
@@ -72,76 +160,65 @@ void i386_stub_glue_init_breakin(void)
{
rtems_raw_irq_connect_data uart_raw_irq_data;
- assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2);
+ if (port_current == NULL) {
+ printk("GDB: no port initialised\n");
+ return;
+ }
- if(uart_current == BSP_UART_COM1)
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM1_IRQ + BSP_IRQ_VECTOR_BASE;
- }
- else
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM2_IRQ + BSP_IRQ_VECTOR_BASE;
- }
+ if ((port_current->ulIntVector == 0) || (port_current->ulIntVector > 16)) {
+ printk("GDB: no UART interrupt support\n");
+ }
+ else {
+ uart_raw_irq_data.idtIndex = port_current->ulIntVector + BSP_IRQ_VECTOR_BASE;
- if(!i386_get_current_idt_entry(&uart_raw_irq_data))
- {
- printk("cannot get idt entry\n");
+ if (!i386_get_current_idt_entry(&uart_raw_irq_data)) {
+ printk("GBD: cannot get idt entry\n");
rtems_fatal_error_occurred(1);
}
- if(!i386_delete_idt_entry(&uart_raw_irq_data))
- {
- printk("cannot delete idt entry\n");
+ if (!i386_delete_idt_entry(&uart_raw_irq_data)) {
+ printk("GDB: cannot delete idt entry\n");
rtems_fatal_error_occurred(1);
}
- uart_raw_irq_data.on = BSP_uart_on;
- uart_raw_irq_data.off = BSP_uart_off;
- uart_raw_irq_data.isOn= BSP_uart_isOn;
+ uart_raw_irq_data.on = BSP_uart_on;
+ uart_raw_irq_data.off = BSP_uart_off;
+ uart_raw_irq_data.isOn= BSP_uart_isOn;
- /* Install ISR */
- if(uart_current == BSP_UART_COM1)
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM1_IRQ + BSP_IRQ_VECTOR_BASE;
- uart_raw_irq_data.hdl = BSP_uart_dbgisr_com1;
- }
- else
- {
- uart_raw_irq_data.idtIndex = BSP_UART_COM2_IRQ + BSP_IRQ_VECTOR_BASE;
- uart_raw_irq_data.hdl = BSP_uart_dbgisr_com2;
- }
+ /* Install ISR */
+ uart_raw_irq_data.idtIndex = port_current->ulIntVector + BSP_IRQ_VECTOR_BASE;
+ uart_raw_irq_data.hdl = i386_gdb_uart_isr;
- if (!i386_set_idt_entry (&uart_raw_irq_data))
- {
- printk("raw exception handler connection failed\n");
+ if (!i386_set_idt_entry (&uart_raw_irq_data)) {
+ printk("GDB: raw exception handler connection failed\n");
rtems_fatal_error_occurred(1);
}
- /* Enable interrupts */
- BSP_uart_intr_ctrl(uart_current, BSP_UART_INTR_CTRL_GDB);
-
- return;
+ /* Enable interrupts, this is a bit of a hack because we
+ * have to know the device but there is no other call. */
+ (*port_current->setRegister)(port_current->ulCtrlPort1, 1, 0x01);
+ }
}
int
putDebugChar(int ch)
{
- assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2);
-
- BSP_uart_polled_write(uart_current, ch);
-
+ if (port_current != NULL) {
+ port_current->pDeviceFns->deviceWritePolled(uart_current, ch);
+ }
return 1;
}
int getDebugChar(void)
{
- int val;
-
- assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2);
+ int c = -1;
- val = BSP_uart_polled_read(uart_current);
+ if (port_current != NULL) {
+ while (c < 0)
+ c = port_current->pDeviceFns->deviceRead(uart_current);
+ }
- return val;
+ return c;
}
void exceptionHandler(int vector, void (*handler)(void))
@@ -152,13 +229,13 @@ void exceptionHandler(int vector, void (*handler)(void))
if(!i386_get_current_idt_entry(&excep_raw_irq_data))
{
- printk("cannot get idt entry\n");
+ printk("GDB: cannot get idt entry\n");
rtems_fatal_error_occurred(1);
}
if(!i386_delete_idt_entry(&excep_raw_irq_data))
{
- printk("cannot delete idt entry\n");
+ printk("GDB: cannot delete idt entry\n");
rtems_fatal_error_occurred(1);
}
@@ -168,7 +245,7 @@ void exceptionHandler(int vector, void (*handler)(void))
excep_raw_irq_data.hdl = handler;
if (!i386_set_idt_entry (&excep_raw_irq_data)) {
- printk("raw exception handler connection failed\n");
+ printk("GDB: raw exception handler connection failed\n");
rtems_fatal_error_occurred(1);
}
return;