summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c
diff options
context:
space:
mode:
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;