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"
17 #include "koptions-def.h"
19 static int ser_io_base;
22 struct bootstrap_termios {
23 unsigned long c_iflag;
24 unsigned long c_oflag;
25 unsigned long c_cflag;
26 unsigned long c_lflag;
27 unsigned char c_cc[20];
34 OPOST, /* output flags */
35 CS8, /* control flags */
38 _POSIX_VDISABLE, /* VEOL */
52 115200, /* input speed */
53 115200, /* output speed */
57 com_cons_putchar(int ch)
59 base_critical_enter();
63 base_critical_leave();
67 if (serial_termios.c_oflag & OPOST)
69 com_cons_putchar('\r');
71 /* Wait for the transmit buffer to become available. */
72 while (!(l4util_in8(ser_io_base + 5) & 0x20));
74 l4util_out8(ch, ser_io_base + 0);
76 base_critical_leave();
80 com_cons_char_avail(void)
82 return !!(l4util_in8(ser_io_base + 5) & 0x01);
86 com_cons_try_getchar(void)
90 base_critical_enter();
94 base_critical_leave();
98 /* character available? */
99 if (com_cons_char_avail()) {
101 ch = l4util_in8(ser_io_base + 0);
104 base_critical_leave();
109 have_serial(unsigned port_base)
111 unsigned char scratch, scratch2, scratch3;
113 scratch = l4util_in8(port_base + 1);
114 l4util_out8(0, port_base + 1);
118 scratch2 = l4util_in8(port_base + 1);
119 l4util_out8(0x0f, port_base + 1);
123 scratch3 = l4util_in8(port_base + 1);
124 l4util_out8(scratch, port_base + 1);
126 if (scratch2 || scratch3 != 0x0f)
133 com_cons_init(int com_port_or_base,
134 int com_irq, L4_kernel_options::Uart *kuart,
135 unsigned int *kuart_flags)
140 base_critical_enter();
142 switch (com_port_or_base)
144 case 1: com_port_or_base = 0x3f8;
148 case 2: com_port_or_base = 0x2f8;
152 case 3: com_port_or_base = 0x3e8; break;
153 case 4: com_port_or_base = 0x2e8; break;
156 if (!have_serial(com_port_or_base))
158 base_critical_leave();
162 ser_io_base = com_port_or_base;
164 kuart->access_type = L4_kernel_options::Uart_type_ioport;
165 kuart->irqno = com_irq;
166 kuart->base_address = com_port_or_base;
167 kuart->baud = 115200;
168 *kuart_flags |= L4_kernel_options::F_uart_base
169 | L4_kernel_options::F_uart_baud;
171 *kuart_flags |= L4_kernel_options::F_uart_irq;
173 /* Determine what to plug in the data format register. */
174 if (serial_termios.c_cflag & PARENB)
175 if (serial_termios.c_cflag & PARODD)
181 if (serial_termios.c_cflag & CSTOPB)
183 switch (serial_termios.c_cflag & 0x00000300)
185 case CS5: dfr |= 0x00; break;
186 case CS6: dfr |= 0x01; break;
187 case CS7: dfr |= 0x02; break;
188 case CS8: dfr |= 0x03; break;
191 /* Convert the baud rate into a divisor latch value. */
192 divisor = 115200 / serial_termios.c_ospeed;
194 /* Initialize the serial port. */
195 l4util_out8(0x80 | dfr, ser_io_base + 3); /* DLAB = 1 */
196 l4util_out8(divisor & 0xff, ser_io_base + 0);
197 l4util_out8(divisor >> 8, ser_io_base + 1);
198 l4util_out8(0x03 | dfr, ser_io_base + 3); /* DLAB = 0, frame = 8N1 */
199 l4util_out8(0x00, ser_io_base + 1); /* no interrupts enabled */
200 l4util_out8(0x0b, ser_io_base + 4); /* OUT2, RTS, and DTR enabled */
202 l4util_out8(0x41, ser_io_base + 2); /* 4 byte trigger + on */
204 /* Clear all serial interrupts. */
205 l4util_in8(ser_io_base + 6); /* ID 0: read RS-232 status register */
206 l4util_in8(ser_io_base + 2); /* ID 1: read interrupt identification reg */
207 l4util_in8(ser_io_base + 0); /* ID 2: read receive buffer register */
208 l4util_in8(ser_io_base + 5); /* ID 3: read serialization status reg */
210 base_critical_leave();