2 * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>,
4 * Frank Mehnert <fm3@os.inf.tu-dresden.de>
5 * economic rights: Technische Universität Dresden (Germany)
7 * This file is part of TUD:OS and distributed under the terms of the
8 * GNU General Public License 2.
9 * Please see the COPYING-GPL-2 file for details.
14 #include <l4/util/port_io.h>
15 #include "base_critical.h"
18 static int ser_io_base;
21 struct bootstrap_termios {
22 unsigned long c_iflag;
23 unsigned long c_oflag;
24 unsigned long c_cflag;
25 unsigned long c_lflag;
26 unsigned char c_cc[20];
33 OPOST, /* output flags */
34 CS8, /* control flags */
37 _POSIX_VDISABLE, /* VEOL */
51 115200, /* input speed */
52 115200, /* output speed */
56 com_cons_putchar(int ch)
58 base_critical_enter();
62 base_critical_leave();
66 if (serial_termios.c_oflag & OPOST)
68 com_cons_putchar('\r');
70 /* Wait for the transmit buffer to become available. */
71 while (!(l4util_in8(ser_io_base + 5) & 0x20));
73 l4util_out8(ch, ser_io_base + 0);
75 base_critical_leave();
79 com_cons_char_avail(void)
81 return !!(l4util_in8(ser_io_base + 5) & 0x01);
85 com_cons_try_getchar(void)
89 base_critical_enter();
93 base_critical_leave();
97 /* character available? */
98 if (com_cons_char_avail()) {
100 ch = l4util_in8(ser_io_base + 0);
103 base_critical_leave();
108 have_serial(unsigned port_base)
110 unsigned char scratch, scratch2, scratch3;
112 scratch = l4util_in8(port_base + 1);
113 l4util_out8(0, port_base + 1);
117 scratch2 = l4util_in8(port_base + 1);
118 l4util_out8(0x0f, port_base + 1);
122 scratch3 = l4util_in8(port_base + 1);
123 l4util_out8(scratch, port_base + 1);
125 if (scratch2 || scratch3 != 0x0f)
132 com_cons_init(int com_port_or_base)
137 base_critical_enter();
139 switch (com_port_or_base)
141 case 1: com_port_or_base = 0x3f8; break;
142 case 2: com_port_or_base = 0x2f8; break;
143 case 3: com_port_or_base = 0x3e8; break;
144 case 4: com_port_or_base = 0x2e8; break;
147 /* Silently fail if serial port is not available */
148 if (!have_serial(com_port_or_base))
150 base_critical_leave();
154 ser_io_base = com_port_or_base;
156 /* Determine what to plug in the data format register. */
157 if (serial_termios.c_cflag & PARENB)
158 if (serial_termios.c_cflag & PARODD)
164 if (serial_termios.c_cflag & CSTOPB)
166 switch (serial_termios.c_cflag & 0x00000300)
168 case CS5: dfr |= 0x00; break;
169 case CS6: dfr |= 0x01; break;
170 case CS7: dfr |= 0x02; break;
171 case CS8: dfr |= 0x03; break;
174 /* Convert the baud rate into a divisor latch value. */
175 divisor = 115200 / serial_termios.c_ospeed;
177 /* Initialize the serial port. */
178 l4util_out8(0x80 | dfr, ser_io_base + 3); /* DLAB = 1 */
179 l4util_out8(divisor & 0xff, ser_io_base + 0);
180 l4util_out8(divisor >> 8, ser_io_base + 1);
181 l4util_out8(0x03 | dfr, ser_io_base + 3); /* DLAB = 0, frame = 8N1 */
182 l4util_out8(0x00, ser_io_base + 1); /* no interrupts enabled */
183 l4util_out8(0x0b, ser_io_base + 4); /* OUT2, RTS, and DTR enabled */
185 l4util_out8(0x41, ser_io_base + 2); /* 4 byte trigger + on */
187 /* Clear all serial interrupts. */
188 l4util_in8(ser_io_base + 6); /* ID 0: read RS-232 status register */
189 l4util_in8(ser_io_base + 2); /* ID 1: read interrupt identification reg */
190 l4util_in8(ser_io_base + 0); /* ID 2: read receive buffer register */
191 l4util_in8(ser_io_base + 5); /* ID 3: read serialization status reg */
193 base_critical_leave();