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::Ipc::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 unsigned vcon_read(char *buffer, unsigned size);
67 L4::Cap<void> rcv_cap() { return srv_rcv_cap; }
72 int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
77 L4::Cap<L4::Irq> _uart_irq;
78 Icu_cap_array_svr<Serial_drv>::Irq _irq;
81 Serial_drv::Serial_drv()
82 : Icu_cap_array_svr<Serial_drv>(1, &_irq),
83 _running(false), _uart(0), _uart_irq(L4_INVALID_CAP),
91 Serial_drv::vcon_write(const char *buffer, unsigned size)
93 _uart->write(buffer, size);
98 Serial_drv::vcon_read(char *buffer, unsigned size)
101 while (_uart->char_avail() && size)
103 int c = _uart->get_char(false);
106 buffer[i++] = (char)c;
112 // if there still some data available send this info to the client
113 if (_uart->char_avail())
121 Serial_drv::handle_irq()
123 if (_irq.cap().is_valid())
124 _irq.cap()->trigger();
126 //_uart_irq->unmask();
135 l4_addr_t phys_base = 0x1000a000;
138 l4_addr_t phys_base = 0x49020000;
140 l4_addr_t virt_base = 0;
142 if (l4io_request_iomem(phys_base, 0x1000, L4IO_MEM_NONCACHED, &virt_base))
144 printf("serial-drv: request io-memory from l4io failed.\n");
147 printf("serial-drv: virtual base at:%lx\n", virt_base);
149 L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base);
150 _uart = new (malloc(sizeof(L4::Uart_pl011))) L4::Uart_pl011;
151 //_uart = new (malloc(sizeof(L4::Uart_omap35x))) L4::Uart_omap35x;
152 _uart->startup(regs);
154 _uart_irq = L4Re::Util::cap_alloc.alloc<L4::Irq>();
155 if (!_uart_irq.is_valid())
157 printf("serial-drv: Alloc capability for uart-irq failed.\n");
161 if (l4io_request_irq(irq_num, _uart_irq.cap()))
163 printf("serial-drv: request uart-irq from l4io failed\n");
167 /* setting IRQ type to L4_IRQ_F_POS_EDGE seems to be wrong place */
168 if (l4_error(_uart_irq->attach((l4_umword_t)static_cast<L4::Server_object *>(this),
169 L4Re::Env::env()->main_thread())))
171 printf("serial-drv: attach to uart-irq failed.\n");
175 if ((l4_ipc_error(_uart_irq->unmask(), l4_utcb())))
177 printf("serial-drv: unmask uart-irq failed.\n");
180 _uart->enable_rx_irq(true);
182 srv_rcv_cap = L4Re::Util::cap_alloc.alloc<void>();
183 if (!srv_rcv_cap.is_valid())
185 printf("serial-drv: Alloc capability for rcv-cap failed.\\n");
193 Serial_drv::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
200 if (!L4Re::Util::Icu_svr<Serial_drv>::dispatch(obj, ios))
203 return L4Re::Util::Vcon_svr<Serial_drv>::dispatch(obj, ios);
205 return -L4_EBADPROTO;
211 Serial_drv serial_drv;
213 if (!server.registry()->register_obj(&serial_drv, "vcon"))
215 printf("Failed to register serial driver; Aborting.\n");
219 if (!serial_drv.running())
221 printf("Failed to initialize serial driver; Aborting.\n");
225 printf("Starting server loop\n");