diff options
Diffstat (limited to '')
-rw-r--r-- | c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c | 195 |
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; |