2 * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>,
3 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
10 #include <l4/drivers/uart_pl011.h>
11 #include <l4/drivers/uart_omap35x.h>
14 #include <l4/re/error_helper>
15 #include <l4/re/namespace>
16 #include <l4/re/util/cap_alloc>
17 #include <l4/re/util/object_registry>
18 #include <l4/re/util/icu_svr>
19 #include <l4/re/util/vcon_svr>
21 #include <l4/util/util.h>
27 static L4::Cap<void> srv_rcv_cap;
30 public L4::Ipc_svr::Ignore_errors,
31 public L4::Ipc_svr::Default_timeout,
32 public L4::Ipc_svr::Compound_reply
35 void setup_wait(L4::Ipc_istream &istr, bool)
38 istr << L4::Small_buf(srv_rcv_cap.cap(), L4_RCV_ITEM_LOCAL_ID);
39 l4_utcb_br_u(istr.utcb())->bdr = 0;
44 using L4Re::Util::Registry_server;
46 static Registry_server<Loop_hooks> server(l4_utcb(),
47 Env::env()->main_thread(),
48 Env::env()->factory());
50 using L4Re::Util::Vcon_svr;
51 using L4Re::Util::Icu_cap_array_svr;
54 public Vcon_svr<Serial_drv>,
55 public Icu_cap_array_svr<Serial_drv>,
56 public L4::Server_object
60 virtual ~Serial_drv() throw() {}
62 bool running() const { return _running; }
64 int vcon_write(const char *buffer, unsigned size);
65 int vcon_read(char *buffer, unsigned size);
68 L4::Cap<void> rcv_cap() { return srv_rcv_cap; }
73 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
78 L4::Cap<L4::Irq> _uart_irq;
79 Icu_cap_array_svr<Serial_drv>::Irq _irq;
82 Serial_drv::Serial_drv()
83 : Icu_cap_array_svr<Serial_drv>(1, &_irq),
84 _running(false), _uart(0), _uart_irq(L4_INVALID_CAP),
92 Serial_drv::vcon_write(const char *buffer, unsigned size)
94 _uart->write(buffer, size);
99 Serial_drv::vcon_read(char *buffer, unsigned size)
102 while (_uart->char_avail() && size)
104 int c = _uart->get_char(false);
107 buffer[i++] = (char)c;
113 // if there still some data available send this info to the client
114 if (_uart->char_avail())
122 Serial_drv::vcon_end()
124 return !_uart->char_avail();
129 Serial_drv::handle_irq()
131 if (_irq.cap().is_valid())
132 _irq.cap()->trigger();
134 //_uart_irq->unmask();
143 l4_addr_t phys_base = 0x1000a000;
146 l4_addr_t phys_base = 0x49020000;
148 l4_addr_t virt_base = 0;
150 if (l4io_request_iomem(phys_base, 0x1000, L4IO_MEM_NONCACHED, &virt_base))
152 printf("serial-drv: request io-memory from l4io failed.\n");
155 printf("serial-drv: virtual base at:%lx\n", virt_base);
157 _uart = new (malloc(sizeof(L4::Uart_pl011))) L4::Uart_pl011(irq_num, irq_num);
158 //_uart = new (malloc(sizeof(L4::Uart_omap35x))) L4::Uart_omap35x(irq_num, irq_num);
159 _uart->startup(virt_base);
161 _uart_irq = L4Re::Util::cap_alloc.alloc<L4::Irq>();
162 if (!_uart_irq.is_valid())
164 printf("serial-drv: Alloc capability for uart-irq failed.\n");
168 if (l4io_request_irq(irq_num, _uart_irq.cap()))
170 printf("serial-drv: request uart-irq from l4io failed\n");
174 /* setting IRQ type to L4_IRQ_F_POS_EDGE seems to be wrong place */
175 if (l4_error(_uart_irq->attach((l4_umword_t)static_cast<L4::Server_object *>(this),
176 L4Re::Env::env()->main_thread())))
178 printf("serial-drv: attach to uart-irq failed.\n");
182 if ((l4_ipc_error(_uart_irq->unmask(), l4_utcb())))
184 printf("serial-drv: unmask uart-irq failed.\n");
187 _uart->enable_rx_irq(true);
189 srv_rcv_cap = L4Re::Util::cap_alloc.alloc<void>();
190 if (!srv_rcv_cap.is_valid())
192 printf("serial-drv: Alloc capability for rcv-cap failed.\\n");
200 Serial_drv::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
207 if (!L4Re::Util::Icu_svr<Serial_drv>::dispatch(obj, ios))
210 return L4Re::Util::Vcon_svr<Serial_drv>::dispatch(obj, ios);
212 return -L4_EBADPROTO;
218 Serial_drv serial_drv;
220 if (!server.registry()->register_obj(&serial_drv, "vcon"))
222 printf("Failed to register serial driver; Aborting.\n");
226 if (!serial_drv.running())
228 printf("Failed to initialize serial driver; Aborting.\n");
232 printf("Starting server loop\n");