source: rtems/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c @ 02ef5d9

5
Last change on this file since 02ef5d9 was 014292a1, checked in by Chris Johns <chrisj@…>, on 04/08/16 at 08:39:38

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.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2016.
3 * Chris Johns <chrisj@rtems.org>
4 *
5 * This software is Copyright (C) 1998 by T.sqware - all rights limited
6 * It is provided in to the public domain "as is", can be freely modified
7 * as far as this copyight notice is kept unchanged, but does not imply
8 * an endorsement by T.sqware of the product in which it is included.
9 */
10
11#include <bsp.h>
12#include <bsp/irq.h>
13#include <libchip/serial.h>
14
15#include "../../../shared/console_private.h"
16
17int  putDebugChar(int ch);     /* write a single character      */
18int  getDebugChar(void);       /* read and return a single char */
19
20/* Check is any characters received are a ^C */
21int i386_gdb_uart_ctrl_c_check(void);
22
23/* Raw interrupt handler. */
24void i386_gdb_uart_isr(void);
25
26/* assign an exception handler */
27void exceptionHandler(int, void (*handler)(void));
28
29/* User supplied remote debug option. */
30extern int remote_debug;
31
32/* Current uart and port used by the gdb stub */
33static int          uart_current;
34static console_tbl* port_current;
35
36/*
37 * Interrupt service routine for all, it does it check whether ^C is received
38 * if yes it will flip TF bit before returning.
39 *
40 * Note: it should be installed as raw interrupt handler.
41 *
42 * Warning: I do not like the use of the global data, I am not
43 *          sure if this is SMP safe.
44 */
45int i386_gdb_uart_isr_regsav[4] RTEMS_UNUSED;
46__asm__ (".p2align 4");
47__asm__ (".text");
48__asm__ (".globl i386_gdb_uart_isr");
49__asm__ ("i386_gdb_uart_isr:");
50__asm__ ("    pusha");                                       /* Push all */
51__asm__ ("    call  i386_gdb_uart_ctrl_c_check");            /* Look for ^C */
52__asm__ ("    movl  %eax, i386_gdb_uart_isr_regsav");        /* Save eax */
53__asm__ ("    popa");                                        /* Pop all */
54__asm__ ("    xchgl %eax, i386_gdb_uart_isr_regsav");        /* Exchange eax */
55__asm__ ("    cmpl  $0, %eax");                              /* 1 == ^C */
56__asm__ ("    je    i386_gdb_uart_isr_1");                   /* branch if 0 */
57__asm__ ("    movl  %ebx, i386_gdb_uart_isr_regsav + 4");    /* Save ebx */
58__asm__ ("    movl  %edx, i386_gdb_uart_isr_regsav + 8");    /* Save edx */
59__asm__ ("    popl  %ebx");                                  /* Pop eip */
60__asm__ ("    popl  %edx");                                  /* Pop cs */
61__asm__ ("    popl  %eax");                                  /* Pop flags */
62__asm__ ("    orl   $0x100, %eax");                          /* Modify it */
63__asm__ ("    pushl %eax");                                  /* Push it back */
64__asm__ ("    pushl %edx");                                  /* Push cs */
65__asm__ ("    pushl %ebx");                                  /* Push eip */
66__asm__ ("    movl  i386_gdb_uart_isr_regsav + 4, %ebx");    /* Restore ebx */
67__asm__ ("    movl  i386_gdb_uart_isr_regsav + 8, %edx");    /* Restore edx */
68__asm__ ("i386_gdb_uart_isr_1:");
69__asm__ ("    movb  $0x20, %al");
70__asm__ ("    outb  %al, $0x20");
71__asm__ ("    movl  i386_gdb_uart_isr_regsav, %eax");        /* Restore eax */
72__asm__ ("    iret");                                        /* Done */
73
74static int gdb_hello_index;
75static const char const* gdb_hello = "+";
76
77int i386_gdb_uart_ctrl_c_check(void)
78{
79  if (port_current) {
80    int c = 0;
81    while (c >= 0) {
82      c = port_current->pDeviceFns->deviceRead(uart_current);
83      if (c == 3) {
84        gdb_hello_index = 0;
85        return 1;
86      } else if (gdb_hello[gdb_hello_index] == (char) c) {
87        ++gdb_hello_index;
88        if (gdb_hello[gdb_hello_index] == '\0') {
89          gdb_hello_index = 0;
90          return 1;
91        }
92      } else {
93        gdb_hello_index = 0;
94      }
95    }
96  }
97  return 0;
98}
99
100static void
101nop(const rtems_raw_irq_connect_data* notused)
102{
103}
104
105static int
106isOn(const rtems_raw_irq_connect_data* notused)
107{
108  return 1;
109}
110
111int i386_stub_glue_uart(void)
112{
113  if (port_current == NULL)
114    return -1;
115  return uart_current;
116}
117
118/*
119 * Initialize glue code linking i386-stub with the rest of
120 * the system
121 */
122void
123i386_stub_glue_init(int uart)
124{
125  rtems_device_minor_number minor = (rtems_device_minor_number) uart;
126
127  port_current = console_find_console_entry(NULL, 0, &minor);
128
129  if (port_current == NULL) {
130    printk("GDB: invalid minor number for UART\n");
131    return;
132  }
133
134  uart_current = uart;
135
136  /* Intialise the UART, assuming polled drivers */
137  port_current->pDeviceFns->deviceInitialize(uart);
138}
139
140static void BSP_uart_on(const rtems_raw_irq_connect_data* used)
141{
142  BSP_irq_enable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
143}
144
145static void BSP_uart_off(const rtems_raw_irq_connect_data* used)
146{
147  BSP_irq_disable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
148}
149
150static int BSP_uart_isOn(const rtems_raw_irq_connect_data* used)
151{
152  return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
153}
154
155/*
156 * In order to have a possibility to break into
157 * running program, one has to call this function
158 */
159void i386_stub_glue_init_breakin(void)
160{
161  rtems_raw_irq_connect_data uart_raw_irq_data;
162
163  if (port_current == NULL) {
164    printk("GDB: no port initialised\n");
165    return;
166  }
167
168  if ((port_current->ulIntVector == 0) || (port_current->ulIntVector > 16)) {
169    printk("GDB: no UART interrupt support\n");
170  }
171  else {
172    uart_raw_irq_data.idtIndex = port_current->ulIntVector + BSP_IRQ_VECTOR_BASE;
173
174    if (!i386_get_current_idt_entry(&uart_raw_irq_data)) {
175      printk("GBD: cannot get idt entry\n");
176      rtems_fatal_error_occurred(1);
177    }
178
179    if (!i386_delete_idt_entry(&uart_raw_irq_data)) {
180      printk("GDB: cannot delete idt entry\n");
181      rtems_fatal_error_occurred(1);
182    }
183
184    uart_raw_irq_data.on  = BSP_uart_on;
185    uart_raw_irq_data.off = BSP_uart_off;
186    uart_raw_irq_data.isOn= BSP_uart_isOn;
187
188    /* Install ISR  */
189    uart_raw_irq_data.idtIndex = port_current->ulIntVector + BSP_IRQ_VECTOR_BASE;
190    uart_raw_irq_data.hdl = i386_gdb_uart_isr;
191
192    if (!i386_set_idt_entry (&uart_raw_irq_data)) {
193      printk("GDB: raw exception handler connection failed\n");
194      rtems_fatal_error_occurred(1);
195    }
196
197    /* Enable interrupts, this is a bit of a hack because we
198     * have to know the device but there is no other call. */
199    (*port_current->setRegister)(port_current->ulCtrlPort1, 1, 0x01);
200  }
201}
202
203int
204putDebugChar(int ch)
205{
206  if (port_current != NULL) {
207    port_current->pDeviceFns->deviceWritePolled(uart_current, ch);
208  }
209  return 1;
210}
211
212int getDebugChar(void)
213{
214  int c = -1;
215
216  if (port_current != NULL) {
217    while (c < 0)
218      c = port_current->pDeviceFns->deviceRead(uart_current);
219  }
220
221  return c;
222}
223
224void exceptionHandler(int vector, void (*handler)(void))
225{
226  rtems_raw_irq_connect_data excep_raw_irq_data;
227
228  excep_raw_irq_data.idtIndex = vector;
229
230  if(!i386_get_current_idt_entry(&excep_raw_irq_data))
231    {
232      printk("GDB: cannot get idt entry\n");
233      rtems_fatal_error_occurred(1);
234    }
235
236  if(!i386_delete_idt_entry(&excep_raw_irq_data))
237    {
238      printk("GDB: cannot delete idt entry\n");
239      rtems_fatal_error_occurred(1);
240    }
241
242  excep_raw_irq_data.on = nop;
243  excep_raw_irq_data.off = nop;
244  excep_raw_irq_data.isOn = isOn;
245  excep_raw_irq_data.hdl = handler;
246
247  if (!i386_set_idt_entry (&excep_raw_irq_data)) {
248      printk("GDB: raw exception handler connection failed\n");
249      rtems_fatal_error_occurred(1);
250    }
251  return;
252}
Note: See TracBrowser for help on using the repository browser.