]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/serial-drv/server/src/main.cc
Some minor fixes.
[l4.git] / l4 / pkg / serial-drv / server / src / main.cc
1 /*
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)
5  *
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.
9  */
10 #include <l4/drivers/uart_pl011.h>
11 #include <l4/drivers/uart_omap35x.h>
12 #include <l4/io/io.h>
13 #include <l4/re/env>
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>
20 #include <l4/re/util/br_manager>
21 #include <l4/sys/irq>
22 #include <l4/util/util.h>
23
24 #include <cstdlib>
25 #include <cstdio>
26 #include <stdarg.h>
27
28 #include <l4/cxx/ipc_server>
29 #include <l4/sys/cxx/ipc_legacy>
30
31
32 using L4Re::Env;
33 using L4Re::Util::Registry_server;
34
35 static Registry_server<L4Re::Util::Br_manager_hooks> server(l4_utcb(),
36                                           Env::env()->main_thread(),
37                                           Env::env()->factory());
38
39 using L4Re::Util::Vcon_svr;
40 using L4Re::Util::Icu_cap_array_svr;
41
42 class Serial_drv :
43   public Vcon_svr<Serial_drv>,
44   public Icu_cap_array_svr<Serial_drv>,
45   public L4::Server_object_t<L4::Vcon>
46 {
47 public:
48   Serial_drv();
49   virtual ~Serial_drv() throw() {}
50
51   bool running() const { return _running; }
52
53   int vcon_write(const char *buffer, unsigned size);
54   unsigned vcon_read(char *buffer, unsigned size);
55
56   int handle_irq();
57
58   bool init();
59
60   // FIXME: this breaks IRQ handling need an extra object for this!
61   L4_RPC_LEGACY_DISPATCH(L4::Vcon);
62   int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
63   { return dispatch<L4::Ipc::Iostream>(obj, ios); }
64
65   void serprintf(char const *fmt, ...)
66     __attribute__((format(printf, 2, 3)));
67
68 private:
69   bool _running;
70   L4::Uart *_uart;
71   L4::Cap<L4::Irq> _uart_irq;
72   Icu_cap_array_svr<Serial_drv>::Irq _irq;
73 };
74
75 Serial_drv::Serial_drv()
76   : Icu_cap_array_svr<Serial_drv>(1, &_irq),
77     _running(false), _uart(0), _uart_irq(L4_INVALID_CAP),
78     _irq()
79 {
80   if (init())
81     _running = true;
82 }
83
84 int
85 Serial_drv::vcon_write(const char *buffer, unsigned size)
86 {
87   _uart->write(buffer, size);
88   return -L4_EOK;
89 }
90
91 unsigned
92 Serial_drv::vcon_read(char *buffer, unsigned size)
93 {
94   unsigned i = 0;
95   while (_uart->char_avail() && size)
96     {
97       int c = _uart->get_char(false);
98       if (c >= 0)
99         {
100           buffer[i++] = (char)c;
101           size--;
102         }
103       else
104         break;
105     }
106   // if there still some data available send this info to the client
107   if (_uart->char_avail())
108     i++;
109   else
110     _uart_irq->unmask();
111   return i;
112 }
113
114 int
115 Serial_drv::handle_irq()
116 {
117   if (_irq.cap().is_valid())
118     _irq.cap()->trigger();
119
120   //_uart_irq->unmask();
121
122   return L4_EOK;
123 }
124
125 void
126 Serial_drv::serprintf(const char *fmt, ...)
127 {
128   va_list l;
129   va_start(l, fmt);
130   char buf[200];
131   unsigned len = vsnprintf(buf, sizeof(buf), fmt, l);
132   buf[sizeof(buf) - 1] = 0;
133
134   if (running())
135     _uart->write(buf, len > sizeof(buf) ? sizeof(buf) : len);
136   va_end(l);
137 }
138
139 bool
140 Serial_drv::init()
141 {
142   int irq_num = 37;
143   l4_addr_t phys_base = 0x1000a000;
144 #if 0
145   int irq_num = 74;
146   l4_addr_t phys_base = 0x49020000;
147 #endif
148   l4_addr_t virt_base = 0;
149
150   if (l4io_request_iomem(phys_base, 0x1000, L4IO_MEM_NONCACHED, &virt_base))
151     {
152       printf("serial-drv: request io-memory from l4io failed.\n");
153       return false;
154     }
155   printf("serial-drv: virtual base at:%lx\n", virt_base);
156
157   L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base);
158   _uart = new (malloc(sizeof(L4::Uart_pl011))) L4::Uart_pl011(24019200);
159   //_uart = new (malloc(sizeof(L4::Uart_omap35x))) L4::Uart_omap35x;
160   _uart->startup(regs);
161
162   _uart_irq = L4Re::Util::cap_alloc.alloc<L4::Irq>();
163   if (!_uart_irq.is_valid())
164     {
165       serprintf("serial-drv: Alloc capability for uart-irq failed.\n");
166       return false;
167     }
168
169   if (l4io_request_irq(irq_num, _uart_irq.cap()))
170     {
171       serprintf("serial-drv: request uart-irq from l4io failed\n");
172       return false;
173     }
174
175   /* setting IRQ type to L4_IRQ_F_POS_EDGE seems to be wrong place */
176   if (l4_error(_uart_irq->attach((l4_umword_t)static_cast<L4::Server_object *>(this),
177           L4Re::Env::env()->main_thread())))
178     {
179       serprintf("serial-drv: attach to uart-irq failed.\n");
180       return false;
181     }
182
183   if ((l4_ipc_error(_uart_irq->unmask(), l4_utcb())))
184     {
185       serprintf("serial-drv: unmask uart-irq failed.\n");
186       return false;
187     }
188   _uart->enable_rx_irq(true);
189
190   return true;
191 }
192
193 #if 0
194 int
195 Serial_drv::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
196 {
197   l4_msgtag_t tag;
198   ios >> tag;
199   switch (tag.label())
200     {
201     case L4_PROTO_IRQ:
202         {
203           int r = L4Re::Util::Icu_svr<Serial_drv>::dispatch(obj, ios);
204           if (r)
205             return r;
206           return handle_irq();
207         }
208     case L4_PROTO_LOG:
209       return L4Re::Util::Vcon_svr<Serial_drv>::dispatch(obj, ios);
210     default:
211       return -L4_EBADPROTO;
212     }
213 }
214 #endif
215
216 int main()
217 {
218   Serial_drv serial_drv;
219
220   if (!server.registry()->register_obj(&serial_drv, "vcon"))
221     {
222       printf("Failed to register serial driver; Aborting.\n");
223       return 1;
224     }
225
226   if (!serial_drv.running())
227     {
228       printf("Failed to initialize serial driver; Aborting.\n");
229       return 1;
230     }
231
232   printf("Starting server loop\n");
233   server.loop();
234
235   return 0;
236 }