2 * gdb_stub/serial_connection.cc --
4 * Connectivity through serial interface
6 * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
7 * economic rights: Technische Universität Dresden (Germany)
8 * This file is part of TUD:OS and distributed under the terms of the
9 * GNU General Public License 2.
10 * Please see the COPYING-GPL-2 file for details.
17 #define MSG() DEBUGf(Romain::Log::Gdb)
25 #include <l4/sys/kdebug.h>
26 #include <l4/re/c/namespace.h>
28 #include <l4/vbus/vbus.h>
29 #include <l4/vbus/vbus_types.h>
30 #include <l4/vbus/vbus_pci.h>
32 #include <l4/util/port_io.h>
33 #include <l4/util/util.h>
35 /* guess where i stole that... */
36 static struct bootstrap_termios {
37 unsigned long c_iflag;
38 unsigned long c_oflag;
39 unsigned long c_cflag;
40 unsigned long c_lflag;
41 unsigned char c_cc[20];
48 OPOST, /* output flags */
49 CS8, /* control flags */
52 _POSIX_VDISABLE, /* VEOL */
66 115200, /* input speed */
67 115200, /* output speed */
76 bool Uart_x86::startup(unsigned long base)
81 /* Determine what to plug in the data format register. */
82 if (serial_termios.c_cflag & PARENB)
83 if (serial_termios.c_cflag & PARODD)
89 if (serial_termios.c_cflag & CSTOPB)
91 switch (serial_termios.c_cflag & 0x00000300)
93 case CS5: dfr |= 0x00; break;
94 case CS6: dfr |= 0x01; break;
95 case CS7: dfr |= 0x02; break;
96 case CS8: dfr |= 0x03; break;
99 /* Convert the baud rate into a divisor latch value. */
100 divisor = 115200 / serial_termios.c_ospeed;
102 /* Initialize the serial port. */
103 l4util_out8(0x80 | dfr, _base + 3); /* DLAB = 1 */
104 l4util_out8(divisor & 0xff, _base + 0);
105 l4util_out8(divisor >> 8, _base + 1);
106 l4util_out8(0x03 | dfr, _base + 3); /* DLAB = 0, frame = 8N1 */
107 l4util_out8(0x00, _base + 1); /* no interrupts enabled */
108 l4util_out8(0x0b, _base + 4); /* OUT2, RTS, and DTR enabled */
110 l4util_out8(0x41, _base + 2); /* 4 byte trigger + on */
112 /* Clear all serial interrupts. */
113 l4util_in8(_base + 6); /* ID 0: read RS-232 status register */
114 l4util_in8(_base + 2); /* ID 1: read interrupt identification reg */
115 l4util_in8(_base + 0); /* ID 2: read receive buffer register */
116 l4util_in8(_base + 5); /* ID 3: read serialization status reg */
120 write_uart("hello\n", 6);
125 void Uart_x86::shutdown_uart() { }
127 int Uart_x86::get_char(bool blocking) const
131 if (!_base) { // base == 0 -> not started up yet
137 enter_kdebug("!blocking");
140 while (!char_avail()) {
143 c = l4util_in8(_base);
146 c = l4util_in8(_base);
154 int Uart_x86::char_avail() const
156 return !!(l4util_in8(_base + 5) & 0x01);
159 void Uart_x86::out_char(char c) const
161 if (!_base) { // base == 0 -> not started up yet
166 // poll until last char sent
167 while (!(l4util_in8(_base + 5) & 0x20))
170 l4util_out8(c, _base);
173 int Uart_x86::write_uart(char const *s, unsigned long count) const
175 unsigned long c = count;
188 void Romain::SerialConnection::get_vbus_resources()
190 l4vbus_device_handle_t dev = 0;
191 l4vbus_device_t devinfo;
192 l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
193 l4vbus_resource_t res;
196 err = l4vbus_get_device_by_hid(vbus, 0, &dev, "PNP0600", 0, &devinfo);
198 assert(devinfo.num_resources == 1);
200 err = l4vbus_get_resource(vbus, dev, 0, &res);
203 err = l4vbus_request_resource(vbus, &res, 0);
206 if (res.type == L4VBUS_RESOURCE_PORT) {
207 _uart.startup(res.start);
209 enter_kdebug("resource not a port!?");
215 void Romain::SerialConnection::setup_and_wait()
217 // wait until we see the first character on the serial line
218 while (!_uart.char_avail())
222 void Romain::SerialConnection::disconnect()
227 int Romain::SerialConnection::wait_for_cmd(char * const buf, unsigned bufsize)
229 buf[0] = _uart.get_char();
230 //MSG() << "next packet start: " << buf[0] << "(" << std::hex << (unsigned)buf[0] << ")";
241 ERROR() << "Unknown cmd start? '" << buf[0] << "'";
246 while (idx < bufsize-2) {
247 buf[idx] = _uart.get_char();
249 if (buf[idx] == '#') {
250 buf[idx+1] = _uart.get_char();
251 buf[idx+2] = _uart.get_char();
255 //l4_sleep(1); // XXX sleep synchronization is evil. why does this not work without?
258 if (idx >= bufsize) {
259 ERROR() << "Overflow in cmd buffer: " << buf;
263 //Romain::dump_mem(buf, 40);
267 int Romain::SerialConnection::senddata(char const * const buf, unsigned bufsize)
270 return _uart.write_uart(buf, bufsize);